jmap与堆转储分析
堆转储是分析 Java 堆内存问题的重要证据。jmap 可以生成堆转储文件,用于定位内存泄漏、大对象和异常引用链。
# 1. 生成堆转储
jmap -dump:format=b,file=heap.hprof <pid>
也可以只 dump 存活对象:
jmap -dump:live,format=b,file=heap-live.hprof <pid>
注意:live 可能触发 Full GC,线上使用要谨慎。
# 2. OOM 自动生成 dump
推荐生产配置:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/data/dump
发生 OOM 时自动生成堆转储,便于事后分析。
# 3. dump 文件注意事项
堆转储文件可能非常大,通常接近或超过堆使用量。
注意:
- 磁盘空间。
- 文件传输时间。
- 敏感数据。
- 对线上进程的停顿影响。
不要随便在高峰期对大堆进程执行 dump。
# 4. 分析工具
常用分析工具:
- Eclipse MAT。
- VisualVM。
- JProfiler。
- YourKit。
- JDK Mission Control 的部分能力。
MAT 是分析堆转储的常用免费工具。
# 5. 看什么
分析堆转储重点看:
- 最大对象。
- 最大集合。
- Dominator Tree。
- Retained Size。
- GC Roots 引用链。
- 类实例数量。
- 类加载器数量。
Shallow Size 是对象自身大小,Retained Size 是对象被回收后可以释放的总大小。排查泄漏更关注 Retained Size。
# 6. 内存泄漏分析思路
常见步骤:
- 找占用最大的对象或集合。
- 看它为什么不能被回收。
- 沿 GC Roots 引用链向上找持有者。
- 判断持有者是否符合业务预期。
- 对比多个时间点 dump,看对象是否持续增长。
内存泄漏的核心不是“对象大”,而是“不该活着的对象还活着”。
# 7. 类直方图
可以用 jcmd 或 jmap 查看类实例统计:
jcmd <pid> GC.class_histogram
适合快速判断哪些类实例数量异常。
# 8. 阶段小结
堆转储是定位堆内存问题的硬证据。分析时不要只看最大对象,还要看引用链和 Retained Size。线上 dump 有成本,要结合自动 dump、低峰操作和敏感数据保护。
# 9. MAT 分析流程图
打开 heap dump
│
├─ 看 Leak Suspects
│
├─ 看 Dominator Tree
│
├─ 按 Retained Size 排序
│
├─ 找异常大对象/集合
│
├─ Path to GC Roots
│
└─ 回到代码找持有者生命周期
关键点是从对象回到“谁持有它”,再回到“为什么业务上没释放”。
# 10. Shallow Size 与 Retained Size
Map 对象本身 Shallow Size 很小
└─ 持有 100 万个 Entry 和 Value
└─ Retained Size 很大
| 概念 | 含义 |
|---|---|
| Shallow Size | 对象自身占用 |
| Retained Size | 回收该对象后可释放的总内存 |
排查泄漏更关注 Retained Size。
# 11. Tips 快问快答
Q:heap dump 里最大的对象就是泄漏源吗?
A:不一定。大对象可能是正常缓存,泄漏要看它是否不该存活以及被谁引用。
Q:为什么建议对比两个 dump?
A:单个 dump 只能看瞬时状态,对比能看哪些对象持续增长。
Q:生产 dump 文件怎么处理?
A:注意磁盘、传输、脱敏和访问权限,dump 中可能包含用户数据。
Q:class histogram 能替代 heap dump 吗?
A:不能。histogram 只能看类实例数量和大小,看不到完整引用链。
上次更新: 2026/06/24, 16:03:01