元空间(metaspace)概念

在之前介绍的分代垃圾回收算法中,我们一直有一个永久代存在,叫 PermGen,内存上它是挨着堆的。为了垃圾回收方便,HotSpot 在永久代上一直是使用老年代的垃圾回收算法。

永久代主要存放以下数据:

  • JVM internal representation of classes and their metadata
  • Class statics
  • Interned strings

从 JDK7 开始,JDK 开发者们就有消灭永久代的打算了。有部分数据移到永久代之外了:

  • Symbols => native memory
  • Interned strings => Java Heap
  • Class statics => Java Heap

到了 JDK8,这个工作终于完成了,彻底废弃了 PermGen,Metaspace 取而代之。

什么是 Metaspace

Metaspace 区域位于堆外,所以它的最大内存大小取决于系统内存,而不是堆大小,我们可以指定 MaxMetaspaceSize 参数来限定它的最大内存。

Metaspace 是用来存放 class metadata 的,class metadata 用于记录一个 Java 类在 JVM 中的信息,包括但不限于 JVM class file format 的运行时数据:

1、Klass 结构,这个非常重要,把它理解为一个 Java 类在虚拟机内部的表示吧;
2、method metadata,包括方法的字节码、局部变量表、异常表、参数信息等;
3、常量池;
4、注解;
5、方法计数器,记录方法被执行的次数,用来辅助 JIT 决策;
6、 其他

虽然每个 Java 类都关联了一个 java.lang.Class 的实例,而且它是一个贮存在堆中的 Java 对象。但是类的 class metadata 不是一个 Java 对象,它不在堆中,而是在 Metaspace 中。

什么时候分配 Metaspace 空间

当一个类被加载时,它的类加载器会负责在 Metaspace 中分配空间用于存放这个类的元数据。