最有效方式是通过VisualVM观察堆内存曲线与类实例数量变化:关注Full GC后内存不回落的阶梯式上升、Old区持续爬升、Instances增长异常的类,并结合堆快照对比及引用链分析定位static或ThreadLocal等泄漏源头。

直接看堆内存曲线和类实例数量变化,是识别变量增长异常最有效的方式。VisualVM 不需要写代码、不依赖日志,靠实时图表就能暴露问题——比如一个 ArrayList 在几天内持续扩容却从不清理,内存占用会呈现“阶梯式上升+Full GC后不回落”的典型特征。
监控堆内存趋势:抓住泄漏的呼吸节奏
内存泄漏不是直线暴涨,而是有节奏的“涨—停—再涨”。在 VisualVM 的 Monitor 标签页中,重点关注堆内存(Heap)曲线:
- 观察是否出现多个“台阶”:每次 Full GC 后内存没回到原有基线,而是停在更高位置
- 对比 Eden/Survivor/Old 区(需安装 VisualGC 插件):若 Old 区持续缓慢爬升,而 Eden 区回收正常,说明对象“活过多次 GC”后进入了老年代且未释放
- 注意时间尺度:把图表时间范围拉长到几小时甚至一两天,短期抖动容易掩盖真实趋势
聚焦类实例数量:一眼锁定“越用越多”的变量
堆内存涨了,但到底是哪个类在偷偷囤货?切换到 Classes 标签页,按“Instances”列倒序排列:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 查找数量异常高、且随运行时间明显增长的类,比如 java.util.ArrayList、java.lang.String、或你业务中的某个 DTO 或缓存容器类
- 右键点击可疑类 → “Show in Heap Walker”,进入堆分析视图,查看这些实例的大小分布和引用链
- 特别留意静态字段(如 static List>)或单例对象持有的集合,它们往往是增长源头
抓取并对比堆快照:让变化可视化
单一时点的快照看不出增长,但两个时间点的快照一比,问题就浮出水面:
立即学习“Java免费学习笔记(深入)”;
- 在应用稳定运行一段时间后,点击工具栏的 Heap Dump 按钮,保存为 heap1.hprof
- 等待 2–4 小时(或复现疑似增长阶段),再抓一次 heap2.hprof
- 在 VisualVM 中依次打开两个快照 → 右键 heap2 → “Compare With” → 选择 heap1 → 查看“Added Classes”和“Increased Instances”列表
- 新增最多的类,大概率就是变量失控的起点
结合线程与引用链:确认谁在“不让它走”
发现 ArrayList 实例暴增后,别急着改代码。先弄清它为什么不能被回收:
- 在堆分析视图中,选中一个大 ArrayList 实例 → 右键 → “References” → 查看“Outgoing References”(它持有哪些对象)和“Incoming References”(谁在引用它)
- 重点检查引用路径中是否含 static、java.lang.ThreadLocal、或未注销的监听器/回调
- 如果看到类似 com.example.service.CacheManager.cacheList → static 这样的路径,基本可以定位到泄漏源头类和字段

















