一、从方法区(PermGen)到元空间(Metaspace)

  • 方法区(PermGen)
  1. JDK1.8以前的HotSpot JVM有方法区,也叫永久代(permanent generation)。
  2. 方法区用于存放已被虚拟机加载的类信息、常量、静态变量,即编译器编译后的代码。
  3. 方法区是一片连续的堆空间,通过-XX:MaxPermSize来设定永久代最大可分配空间,当JVM加载的类信息容量超过了这个值,会报OOM:PermGen错误。
  4. 永久代的GC是和老年代(old generation)捆绑在一起的,无论谁满了,都会触发永久代和老年代的垃圾收集。
  5. JDK1.7开始了方法区的部分移除:符号引用(Symbols)移至native heap,字面量(interned strings)和静态变量(class statics)移至java heap。

 

 

1,为什么要用Metaspace替代方法区

随着动态类加载的情况越来越多,这块内存变得不太可控,如果设置小了,系统运行过程中就容易出现内存溢出,设置大了又浪费内存。

 

Metaspace由两大部分组成:Klass Metaspace和NoKlass Metaspace。

  • Klass Metaspace
  1. Klass Metaspace就是用来存klass的,就是class文件在jvm里的运行时数据结构(不过我们看到的类似A.class其实是存在heap里的,是java.lang.Class的对象实例)。
  2. 这部分默认放在Compressed Class Pointer Space中,是一块连续的内存区域,

紧接着Heap,和之前的perm一样。通过-XX:CompressedClassSpaceSize来控制这块内存的大小,默认是1G。

 

下图展示了对象的存储模型,_mark是对象的Mark Word,_klass是元数据指针

 

Compressed Class Pointer Space不是必须有的,如果设置了-XX:-UseCompressedClassPointers,或者-Xmx设置大于32G,就不会有这块内存,这种情况下klass都会存在NoKlass Metaspace里。

 

  • NoKlass Metaspace
  1. NoKlass Metaspace专门来存klass相关的其他的内容,比如method,constantPool等,可以由多块不连续的内存组成。
  2. 这块内存是必须的,虽然叫做NoKlass Metaspace,但是也其实可以存klass的内容,上面已经提到了对应场景。
  3. NoKlass Metaspace在本地内存中分配。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