java个对象头的mark word详情

Details about mark word of java object header

正在研究java对象头的构成

找到了一些文档和一些有趣的问题。

64位vm下,默认object head如下(因为UseCompressedOops默认开启)

|------------------------------------------------ ---------------------------------------------- ----------|--------------------|
|对象头(96 位)|状态 |
|------------------------------------------------ ------------------------------|---------------- ----------|--------------------|
|标记字(64 位) |类字(32 位)| |
|------------------------------------------------ ------------------------------|---------------- ----------|--------------------|
| unused:25 | identity_hashcode:31 | cms_free:1 | age:4 | biased_lock:1 | lock:2 | OOP 到元数据对象 |正常 |
|------------------------------------------------ ------------------------------|---------------- ----------|--------------------|
| thread:54 | epoch:2 | cms_free:1 | age:4 | biased_lock:1 | lock:2 | OOP 到元数据对象 |有偏见 |
|------------------------------------------------ ------------------------------|---------------- ----------|--------------------|
| ptr_to_lock_record | lock:2 | OOP 到元数据对象 |轻量级锁定 |
|------------------------------------------------ ------------------------------|---------------- ----------|--------------------|
| ptr_to_heavyweight_monitor | lock:2 | OOP 到元数据对象 |重量级锁定 |
|------------------------------------------------ ------------------------------|---------------- ----------|--------------------|
| | lock:2 | OOP 到元数据对象 |标记为 GC |
|------------------------------------------------ ------------------------------|---------------- ----------|--------------------|

如果UseCompressedOops关闭,对象头是这样的:

|------------------------------------------------ ---------------------------------------------- ----------|--------------------|
|对象头(128 位)|状态 |
|------------------------------------------------ --------------------------|-------------------- ----------|--------------------|
|标记字(64 位) |类字(64 位)| |
|------------------------------------------------ --------------------------|-------------------- ----------|--------------------|
| unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:1 | lock:2 | OOP 到元数据对象 |正常 |
|------------------------------------------------ --------------------------|-------------------- ----------|--------------------|
| thread:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | lock:2 | OOP 到元数据对象 |有偏见 |
|------------------------------------------------ --------------------------|-------------------- ----------|--------------------|
| ptr_to_lock_record:62 | lock:2 | OOP 到元数据对象 |轻量级锁定 |
|------------------------------------------------ --------------------------|-------------------- ----------|--------------------|
| ptr_to_heavyweight_monitor:62 | lock:2 | OOP 到元数据对象 |重量级锁定 |
|------------------------------------------------ --------------------------|-------------------- ----------|--------------------|
| | lock:2 | OOP 到元数据对象 |标记为 GC |
|------------------------------------------------ --------------------------|-------------------- ----------|--------------------|

关于markword的C++源码在这里: http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/oops/markOop.hpp

我有一个问题:

为什么启用指针压缩后一位从未使用变为cms_free?

我怀疑它与 CMS 垃圾收集器有关,但我不知道它的作用。

而我查看对象头的相关信息时(包括上面两张表),大部分都提到了markOop.hpp文件,而只引入了Lock 有关的。忽略cms_free, narrowOop, promo_bits, PromotedObjec markOop.hpp 那个重要的信息,所以对这部分很好奇

当使用平面指针时,由于对齐,地址指针的最低位始终为零,并且允许通过将 1 写入这些位来标记特殊状态。因此,当 CMS 想要表示特定的内存块(不再是对象)而是空闲内存时,它会将 klass 指针的最低位设置为 1。

但压缩指针功能利用相同的 属性 通过右移地址并不留下未使用的低位通过 32 位指针寻址更多内存。因此,CMS 必须将此位存储在其他地方,即有问题的 cms_free_bit

来源:concurrentMarkSweepGeneration.cpp

// A block of storage in the CMS generation is always in
// one of three states. A free block (FREE), an allocated
// object (OBJECT) whose size() method reports the correct size,
// and an intermediate state (TRANSIENT) in which its size cannot
// be accurately determined.
// STATE IDENTIFICATION:   (32 bit and 64 bit w/o COOPS)
// -----------------------------------------------------
// FREE:      klass_word & 1 == 1; mark_word holds block size
//
// OBJECT:    klass_word installed; klass_word != 0 && klass_word & 1 == 0;
//            obj->size() computes correct size
//
// TRANSIENT: klass_word == 0; size is indeterminate until we become an OBJECT
//
// STATE IDENTIFICATION: (64 bit+COOPS)
// ------------------------------------
// FREE:      mark_word & CMS_FREE_BIT == 1; mark_word & ~CMS_FREE_BIT gives block_size
//
// OBJECT:    klass_word installed; klass_word != 0;
//            obj->size() computes correct size
//
// TRANSIENT: klass_word == 0; size is indeterminate until we become an OBJECT