java.lang.Object 中的“shadow$_klass_”和“shadow$_monitor_”变量是啥?

Posted

技术标签:

【中文标题】java.lang.Object 中的“shadow$_klass_”和“shadow$_monitor_”变量是啥?【英文标题】:What are the 'shadow$_klass_' and 'shadow$_monitor_' variables for in java.lang.Object?java.lang.Object 中的“shadow$_klass_”和“shadow$_monitor_”变量是什么? 【发布时间】:2021-10-09 19:34:04 【问题描述】:

在最新的 android 更新 (SDK 21) 中,java.lang.Object 中似乎添加了两个新变量:

private transient Class<?> shadow$_klass_;
private transient int shadow$_monitor_;

我注意到shadow$_monitor_hashCode() 中被短暂使用:

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 有关吗?还是某种原生的东西?

【问题讨论】:

我没有答案,但是其中一些链接帮助我了解了可能发生的情况。只是张贴他们以防他们帮助别人! ***.com/questions/3362303/whats-a-monitor,***.com/questions/16721021/what-is-klass-klassklass,***.com/questions/1092099/…,***.com/questions/910374/… @Tspoon,这些值的意义是什么或者这些值是如何使用的?知道吗? 【参考方案1】:

它们确实连接到 GC。它们似乎是为了支持布鲁克斯的指针而添加的。我找到了一些关于布鲁克斯指针here的信息:

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

尤其是这两个提交:

libcore: a7c69f785f7d1b07b7da22cfb9150c584ee143f4

art: 9d04a20bde1b1855cefc64aebc1a44e253b1a13b

【讨论】:

这里hashcode的计算是怎么做的?为什么要在 shadow$_monitor_ 上进行计算? 当一个对象被垃圾收集器重新定位时,它的原始哈希码必须存储在某个地方以防再次使用。实现这一点的明显方法是在对象头中添加一个 32 位字段来保存哈希码。但这会给每个对象增加 1 个字的开销,并且在最常见的情况下会浪费空间……在不调用对象的 hashCode 方法的情况下。有关更多详细信息,请访问此线程***.com/a/3796963 这很有趣,但这不是让 WeakReferences 没用吗?【参考方案2】:

这些是与 JDK 中的 Shenandoah Garbage Collection 相关的类。

OpenJDK Serial、Parallel、Concurrent Mark Sweep 和 G1 中有 4 个较旧的 GC。然而,这些问题在于它们需要至少压缩整个旧堆一次,如果堆很大,这将非常重。 Shenandoah 针对 100Gb+ 堆设计了

这是通过使用基于布鲁克斯指针的转发指针来实现的。shadow_$klassshadow$_monitor 是这些转发指针。

Shenandoah GC 的主要思想是,它允许应用程序线程与堆中的对象进行交互,同时它们在压缩期间被移动(将引用的对象移动到更好的位置),无需“停止-世界”

看看这个其他的答案:***s Pointer in Object class

【讨论】:

以上是关于java.lang.Object 中的“shadow$_klass_”和“shadow$_monitor_”变量是啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 java.lang.Object 中的 finalize() 方法是“受保护的”?

java.lang.Object

java.lang.Object

java.lang.Object 中的“shadow$_klass_”和“shadow$_monitor_”变量是啥?

Eclipse 中的 Java 项目:无法解析 java.lang.Object 类型。它是从所需的 .class 文件中间接引用的

如何修复CrudRepository.save(java.lang.Object)是springboot中的无法访问方法?