健康检查和监控是内存泄漏的早期哨兵,需盯住老年代阶梯式上涨、Full GC 回收低效(如5分钟3次且每次回收80%、1小时≥5次Full GC)、条件触发堆转储。

健康检查和监控不是事后补救手段,而是内存泄漏的“早期哨兵”。关键在于盯住那些泄漏刚发生时就显露的异常模式,而不是等 OOM 才报警。
盯住老年代内存的阶梯式上涨
正常 GC 后老年代应明显回落。如果每次 Full GC 后,老年代使用率只下降一点点(比如 jvm_memory_used_bytes{area="old"} / jvm_memory_max_bytes{area="old"} > 0.85
and
delta(jvm_memory_used_bytes{area="old"}[30m]) > 0,即老年代占用高 + 近半小时持续增长。
结合 GC 行为识别回收失效
频繁但低效的 Full GC 是危险信号。例如:5 分钟内触发 3 次 Full GC,每次回收量却都低于 50MB;或单次 Full GC 耗时超过 1.5 秒且停顿后内存几乎不降。这类指标比“GC 次数多”更有指向性。可在 JVM 启动参数中加入:
-Xlog:gc*,safepoint:file=gc.log:time,uptime,level,tags -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=20M,确保日志完整可回溯。
用健康检查暴露隐性泄漏点
标准 HTTP 健康检查(如 /actuator/health)默认只返回 UP/DOWN,无法反映内存状态。应扩展自定义健康指示器,主动上报关键内存指标:
• 当前老年代使用率是否 >80%
• 最近 1 小时 Full GC 次数是否 ≥ 5 次
• 当前活跃线程数是否超阈值(尤其关注虚拟线程数异常增长)
这些结果可集成进 Grafana 面板,让运维和开发一眼看到“哪里不对劲”,而不是只等告警炸响。
把堆转储变成条件触发动作
不能只靠人工 dump,要让系统在可疑时刻自动捕获现场。例如:当健康检查发现老年代连续 2 次 Full GC 后回落 85%,则立即执行:
• jmap -dump:live,format=b,file=/dump/auto_$(date +%s).hprof $PID
• 自动压缩并上传至 MinIO,附带上下文(JVM 参数、QPS、线程数、时间戳)
这样拿到的堆快照,是泄漏正在发生时的“第一手证据”,而非 OOM 后的“废墟残片”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











