JVM-元空间溢出-OutOfMemoryError-Metaspace排查与解决

JVM 元空间溢出(OutOfMemoryError: Metaspace)排查与解决

Metaspace 溢出常被误以为是堆不够,其实根因是类加载器泄漏导致类元数据无法卸载。本文讲清 Heap 与 Metaspace 的区别、类卸载机制,以及 jstat / arthas 排查和治理方法。

一、问题案例

服务频繁热部署,跑几天就报 OutOfMemoryError: Metaspace。第一反应是堆内存不够,加了 -Xmx 也没用,还是挂。

二、原理详解:Metaspace 与类卸载

Metaspace 不在堆里,它存的是类的元数据(类名、方法、字段信息)。

  • Heap(堆) 存对象;
  • Metaspace(元空间) 存类元数据,两者是分开的。

Metaspace 溢出的典型原因:大量类被反复加载,且旧的类加载器没被回收

类想被卸载,前提是「类加载器被 GC」。如果类加载器还被引用(线程、静态引用等),类就卸载不了,Metaspace 只增不减。

热部署框架、动态代理、反射生成类、脚本引擎动态编译,都会反复创建 ClassLoader,是 Metaspace 泄漏的高发场景。

三、实战代码:排查与治理

排查:

bash 复制代码
# 设个上限,避免无限制增长拖垮整个 JVM
-XX:MaxMetaspaceSize=256m

# 观察 Metaspace 用量
jstat -gc <pid> 1000

用 arthas 或 heap dump 定位是哪些 ClassLoader 在堆积:

bash 复制代码
# arthas 查看类加载器
classloader --list

治理:

  • 找到「反复创建 ClassLoader」的源头(热部署、动态代理、反射框架),控制加载频率或复用 ClassLoader;
  • 适当调大 -XX:MaxMetaspaceSize 只能兜底,治标不治本。

四、常见踩坑

  • Metaspace OOM ≠ Heap OOM :加 -Xmx 对 Metaspace 没用。
  • 频繁动态生成类的框架要警惕:Groovy / JS 脚本引擎、大量动态代理,都是 ClassLoader 泄漏重灾区。

五、总结

  • Metaspace 存类元数据,与堆分开,溢出原因也不同。
  • 根因是类加载器泄漏导致类无法卸载。
  • jstat -gc / arthas 定位,从源头控制 ClassLoader 创建。

我是无羡(小剑),全栈偏后端的独立开发者。

作品集:无羡 · 独立开发者作品集

如果对你有帮助,欢迎点赞、收藏、关注。

相关推荐
用户0942485680310 小时前
第12章:JDK 诊断工具箱——jps / jstat / jmap / jcmd / jhsdb
java·jvm
程序员阿鹏11 小时前
双亲委派机制
java·jvm·数据结构·后端
用户0942485680314 小时前
第11章:OpenJDK反射、动态代理与 MethodHandle 初探
java·jvm
wuminyu15 小时前
纯轻量级锁体系下C2编译器锁粗化和消除机制剖析
java·linux·c语言·jvm·c++
binqian15 小时前
【java】Java 两种锁机制与线程阻塞唤醒原理
jvm·spring boot·spring
香吧香1 天前
java服务异常日志只打印异常类型,没有堆栈定位分析
java·jvm·异常
11路没有终点1 天前
Java 微服务性能调优:jstack/jmap/jstat 三剑客实战指南
jvm·性能测试
wuminyu2 天前
Markword在紧凑对象头上的实现原理剖析
java·linux·c语言·jvm·c++