java内存泄漏需结合运行趋势、gc行为和堆使用特征综合判断,核心是老年代内存持续上涨且full gc后不明显回落,如ou/ogcmx长期>85%且每次仅微降。

Java 程序是否发生内存泄漏,不能单靠一次观察判断,而要结合运行趋势、GC 行为和堆使用特征综合识别。关键不是“有没有用很多内存”,而是“该回收的没回收”。
看老年代内存是否持续上涨且不回落
这是最核心的信号。即使年轻代频繁 GC,只要老年代(Old Gen)占用率随时间推高、Full GC 后仍无法明显下降(比如从 85% → 82% → 88% → 90%),就高度提示泄漏。正常情况应有明显回落(如 85% → 40% → 75% → 35%)。
- 用 jstat -gc
1000 每秒输出 GC 数据,重点关注OU(Old Used)和OGCMX(Old Max)比值 - 若 OU / OGCMX 长期 >85%,且每轮 Full GC 后仅微降(
观察 GC 开销是否异常飙升
当 JVM 把大量时间花在垃圾回收上却收效甚微,就是典型预警。
- 日志中出现 GC overhead limit exceeded 错误
- 用 jstat 查看
GCT(总 GC 时间)占比:若 1 分钟内 GC 时间超过 90 秒,说明已陷入“回收—增长—再回收”死循环 - Full GC 频率加快(如从几小时一次变成几分钟一次),单次耗时超 1 秒
对比重启前后内存增长节奏
内存泄漏是渐进式问题,重启后会“重置起点”,但很快复现相同模式。
- 新启动后,监控 30 分钟内老年代是否从 10% 快速爬升至 60%+
- 同样业务流量下,第二次重启后的内存增长速度比第一次更快,说明泄漏在累积
- 注意区分:单纯负载升高也会推高内存,需控制变量(如固定 QPS、关闭缓存预热)
留意是否频繁触发 OOM 但堆 dump 显示“还有空闲空间”
OutOfMemoryError 不等于堆满了——有时是碎片化严重或元空间/直接内存耗尽,但若报 java.lang.OutOfMemoryError: Java heap space,且 dump 显示大量同类型对象堆积(如 50 万个未清理的监听器实例),就是泄漏铁证。
- 开启 -XX:+HeapDumpOnOutOfMemoryError 自动抓取现场
- 别只看总大小,重点看 retained heap 和 dominator tree 中谁占大头
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











