HotSpot 中 java 对象头

1.相关文档 

Java HotSpot VM Options https://www.oracle.com/java/technologies/javase/vmoptions-jsp.html

open jdk 18 mark word源码

https://github.com/openjdk/jdk18/blob/master/src/hotspot/share/oops/markWord.hpp

open jdk 18 klass word源码

https://github.com/openjdk/jdk18/blob/master/src/hotspot/share/oops/klass.hpp

关于klass将被移除的草案

https://openjdk.java.net/jeps/8198332

open jdk 15 mark word源码

https://github.com/openjdk/jdk15/blob/e208d9aa1f185c11734a07

db399bab0be77ef15f/src/hotspot/share/oops/markWord.hpp

Deprecate and Disable Biased Locking https://openjdk.java.net/jeps/374

baeldung https://www.baeldung.com/java-memory-layout

2.对象头

        一个java对象在内存中除了有自身成员属性外,还有 锁信息、Hash码、对象年龄,class信息、数组长度等数据,它们称为对象头信息。

        在HotSpot虚拟机中,对象头包含2个部分:

  • mark word : 保存hashcode、锁信息、偏向锁状态、gc信息。
  • class word  :一个指针,指向本类元数据,它里面保存类的信息:类名、基类、修饰符等
  • 数组长度      : 当变量为数组时,还要一个空间存放数组的长度。

3.查看jvm信息

    @Test
    public void jvm() {
        out.println(VM.current().details());
    }

结果:

# WARNING: Unable to get Instrumentation. Dynamic Attach failed. You may add this JAR as -javaagent manually, or supply -Djdk.attach.allowAttachSelf
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# WARNING | Compressed references base/shifts are guessed by the experiment!
# WARNING | Therefore, computed addresses are just guesses, and ARE NOT RELIABLE.
# WARNING | Make sure to attach Serviceability Agent to get the reliable addresses.
# 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]

其中后两行 (4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]  )含义如下: 

普通对象成员与数组元素各类型占内存字节数
\ 引用 booleans byte short chars int float long double
普通对象 4 1 1 2 2 4 4 8 8
数组 4 1 1 2 2 4 4 8 8

HotSpot JVM 默认启用了指针压缩(-XX:+UseCompressedOops),所以引用的大小是4,未启用(-XX:-UseCompressedOops)时引用的大小是8。

4. mark word 信息

HotSpot 中对象按大端保存数据。保存hashcode、锁信息、偏向锁状态、gc信息。

4.1 open jdk 18 word

https://github.com/openjdk/jdk18/blob/master/src/hotspot/share/oops/markWord.hpp

// The markWord describes the header of an object.
//
// Bit-format of an object header (most significant first, big endian layout below):
//
//  32 bits:
//  --------
//             hash:25 ------------>| age:4  unused_gap:1  lock:2 (normal object)
//
//  64 bits:
//  --------
//  unused:25 hash:31 -->| unused_gap:1  age:4  unused_gap:1  lock:2 (normal object)
//
//  - hash contains the identity hash value: largest value is
//    31 bits, see os::random().  Also, 64-bit vm's require
//    a hash value no bigger than 32 bits because they will not
//    properly generate a mask larger than that: see library_call.cpp
//
//  - the two lock bits are used to describe three states: locked/unlocked and monitor.
//
//    [ptr             | 00]  locked             ptr points to real header on stack
//    [header          | 01]  unlocked           regular object header
//    [ptr             | 10]  monitor            inflated lock (header is wapped out)
//    [ptr             | 11]  marked             used to mark an object
//    [0 ............ 0| 00]  inflating          inflation in progress
//
//    We assume that stack/thread pointers have the lowest two bits cleared.
//
//  - INFLATING() is a distinguished markword value of all zeros that is
//    used when inflating an existing stack-lock into an ObjectMonitor.
//    See below for is_being_inflated() and INFLATING().

32 位机器:(大端)

00000101    00000000     00000000    0 0000 0 00
hash(25位) gc age(4位) unused_gap(1位) lock(2位)

64位机器:(大端)

00000000  00000000 00000000 0 00000000 00000000 00000000 0000000 0 0000 0 00
unused:25 hash:31 unused_gap:1 age:4 unused_gap:1  lock(2位)

