凌晨告警群炸了——接口响应超时,服务器 CPU 飙到 300%。登录一看,Full GC 每 5 秒一次。本文还原完整的排查和修复过程。

一、告警与现场

  • 1.1 从监控看异常——CPU 飙升、接口 RT 暴涨、GC 频率异常
  • 1.2 保留现场的三板斧——jstack / jmap / jstat

二、GC 日志解读

  • 2.1 开启 GC 日志 -Xlog:gc*(JDK 9+)vs -XX:+PrintGCDetails(JDK 8)
  • 2.2 GC 日志字段逐一解析
  • 2.3 GC Easy / GC Viewer 可视化分析
  • 2.4 案例日志:每 5 秒一次 Full GC,每次耗时 2s+

三、jstat 实时监控

  • 3.1 jstat -gc <pid> 1000 查看各代内存变化
  • 3.2 S0C/S1C/EC/OC/MC 字段含义
  • 3.3 YGC/YGCT/FGC/FGCT 变化趋势分析
  • 3.4 老年代持续增长 → Full GC 无法回收 → 内存泄漏

四、jmap 堆 dump 分析

  • 4.1 jmap -dump:format=b,file=heap.hprof <pid>
  • 4.2 注意:Full GC 前 dump 还是手动 GC 后 dump
  • 4.3 线上 dump 的风险——STW 时长控制

五、MAT 分析堆 dump

  • 5.1 Leak Suspects Report——Dominator Tree
  • 5.2 Histogram 按类统计对象数量与大小
  • 5.3 Path to GC Roots——找到引用链
  • 5.4 案例发现:ThreadLocal 未清理导致大量对象泄漏
  • 5.5 OQL 查询辅助定位

六、jstack 线程分析

  • 6.1 找出爆 CPU 的线程 top -Hpprintf '%x'jstack
  • 6.2 死锁检测 jstack -l
  • 6.3 大量线程 BLOCKED/Waiting 分析

七、根因定位与修复

  • 7.1 案例还原:ThreadLocal + 线程池的内存泄漏
  • 7.2 修复代码——try-finally 中 remove()
  • 7.3 验证修复——灰度发布 + GC 日志对比

八、预防措施

  • 8.1 GC 监控告警配置(Prometheus + JMX Exporter)
  • 8.2 代码审查中的内存泄漏 checklist
  • 8.3 压测环境增加 GC 日志观察环节
  • 8.4 自动化内存泄漏检测工具(Arthas memory 命令)