IWA
2025-12-05
点 赞
0
热 度
13
评 论
0

Java 性能优化实战 第 5 篇:JVM GC 调优(下)——GC 事故排查、内存泄漏定位、GC 日志可视化实战

这是 GC 系列的 最实战、最重要 一篇。
我们从真实线上场景出发,讲 排查思路判断逻辑最终定位方法

无论你的系统是:

  • RT 周期性抖动

  • CPU 飙升

  • FullGC 频繁

  • 内存“慢性增长”

  • 线上偶发停顿

本篇提供的流程足以覆盖 90% 的实际问题。


一、GC 事故排查的总流程(黄金 5 步)

把所有 GC 问题归纳到一个非常清晰的流程:


① RT 波动 or CPU 高?先确定表现

常见表现:

表现

典型原因

延迟抖动(P99 突刺)

GC 暂停过长 / Old 区回收不足

CPU 100%

频繁 Young GC / Mixed GC

OOM

老年代爆满 / 元空间不足

全链路慢

队列堆积 + GC 拖慢抢占CPU

第一步永远先看症状,不要直接看 GC 日志。


② 确认是 GC 问题还是业务问题?

你要排除两个常见误伤:

  • 大量 IO 堵塞 → 误以为是 GC

  • 大量线程竞争 → 误以为是 GC

判断技巧:

jstat -gcutil <pid> 1000 10

如果 在异常时间段 出现以下情况:

  • YGC/FULLGC 次数猛增

  • Old 区持续升高并不掉

  • Metaspace 持续上涨

  • GC 时间明显加长

才是 GC 方向。


③ 用 GC 日志确认“什么 GC 在拖累系统”

你需要关注 4 个关键点:

  1. 哪种 GC 占用时间最长?

  2. YGC 是否过频?

  3. MixedGC 是否不足?

  4. Old 区是否被回收?

我们用 G1 为例解析。


④ 判断“GC 回收不掉的原因”是什么

通常只有 3 类原因:

原因 1:对象产生太快 → Young 挂不住→ GC 超频

表现:

  • YGC 明显增加

  • Region 全部耗尽

  • Evacuation time 拉长

原因 2:对象回收不掉 → 老年代涨 → MixedGC 不足

表现:

  • Old 区曲线单方向上升

  • MixedGC 次数很少

  • 有 FullGC 记录

原因 3:存在内存泄漏 → Old 区只增不减

表现:

  • 连续几轮 GC 后 Old 区仍不下降

  • 精确符合泄漏行为


⑤ 使用 MAT / Arthas / GCViewer 定位根因

根据原因不同,用不同工具定位:

  • Young 产生太快 → 分析对象分配热点

  • MixedGC 不足 → 调整 IHOP

  • 老年代对象不降 → MAT 分析泄漏路径

这就是 GC 排查的黄金路线图。


二、最常见的 GC 事故及其定位方法(企业真实案例)

这里给你 5 个生产事故模式,每一个都是线上常见大坑。


事故 1:周期性 RT 峰值(业务并发不高,但卡顿明显)

表现:

  • 每隔几秒到几十秒,RT 出现周期性波峰

  • CPU 正常

  • GC 日志中 YoungGC 响应时间稳定,但有周期性 MixedGC

GC 日志特征:

GC pause (G1 Mixed) ... 70ms

原因:MixedGC 暂停超过 SLA。


解决方案:

-XX:MaxGCPauseMillis=150
-XX:InitiatingHeapOccupancyPercent=30

IHOP 降低能提前开始并发标记,让 MixedGC 分布更均匀。


事故 2:CPU 100%,但业务量正常

表现:

  • CPU 满

  • RT 降到几百毫秒甚至几秒

  • GC 日志显示 YoungGC 每秒几十次

根因:Young 区太小


解决方案:扩大 Young 区

-XX:G1NewSizePercent=25
-XX:G1MaxNewSizePercent=60

如果对象分配非常快:

-XX:ParallelGCThreads=<CPU数>

事故 3:FullGC 周期性爆发(服务基本不可用)

表现:

  • 大量 FullGC(0.5s~3s)

  • Old 区持续涨

  • YoungGC + MixedGC 都回收不动

几乎一定是:

MixedGC 触发太晚,老年代积压太多不可回收对象。


解决方案:提前开始并发标记

-XX:InitiatingHeapOccupancyPercent=20

如果堆 ≥ 8G,这个调整非常关键。


事故 4:老年代持续上升但 YoungGC 正常 → 内存泄漏