其中 :

  • hash  :位保存hash值,无论32位机器还是64位机器,最大到31位。
  • age : 如果对象在Survivor区复制一次,年龄增加1。当对象达到设定的阈值时,将会晋升到老年代。默认情况下,并行GC的年龄阈值为15,并发GC的年龄阈值为6。
  • gap : 空白位
  • lock   :锁状态标记位
  • unused:未使用位
锁状态值含义表
[ptr | 00] locked ptr points to real header on stack
[header | 01] unlocked regular object header
[ptr | 10] monitor inflated lock (header is wapped out)
[ptr | 11] marked used to mark an object
[0 ............ 0| 00] inflating inflation in progress

4.2 open jdk 15 word

https://github.com/openjdk/jdk15/blob/e208d9aa1f185c11734a07db399bab0be77ef15f/src/hotspot/share/oops/markWord.hpp

// The markWord describes the header of an object.
//
// Bit-format of an object header (most significant first, big endian layout below):
//
//  32 bits:
//  --------
//             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
//             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
//
//  64 bits:
//  --------
//  unused:25 hash:31 -->| unused_gap:1   age:4    biased_lock:1 lock:2 (normal object)
//  JavaThread*:54 epoch:2 unused_gap:1   age:4    biased_lock:1 lock:2 (biased object)
//
//  - hash contains the identity hash value: largest value is
//    31 bits, see os::random().  Also, 64-bit vm's require
//    a hash value no bigger than 32 bits because they will not
//    properly generate a mask larger than that: see library_call.cpp
//    and c1_CodePatterns_sparc.cpp.
//
//  - the biased lock pattern is used to bias a lock toward a given
//    thread. When this pattern is set in the low three bits, the lock
//    is either biased toward a given thread or "anonymously" biased,
//    indicating that it is possible for it to be biased. When the
//    lock is biased toward a given thread, locking and unlocking can
//    be performed by that thread without using atomic operations.
//    When a lock's bias is revoked, it reverts back to the normal
//    locking scheme described below.
//
//    Note that we are overloading the meaning of the "unlocked" state
//    of the header. Because we steal a bit from the age we can
//    guarantee that the bias pattern will never be seen for a truly
//    unlocked object.
//
//    Note also that the biased state contains the age bits normally
//    contained in the object header. Large increases in scavenge
//    times were seen when these bits were absent and an arbitrary age
//    assigned to all biased objects, because they tended to consume a
//    significant fraction of the eden semispaces and were not
//    promoted promptly, causing an increase in the amount of copying
//    performed. The runtime system aligns all JavaThread* pointers to
//    a very large value (currently 128 bytes (32bVM) or 256 bytes (64bVM))
//    to make room for the age bits & the epoch bits (used in support of
//    biased locking).
//
//    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread
//    [0           | epoch | age | 1 | 01]       lock is anonymously biased
//
//  - the two lock bits are used to describe three states: locked/unlocked and monitor.
//
//    [ptr             | 00]  locked             ptr points to real header on stack
//    [header      | 0 | 01]  unlocked           regular object header
//    [ptr             | 10]  monitor            inflated lock (header is wapped out)
//    [ptr             | 11]  marked             used to mark an object
//
//    We assume that stack/thread pointers have the lowest two bits cleared.

32位:(大端)

normal object
00000000    00000000    00000000    0 0000 0 00
hash:25 age:4  biased_lock:1  lock:2
biased object
00000000    00000000    0000000 00 0000 0 00
JavaThread*:23 epoch:2 age:4  biased_lock:1 lock:2

64位:(大端)

normal object
00000000    00000000    00000000    0 00000000    00000000    00000000    0000000 0 0000 0 00
unused:25 hash:31 unused_gap:1  age:4 biased_lock:1 lock:2
biased object
00000000    00000000    00000000    00000000   00000000   00000000   000000 00 0 0000 0 00
JavaThread*:54 epoch:2 unused_gap:1 age:4 biased_lock:1 lock:2

其中:

  • hash  :位保存hash值,无论32位机器还是64位机器,最大到31位。
  • age : 如果对象在Survivor区复制一次,年龄增加1。当对象达到设定的阈值时,将会晋升到老年代。默认情况下,并行GC的年龄阈值为15,并发GC的年龄阈值为6。
  • gap : 空白位
  • biased_lock:偏向锁标记,为1时表示对象启用偏向锁,为0时表示对象没有偏向锁
  • lock   :锁状态标记位
  • JavaThread*:持有偏向锁的线程指针。
  • epoch:偏向时间戳

