为什么压缩的Oops为Object Header提供12个字节

时间:2014-08-15 19:02:12

标签: java memory-layout objectsize

这是在Java 6内存模型之后。在32位JVM中,对象的浅层大小为

8 bytes (object header) + total of all instance variables + padding (optional)

如果前两个术语不能加到8的倍数,那么就会有填充。

在64位JVM中,浅层大小为

16 bytes (object header) + total of all instance variables + padding (optional)

我的理解是这个Object头由2个单词组成(oracle hotspot VM)

  • 一个klass词
  • 标记词

在32位JVM上,对象头= 2 * 32位= 64位= 8字节
在64位JVM上,对象头= 2 * 64位= 128位= 16字节

但是使用CompressedOops时,3个低阶位被截断,所以它应该在64位JVM上回到8个字节,小于32个gigs

但是当我使用JOL(Java对象布局)测试对象布局时,它显示了12个字节的Object头。

测试代码

public class App  {
    public static void main( String[] args )
    {
        System.out.println(System.getProperty("java.version"));
        System.out.println(VMSupport.vmDetails());
        System.out.println(ClassLayout.parseClass(A.class).toPrintable());
    } 
}

class A {
   int a; 
}

输出

1.8.0_05
Running 64-bit HotSpot VM.
Using compressed references with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.layout.test.jolTesting.A object internals:
 OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
      0    12       (object header)                N/A
     12     4   int A.a                            N/A
Instance size: 16 bytes (estimated, the sample instance is not available)
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

我在这里错过了什么,增加了额外的4个字节?

2 个答案:

答案 0 :(得分:2)

据我所知,发生的原因是,与klass字相反,标记字不是使用CompressedOops编码的。

4个字节(64位压缩klass字)+8个字节(标记字)= 12个字节(标题)

答案 1 :(得分:1)

HotSpot具有8字节,12字节和16字节的对象标头。这是因为标题包含两个部分:markword(关于对象的metainfo)和classword(对类的引用)。在32/64位模式下,标记字占用4或8个字节。 Classword只是“引用”,因此它可以在64位模式下压缩。

请参阅:https://shipilev.net/blog/2014/heapdump-is-a-lie/