G1与ZGC:现代垃圾收集器详解
2026/8/19大约 5 分钟
G1与ZGC:现代垃圾收集器详解
G1和ZGC是当前最主流的两款低延迟垃圾收集器,理解它们的设计理念和调优方法是Java架构师的必备技能。
本文深入对比G1与ZGC的实现原理、适用场景和调优实战,帮助你做出正确的技术选型。
一、垃圾收集器演进历史
时间线:
1999年 → Serial (单线程)
2002年 → Parallel (多线程,吞吐量优先)
2004年 → CMS (并发标记清除,低停顿)
2010年 → G1 (分区收集,可预测停顿)
2018年 → ZGC (染色指针,亚毫秒停顿)
2021年 → Shenandoah (低停顿,并发压缩)二、G1垃圾收集器
2.1 设计目标
| 目标 | 说明 |
|---|---|
| 可预测停顿 | 用户设定目标停顿时间 |
| 高吞吐量 | 平衡吞吐和延迟 |
| 大堆支持 | 适合4GB-16GB堆 |
| 均衡负载 | 各Region均匀回收 |
2.2 G1堆结构详解
G1 Heap:
┌─────────────────────────────────────────────────────────────┐
│ Region 0 │ Region 1 │ Region 2 │ Region 3 │ ... │
│ (Eden) │ (Old) │ (Survivor)│ (Humongous)│ │
└─────────────────────────────────────────────────────────────┘
Region类型:
- Eden Region: 新生代,存储新对象
- Survivor Region: 新生代,存储存活对象
- Old Region: 老年代,存储长期存活对象
- Humongous Region: 存储大对象(> Region 50%)
- Free Region: 空闲,可分配2.3 G1回收流程
G1回收阶段:
1. Young GC (年轻代回收)
- Eden Region满时触发
- 复制存活对象到Survivor/Old
- 停顿时间可预测
2. 并发标记周期
┌─────────────────────────────────────────┐
│ 初始标记 → 并发标记 → 最终标记 → 筛选回收 │
│ (STW) (并发) (STW) (STW) │
└─────────────────────────────────────────┘
3. Mixed GC (混合回收)
- 回收所有年轻代 + 部分老年代
- 基于垃圾量优先选择Region2.4 G1关键参数
# 基础配置
-XX:+UseG1GC
-Xmx8g -Xms8g
# 停顿时间目标(毫秒)
-XX:MaxGCPauseMillis=200
# Region大小(1MB-32MB,2的幂)
-XX:G1HeapRegionSize=4m
# 触发并发标记的堆占用率
-XX:InitiatingHeapOccupancyPercent=45
# 并发标记线程数
-XX:ConcGCThreads=2
# 保留空间比例
-XX:G1ReservePercent=10
# 期望年轻代Region数最小/最大
-XX:G1NewSizePercent=5
-XX:G1MaxNewSizePercent=60三、ZGC垃圾收集器
3.1 设计目标
| 目标 | 说明 |
|---|---|
| 超低停顿 | < 1ms (亚毫秒级) |
| 大堆支持 | 8MB - 16TB |
| 吞吐量损失 | < 15% |
| 高扩展性 | 支持多核并行 |
3.2 ZGC核心技术
ZGC技术创新:
1. 染色指针 (Colored Pointers)
┌──────────────────────────────────────┐
│ 64位指针结构: │
│ [4位颜色] [60位地址] │
│ │ │
│ ├─ Marked0: 标记位0 │
│ ├─ Marked1: 标记位1 │
│ ├─ Remapped: 重映射位 │
│ └─ Finalizable: 可终结位 │
└──────────────────────────────────────┘
2. 读屏障 (Load Barrier)
- 在对象引用加载时触发
- 检查指针颜色位
- 必要时进行转移动作
3. 多重映射 (Multi-Mapping)
- 同一物理内存映射到多个虚拟地址
- 支持染色指针实现
- 透明处理,应用无感知3.3 ZGC工作流程
ZGC并发回收阶段:
┌─────────────────────────────────────────────────────────────┐
│ 1. 初始标记 (STW) │
│ - 扫描GC Roots │
│ - 停顿时间 < 1ms │
├─────────────────────────────────────────────────────────────┤
│ 2. 并发标记 │
│ - 遍历对象图 │
│ - 与应用并发执行 │
├─────────────────────────────────────────────────────────────┤
│ 3. 最终标记 (STW) │
│ - 处理剩余标记队列 │
│ - 停顿时间 < 1ms │
├─────────────────────────────────────────────────────────────┤
│ 4. 并发转移 │
│ - 转发存活对象 │
│ - 更新引用指针 │
│ - 与应用并发执行 │
└─────────────────────────────────────────────────────────────┘3.4 ZGC关键参数
# 启用ZGC
-XX:+UseZGC
# 堆大小
-Xmx16g -Xms16g
# 并发线程数
-XX:ConcGCThreads=4
# 启用分代模式(JDK 21+)
-XX:+UseZGC -XX:+ZGenerational
# 查看ZGC日志
-XX:+UnlockDiagnosticVMOptions
-XX:+LogCompilation
-XX:LogFile=/var/log/app/zgc.log四、G1 vs ZGC对比
4.1 性能对比
| 指标 | G1 | ZGC | 说明 |
|---|---|---|---|
| 最大停顿时间 | 100-500ms | < 1ms | ZGC优势明显 |
| 吞吐量损失 | 5-10% | 10-15% | G1略优 |
| 内存占用 | 较低 | 较高(15-20%) | ZGC需要额外空间 |
| 适用堆大小 | 4GB-16GB | 8MB-16TB | ZGC支持更大内存 |
| 启动时间 | 快 | 较慢 | G1初始化更快 |
| CPU消耗 | 较低 | 较高 | ZGC并发度更高 |
4.2 适用场景
| 场景 | 推荐选择 | 原因 |
|---|---|---|
| 低延迟要求(< 100ms) | ZGC | 亚毫秒停顿 |
| 大内存应用(> 16GB) | ZGC | 支持TB级内存 |
| 吞吐量优先 | G1 | 吞吐损失小 |
| 中等内存(4-16GB) | G1 | 平衡性能 |
| 客户端应用 | G1 | 资源消耗低 |
| 金融交易系统 | ZGC | 确定性延迟 |
五、调优实战
5.1 G1调优案例
场景:电商订单系统,堆8GB,要求P99延迟< 200ms
# 优化前配置
-XX:+UseG1GC
-Xmx8g -Xms8g
-XX:MaxGCPauseMillis=500 # 停顿时间过长
# 优化后配置
-XX:+UseG1GC
-Xmx8g -Xms8g
-XX:MaxGCPauseMillis=200 # 目标停顿
-XX:G1HeapRegionSize=4m # 适当增大Region
-XX:InitiatingHeapOccupancyPercent=40 # 提前触发标记
-XX:G1NewSizePercent=30 # 增大新生代
-XX:G1MaxNewSizePercent=50
-XX:ConcGCThreads=2 # 并发标记线程效果:
- P99延迟从350ms降至120ms
- Full GC频率从每小时2次降至每天1次
5.2 ZGC调优案例
场景:大数据分析平台,堆64GB,要求亚秒级响应
# ZGC配置
-XX:+UseZGC
-Xmx64g -Xms64g
-XX:ConcGCThreads=8
-XX:ZCollectionInterval=5 # 主动回收间隔(秒)
# 监控配置
-XX:+UnlockDiagnosticVMOptions
-XX:+ZTraceAllocation效果:
- 停顿时间稳定在0.5ms以内
- 吞吐量达到95%以上
六、监控与诊断
6.1 GC日志分析
# G1日志格式
[2026-08-21T10:00:00.123+0800] GC(42) Pause Young GC
[2026-08-21T10:00:00.125+0800] GC(42) Using 4 workers
[2026-08-21T10:00:00.128+0800] GC(42) Eden regions: 8->0
[2026-08-21T10:00:00.128+0800] GC(42) Old regions: 12->13
[2026-08-21T10:00:00.128+0800] GC(42) Pause Full GC (Allocation Failure)
# ZGC日志格式
[2026-08-21T10:00:00.123+0800] GC(42) Garbage Collection (Allocation Rate)
[2026-08-21T10:00:00.124+0800] GC(42) Phase 1: Mark
[2026-08-21T10:00:00.125+0800] GC(42) Phase 2: Prepare for Relocate
[2026-08-21T10:00:00.126+0800] GC(42) Phase 3: Relocate6.2 关键指标
| 指标 | G1目标 | ZGC目标 | 监控命令 |
|---|---|---|---|
| 停顿时间 | < 200ms | < 1ms | jstat -gc |
| GC频率 | < 1次/分钟 | < 1次/分钟 | GC日志 |
| 吞吐量 | > 90% | > 85% | jstat -gcutil |
| 堆使用率 | < 70% | < 70% | jstat -gc |
七、最佳实践
7.1 选择建议
决策流程:
1. 是否需要亚毫秒停顿?
├─ 是 → ZGC
└─ 否 → 继续
2. 堆大小是否超过16GB?
├─ 是 → ZGC
└─ 否 → 继续
3. 是否追求极致吞吐量?
├─ 是 → G1
└─ 否 → G1 (默认选择)7.2 注意事项
| 注意点 | G1 | ZGC |
|---|---|---|
| JDK版本 | 8u40+ | 11+ (推荐21+) |
| 内存开销 | 低 | 高(15-20%) |
| CPU开销 | 中 | 高 |
| 大对象处理 | Humongous Region | 透明处理 |
| 生产验证 | 充分 | 需充分测试 |