1. 什么是metaspace
JDK8中去掉了原来的永久代,而用metaspace来替代。并且metaspace现在是使用了netive memory。
原来放在永久代里面的东西也全部放到元数据区了。元数据区主要包含以下内容:
- name and fields of the class: 存放类名字、成员变量相关的元数据
- methods of a class with the bytecode of the methods: 存放类方法的元数据
- constant pool: 常量池
- JIT optimizations: JIT优化相关的数据
- etc...
2. 为什么用元数据区替换永久代
详细可以参考JEP 122: Remove the Permanent Generation.
简单概括下就是:
- 元数据如果不设置MaxMetaspaceSize的话,可以自动调整大小。永久代的大小总是难以预测,设置太大造成资源浪费,设置太小容易造成OOM
- 处于提升GC性能考虑。可以支持无停顿的并发类卸载。
- 支持G1垃圾收集器的类并发卸载。
3. 实战
3.1 JVM选项
建议开启:
-XX:+HeapDumpOutOfMemoryError,方便出现OOM的时候自动heap dump
3.2 哪些原因会造成metaspace OOM
- 元数据区内存不足:对于应用来说,如果你设置了MaxMetaspaceSize的话,可能设置的太小了。如果没设置MaxMetaspaceSize,那可能就是内存太小。这个可以评估下正常运行时所需的MetaspaceSize。
- 运行时瞬间load了大量的类: 看看自己的应用是否有代码在运行时异常load大量类。
- 使用了ASM这种字节码编辑技术: 使用ASM也会导致频繁创建class,导致对元数据的大量占用。
参考资料: