0%

方法区、永久代和元空间Metaspace

方法区

方法区与 Java 堆一样,是各个线程共享的内存区域,它用于存储常量池、域、方法数据、方法体、构造函数、类中专用方法、实例初始化、接口初始化等数据,其大小可以通过参数来设置。通常方法区存储区域的大小在程序启动后就是固定的了,JVM运行一段时间后,需要加载的类通常都已经加载到JVM中了。
《Java 虚拟机规范》只是规定了有方法区这么个概念和它的作用,并没有规定如何去实现它。
同时,在JDK1.7开始,原本规定在方法区中的常量池移了出来,在Java堆中中开辟了一块区域存放。

永久代

方法区和永久代的关系很像Java中接口和类的关系,类实现了接口,而永久代就是HotSpot虚拟机对虚拟机规范中方法区的一种实现方式,简而言之,方法区是Java虚拟机规范,而永久代是一种实现。
在Java虚拟机规范中,方法区在虚拟机启动的时候创建,虽然方法区是堆的逻辑组成部分,但是简单的虚拟机实现可以选择不在方法区实现垃圾回收与压缩。这个版本的虚拟机规范也不限定实现方法区的内存位置和编译代码的管理策略。所以不同的JVM厂商,针对自己的JVM可能有不同的方法区实现方式。
在HotSpot中,设计者将方法区纳入GC分代收集。HotSpot虚拟机堆内存被分为新生代和老年代,对堆内存进行分代管理,所以HotSpot虚拟机使用者更愿意将方法区称为老年代。

元空间Metaspace

Java8以前,HotSpots取消了永久代,但不代表方法区这个规范不存在了,取而代之的技术叫元空间。 因为以前的永久代是在JVM分配的内存中,本身是设置好的固定大小上限,无法改变,所以溢出的可能性比较大,Java8开始把这一部分移到了本机内存,也就是元空间的大小只受本机内存的限制,虽然元空间仍旧可能溢出,但是比原来出现的几率会更小。
你可以使用-XX:MaxMetaspaceSize标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系统内存的限制。-XX:MetaspaceSize调整标志定义元空间的初始大小如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。