典型表现:

  • Old 区只增不减

  • YoungGC 和 MixedGC 均有效

  • RT 稳定直到最终 OOM


定位泄漏工具:

方案 1:Arthas

heapdump

方案 2:MAT 重点看 Dominator Tree

关注:

  • 单实例占用巨大

  • 集合类对象(HashMap、ArrayList)不断膨胀

  • 缓存未过期(LocalCache)

  • 自定义 ThreadLocal 没有 remove()

方案 3:jmap + grep 生存代分析

jmap -histo:live <pid>

排查哪些类增长明显。


事故 5:Metaspace 不断上涨导致 OOM

常见由:

  • 频繁动态生成类(cglib、proxy)

  • 大量 SPI、ServiceLoader

  • 热加载类未卸载

解决:

-XX:MaxMetaspaceSize=512m
-XX:MinMetaspaceFreeRatio=50
-XX:MaxMetaspaceFreeRatio=80

加上:

  • 检查是否重复创建 ClassLoader

  • 是否大量动态代理未复用


三、GC 日志可视化分析工具(强烈推荐)


① GCeasy(最强可视化)

功能:

  • 显示 pause 分布

  • 显示 Old/Younng 区曲线

  • 给出调优建议

  • 自动检测泄漏风险

适合运维、开发一起使用。


② GCViewer

适合离线分析,优点:

  • 老牌工具

  • 图表稳定

  • 能快速看出 MixedGC 触发是否正常


③ JDK 自带 jstat 命令(在线监控首选)

常用命令:

jstat -gcutil <pid> 1000       

可以看到:

  • Young 区使用

  • Old 区变化

  • GC 次数

  • FullGC 次数

这对 事故期间 的快速判断非常重要。


四、不同堆大小对应的 G1 最佳调优模版(企业级)


🟦 1)堆大小 < 4G(常见 Web 服务)

-XX:+UseG1GC
-XX:MaxGCPauseMillis=150
-XX:InitiatingHeapOccupancyPercent=45
-XX:G1HeapRegionSize=4m

🟩 2)堆大小 4G–8G(常见中型系统)

-XX:+UseG1GC
-XX:MaxGCPauseMillis=120
-XX:InitiatingHeapOccupancyPercent=35
-XX:G1HeapRegionSize=8m

🟧 3)堆大小 8G–32G(大业务系统)

-XX:+UseG1GC
-XX:MaxGCPauseMillis=100
-XX:InitiatingHeapOccupancyPercent=25
-XX:G1HeapRegionSize=16m
-XX:G1ReservePercent=20

混合 GC 会更容易均匀触发。


🟥 4)堆大小 ≥ 32G(延迟不敏感、吞吐优先)

如果延迟敏感:优先 ZGC
如果吞吐优先:G1 + 更大 Region


五、什么时候要从 G1 切换到 ZGC?

满足任意两条即可考虑 ZGC:

✓ P99 要求 < 10ms
✓ 业务链路长,无法承受任何周期性抖动
✓ 堆 > 16G
✓ 并发线程数多
✓ FullGC 一直无法优化

ZGC 的减少停顿能力远在 G1 之上。


下一篇预告(第 6 篇)

第 6 篇我们将进入另一个重头戏:


**《Java 性能优化实战 30 讲》第 6 篇:

CPU 使用率飙高的根因定位(火焰图 + Linux 实战)

内容包括:

  • 如何使用 top -H, pidstat, ps -L 定位线程热点

  • Java 内部 CPU 飙升的典型原因

  • 线程死循环、锁竞争、GC 打满 CPU 的识别方式

  • 火焰图(FlameGraph)完整排查流程

  • Java 服务 CPU 优化清单(生产级)


用键盘敲击出的不只是字符,更是一段段生活的剪影、一个个心底的梦想。希望我的文字能像一束光,在您阅读的瞬间,照亮某个角落,带来一丝温暖与共鸣。

IWA

infp 调停者

具有版权性

请您在转载、复制时注明本文 作者、链接及内容来源信息。 若涉及转载第三方内容,还需一同注明。

具有时效性

文章目录

IWA的艺术编程,为您导航全站动态

42 文章数
9 分类数
10 评论数
34标签数
最近评论
IWA

IWA


👍

M丶Rock

M丶Rock


😂

M丶Rock

M丶Rock


感慨了

M丶Rock

M丶Rock


厉害了

M丶Rock

M丶Rock


6666666666666666666

访问统计