我试图详细了解ZGC的工作原理。让我们考虑一个简单的Java示例:
var v = new Object[]{ new Object() };
我们打电话吧
-
一
:数组对象
-
o
:引用的对象
v[0]
-
r
:参考
一
-
s
:参考
o
下图以图形方式显示了伪影:
让我们假设第一个gc循环开始
一
,
o
被重新安置。让我们进一步假设应用程序不访问对象。
气相色谱循环1:
a) 标记阶段:标记阶段结束时
标记为0
位已设置
r
,
s
.
b) 重定位阶段:首先,根对象
一
被重新安置,
r
被重新映射到新位置
重新映射
一点点
r
已设置。然后,
o
被重新安置,新的位置
o
被写入转发表。
注:
源自堆的引用在重新定位阶段不会重新映射(
2
9:20)-它们将在下一个标记阶段重新映射(或者如果应用程序在下一标记阶段之前加载了引用,则由负载屏障重新映射)。因此,据我所知
标记为0
位仍处于设置状态
s
.
气相色谱循环2:
a) 标记阶段:
a1)
标记1
一点点
r
已设置。
a2)由于
重新映射
一点点
s
如果未设置,gc会查看转发表,查看
o
,重新映射
s
到新的位置
o
并从转发表中删除该条目。
问题:
哪种颜色的
s
现在设置好了吗?
考虑因素:
自从
s
刚刚重新映射,设置
重新映射
比特。但gc也处于标记阶段,因此
地图1
位必须设置。
为什么这很重要:
如果在步骤a2)中
标记
bit已设置,这意味着通常在标记阶段结束后,源自堆的所有引用都已设置
标记
比特。因此,每当应用程序在标记阶段完成后首次从堆中加载引用时,负载屏障必须通过访问转发表来检查引用是否已被重新映射。
这是(i)性能负担,也是(ii)不必要的,因为gc从重映射步骤(示例中的步骤a2)中知道引用已被重映射。因此,要么算法不是最优的,要么颜色位的设置方式与上述不同。