oom时自动堆转储可捕获泄漏现场:配置-xx:+heapdumponoutofmemoryerror与-xx:heapdumppath,再用mat通过dominator tree、leak suspects report和path to gc roots定位静态集合、threadlocal、监听器等典型泄漏源。

遇到线上 Java 应用内存持续上涨、频繁 Full GC 甚至 OutOfMemoryError: Java heap space,说明很可能存在大对象堆积或内存泄漏。关键不是等它崩,而是让 JVM 在崩溃瞬间“留下证据”——即自动生成堆转储(heap dump),再用专业工具定位谁在偷偷吃内存。
配置 JVM 自动触发 dump
在启动参数中加入以下两项,让 JVM 在 OOM 时自动保存现场:
- -XX:+HeapDumpOnOutOfMemoryError:启用 OOM 自动 dump
-
-XX:HeapDumpPath=/path/to/dumps/:指定 dump 文件保存路径(建议挂载到有足够空间的独立目录,如
/data/dumps)
补充建议:
- 加上 -XX:+HeapDumpBeforeFullGC(谨慎开启,仅调试期用),可捕获 Full GC 前的堆快照,便于对比分析;
- 确保目标路径对运行 Java 的用户(如 appuser)有写权限,否则 dump 会静默失败。
快速验证 dump 是否生成成功
OOM 发生后,立刻检查 dump 目录:
- 文件名通常形如
java_pid12345.hprof,大小常达几百 MB 甚至数 GB - 用
ls -lh /path/to/dumps/查看是否生成、是否有写入权限问题 - 若没生成,检查日志中是否含
Heap dump file created或警告Unable to create heap dump
用 MAT 分析大对象与泄漏根因
将 .hprof 文件拖入 Eclipse Memory Analyzer (MAT),重点看三个视图:
-
Dominator Tree:按“支配内存大小”排序,一眼锁定 top 几个大对象(如
byte[]、char[]、HashMap实例)。点击某行,右键 → Path to GC Roots → exclude weak/soft references,查看谁长期持有着它 - Leak Suspects Report:MAT 自动生成的诊断报告,直接标出疑似泄漏组件(如静态集合、未关闭的连接池、缓存未清理)
-
Histogram + Group by package/class:统计各类实例数量,若某业务类数量异常高(如
OrderDetail百万级),大概率是缓存未过期或集合未清理
结合代码定位典型泄漏点
常见“大对象持有者”模式,对照 MAT 中的 GC Root 路径检查:
-
静态容器:如
private static Map<string byte> cache = new HashMap();</string>—— 检查是否漏了remove()或没设容量上限 -
ThreadLocal 泄漏:尤其在线程池中,
ThreadLocal<inputstream></inputstream>未调用remove(),导致线程复用时旧对象一直被引用 -
监听器/回调未注销:GUI 或事件总线中注册了监听器但忘记
unregister(),其隐式持有 Activity/Service 引用(Android)或业务上下文 -
未关闭的资源句柄:
FileInputStream、Connection、ResultSet等未在finally或 try-with-resources 中释放,底层 native 内存可能不回收
不复杂但容易忽略