4.3 open jdk 18 与 15 区别

对比发现:

  • open jdk18 中不在对象头里区分biased_object还是normal object,默认不打开biased locking.可通过XX:+UseBiasedLocking打开。
  • 没有了 biased_lock、epoch、JavaThread*
  • 具体参见 源码:https://github.com/openjdk/jdk18

详细可参看官方文档:

https://openjdk.java.net/jeps/374

4.4 hash值示例

    @Test
    public void hash(){
        class A {}
        final A a = new A();
        ClassLayout layout = ClassLayout.parseInstance(a);

        out.println(VM.current().details());
        out.println("**** Fresh object");
        out.println(layout.toPrintable());

        out.println("hashCode: " + Integer.toHexString(a.hashCode()));
        out.println();

        out.println("**** After identityHashCode()");
        out.println(layout.toPrintable());
    }

结果

# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# WARNING | Compressed references base/shifts are guessed by the experiment!
# WARNING | Therefore, computed addresses are just guesses, and ARE NOT RELIABLE.
# WARNING | Make sure to attach Serviceability Agent to get the reliable addresses.
# 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]

**** Fresh object
com.example.sjjg.java.ObjectLayout$8A object internals:
 OFFSET  SIZE                                 TYPE DESCRIPTION                               VALUE
      0     4                                      (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4                                      (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                                      (object header)                           a3 63 03 20 (10100011 01100011 00000011 00100000) (537093027)
     12     4   com.example.sjjg.java.ObjectLayout ObjectLayout$8A.this$0                    (object)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

hashCode: 455b6df1

**** After identityHashCode()
com.example.sjjg.java.ObjectLayout$8A object internals:
 OFFSET  SIZE                                 TYPE DESCRIPTION                               VALUE
      0     4                                      (object header)                           01 f1 6d 5b (00000001 11110001 01101101 01011011) (1533931777)
      4     4                                      (object header)                           45 00 00 00 (01000101 00000000 00000000 00000000) (69)
      8     4                                      (object header)                           a3 63 03 20 (10100011 01100011 00000011 00100000) (537093027)
     12     4   com.example.sjjg.java.ObjectLayout ObjectLayout$8A.this$0                    (object)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

当调用对象的hashCode()或者System.identityHashCode(obj) 函数时,才生成hash值,保存在相应的hash位中。

  • 上述代码第9行,第1次打印对象头,这时并没有调用hashCode()函数,并没有生成相应的值,
  • 第11行调用了hashCode(),其值为:0x45456df1
  • 第14行再次打印对象布局时,发现在对象头中已经保存了对应的值。

4.5 锁信息示例

    /*
     * This is another dive into the mark word.
     *
     * This one is the example of thin (displaced) lock. The data
     * in mark word when lock is acquired is the reference to the
     * displaced object header, allocated on stack. Once we leave
     * the lock, the displaced header is discarded, and mark word
     * is reverted to the default value.
     *
     * This example relies on biased locking not biasing the object
     * at the first lock acquisition. Since JDKs up to 8 have biased
     * locking startup delay, this example works out of the box there.
     * On modern JDKs, starting with 9, this example should be run
     * with with -XX:-UseBiasedLocking.
     */
    @Test
    public void thin_locking(){
        class A { /* no fields */ }
        final A a = new A();
        ClassLayout layout = ClassLayout.parseInstance(a);

        out.println(VM.current().details());

        out.println("**** Fresh object");
        out.println(layout.toPrintable());

        synchronized (a) {
            out.println("**** With the lock");
            out.println(layout.toPrintable());
        }
        out.println("**** After the lock");
        out.println(layout.toPrintable());
    }

结果

# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# WARNING | Compressed references base/shifts are guessed by the experiment!
# WARNING | Therefore, computed addresses are just guesses, and ARE NOT RELIABLE.
# WARNING | Make sure to attach Serviceability Agent to get the reliable addresses.
# 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]

**** Fresh object
com.example.sjjg.java.ObjectLayout$10A object internals:
 OFFSET  SIZE                                 TYPE DESCRIPTION                               VALUE
      0     4                                      (object header)                           0d 00 00 00 (00001101 00000000 00000000 00000000) (13)
      4     4                                      (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                                      (object header)                           0a d6 02 20 (00001010 11010110 00000010 00100000) (537056778)
     12     4   com.example.sjjg.java.ObjectLayout ObjectLayout$10A.this$0                   (object)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

**** With the lock
com.example.sjjg.java.ObjectLayout$10A object internals:
 OFFSET  SIZE                                 TYPE DESCRIPTION                               VALUE
      0     4                                      (object header)                           0d 98 01 b0 (00001101 10011000 00000001 10110000) (-1342072819)
      4     4                                      (object header)                           ed 7f 00 00 (11101101 01111111 00000000 00000000) (32749)
      8     4                                      (object header)                           0a d6 02 20 (00001010 11010110 00000010 00100000) (537056778)
     12     4   com.example.sjjg.java.ObjectLayout ObjectLayout$10A.this$0                   (object)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

**** After the lock
com.example.sjjg.java.ObjectLayout$10A object internals:
 OFFSET  SIZE                                 TYPE DESCRIPTION                               VALUE
      0     4                                      (object header)                           0d 98 01 b0 (00001101 10011000 00000001 10110000) (-1342072819)
      4     4                                      (object header)                           ed 7f 00 00 (11101101 01111111 00000000 00000000) (32749)
      8     4                                      (object header)                           0a d6 02 20 (00001010 11010110 00000010 00100000) (537056778)
     12     4   com.example.sjjg.java.ObjectLayout ObjectLayout$10A.this$0                   (object)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

4.6 对象age信息

    volatile Object consumer;
    @Test
    public void gc_age(){
        Object instance = new Object();
        long lastAddr = VM.current().addressOf(instance);
        ClassLayout layout = ClassLayout.parseInstance(instance);

        for (int i = 0; i < 10_000; i++) {
            long currentAddr = VM.current().addressOf(instance);
            if (currentAddr != lastAddr) {
                System.out.println(layout.toPrintable());
            }

            for (int j = 0; j < 10_000; j++) {
                consumer = new Object();
            }

            lastAddr = currentAddr;
        }
    }

结果:

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           11 00 00 00 (00010001 00000000 00000000 00000000) (17)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           19 00 00 00 (00011001 00000000 00000000 00000000) (25)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           21 00 00 00 (00100001 00000000 00000000 00000000) (33)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           29 00 00 00 (00101001 00000000 00000000 00000000) (41)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           31 00 00 00 (00110001 00000000 00000000 00000000) (49)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           39 00 00 00 (00111001 00000000 00000000 00000000) (57)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           41 00 00 00 (01000001 00000000 00000000 00000000) (65)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           49 00 00 00 (01001001 00000000 00000000 00000000) (73)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           51 00 00 00 (01010001 00000000 00000000 00000000) (81)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           59 00 00 00 (01011001 00000000 00000000 00000000) (89)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           61 00 00 00 (01100001 00000000 00000000 00000000) (97)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 02 00 20 (00000000 00000010 00000000 00100000) (536871424)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

注意结果中age位中值的变化

    11 00 00 00 (00010001 00000000 00000000 00000000) (17)
                  ^^^^
    19 00 00 00 (00011001 00000000 00000000 00000000) (25)
                  ^^^^
    21 00 00 00 (00100001 00000000 00000000 00000000) (33)
                  ^^^^
    29 00 00 00 (00101001 00000000 00000000 00000000) (41)
                  ^^^^
    31 00 00 00 (00110001 00000000 00000000 00000000) (49)
                  ^^^^
    39 00 00 00 (00111001 00000000 00000000 00000000) (57)
                  ^^^^
    41 00 00 00 (01000001 00000000 00000000 00000000) (65)
                  ^^^^
    49 00 00 00 (01001001 00000000 00000000 00000000) (73)
                  ^^^^
    51 00 00 00 (01010001 00000000 00000000 00000000) (81)
                  ^^^^
    59 00 00 00 (01011001 00000000 00000000 00000000) (89)
                  ^^^^
    61 00 00 00 (01100001 00000000 00000000 00000000) (97)
                  ^^^^

5. class word 信息

5.1 作用

一个指针,指向本类元数据,它里面保存类的信息:类名、基类、修饰符等。在64位机器上如果可压缩,那么为32位

The klass word in the object header points to the internal type metadata for the object. This word can be 64 bits, or if compressed, 32 bits.

5.2 示例

    /*
     * This is the example to have insight into object headers.
     *
     * In HotSpot, object header consists of two parts: mark word,
     * and class word. We can clearly see the class word by analysing
     * two empty instances of two distinct classes. See the difference
     * in class word, that difference is the reference to class.
     */
    @Test  //10 ClassWord
    public void class_word(){
        class A { /* no fields */  }
        class B { /* no fields */  }
        out.println(VM.current().details());
        out.println(ClassLayout.parseInstance(new A()).toPrintable());
        out.println(ClassLayout.parseInstance(new A()).toPrintable());
        out.println(ClassLayout.parseInstance(new B()).toPrintable());
    }

结果:

# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# WARNING | Compressed references base/shifts are guessed by the experiment!
# WARNING | Therefore, computed addresses are just guesses, and ARE NOT RELIABLE.
# WARNING | Make sure to attach Serviceability Agent to get the reliable addresses.
# 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.example.sjjg.java.ObjectLayout$7A object internals:
 OFFSET  SIZE                                 TYPE DESCRIPTION                               VALUE
      0     4                                      (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4                                      (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                                      (object header)                           15 63 03 20 (00010101 01100011 00000011 00100000) (537092885)
     12     4   com.example.sjjg.java.ObjectLayout ObjectLayout$7A.this$0                    (object)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

com.example.sjjg.java.ObjectLayout$7A object internals:
 OFFSET  SIZE                                 TYPE DESCRIPTION                               VALUE
      0     4                                      (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4                                      (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                                      (object header)                           15 63 03 20 (00010101 01100011 00000011 00100000) (537092885)
     12     4   com.example.sjjg.java.ObjectLayout ObjectLayout$7A.this$0                    (object)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

com.example.sjjg.java.ObjectLayout$5B object internals:
 OFFSET  SIZE                                 TYPE DESCRIPTION                               VALUE
      0     4                                      (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4                                      (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                                      (object header)                           90 65 03 20 (10010000 01100101 00000011 00100000) (537093520)
     12     4   com.example.sjjg.java.ObjectLayout ObjectLayout$5B.this$0                    (object)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

其中:

  • 代码中new了两个A类对象,一个B类对象。
  • 两个A对象指向相同的类元数据。
  • A与B指向不同的类元数据。

5.3 注意事项:klass word 将被移除的草案  

具体见:

https://openjdk.java.net/jeps/8198332

6.对象头中数组的长度

除了mark word 和 klass word 外,数组的对象头中还需要4个字节保存数组元素的个数。

    /*
     * The example for array length.
     *
     * Array length is not the part of array type, so VMs need another
     * slot in header to store the array length. This can be demonstrated
     * by this example.
     */
    @Test  //11
    public void array_length(){
        out.println(VM.current().details());
        for (int c = 0; c < 8; c++) {
            out.println("**** int[" + c + "]");
            out.println(ClassLayout.parseInstance(new int[c]).toPrintable());
        }
    }

结果

# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# WARNING | Compressed references base/shifts are guessed by the experiment!
# WARNING | Therefore, computed addresses are just guesses, and ARE NOT RELIABLE.
# WARNING | Make sure to attach Serviceability Agent to get the reliable addresses.
# 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]

**** int[0]
[I object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           82 01 00 20 (10000010 00000001 00000000 00100000) (536871298)
     12     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     0    int [I.<elements>                             N/A
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

**** int[1]
[I object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           82 01 00 20 (10000010 00000001 00000000 00100000) (536871298)
     12     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
     16     4    int [I.<elements>                             N/A
     20     4        (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

**** int[2]
[I object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           82 01 00 20 (10000010 00000001 00000000 00100000) (536871298)
     12     4        (object header)                           02 00 00 00 (00000010 00000000 00000000 00000000) (2)
     16     8    int [I.<elements>                             N/A
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

**** int[3]
[I object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           82 01 00 20 (10000010 00000001 00000000 00100000) (536871298)
     12     4        (object header)                           03 00 00 00 (00000011 00000000 00000000 00000000) (3)
     16    12    int [I.<elements>                             N/A
     28     4        (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

其中的 

    12     4        (object header)        00 00 00 00 (00000000 00000000 00000000 00000000) (0)
    12     4        (object header)        01 00 00 00 (00000001 00000000 00000000 00000000) (1)
    12     4        (object header)        02 00 00 00 (00000010 00000000 00000000 00000000) (2)
    12     4        (object header)        03 00 00 00 (00000011 00000000 00000000 00000000) (3)

就是4个数组的长度。 

 

 

posted @ 2015-06-12 23:12  f9q  阅读(423)  评论(0编辑  收藏  举报