在java.lang.Object中,“shadow$_klass_”和“shadow$_monitor_”变量是用于什么目的?

61
在最新的Android更新中(SDK 21),似乎已经向java.lang.Object添加了两个新变量:
private transient Class<?> shadow$_klass_;
private transient int shadow$_monitor_;

我注意到在hashCode()中短暂使用了shadow$_monitor_:
public int hashCode() {
    int lockWord = shadow$_monitor_;
    final int lockWordMask = 0xC0000000;  // Top 2 bits.
    final int lockWordStateHash = 0x80000000;  // Top 2 bits are value 2 (kStateHash).
    if ((lockWord & lockWordMask) == lockWordStateHash) {
        return lockWord & ~lockWordMask;
    }
    return System.identityHashCode(this);
}

但是除此之外,没有任何关于它们的参考资料。它们与ART中的GC有关吗?或者是某种本地内容?


2
我没有答案,但是这些链接中的一些帮助我理解可能发生的事情。只是发布它们以防它们能帮助其他人!https://dev59.com/8HA75IYBdhLWcg3wUHOQ,https://dev59.com/i2Qn5IYBdhLWcg3wmH8s,https://dev59.com/8XNA5IYBdhLWcg3wGJwV,https://dev59.com/qHNA5IYBdhLWcg3wkuzO - Kevvvvyp
@Tspoon,这些值的意义是什么或者这些值如何使用?有任何想法吗? - Diffy
2个回答

28

它们确实与GC有关。它们似乎是为了支持Brooks指针而添加的。我在这里找到了一些Brooks指针的信息:

这个想法是堆上的每个对象都有一个额外的引用字段。该字段要么指向对象本身,要么,在对象被复制到新位置后,指向那个新位置。这将使我们能够与mutator线程同时疏散对象。

特别注意这两个提交记录:

libcore:a7c69f785f7d1b07b7da22cfb9150c584ee143f4

art:9d04a20bde1b1855cefc64aebc1a44e253b1a13b


这里的哈希码计算是如何完成的?为什么要在shadow$_monitor_上进行计算? - Diffy
1
当垃圾回收器重新定位对象时,必须将其原始哈希码存储在某个地方,以防再次使用。实现这一点的明显方法是向对象头添加一个32位字段来保存哈希码。但这将为每个对象增加1个字的开销,并且会在最常见的情况下浪费空间...即不调用Object的hashCode方法的情况。有关更多详细信息,请访问此线程https://dev59.com/om865IYBdhLWcg3wd-ce#3796963。 - Mahendra Chhimwal
这很有趣,但这不会使WeakReferences变得无用吗? - Matt J.

1
这些是与JDK中Shenandoah垃圾收集相关的类。
在OpenJDK中,有4个旧的GC:Serial、Parallel、Concurrent Mark Sweep和G1。然而,这些的问题在于它们需要至少一次压缩整个旧堆,如果堆很大,这将非常耗费时间。Shenandoah GC被设计为对100Gb+堆只有<10ms的暂停时间。
通过使用基于Brooks Pointers的前向指针来实现这一点。`shadow_$klass`和`shadow$_monitor`就是这些前向指针。
Shenandoah GC的主要思想是允许应用程序线程在紧凑(移动引用对象到更好的位置)期间与堆中的对象进行交互,从而消除了“停止-世界”的需求。
看看这个其他的SO答案: Object类中的Brooks Pointer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接