1. 什么是metaspace

JDK8中去掉了原来的永久代,而用metaspace来替代。并且metaspace现在是使用了netive memory。

原来放在永久代里面的东西也全部放到元数据区了。元数据区主要包含以下内容:

  1. name and fields of the class: 存放类名字、成员变量相关的元数据
  2. methods of a class with the bytecode of the methods: 存放类方法的元数据
  3. constant pool: 常量池
  4. JIT optimizations: JIT优化相关的数据
  5. etc...

2. 为什么用元数据区替换永久代

详细可以参考JEP 122: Remove the Permanent Generation.
简单概括下就是:

  1. 元数据如果不设置MaxMetaspaceSize的话,可以自动调整大小。永久代的大小总是难以预测,设置太大造成资源浪费,设置太小容易造成OOM
  2. 处于提升GC性能考虑。可以支持无停顿的并发类卸载。
  3. 支持G1垃圾收集器的类并发卸载。

3. 实战

3.1 JVM选项

建议开启:
-XX:+HeapDumpOutOfMemoryError,方便出现OOM的时候自动heap dump

3.2 哪些原因会造成metaspace OOM

  1. 元数据区内存不足:对于应用来说,如果你设置了MaxMetaspaceSize的话,可能设置的太小了。如果没设置MaxMetaspaceSize,那可能就是内存太小。这个可以评估下正常运行时所需的MetaspaceSize。
  2. 运行时瞬间load了大量的类: 看看自己的应用是否有代码在运行时异常load大量类。
  3. 使用了ASM这种字节码编辑技术: 使用ASM也会导致频繁创建class,导致对元数据的大量占用。

参考资料:

  1. java.lang.OutOfMemoryError:Metaspace