Java Shenandoah 2.0消除转发指针
在Java Shenandoah 2.0消除转发指针,java,garbage-collection,jvm,shenandoah,Java,Garbage Collection,Jvm,Shenandoah,在Shenandoah 1.0中,每个对象都有一个额外的头,称为转发指针。为什么需要这样做?是什么原因导致它在shenandoah2.0中被消除?首先,每个java对象都有两个头:klass和mark。它们一直存在于每个实例中(例如,它们可以稍微改变JVM处理最近的JVM的方式),并用于各种原因(在回答中只会进一步详细介绍其中一个) 需要一个转发指针。在Shenandoah 1.0中的读取屏障和写入屏障中都需要转发指针(尽管对于某些字段类型,读取可以跳过屏障-不会详细介绍)。简单地说,它大大简化
Shenandoah 1.0
中,每个对象都有一个额外的头,称为转发指针
。为什么需要这样做?是什么原因导致它在shenandoah2.0
中被消除?首先,每个java对象都有两个头:klass
和mark
。它们一直存在于每个实例中(例如,它们可以稍微改变JVM处理最近的JVM的方式),并用于各种原因(在回答中只会进一步详细介绍其中一个)
需要一个转发指针
。在Shenandoah 1.0
中的读取屏障
和写入屏障
中都需要转发指针
(尽管对于某些字段类型,读取可以跳过屏障-不会详细介绍)。简单地说,它大大简化了并发复制。正如回答中所说,它允许原子地将转发指针
切换到对象的新副本,然后同时更新指向该新对象的所有引用
在Shenandoah 2.0
中,“到空间不变量”已经就位:这意味着所有的写和读操作都是通过到空间
完成的。这意味着一件有趣的事情:一旦到空间
的拷贝建立起来,就永远不会使用从拷贝
。想象一下这样的情况:
refA refB
| |
fwdPointer1 ---- fwdPointer2
|
--------- ---------
| i = 0 | | i = 0 |
| j = 0 | | j = 0 |
--------- ---------
| -------------------|
| forwarding Pointer |
| -------------------|
| -------------------|
| mark |
| -------------------|
| -------------------|
| class |
| -------------------|
在Shenandoah 1.0
中,当通过refA
读取时,可能会绕过障碍(根本不使用它),并且仍然通过从副本读取。例如,final
字段允许这样做(通过特殊标志)。这意味着,即使到space
复制已经存在,并且已经有对它的引用,仍然可能有从space
复制到的读取(通过refA
)。在Shenandoah 2.0中,这是禁止的
这一信息的使用方式相当有趣。Java中的每个对象都与64位对齐,这意味着最后3位始终为零。因此,他们放弃了转发指针
,并说:如果标记
单词的最后两位是11
(这是允许的,因为没有其他人以这种方式使用它)->这是一个转发指针
,否则到空格的副本仍然存在,这是一个普通标题。你可以,你可以追踪掩蔽和
它过去是这样的:
refA refB
| |
fwdPointer1 ---- fwdPointer2
|
--------- ---------
| i = 0 | | i = 0 |
| j = 0 | | j = 0 |
--------- ---------
| -------------------|
| forwarding Pointer |
| -------------------|
| -------------------|
| mark |
| -------------------|
| -------------------|
| class |
| -------------------|
并已转变为:
| -------------------|
| mark or forwarding | // depending on the last two bits
| -------------------|
| -------------------|
| class |
| -------------------|
因此,这里有一个可能的场景(为了简单起见,我将跳过类标题
):
GC
开始生效。refA/refB
引用的对象处于活动状态,因此必须排空(据说它位于“集合集中”)。首先,创建一份副本,并以原子方式标记该副本(最后两位标记为11
,现在将其标记为转发人
,而不是标记字
):
现在,标记字
s中的一个有一个位模式(以11
结尾),表示它是转发器,不再是标记字
refA refB
| |
mark (11) ------ mark (00)
|
--------- ---------
| i = 0 | | i = 0 |
| j = 0 | | j = 0 |
--------- ---------
refB
可以同时移动,因此refA
最终不会从空间中引用对象,它是垃圾。这就是标记单词
在需要时充当转发指针的方式