3

Shenandoah 1.0每个单独的 Object 中都有一个额外的标题 - 称为forwarding pointer. 为什么需要这样做,导致它被淘汰的原因是什么Shenandoah 2.0

4

1 回答 1

6

首先,每个 java 对象都有两个头文件:klassmark. 它们一直存在于每个实例中(例如,它们可以稍微改变 JVM在内部使用最近的 JVM 处理其标志的方式)并且用于各种原因(将在答案中进一步详细介绍其中一个)。

对 a 的需要forwarding pointer实际上是在这个答案的第二部分。两者和inforwarding pointer都需要(尽管读取可以跳过某些字段类型的障碍 - 不会详细说明)。用非常简单的话来说,它非常简化了并发复制。正如该答案中所说,它允许原子地切换到对象的新副本,然后同时更新所有引用以指向该新对象。read barrierwrite barrierShenandoah 1.0forwarding pointer

在“to-space 不变量”的位置发生了一些变化Shenandoah 2.0:这意味着所有的写入和读取都是通过to-space. 这意味着一件有趣的事情:一旦to-space建立了副本,from-copy就永远不会使用 。想象一下这样的情况:

    refA            refB
      |               |
fwdPointer1 ---- fwdPointer2        
                      |
  ---------       ---------  
  | i = 0 |       | i = 0 | 
  | j = 0 |       | j = 0 | 
  ---------       ---------

Shenandoah 1.0某些情况下,通过读取refA可以绕过障碍(根本不使用它)并仍然通过from-copy. final例如,字段允许这样做(通过特殊标志)。这意味着即使to-space副本已经存在并且已经存在对它的引用,仍然可以读取(通过refA)将转到from-space副本。在Shenandoah 2.0此是禁止的。

这些信息以一种相当有趣的方式使用。Java 中的每个对象都与 64 位对齐——这意味着最后 3 位始终为零。所以,他们放弃了并说:如果单词forwarding pointer的最后两位是(这是允许的,因为没有其他人以这种方式使用它)-> 这是 a ,否则副本确实存在并且这是一个普通的标题。您可以在此处看到它的运行情况,您可以在此处此处跟踪掩蔽。mark11forwarding pointerto-space

它曾经看起来像这样:

| -------------------|
| forwarding Pointer |
| -------------------|

| -------------------|
|        mark        |
| -------------------|

| -------------------|
|        class       |
| -------------------|

并转变为:

| -------------------|
| mark or forwarding |     // depending on the last two bits
| -------------------|

| -------------------|
|        class       |
| -------------------|

所以这是一个可能的场景(为简单起见,我将跳过class header):

  refA, refB            
       |               
      mark   (last two bits are 00)   
       |              
    ---------   
    | i = 0 |      
    | j = 0 |      
    ---------  

GC开始。 引用的对象refA/refB是活动的,因此必须撤离(据说它在“集合集”中)。首先创建一个副本并以原子mark方式引用该副本(最后两位也被标记为11现在使其成为 aforwardee而不是 a mark word):

  refA, refB            
       |               
     mark (11) ------  mark (00)   
                           |
    ---------          ---------
    | i = 0 |          | i = 0 |
    | j = 0 |          | j = 0 |
    ---------          ---------

现在其中一个mark words 有一个位模式(以 结尾11),表明它是转发者而不是标记词。

       refA              refB            
         |                 |               
     mark (11) ------  mark (00)   
                           |
    ---------          ---------
    | i = 0 |          | i = 0 |
    | j = 0 |          | j = 0 |
    ---------          ---------

refB可以同时移动,所以refA最终没有对from-space对象的引用,它是垃圾。如果需要,这就是mark word充当 的方式。forwarding pointer

于 2020-09-22T02:47:47.443 回答