dump分析核心是区分合理存活与内存泄漏:存活对象指从gc roots可达且未被标记回收的对象;mat中用直方图、支配树和路径到gc roots定位异常;需结合线程栈、创建时间及多时间点dump对比验证,避开jvm内部结构、软弱引用及单点误判。

分析Dump文件中存活的对象,核心是区分“该留的”和“不该留的”——不是所有存活对象都代表泄漏,关键看它们是否被业务逻辑合理持有、能否随请求结束自然释放。
明确“存活对象”的定义
存活对象指从GC Roots(如线程栈、静态变量、JNI引用等)出发,可达且未被标记为可回收的对象。jmap加 live 参数生成的dump,默认只包含这部分对象,排除了已死亡但尚未被GC清理的垃圾,更贴近真实内存压力来源。
用MAT快速定位异常存活对象
打开MAT后,优先使用以下视图:
-
直方图(Histogram):按类名统计实例数和浅堆(Shallow Heap)大小,排序后重点关注“实例数多+单个对象大”的组合,比如
byte[]、String、HashMap或自定义DTO集合; - 支配树(Dominator Tree):按“保留堆(Retained Heap)”降序排列,直接暴露谁占用了最多内存,且其下的对象无法被单独释放——这是泄漏嫌疑最高的入口;
- 路径到GC Roots(Path to GC Roots):对可疑对象右键选择“exclude all weak/soft/phantom references”,再查看强引用链,重点看是否意外持有了本该短期存在的对象(如缓存未设过期、监听器未注销、ThreadLocal未清理)。
结合上下文判断是否真泄漏
看到一个大对象存活,不能立刻断定是泄漏。需交叉验证:
- 查对应线程栈(如有thread dump或jstack日志),确认该对象是否属于一次正常长耗时操作(如导出10万行Excel);
- 看对象创建时间与业务行为是否匹配,比如某个Service实例在应用启动后一直存在,但它的成员Map却持续增长,就值得深挖;
- 对比多个时间点的dump(如每隔5分钟取一次),观察特定类的实例数或总大小是否单调上升,这是泄漏的强信号。
避开常见误判陷阱
实际分析中容易踩坑:
- 把JVM内部结构(如
java.util.concurrent.ConcurrentHashMap$Node)或框架缓存(Spring代理对象、MyBatis一级缓存)当泄漏,其实它们是设计使然; - 忽略 SoftReference 和 WeakReference 的对象——它们虽存活,但GC时会优先回收,不构成硬性泄漏;
- 只看单个dump,没结合GC日志(-Xlog:gc*)看Full GC后老年代是否持续上涨,导致误判年轻代对象为根源。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











