线上jvm内存问题排查需三步闭环:先用jstat监控gc指标(ou>80%、fgc>2次/分钟等)发现异常,再用jmap dump快照结合mat分析泄漏根源,最后通过参数调优(如-xms/-xmx相等、合理选gc算法)并压测验证效果。

JVM内存问题不是靠猜,而是靠看——看指标、看趋势、看引用链。关键不在于工具多,而在于每一步都指向明确的判断依据。
日常监控:用jstat抓住GC异常信号
线上问题80%能通过jstat提前发现。执行jstat -gc
- 老年代使用量(OU)持续超过80%:说明对象晋升过多或回收不力,可能已存在内存泄漏
- FGC频率>2次/分钟:Full GC频繁触发,系统响应会明显卡顿,需立即介入
- YGC次数突增且EU快速填满:表明短生命周期对象暴增,可能是循环创建大对象或缓存未清理
注意:单次FGCT>1秒或GCT占总运行时间>20%,就已影响业务可用性。
堆快照分析:用jmap + MAT定位泄漏根源
当jstat提示异常后,用jmap生成快照再用MAT深度分析:
- 低峰期执行jmap -dump:format=b,file=heap.hprof
获取现场快照 - 在MAT中打开后,先看“Leak Suspects”报告——它自动识别最可疑的内存泄漏路径
- 若无明显泄漏点,用“Dominator Tree”按对象占用内存排序,重点排查List、Map、Cache等集合类实例
- 结合“Histogram”查看某类对象实例数是否异常高,并右键“Merge Shortest Paths to GC Roots”确认强引用链
常见陷阱:只看对象数量忽略大小;未过滤“java.lang.Class”或“java.util.HashMap$Node”等底层结构;忽略线程局部变量(ThreadLocal)导致的隐式持有。
JVM参数调优:从配置到验证闭环
调优不是调数字,而是匹配业务特征:
- 堆大小设置-Xms和-Xmx相等,避免运行时扩容抖动
- 高吞吐场景优先选-XX:+UseParallelGC;延迟敏感场景用-XX:+UseG1GC并设-XX:MaxGCPauseMillis=200
- 元空间溢出(Metaspace OOM)时,检查是否动态生成类(如反射、Groovy脚本、CGLIB代理过多),而非盲目加大-XX:MaxMetaspaceSize
- 务必开启GC日志:-Xlog:gc*:gc.log:time,配合GCEasy做可视化分析
每次调整后,必须通过压测验证效果,关注YGC频率、FGC是否归零、平均RT是否下降。
生产环境避坑要点
很多问题源于操作习惯而非技术本身:
- 禁止在高峰期执行jmap -dump:live,它会触发Full GC,可能引发雪崩
- OOM发生前应预置-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path,确保故障现场可追溯
- jstack导出线程栈时,建议同时执行top -Hp
抓CPU热点,再将线程ID转十六进制去栈文件里查对应栈帧 - 容器环境下需配合-XX:+UseContainerSupport,否则JVM可能误判可用内存
不复杂但容易忽略











