Metaspace OOM需确认日志精确匹配“OutOfMemoryError: Metaspace”,检查GC日志中“Metadata GC Threshold”,用jstat观察MU/MC持续上涨,Arthas查ClassLoader实例,调参设-XX:MetaspaceSize与-XX:MaxMetaspaceSize,启用ClassUnloading,加堆转储分析类加载异常。

遇到 java.lang.OutOfMemoryError: Metaspace,说明 JVM 元空间已耗尽,无法为新加载的类分配元数据内存。这不是堆内存问题,不能靠加大 -Xmx 解决,必须针对性排查类加载行为和元空间配置。
确认确实是 Metaspace OOM
别凭监控曲线或“内存高”就下结论。关键看日志第一行是否精确匹配:
- 打开应用启动日志或错误日志,搜索
OutOfMemoryError: Metaspace—— 必须完全一致; - 如果看到的是
Java heap space或unable to create new native thread,走错方向了; - 检查 GC 日志中是否有
[GC (Metadata GC Threshold)],有则证实是元空间触发的 GC,但回收失败。
查类加载是否异常增长
元空间爆掉,90% 是因为类被反复加载却没卸载。重点盯动态生成类的场景:
- 用
jstat -gc <pid></pid>持续观察:MU(Metaspace Used)持续上涨、MC(Metaspace Capacity)接近上限,且CCSU(Compressed Class Space Used)也同步涨,大概率是类加载失控; - 运行时用 Arthas 连上进程:
arthas-boot.jar <pid></pid>,再执行vmtool --action getInstances --className java.lang.ClassLoader --limit 10,看是否存在大量不同 ClassLoader 实例; - 常见诱因:频繁热部署(如开发态 Spring Boot DevTools)、大量使用 CGLIB/ASM 动态代理、JSP 编译、OSGi 插件式架构、或框架未正确关闭上下文(如 Spring 容器重复刷新)。
调参与加固配置
参数不是越大越好,但不设上限风险极高(默认无上限,可能吃光系统内存):
- 设置合理上限:
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m(中小应用起步值,可根据jstat观察峰值上浮 20% 设定); - 启用类卸载支持(尤其对动态类场景):
-XX:+UseG1GC -XX:+ClassUnloadingWithConcurrentMark(G1 下推荐),或旧版 CMS:-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled; - 加日志辅助判断:
-Xlog:gc*:file=gc.log:time,uptime,level,tags(Java 9+),确保日志里含 Metaspace 使用量字段。
抓现场做深度分析
OOM 发生后,仅看日志不够,要拿到“案发现场”:
- 启动时加参数:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumps/,OOM 时自动生成.hprof; - 用 Eclipse MAT 打开 dump 文件,按
java.lang.ClassLoader或java.lang.Class分组查看实例数,找出异常多的 ClassLoader 及其加载的类; - 结合
jcmd <pid> VM.native_memory summary scale=MB</pid>,确认Class模块的 native 内存占用是否远超预期(比如 >300MB),进一步佐证类膨胀。


















