3. JVM垃圾回收器实战:CMS、G1、ZGC核心原理与适用场景、GC日志解读、GC停顿分析
在支付订单系统中,GC停顿直接导致接口响应时间毛刺,严重时引发交易超时。本章深入剖析CMS、G1、ZGC三大主流垃圾回收器的核心原理、适用场景,并通过真实GC日志解读与停顿分析,帮助你在生产环境中做出正确选型与调优决策。
3.1 三大垃圾回收器核心原理对比
CMS、G1、ZGC分别代表了JVM垃圾回收技术的三个重要发展阶段。下表从核心原理、停顿模型、适用堆大小等维度进行对比:
| 特性维度 | CMS (Concurrent Mark Sweep) | G1 (Garbage First) | ZGC (Z Garbage Collector) |
|---|---|---|---|
| 设计目标 | 最短回收停顿时间 | 可预测的停顿时间模型 | 极低延迟(<10ms) |
| 堆内存结构 | 新生代(Eden/S0/S1)+ 老年代(连续空间) | Region(1MB~32MB,逻辑分区) | Region(动态大小,支持大页) |
| 并发阶段 | 初始标记(STW) → 并发标记 → 重新标记(STW) → 并发清除 | 初始标记(STW) → 并发标记 → 最终标记(STW) → 筛选回收(STW) | 并发标记 → 并发转移准备 → 并发重映射(几乎无STW) |
| 主要STW阶段 | 初始标记、重新标记 | 初始标记、最终标记、筛选回收(部分) | 初始标记(极短) |
| 停顿时间 | 几十~几百ms | 10ms~200ms(可配置目标) | <1ms(典型) |
| 适用堆大小 | ≤4GB(推荐) | 4GB~64GB | 8GB~16TB |
| 内存占用 | 低 | 中等(约额外10%~20%) | 较高(约额外15%~25%) |
| JDK版本 | JDK 9起标记为废弃,JDK 14移除 | JDK 9默认,持续优化 | JDK 11实验,JDK 15生产,JDK 17+默认 |
3.2 CMS垃圾回收器:并发标记清除的得与失
CMS(Concurrent Mark Sweep)是第一款真正意义上的并发收集器,其核心思想是尽可能减少STW时间,让垃圾回收线程与用户线程并发执行。
3.2.1 CMS工作流程
CMS的完整回收周期分为四个主要阶段,其中两个阶段需要STW:
- 初始标记(Initial Mark,STW):标记GC Roots直接关联的对象,停顿时间短。
- 并发标记(Concurrent Mark):从GC Roots开始遍历整个对象图,与用户线程并发执行。
- 重新标记(Remark,STW):修正并发标记期间因用户线程继续运行而产生变动的对象引用,停顿时间比初始标记长。
- 并发清除(Concurrent Sweep):清除标记阶段判定为死亡的对象,与用户线程并发执行。
- 浮动垃圾:并发清除阶段新产生的垃圾只能等下一次GC处理,可能导致"Concurrent Mode Failure"。
- 内存碎片:标记-清除算法产生大量空间碎片,最终触发Full GC(Serial Old串行回收)。
- CPU敏感:并发阶段占用CPU资源,对计算密集型应用不友好。
3.2.2 CMS典型GC日志解读
2025-03-15T10:23:45.123+0800: 2.456: [GC (CMS Initial Mark) [1 CMS-initial-mark: 2048K(4096K)] 3072K(6144K), 0.0012345 secs]
2025-03-15T10:23:45.124+0800: 2.457: [CMS-concurrent-mark-start]
2025-03-15T10:23:45.567+0800: 2.900: [CMS-concurrent-mark: 0.443/0.443 secs]
2025-03-15T10:23:45.567+0800: 2.900: [CMS-concurrent-preclean-start]
2025-03-15T10:23:45.589+0800: 2.922: [CMS-concurrent-preclean: 0.022/0.022 secs]
2025-03-15T10:23:45.589+0800: 2.922: [GC (CMS Remark) [YG occupancy: 1024K(2048K)] 3072K(6144K), 0.0087654 secs]
2025-03-15T10:23:45.598+0800: 2.931: [CMS-concurrent-sweep-start]
2025-03-15T10:23:45.789+0800: 3.122: [CMS-concurrent-sweep: 0.191/0.191 secs]
日志关键指标解读:
CMS-initial-mark:老年代已使用2048K,总容量4096K,STW耗时1.23ms。CMS-concurrent-mark:并发标记阶段总耗时443ms,与用户线程并行。CMS Remark:重新标记阶段STW耗时8.77ms,此时新生代占用1024K。CMS-concurrent-sweep:并发清除阶段耗时191ms。
3.3 G1垃圾回收器:Region化与停顿预测
G1(Garbage First)将堆内存划分为多个大小相等的Region,通过优先回收垃圾最多的Region来实现可预测的停顿时间。G1是JDK 9+的默认垃圾回收器,也是支付系统在JDK 11/17环境下的主流选择。
3.3.1 G1核心架构与工作流程
下图展示了G1的Region化堆内存结构及回收流程:
3.3.2 G1典型GC日志解读
2025-03-15T10:23:45.123+0800: 2.456: [GC pause (G1 Evacuation Pause) (young) 256M->64M(1024M), 0.0123456 secs]
2025-03-15T10:23:45.135+0800: 2.468: [GC pause (G1 Evacuation Pause) (mixed) 512M->256M(1024M), 0.0234567 secs]
2025-03-15T10:23:45.158+0800: 2.491: [GC pause (G1 Humongous Allocation) (young) (initial-mark) 768M->512M(1024M), 0.0156789 secs]
日志关键指标解读:
G1 Evacuation Pause (young):Young GC,堆内存从256M降至64M,STW耗时12.3ms。G1 Evacuation Pause (mixed):Mixed GC,同时回收年轻代和老年代Region,STW耗时23.5ms。G1 Humongous Allocation (initial-mark):大对象分配触发的初始标记,为并发标记做准备。
-XX:MaxGCPauseMillis=100:设置目标停顿时间,G1会动态调整新生代大小和回收策略。-XX:G1HeapRegionSize=4m:设置Region大小,建议根据堆内存自动计算。-XX:InitiatingHeapOccupancyPercent=45:触发Mixed GC的堆占用阈值,支付系统建议设为35~45。-XX:G1MixedGCCountTarget=8:一次并发标记周期后执行Mixed GC的次数。
3.4 ZGC垃圾回收器:亚毫秒级停顿的架构革命
ZGC(Z Garbage Collector)通过染色指针(Colored Pointers)和读屏障(Load Barrier)技术,将STW时间压缩到1ms以内,几乎消除了GC停顿对支付交易的影响。
3.4.1 ZGC核心架构
下图展示了ZGC的染色指针机制与并发转移流程:
3.4.2 ZGC典型GC日志解读
[2025-03-15T10:23:45.123+0800][gc,start] GC(0) Garbage Collection (Proactive)
[2025-03-15T10:23:45.123+0800][gc,phases] GC(0) Pause Mark Start 0.045ms
[2025-03-15T10:23:45.456+0800][gc,phases] GC(0) Concurrent Mark 332.789ms
[2025-03-15T10:23:45.456+0800][gc,phases] GC(0) Pause Mark End 0.032ms
[2025-03-15T10:23:45.456+0800][gc,phases] GC(0) Concurrent Process Non-Strong References 12.345ms
[2025-03-15T10:23:45.456+0800][gc,phases] GC(0) Concurrent Relocate 156.789ms
[2025-03-15T10:23:45.456+0800][gc,phases] GC(0) Pause Relocate Start 0.021ms
[2025-03-15T10:23:45.456+0800][gc,phases] GC(0) Concurrent Uncommit 0.001ms
[2025-03-15T10:23:45.456+0800][gc,stats] GC(0) 32G->28G(64G) 489.032ms
日志关键指标解读:
Pause Mark Start:初始标记STW仅0.045ms,几乎无感知。Concurrent Mark:并发标记阶段耗时332.789ms,与用户线程并行。Pause Mark End:最终标记STW仅0.032ms。Pause Relocate Start:转移开始STW仅0.021ms。32G->28G(64G):堆内存从32G降至28G,总耗时489ms,但STW总时间不到0.1ms。
- ZGC需要JDK 11+,JDK 15+生产可用,JDK 17+为默认回收器之一。
- ZGC对内存带宽敏感,建议搭配足够的内存带宽(如多通道DDR4/DDR5)。
- ZGC不支持压缩指针(-XX:+UseCompressedOops),64位系统下指针占用更大。
- ZGC的并发阶段会占用CPU资源,建议预留2~4个CPU核心给GC线程。
3.5 GC停顿分析与调优实战
在支付订单系统中,GC停顿的根因分析是性能调优的核心环节。以下是常见的停顿问题及解决方案:
| 停顿现象 | 可能原因 | 诊断方法 | 解决方案 |
|---|---|---|---|
| CMS Full GC频繁 | 老年代碎片化严重,Concurrent Mode Failure | 查看GC日志中"Full GC (System)"或"Concurrent Mode Failure" | 启用-XX:+UseCMSCompactAtFullCollection,或迁移至G1 |
| G1 Mixed GC停顿超预期 | IHOP阈值过低,或Region回收效率低 | 检查-XX:G1MixedGCLiveThresholdPercent和G1HeapWastePercent | 调高IHOP至45~55,增加Mixed GC次数 |
| ZGC并发标记耗时过长 | 对象图复杂,或CPU资源不足 | 查看Concurrent Mark阶段耗时,监控CPU使用率 | 增加GC线程数(-XX:ConcGCThreads),或优化对象结构 |
| Young GC停顿突增 | 新生代过大,或TLAB分配失败 | 检查GC日志中Young GC前后的堆占用变化 | 调整-XX:NewRatio或-XX:SurvivorRatio,启用TLAB统计 |
| GC日志中"System.gc()"触发Full GC | 代码中显式调用System.gc(),或RMI/NIO触发 | 添加-XX:+PrintGCApplicationStoppedTime和-XX:+PrintGCApplicationConcurrentTime | 添加-XX:+DisableExplicitGC禁用显式GC |
3.5.1 支付系统GC停顿分析案例
某支付订单系统在双11大促期间出现接口响应时间从50ms飙升至500ms的毛刺现象。通过GC日志分析发现:
2025-03-15T10:23:45.123+0800: 2.456: [Full GC (System.gc()) 4096M->2048M(8192M), 1.2345678 secs]
根因分析:
- 日志显示Full GC由
System.gc()触发,STW耗时1.23秒。 - 通过
-XX:+PrintGCApplicationStoppedTime确认停顿期间所有线程被挂起。 - 代码审查发现某第三方支付SDK在交易失败时调用了
System.gc()。
解决方案:
- JVM参数添加
-XX:+DisableExplicitGC禁用显式GC。 - 升级第三方SDK版本,移除不必要的GC调用。
- 启用
-XX:+ExplicitGCInvokesConcurrent(若必须保留System.gc(),则转为并发GC)。
- GCeasy:在线GC日志分析工具,自动识别停顿根因并给出调优建议。
- GCViewer:开源GC日志可视化工具,支持吞吐量、停顿时间、内存占用等指标。
- jstat:JDK自带工具,实时监控GC情况,适合快速排查。
- JMC (Java Mission Control):Oracle官方工具,支持飞行记录器(JFR)分析GC停顿。
3.6 本章小结
CMS、G1、ZGC代表了JVM垃圾回收技术的三个时代,各自适用于不同的场景:
- CMS:适合JDK 8及以下、堆内存≤4GB的遗留系统,但需警惕碎片化和Concurrent Mode Failure。
- G1:JDK 9+默认回收器,适合4GB~64GB堆内存,通过Region化和停顿预测模型实现可控延迟。
- ZGC:JDK 15+生产可用,适合大堆内存(8GB~16TB)和亚毫秒级停顿要求的场景,是支付系统未来的首选。
在实际调优中,建议结合GC日志分析工具,从停顿时间、吞吐量、内存占用三个维度综合评估,选择最适合当前业务场景的垃圾回收器。