JVM中对象的由object header+object instance+padding组成,而object header又由mark word以及klass pointer组成,其中klass pointer和padding是非必需的,后面将会由详细的解释。

Mark word

在32位系统中占用4个byte,64位系统中占用8个byte,这里列出关键部分,详情请参考markOop

//  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)
//             size:32 ------------------------------------------>| (CMS free block)
//             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
//  64 bits:
//  --------
//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
//  size:64 ----------------------------------------------------->| (CMS free block)
//
//  unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)
//  JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)
//  narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
//  unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)

Klass pointer

上文有提到klass pointer并不是object header中必需的部分,原因在于JVM采用何种方式实现对实例的引用,引用方式主要由两种,一种是通过handler,另一种是direct pointer,Hotspot中采用后者,因此Hotspot中的klass pointer是必需的。《深入理解Java虚拟机》中$2.3.3中有详细介绍这两者的区别及优缺点。

Padding

字节填充部分同样也不是object header中必需的部分,Hotspot只规定类对象的内存起始地址必须是8bytes的整数倍,因此只有mark word+klass pointer+object instance的字节数不是8bytes的整数倍时才会有padding。

Example

这里我用了java.lang.Long作为测试类,工具位(JOL)[http://openjdk.java.net/projects/code-tools/jol/]。

*:Desktop *$ java -jar jol-cli-0.9-full.jar internals java.lang.Long
# 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]

Instantiated the sample instance via public java.lang.Long(long)

java.lang.Long 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)                           b9 25 00 f8 (10111001 00100101 00000000 11111000) (-134208071)
     12     4        (alignment/padding gap)                  
     16     8   long Long.value                                0
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

我本地的机器为64位系统,测试结果显示,java.lang.Long占用24bytes,object header占用12bytes,其中8bytes为mark word,4bytes为klass pointer(这里出现了指针压缩),padding为4bytes。