ZGC垃圾收集的主要流程

值得说明的是,在执行就地迁移时,ZGC 必须首先压缩指定为对象迁移区域内的对象,这可能会对性能产生负面影响。增加堆大小可以帮助 ZGC 避免使用就地迁移。

图片

如上图,ZGC 的工作流程主要包括以下几个步骤:

  • (STW)标记开始

标记阶段开始的同步点,只会执行一些小的操作,例如设置一些标记位和确定全局颜色。

值得说明的是,在 JDK 16 之前,该阶段的耗时和 GC Roots(静态变量与线程栈中的局部变量)的数量成正比。因此在 JEP 376 中引入了一种新的算法,将扫描线程栈的操作转移到并发阶段,从而显著减少了该阶段的耗时。

  • (并发)标记与重映射

在这个并发阶段,ZGC 将遍历整个对象图,并标记所有对象(根据 GC 周期不同,设置 Marked0 或 Marked1 标记)。同时,将上一个 GC 周期中尚未被重映射的对象(标记仍为 Marked1 或 Marked0)进行重映射。

  • (STW)标记结束

标记阶段结束的同步点,会处理一些边界情况。

  • (并发)迁移准备

该阶段会处理弱引用、清理不再使用的对象,并筛选出需要迁移的对象(Relocation Set)。

  • (STW)迁移开始

迁移阶段开始的同步点,通知所有涉及到对象迁移的线程。

同样的,在 JDK 16 引入 JEP 376 之后,该阶段的耗时不再与 GC Roots 的数量成正比。

  • (并发)迁移

该阶段会并发地迁移对象,压缩堆中的区域,以释放空间。迁移后的对象的新地址会记录到转发表(Forwarding Table)中,用于后续重映射时获取对象的新的地址;该转发表是一个哈希表,使用堆外内存,每个区域分别有一个转发表。

可以看到,在一个 GC 周期中,STW 的阶段和并发阶段交替执行,并且绝大多数操作均在并发阶段执行。

示例

为了更好地理解 ZGC 的工作原理,下面通过一个例子来展示 ZGC 工作各阶段执行的操作。

1. 【GC 开始】初始状态

图片

  • 上图中为 GC 开始前 Java 堆的状态:共有 3 个区域,9 个对象。

  • 所有新创建的对象初始颜色均为 Remapped。

2. 【标记阶段】从 GC Roots 开始遍历,标记所有存活的对象

图片

  • 每次 GC 之间的标记阶段轮流使用 Marked0 与 Marked1,本次使用 Marked0。

  • GC Roots(例如,线程栈中引用的对象,静态变量等)为每次标记的起点,所有被 GC Roots 引用的对象都应被认为是存活的;同样的,如果未被标记(颜色仍为 Remapped),则认为可被回收。

3. 【迁移准备阶段】选择需要压缩的区域,并创建转发表

图片

  • 检查各区域发现,区域 1 与区域 2 存在需要回收的对象,将它们加入迁移集合。

  • 并为所有迁移集合中的区域创建转发表。

4. 【迁移阶段】遍历所有对象,迁移其中处于迁移集合中的对象

图片

a. 遍历到对象 1、2,发现它们位于区域 0(不在迁移集合中),无需迁移,仅将颜色恢复为 Remapped。

b. 遍历到对象 4、5、7,均在迁移集合中,需要迁移。

  1. 创建(或复用)一个新的区域——区域 3,用于放置这 3 个对象。

  2. 依次将这 3 个对象迁移至新的区域,并将它们新的地址记录在转发表中。

  3. 将这 3 个对象的颜色恢复为 Remapped。

注意:

  • 迁移完成后,迁移集合中的区域 1 与区域 2 即可被复用,用于分配新的对象。但为了便于理解,图中保留了 4、5、7 这 3 个对象的历史位置,并加了“'”号用以区分新老位置。

  • 值得注意的是,此时对象 2(对象 4')中记录的对象 5(对象 7)的地址仍为迁移前的地址,指针的颜色也仍为标记时的颜色 Marked0。

5. 【迁移后的任意时间】用户线程加载对象

图片

  • 在对象 7 迁移完成后,如果此时用户线程尝试加载对象 7,会触发读屏障(指针实际颜色 Marked0 与期望颜色 Remapped 不符,是“坏的”)。在读屏障中,会基于转发表,将对象 7 的地址重映射对象 7'。

6. 【下一次 GC 标记阶段】重映射所有未被用户线程加载过的对象

图片

  • 在下一次 GC 的标记阶段,会使用 Marked1 标记出所有存活对象。

  • 与此同时,发现对象 2 引用了对象 5,而对象 5 的颜色是“坏的”(对象 5 的实际颜色 Marked0 与期望颜色 Remapped 不符),会基于转发表,将对象 5 的地址重映射对象 5'。

注意:

  • 每次 GC 的 GC Roots 引用的对象可能不同,在本例中,从对象 1 与对象 4' 变成了对象 2 与对象 7'。

7. 【下一次 GC 迁移准备阶段】清理转发表

图片

  • 与之前的迁移准备阶段类似,需要确定迁移集合、创建转发表。此外,还需要将上一次 GC 的转发表删除。

参考文档

Java ZGC 深度剖析及其在构建低延迟流系统中的实践心得

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值