生产环境内存问题排查应以快速定位“谁在撑大堆”为核心,采用jstat初筛、mat分析快照、arthas实时追踪三步闭环;jprofiler/visualvm仅作辅助验证。

生产环境内存问题,核心是快速定位“谁在撑大堆”,而不是追求工具炫酷。真正有效的方案,是组合使用轻量筛查 + 精准快照 + 实时追踪,三步闭环。
用 jstat 和 jmap 快速初筛异常
不中断服务的前提下,先确认是不是真有泄漏:
-
jstat -gc
5s :每5秒输出一次GC统计,重点关注 OU(Old Used)是否持续上涨、FGC次数增加但老年代回收后仍不下降——这是典型泄漏信号 -
jmap -histo:live
:触发一次Full GC后统计存活对象,按实例数或内存占用排序,一眼看到排前三的类(如 char[]、ConcurrentHashMap$Node、ArrayList) - 注意:jmap -histo 输出里,Objects 列是实例数量,Bytes 列是总浅堆大小,两者都要看——数量爆炸和单个巨大都可能是问题源头
用 MAT 分析堆快照定位根因
确认异常后,生成并打开 .hprof 文件深入分析:
- 生成快照:jmap -dump:live,format=b,file=/tmp/heap.hprof
(低峰期执行,会短暂STW) - 打开 MAT,加载后直接进 Histogram 视图 → 点击 Total Shallow Heap 或 Objects 排序 → 前三名就是当前堆里最“占地方”的类
- 关键动作:对可疑类右键 → Merge Shortest Paths to GC Roots(排除弱引用),看是谁在强持有这些对象;再点 Open in New Histogram 过滤出该类的子类或特定字段实例
- 常见陷阱:char[]、byte[] 排高很常见,它们本身不是问题,要顺引用链找到业务对象(比如某个未清理的缓存 Map 或日志上下文)
用 Arthas 实时追踪创建热点
适合无法 dump 大文件、或问题偶发/高频的场景:
- attach 进程后,执行 vmtool --action getInstances --className com.example.User --limit 20 查当前实例数
- 更关键的是 trace -n 10 'com.example.UserService createOrder',看方法内部哪行代码在频繁 new 对象
- 配合 dashboard 实时观察堆内存趋势,再用 monitor -c 5 'com.example.CacheManager put' 看特定方法调用量是否突增
- 优势在于无需停机、不生成大文件、能关联到具体业务代码行,特别适合验证修复效果
JProfiler / VisualVM 作为辅助验证工具
它们更适合开发测试环境或问题复现阶段:
- JProfiler 的 Allocation Recording 可以记录对象分配热点,但开启后性能损耗明显,生产环境慎用
- VisualVM 的 Monitor 标签页可手动触发 GC 并观察回收效果,适合做简单对比验证
- 二者都不替代 jstat + MAT + Arthas 组合,但在排查线程级内存行为(如 ThreadLocal 泄漏)时,Heap Walker 的引用链可视化更直观
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











