首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Shenandoah 2.0消除转发指针

Shenandoah 2.0消除转发指针
EN

Stack Overflow用户
提问于 2020-09-22 02:47:47
回答 1查看 157关注 0票数 3

Shenandoah 1.0中,每个对象都有一个额外的标题--名为forwarding pointer。为什么需要这样做?导致在Shenandoah 2.0中消除它的原因是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-22 02:47:47

首先,每个java对象都有两个头:klassmark。它们一直存在于每个实例中(例如,它们可以稍微改变JVM使用最近JVM处理他们的旗帜在内部的方式),并且由于各种原因而被使用(在回答中只会详细介绍其中的一个)。

forwarding pointer的需求实际上是在答案的第二部分中。forwarding pointerread barrierwrite barrier中都是需要的(尽管读取可能会跳过某些字段类型的障碍-不会详细说明)。简单地说,它非常简化了并发复制。如前所述,它允许原子地将forwarding pointer切换到对象的新副本,然后并发更新所有引用以指向该新对象。

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

代码语言:javascript
复制
    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,并说:如果mark单词的最后两位是11 (这是允许的,因为没有其他人以这种方式使用它),那么这是一个forwarding pointer,否则to-space副本仍然存在,这是一个普通的头。您可以在这里看到它的行动,也可以跟踪掩蔽这里这里

它以前是这样的:

代码语言:javascript
复制
| -------------------|
| forwarding Pointer |
| -------------------|

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

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

并已转变为:

代码语言:javascript
复制
| -------------------|
| mark or forwarding |     // depending on the last two bits
| -------------------|

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

因此,这里有一个可能的场景(为了简单起见,我将跳过class header ):

代码语言:javascript
复制
  refA, refB            
       |               
      mark   (last two bits are 00)   
       |              
    ---------   
    | i = 0 |      
    | j = 0 |      
    ---------  

GC踢了进去。refA/refB引用的对象是活动的,因此必须退出(据说在“集合集”中)。首先,创建一个副本,原子化地将mark用于引用该副本(最后两个位标记为11,现在将其标记为forwardee而不是mark word):

代码语言:javascript
复制
  refA, refB            
       |               
     mark (11) ------  mark (00)   
                           |
    ---------          ---------
    | i = 0 |          | i = 0 |
    | j = 0 |          | j = 0 |
    ---------          ---------

现在,其中一个mark word有一个位模式(以11结尾),它指示它是一个远期词,不再是一个标记词。

代码语言:javascript
复制
       refA              refB            
         |                 |               
     mark (11) ------  mark (00)   
                           |
    ---------          ---------
    | i = 0 |          | i = 0 |
    | j = 0 |          | j = 0 |
    ---------          ---------

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

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64002388

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档