第1章 · 现象识别:OOM异常特征、GC日志告警标记、应用响应变慢与吞吐下降的关联判断

内存泄漏排查本质上是一场与数据衰减赛跑的实证工程。首要是快速、准确地捕捉异常信号。本章将遵循结构化问题排查生命周期,系统讲解如何通过OOM异常类型、GC日志告警标记以及应用层指标的联动判断,锁定内存泄漏嫌疑,并建立完整的排查前置动作。

1. 现象识别(核心主题)

当应用内存出现泄漏时,异常信号会从应用层 → JVM层 → OS层逐级传导。故障树的根节点通常是用户可感知的响应变慢或超时,而底层则对应着特定的GC失败模式或OOM错误。

现象维度 关键指标 泄漏关联度
应用层 P99延迟翻倍、接口超时率飙升、熔断触发 高(通常是最早感知)
JVM层 Full GC频率 > 5次/分钟、GC暂停时间 > 1s 极高(直接证据)
OS层 CPU利用率持续高(GC线程)、内存交换(SWAP)增高 中(需排除其他资源争抢)
关联判断规则(3-5-85法则): 当以下三个条件同时满足时,可判定为内存泄漏高危场景:
  • 连续3次以上的Full GC发生后,老年代占用率未下降。
  • 每分钟Full GC次数超过5次。
  • 堆内存(Old区)占用率持续超过85%且仍在上升。

OOM异常特征速查表:不同的OOM类型直接指向不同的泄漏区域,这是现象识别阶段的核心依据。

OOM错误类型 核心特征 嫌疑区域
Java heap space 无法分配新对象,堆内存耗尽 集合类膨胀、缓存泄漏、字符串驻留泄漏
GC overhead limit exceeded GC花费>98%时间,回收<2%堆 重度泄漏导致GC失效
Metaspace 元数据区溢出 动态类加载(CGLib/反射)、classLoader泄漏
Direct buffer memory 堆外内存耗尽 NIO Buffer未回收、未配置MaxDirectMemorySize
unable to create new native thread OS线程资源耗尽 线程泄漏(未正确关闭线程池)、ThreadLocal未清理

GC日志告警标记:GC日志是定位泄漏的关键数据源,以下为需要立即触发告警的关键词以及对应的含义。

日志关键词 告警等级 排查指向
Full GC (Allocation Failure) 严重 老年代空间不足,触发Stop-The-World
Concurrent Mode Failure 致命 CMS GC无法完成并发标记,退化为Serial Old
Promotion Failed 严重 Young GC晋升对象时老年代空间不足
Metadata GC Threshold 信息 Metaspace触发GC,需关注类加载数量

2. 数据采集

当识别到上述现象后,需在第一时间保留现场,回传诊断数据。

# 1. 采集堆转储文件(核心证据,会触发Full GC,谨慎操作)
jmap -dump:format=b,file=/data/logs/heap.hprof 

# 2. 持续监控GC频率与内存占用变化
jstat -gcutil  1000 10

# 3. 采集当前线程快照(排查死锁或线程泄漏)
jstack  > /data/logs/jstack.log
避坑警示: 不要在生产环境直接重启应用!必须先通过 jmap 采集堆转储(heap.hprof),否则一旦重启,所有堆内对象分配历史将永久丢失,导致后续无法通过MAT定位泄漏源。

3. 原因定位

基于采集的数据,快速缩小嫌疑范围,为MAT分析提供方向。

  • Old区持续增长且GC无效: 对象泄漏(如缓存、集合类)。
  • Metaspace持续增长: 类加载泄漏(框架动态代理、Groovy脚本等)。
  • 线程数飙升: 线程泄漏(未关闭的线程池或连接池)。
  • Direct Memory异常: NIO Buffer未主动释放。

4. 修复动作

在精准定位之前,执行应急恢复策略,保证业务连续性。

  • 重启节点: 快速恢复服务能力,但必须确保已采集堆转储。
  • 降级或限流: 减少进入故障节点的请求量,防止雪崩。
  • 回滚代码: 如果泄漏与最近上线版本强相关,立即回滚。

5. 复测

修复或重启后,需要通过持续观察确认泄漏已被隔离。

  • 观察 jstat -gcutil 中Old区占比是否恢复至基线水平。
  • 确认Full GC频率是否降至0或接近0。
  • 确认应用P99延迟和吞吐量是否回归正常。

6. 预防

建立可观测的JVM监控体系,提前发现泄漏趋势。

  • 对 jvm.gc.pause 和 jvm.memory.used 设置阈值告警。
  • 集成 Grafana + Prometheus + JMX Exporter,实时展示堆各代际曲线。
  • 定期执行 自动化堆转储分析(通过CI/CD流水线触发MAT脚本)。

知识结构图:内存泄漏现象识别故障树

内存泄漏现象识别故障树 应用报警风暴 接口超时 / 熔断 吞吐量 & CPU异常 CPU飙高 / 请求堆积 GC暂停时间飙升 STW > 1s / Full GC频繁 GC日志告警标记 CMF / Promotion Failed 堆转储与线程转储采集 jmap / jstack / jstat 使用MAT定位泄漏根因 Histogram / Dominator Tree OOM异常类型 • Java heap space • Metaspace • Direct buffer memory