如何解释实例的标记词?



我正在尝试理解 64 位 HotSpot VM (v8( 上 Java 对象布局的输出。我不明白如何使用标记词的前三位,根据链接类文件中的注释,它应该指示在实例上设置了有偏见的锁或无偏见的锁

当我使用 JOL 分析Object实例时

ClassLayout layout = ClassLayout.parseClass(Object.class);
Object object = new Object();
System.out.println(layout.toPrintable(object));

我得到以下输出:

java.lang.Object object internals:
 OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
      0     4       (object header)                01 00 00 00 (0000 0001 0000 0000 0000 0000 0000 0000)
      4     4       (object header)                00 00 00 00 (0000 0000 0000 0000 0000 0000 0000 0000)
      8     4       (object header)                e5 01 00 f8 (1110 0101 0000 0001 0000 0000 1111 1000)
     12     4       (loss due to the next object alignment)
Instance size: 16 bytes (estimated, add this JAR via -javaagent: to get accurate result)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

从 HotPoint 对标记字(前 8 个字节(的描述中,我明白我应该将输出的上述位范围解释如下:

  • 00:01 - 锁定标志(示例中为00
  • 02:02 - 偏置锁定的标志(示例中为0
  • 03:06 - 年龄为年轻垃圾回收迭代次数。(0000示例中。
  • 07:07 - 未使用。(似乎总是1
  • 08:39 - 标识哈希代码。(仅在计算之后,在用零填充之前。
  • 40:63 - 未使用。(似乎用零填充。

确认哈希代码范围的此布局

至少对于哈希码,这可以通过计算身份哈希码并比较值来轻松确认:

ClassLayout layout = ClassLayout.parseClass(Object.class);
Object object = new Object();
// Check that the hash code is not set.
System.out.println(layout.toPrintable(object));
System.out.println("hash code: 0x" + Integer.toHexString(object.hashCode()));
// Confirm that the value is set:
System.out.println(layout.toPrintable(object));
// Compute the hash code manually:
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
long hashCode = 0;
for (long index = 7; index > 0; index--) {
  hashCode |= (unsafe.getByte(object, index) & 0xFF) << ((index - 1) * 8);
}
System.out.println("hash code: 0x" + Long.toHexString(hashCode));

其中哈希代码设置为实际位(忽略它仅由 31 位而不是 32 表示的事实,因为提醒设置为零(。锁的标志都按预期设置为零。

验证偏置锁定的布局

markOops 还提供了对象何时受到偏置锁定的布局。在这里,最后两个项目符号点替换为以下范围:

  • 08:09 - 纪元位
  • 10:63 - 持有此偏置锁的线程的指针。

当我现在尝试使用-XX:BiasedLockingStartupDelay=0运行以下代码的偏置锁时,我还可以观察偏置锁是如何设置的。当我运行以下代码时:

ClassLayout layout = ClassLayout.parseClass(Object.class);
Object object = new Object();
// Before using any lock, the layout is as above.
System.out.println(layout.toPrintable(object));
// When acquiring the lock, the thread ID can be seen as below:
synchronized (object) {
  System.out.println(layout.toPrintable(object));
}
// After leaving the lock, the object is biased towards this thread:
System.out.println(layout.toPrintable(object));

偏置锁在初始锁定后的标记字中可见,如下所示:

java.lang.Object object internals:
 OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
      0     4       (object header)                05 f0 3f 02 (0000 0101 1111 0000 0011 1111 0000 0010)
      4     4       (object header)                00 00 00 00 (0000 0000 0000 0000 0000 0000 0000 0000)
      8     4       (object header)                e5 01 00 f8 (1110 0101 0000 0001 0000 0000 1111 1000)
     12     4       (loss due to the next object alignment)
Instance size: 16 bytes (estimated, add this JAR via -javaagent: to get accurate result)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

一旦我调用object.hashCode(),我可以验证这并不代表哈希代码,因为标记词发生了变化(有偏见的锁被撤销(。

我不明白的是,偏置锁和非偏置锁的标志仍设置为零。HotSpot 如何知道这是一个有偏见的锁,而不是对象中表示的哈希代码。我还想知道:纪元位表示什么?

答案很简单:OpenJDK的评论已经过时了,今天的标记词组织方式也不同了。

相关内容

  • 没有找到相关文章

最新更新