07-G1&ZGC
type
status
date
slug
summary
tags
category
icon
password
1️⃣ G1收集器(-XX:+UseG1GC)
G1 垃圾收集器(Garbage-First GC,启用参数为-XX:+UseG1GC
)是 Oracle JDK 中面向服务端应用的高性能垃圾收集器,自JDK9起成为默认GC。G1的设计目标是:高吞吐、可预测的停顿时间、低碎片化,特别适合大堆内存环境(如 4GB 以上)。
1. G1 的核心设计理念
1️⃣ 区域划分(Region)
- G1 将堆划分为多个等大小的 Region(区域),每个 Region 一般为 1MB ~ 32MB,默认是 2048 个 Region。
- 每个 Region 会被动态标记为不同角色:
- Eden 区
- Survivor 区
- Old 区
- Humongous 区:存放大对象(大于 Region 大小一半的对象)
2️⃣ 分代收集,但不固定空间
- G1 仍然是分代 GC,分为 Young Generation 和 Old Generation。
- Young / Old 的空间不是连续的,而是由多个分散的 Region 动态组成。
2. G1 的垃圾收集过程
1️⃣ Young GC(Minor GC)
- 回收 Eden + 部分 Survivor,对象晋升到 Old。
- 采用 并发回收 + 多线程处理,低停顿。
2️⃣ Mixed GC(G1 的关键特点)
- 回收 Young 区 + 一部分 Old 区。
- 优化停顿时间和回收效率的平衡:根据“垃圾优先”策略,优先回收垃圾多的 Region。
- G1 不再等到 Old 区满再触发 Full GC,而是通过 Mixed GC 做预防式回收。
3️⃣ Full GC(最后手段)
- 使用 Serial Old GC 实现,单线程,效率低,应尽量避免触发。
3. G1的核心机制
1️⃣ Remembered Set(RSet)
- 记录引用跨 Region 的引用关系。
- 每个 Region 都维护一个 RSet,记录“谁引用了我”。
- 写屏障 + 卡表机制更新 RSet(类似传统 GC 中的 Card Table + Remembered Set 机制)。
2️⃣ 并发标记阶段(Concurrent Marking)
阶段 | 描述 |
初始标记(Initial Mark) | 标记 GC Roots 引用的对象,只扫描 Survivor 区;伴随 Young GC 发生,停顿。 |
并发标记(Concurrent Mark) | 标记整个堆中存活对象(Tracing GC Roots)。并发进行。 |
最终标记(Remark) | 修正并发标记期间发生的变动。Stop-The-World。 |
筛选回收(Cleanup) | 计算每个 Region 的存活率,筛选可回收的 Region,决定 Mixed GC 回收计划。 |
4. G1的目标与优势
特性 | 描述 |
可预测的停顿时间 | 支持参数 -XX:MaxGCPauseMillis=目标毫秒数 指定期望最大停顿时间(默认 200ms) |
并发回收 | 大量操作在应用线程运行时并发进行,减少 STW(Stop The World)时间 |
减少碎片 | 回收以 Region 为单位,天然具备压缩能力,避免老年代碎片化问题 |
无需手动调优分代比例 | 自动管理 Eden/Survivor/Old 空间比例 |
适用场景与注意事项
✅ 适合:
- 大堆(4GB 以上)
- 停顿时间敏感的在线系统(如 Web 服务、API 网关)
- 想避免频繁 Full GC 的场景
⚠️ 不适合:
- 嵌入式、低内存场景
- 停顿时间毫秒级别严格控制(如高频交易),可能需使用 ZGC/SHENANDOAH
2️⃣ ZGC收集器(-XX:+UseZGC)
ZGC(Z Garbage Collector,启用参数为-XX:+UseZGC
)是一种低延迟(Low Latency)、可扩展(Scalable)、并发(Concurrent)的垃圾收集器,目标是在任意堆大小下都能将 GC 停顿时间控制在 1ms 以下,适用于延迟敏感型大内存系统。
特性 | 说明 |
目标 | 停顿时间不超过 1ms(即使在 TB 级堆上) |
分代模型 | 默认是 非分代 GC(JDK 15 起支持分代) |
并发性 | 几乎所有 GC 工作都在并发阶段完成,最大限度减少 STW |
GC 类型 | 并发标记、并发转移、并发重映射 |
适用平台 | JDK 11+ 开始引入,JDK 15 起稳定;Linux/Windows/macOS 均支持 |
1. ZGC 的核心原理
基于“染色指针”(Colored Pointer)
ZGC 最大的技术创新是染色指针(colored pointer):
- 将对象头(64 位地址的高位)中的部分位用于存储元信息(如标记状态、重定向信息)。
- 实现无需停顿的标记与重定向。
- 所有对象访问都通过load barrier(加载屏障)处理其元信息。
并发阶段为主,停顿极短,只有两个 STW:初始标记、重定位开始,耗时通常 <1ms。
阶段 | 是否 STW | 描述 |
Mark Start | STW(短暂停顿) | 初始标记 GC Roots |
Mark | 并发 | 遍历堆中所有活对象(并发标记) |
Relocate Start | STW(短) | 准备对象迁移 |
Relocate | 并发 | 将对象移动到新位置(并发转移) |
Remap | 并发 | 修复指向旧对象的引用 |
1. 颜色指针
在 ZGC 中,颜色指针是指 在对象引用的高位中嵌入标记位(Metadata),这些位用于表示对象的 GC 状态,例如:
功能 | 说明 |
标记对象是否存活 | 比如对象是否被标记过 |
标记对象是否已经转发(重定位) | 用于并发拷贝阶段 |
标记使用的是哪一代页表(Remap Table) | 实现转发指针 |
功能 | 示例 |
并发标记 | 标记对象是否存活 |
转发(relocation) | 判断对象是否已迁移 |
多版本地址映射(Remap) | 管理从旧地址到新地址的页表映射关系 |
压缩地址空间(heap) | 使用高位做标志而非扩大地址空间 |
虽然名字都提到“颜色”,但:
- 三色标记法:是一种标记算法(白/灰/黑)
- 颜色指针:是 ZGC 实现中的一种技术手段,与三色标记不直接等价
它们都涉及“颜色”概念,但一个是抽象算法,另一个是具体实现技术。
ZGC 能这样做的原因:
- 现代 64 位 CPU 并不使用完整的 64 位地址空间(通常只用 48 ~ 52 位)
- 上位的若干位未用,可用于扩展和标记
- ZGC 在 Linux/x86-64 上通过虚拟地址映射实现这种优化
2. Load Barrier(加载屏障)
ZGC 对所有的对象引用读取操作都加了一个透明的 Load Barrier:
该屏障能判断:
- 当前引用是否指向旧地址
- 如果是,就 remap 到新地址(通过转发表)
- 如果对象已被搬迁,就更新引用为新地址
🔁 这是实现 对象地址不变承诺 的关键技术。
3. 转发表(Remap Table)
- 存储对象从旧地址 → 新地址的映射
- Load Barrier 会在 remap 时访问这张表
- 实现“地址永远可达”
4. 并发重定位(Concurrent Relocation)
- 搬迁对象时,不停止应用线程
- 通过转发表、Load Barrier 让访问不会出错
- 避免大规模 STW 压缩的代价
2. ZGC 垃圾回收流程
1️⃣ Initial Mark(初始标记)
- STW(极短暂)
- 标记 GC Roots
2️⃣ Concurrent Mark(并发标记)
- 从 GC Roots 开始扫描整个对象图,标记可达对象
- 并发进行,不阻塞应用线程
3️⃣ Concurrent Prepare for Relocate(并发准备重定位)
- 计算哪些区域需要移动(碎片整理)
- 构建转发表(Remap Table)
4️⃣ Relocation Set Selection(选择要压缩的内存区域)
- 找出可搬迁对象区域
5️⃣ Concurrent Relocate(并发重定位)
- 将对象从原区域复制到新区域
- 原对象记录转发地址(forwarding pointer)
6️⃣ Remap(访问时重映射)
- 所有对旧对象地址的访问通过 Load Barrier 自动 remap 到新地址
3. ZGC 的参数配置
参数 | 说明 |
-XX:+UseZGC | 启用 ZGC |
-Xmx -Xms | 设置堆大小(ZGC 适合大堆,推荐至少 8GB+) |
-XX:+ZGenerational | 启用 ZGC 的分代模式(JDK 15+ 支持) |
-XX:ZUncommitDelay=<秒> | 多久释放未使用内存(默认 300 秒) |
-XX:MaxHeapFreeRatio | 空闲内存百分比过高则回收 |
4. ZGC 的优势与限制
✅ 优势
项目 | 描述 |
极低延迟 | 停顿时间 < 1ms,即使在 TB 级堆上 |
并发性强 | 所有关键阶段均为并发,极少暂停 |
无碎片 | 搬迁对象后压缩堆,避免内存碎片 |
可扩展性强 | 支持大堆(最大可达数 TB) |
自动内存回收 | 支持堆内存自动收缩(按需归还操作系统) |
⚠️ 局限
限制项 | 描述 |
内存占用较大 | 因为需要维护元信息和备用空间 |
依赖 load barrier | 性能依赖于平台和指针压缩实现 |
垃圾产生速率高时表现受限 | 如果对象分配和存活速率远超回收速率,仍可能 OOM |
JDK 版本要求高 | 建议使用 JDK 17+(长期支持),ZGC 更加稳定 |
5. 典型使用建议
✅ 适用场景:
- 大堆、高吞吐场景(8GB ~ 数 TB)
- 停顿时间敏感型应用(金融、游戏、在线服务)
- 高并发、低延迟系统(微服务、大数据流处理)
❌ 不推荐场景:
- 小内存、嵌入式系统
- GC 暂停时间不敏感的批处理任务
3️⃣ ZGC vs G1GC 对比
特性 | ZGC | G1GC |
停顿时间 | 低于 1ms | 目标时间(默认 200ms) |
堆支持大小 | 数 TB | 推荐 <= 32GB |
是否分代 | 默认不分代(支持分代) | 分代 |
并发能力 | 几乎全并发 | 部分并发 |
实现复杂度 | 高(依赖 load barrier) | 中 |
ZGC 与其他 GC 的对比
特性 | ZGC | G1GC | CMS | Shenandoah |
最小 STW | ✅ <10ms | ❌ 可能 100ms+ | ❌ 可能秒级 | ✅ 极短 |
并发标记 | ✅ | ✅ | ✅ | ✅ |
并发移动对象 | ✅ | ❌(STW copy) | ❌ | ✅ |
适合大堆(TB) | ✅ | ⚠️ 最大几百 GB | ❌ | ✅ |
多线程并发 | ✅ | ✅ | ⚠️ | ✅ |
上一篇
06-垃圾收集底层算法
下一篇
01-MySQL数据结构
Loading...