1. 内存泄漏现象识别

内存泄漏在应用运行中会逐渐恶化,早期往往表现为三种可观测现象:GC 日志异常、堆内存持续增长、应用响应变慢。这三者构成一条因果链,破解它就能找到泄漏源头。

1.1 现象因果链

现象因果链: 泄漏对象无法被回收 → 堆内存增长 → 触发更多 Full GC → GC 暂停时间延长 → 应用响应变慢 → 最终 OutOfMemoryError 或容器 OOM Kill。

1.2 GC 日志异常关键指标

指标 健康应用 内存泄漏应用
Young GC 频率 稳定(例:每 5~10 秒一次) 快速上升(例:每 1~2 秒一次)
Full GC 频率 极低(数天一次) 频繁(分钟级甚至秒级)
GC 后堆占用率 明显下降(通常 <40%) 下降不明显甚至持续上升
GC 暂停时间 <200ms(正常范围) 持续 >1s,甚至 >10s
日志模式 GC (Allocation Failure)... 堆: 100M->40M Full GC (Metadata GC Threshold)... 堆: 800M->780M

1.3 堆内存持续增长判断规则

  1. 启动后一段时间内:堆内存曲线先上升后稳定(正常);若持续线性上升,高度怀疑泄漏。
  2. Full GC 后:健康应用堆占用率回落至基线;泄漏应用回落幅度极小或完全不回落。
  3. 对比多个时间窗口:取 10 分钟、30 分钟、1 小时三个时间点的堆快照,计算 “回收后占用率”,若逐窗口递增则判定为泄漏。

1.4 应用响应变慢的典型表现

  • 用户请求延迟从 <50ms 上升至 >500ms,甚至超时。
  • 线程池队列积压,CPU 使用率虽低但线程大量阻塞在 GC 停顿中。
  • 负载不高时出现 Connection Timeout、SocketException 等网络超时错误。
内存泄漏现象识别故障树 内存泄漏 GC 日志异常 堆内存持续增长 应用响应变慢 Full GC 频率激增 GC 后堆降幅 <10% 堆占用线性上升 GC 暂停时间 >1s 任意一个现象出现时即应启动排查流程 同时出现两个以上现象时泄漏概率 > 90% 现象识别阶段目标:确认泄漏存在,为数据采集提供方向

1.5 快速自查清单

  • ☐ 观察监控面板(如 Grafana):堆曲线是否为 “上升—平台—上升—平台” 模式?
  • ☐ 执行 jstat -gcutil <pid> 1000 10 查看 Full GC 次数是否在 10 秒内增加?
  • ☐ 检查最近一次 Full GC 后的堆占用是否接近最大值(例如 90% 以上)?
  • ☐ 压测场景下响应时间是否与 GC 暂停时间正相关?
操作提示: 在容器环境中,推荐开启 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/gc.log,并将 GC 日志同步到集中日志系统以便时间维度分析。
易犯错误: 不要只依赖“应用重启后恢复正常”来判断泄漏 —— 有些泄漏需要积累数小时才显现,重启只是暂时重置堆状态。一定要采集持续运行的 Post-GC 堆占用曲线。

1.6 章节小结

第 1 章建立了内存泄漏的现象识别基线:GC 日志异常、堆内存持续增长、应用响应变慢是三个核心观测维度。利用本章给出的指标表格和故障树,开发与运维人员可以快速判断是否存在泄漏,并为后续数据采集(第 2 章)提供明确入口。