三步可快速定位静态内存泄漏:先看leak suspects报告,再进dominator tree找retained heap最大的static字段对象,最后用path to gc roots确认强引用链终点为java.lang.class→static field。

直接看“Leak Suspects”报告,再进“Dominator Tree”找 Retained Heap 最大的 static 字段对象,最后用“Path to GC Roots”确认强引用链终点是 java.lang.Class → static field——这三步就能快速揪出被静态持有却长期不清理的大对象。
一、先让 MAT 稳住,再加载堆转储
大 dump 文件(比如 10GB+)容易让 MAT 崩溃,必须提前调参:
- 打开
MemoryAnalyzer.ini,把-Xmx设为 dump 大小的 1.2~1.5 倍(例如 dump 是 12GB,就设-Xmx20g) - 确保系统物理内存充足,否则索引生成会卡住或失败
- 首次打开时勾选 Leak Suspects Report,让它自动跑一遍初步分析
二、盯住“Leak Suspects”和“Dominator Tree”两个视图
- Leak Suspects 报告里如果出现 “Problem Suspect 1” 占了 60%+ 内存,点进去看详情:大概率是某个
static java.util.ArrayList或static java.util.HashMap实例 - 切换到 Dominator Tree,按 Retained Heap 降序排列,排第一的对象往往就是那个“肥大”的 static 集合;注意看它的类名、包路径,以及 Shallow Heap 很小但 Retained Heap 极大(比如几 GB),这就是典型信号
三、用 Path to GC Roots 锁定静态根源
- 在可疑对象上右键 → Path to GC Roots → 选 exclude all phantom/weak/soft references
- 如果最终路径终点是:
Thread→...→java.lang.Class→static field
那就坐实了:这个对象是被某个类的静态字段直接持有着,没被释放过 - 特别留意常见高危位置:工具类里的
private static Map、Service 类里的static cache、甚至ThreadLocal配 static 使用(实际等于多个强引用集合)
四、代码侧快速扫描与修复方向
- 全局搜索关键词:
private static.*List、static.*Map、static.*cache、ThreadLocal.*static - 重点检查三类写法:
- 只 add 不 clear 的裸集合
- 没配置淘汰策略的伪缓存
- ThreadLocal + static 组合(等效于线程级内存泄漏)
- 修复不是清空内容,而是断掉 GC Root:优先换成 Caffeine/Guava Cache,或加定时清理逻辑,避免靠
list.clear()治标不治本
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











