Co2y's Blog

Metaspace记录

Metaspace历史

Metaspace自JDK8加入,用于替代永久代(PermGen)。相应的参数也从-XX:PermSize-XX:MaxPermSize改为-XX:MetaspaceSize-XX:MaxMetaspaceSize

Metaspace本身占用的是native heap,所以通常不会有PermGen OOM的问题。默认Metaspace大小约为~21M,可以通过-XX:MetaspaceSize参数设置初始大小,避免启动时产生full gc。

那么,Metaspace里到底存了哪些东西?

通常来说,Metaspace存了加载的类的元信息、这些类的方法信息(静态与非静态方法)、静态原始变量的值(primitive value)、静态变量的引用信息、JIT信息等。

ClassLoader与Metaspace

Metaspace里存放了加载的类的元信息,那么Metaspace与ClassLoader是什么关系?

首先,我们知道ClassLoader本身的实例是存放在heap中的,同时每一个Metaspace里的类对应heap里的一个class实例。以下这些东西也在heap中:

  • ClassLoader加载的class通常会缓存在堆中
  • ClassLoader引用的class对象(class只引用静态变量)
  • ClassLoader引用的静态变量实例(其它类的实例,例如String)

Metaspace使用率过高

有时我们会发现Metaspace使用率比较高(达到了98%),这时首先要看下Metaspace具体占了多少native内存,以及-XX:MaxMetaspaceSize参数配置了多少。

如果Metaspace实际占用空间不大,或是小于-XX:MaxMetaspaceSize,那么使用率较高问题不大,因为Metaspace会自动扩容。

另外heap dump排查时也有用,因为前面说过,每个Metaspace中的class,在堆中会有一个对应的instance。