Java内存泄漏应早期捕获,分三步:jstat盯老年代与GC趋势确认泄漏;jmap或VisualVM在峰值时主动dump存活对象;MAT/VisualVM分析路径定位static、ThreadLocal等强引用源。

盯住老年代和GC行为,快速判断是否真泄漏
先别急着dump,用 jstat 实时看堆内存趋势:
- jstat -gc <pid> 1000:每秒刷新一次,重点关注 OU(Old Used) 和 FGC(Full GC次数)
- 如果 OU 持续上涨、每次 Full GC 后不回落,或 FGC 频次陡增但回收量极少,基本可确认存在泄漏
- 配合 jstat -gcutil <pid> 看百分比更直观,比如 OU% 长期 >90% 且无下降趋势
在内存峰值时生成有效堆转储
等OOM再dump已晚,应在疑似泄漏中段主动抓快照:
-
jmap -dump:live,format=b,file=heap.hprof <pid>:加
live参数只导出存活对象,避免冗余噪声 - 若进程响应慢,可用 VisualVM 远程连接后直接“Heap Dump”,操作更稳
- 生产环境建议提前配置
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/dumps/,兜底自动保存
用 MAT 或 VisualVM 定位泄漏对象
堆转储文件本身没用,关键在分析路径:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- MAT 打开 .hprof → “Leak Suspects Report”:自动标出最可疑的几个对象及内存占比(如一个静态List占72%)
- 点进问题对象 → 右键 “Show Objects by Class” → 查看实例数是否异常膨胀
- 选中典型实例 → “Paths to GC Roots” → 勾选 “exclude weak/soft references” → 看谁在强引用它
- 常见泄漏源会直接暴露:static final HashMap、ThreadLocalMap 中残留的 value、未注销的监听器、未 close 的 Closeable 对象
结合运行时诊断缩小范围
有些泄漏是动态触发的,需配合实时观察:
立即学习“Java免费学习笔记(深入)”;
- VisualVM 的“Sampler”标签页:开启内存采样,按类名排序,看哪些类实例数持续增长
-
Arthas 的 vmtool --action getInstances:例如
vmtool --action getInstances --className java.util.ArrayList --limit 10,查具体实例内容 - 检查线程栈:jstack <pid> | grep -A 10 “RUNNABLE”,看是否有线程长期持有大集合或缓存

















