MAT分析堆转储是诊断Java堆内存溢出最可靠方式,需配置-XX:+HeapDumpOnOutOfMemoryError自动生成.hprof文件,再通过Leak Suspects、Top Consumers、Histogram定位泄漏对象及强引用链。

直接用 Memory Analyzer Tool(MAT)分析堆转储文件,是诊断 Java 堆内存溢出最可靠的方式。核心不是看报错信息,而是看“OOM 时内存里到底存了什么”。
生成有效的堆转储文件
没有准确的 dump 文件,后续所有分析都无从谈起。关键要让 JVM 在 OOM 发生时自动留下快照:
- 启动时添加 JVM 参数:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumps/,确保路径有写入权限
- 为加快复现可临时调小堆:比如加 -Xmx256m,配合能持续创建对象的测试接口(如往静态 Map 不断 put)
- OOM 报错后,检查指定目录是否生成 .hprof 文件(如 java_pid12345.hprof),大小通常几十 MB 起
用 MAT 快速定位内存大户
打开 dump 后,优先看三个视图,它们指向性极强:
- Leak Suspects Report:MAT 自动扫描后弹出的首屏报告,会标出 1–2 个最可疑的泄漏点,例如“某个静态 HashMap 占用堆的 87%”,点击即可展开详情
- Top Consumers:按类统计总占用内存,排序后一眼看出谁占得多——常见高占比类包括 byte[]、char[]、HashMap$Node、ArrayList
- Histogram:列出所有类的实例数量和浅大小(Shallow Size),右键某类 → “Merge Shortest Paths to GC Roots”,勾选 “exclude all phantom/weak/soft references”,只保留强引用链,避免干扰
顺着引用链找到泄漏源头
看到大对象只是第一步,必须查清“它为什么活下来”:
立即学习“Java免费学习笔记(深入)”;
- 对高占比对象(如一个超大的 ArrayList),右键 → “Path to GC Roots”,查看完整强引用路径
- 典型泄漏路径示例:MyService.INSTANCE → static cacheMap → HashMap$Node.value → ArrayList → elementData[],说明是静态缓存未做容量控制或清理
- 若路径含 ThreadLocalMap,检查对应线程是否长期存活且未调用 remove()
- 若路径终点是 ClassLoader,可能是热部署、OSGi 或动态代理导致类及其实例无法卸载
交叉验证增长行为
单次 dump 是静态切片,需确认是否持续增长才能判定是泄漏:
- 用 jstat -gc <pid> 每 5 秒采样一次,观察老年代使用率是否阶梯上升、Full GC 是否越来越频繁
- 开启 GC 日志:-XX:+PrintGCDetails -Xloggc:gc.log,重点看每次 Full GC 后老年代剩余空间是否不降反升
- 用 JVisualVM 或 JProfiler 实时连接进程,在“Monitor”页签中观察关键集合类(如 HashMap、ConcurrentHashMap)的实例数随时间变化趋势
不复杂但容易忽略的是:别只盯着“谁最大”,要盯住“谁不该活这么久”。引用链就是证据链,每一步都要能解释清楚为什么这个引用还存在。


















