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。