java对象头标记词详细说明

stu*_*ent 5 c++ java jvm jvm-hotspot hotspot

我正在研究java对象头的组成。

发现了一些文档和一些有趣的问题。

64位vm下,默认对象头如下(因为UseCompressedOops默认是开启的)

|------------------------------------------------- -------------------------------------------------- -----------|--------------------|
| 对象头(96 位)| 状态 |
|------------------------------------------------- -------------------------------|------------------- -----------|--------------------|
| 标记字(64 位) | 类字(32 位) | |
|------------------------------------------------- -------------------------------|------------------- -----------|--------------------|
| 未使用:25 | identity_hashcode:31 | cms_free:1 | 年龄:4 | 偏向锁:1 | 锁:2 | OOP 到元数据对象 | 正常 |
|------------------------------------------------- -------------------------------|------------------- -----------|--------------------|
| 线程:54 | 时代:2 | cms_free:1 | 年龄:4 | 偏向锁:1 | 锁:2 | OOP 到元数据对象 | 有偏见 |
|------------------------------------------------- -------------------------------|------------------- -----------|--------------------|
| ptr_to_lock_record | 锁:2 | OOP 到元数据对象 | 轻量级锁定 |
|------------------------------------------------- -------------------------------|------------------- -----------|--------------------|
| ptr_to_heavyweight_monitor | 锁:2 | OOP 到元数据对象 | 重量级锁定 |
|------------------------------------------------- -------------------------------|------------------- -----------|--------------------|
| | 锁:2 | OOP 到元数据对象 | 标记为 GC |
|------------------------------------------------- -------------------------------|------------------- -----------|--------------------|

如果UseCompressedOops关闭,对象头长这个样子?

|------------------------------------------------- -------------------------------------------------- ---------|--------------------|
| 对象头(128 位)| 状态 |
|------------------------------------------------- -----------------------------|-------------------- ---------|--------------------|
| 标记字(64 位) | 类字(64 位) | |
|------------------------------------------------- -----------------------------|-------------------- ---------|--------------------|
| 未使用:25 | identity_hashcode:31 | 未使用:1 | 年龄:4 | 偏向锁:1 | 锁:2 | OOP 到元数据对象 | 正常 |
|------------------------------------------------- -----------------------------|-------------------- ---------|--------------------|
| 线程:54 | 时代:2 | 未使用:1 | 年龄:4 | 偏向锁:1 | 锁:2 | OOP 到元数据对象 | 有偏见 |
|------------------------------------------------- -----------------------------|-------------------- ---------|--------------------|
| ptr_to_lock_record:62 | 锁:2 | OOP 到元数据对象 | 轻量级锁定 |
|------------------------------------------------- -----------------------------|-------------------- ---------|--------------------|
| ptr_to_heavyweight_monitor:62 | 锁:2 | OOP 到元数据对象 | 重量级锁定 |
|------------------------------------------------- -----------------------------|-------------------- ---------|--------------------|
| | 锁: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相关的内容。忽略markOop.hpp那个重要信息中提到的cms_free、narrowOop、promo_bits、PromotedObjec ,所以我对这部分很好奇。

Hol*_*ger 5

使用平面指针时,地址指针的最低位由于对齐而始终为零,并允许通过将 1 写入这些位来标记特殊状态。因此,当 CMSklass想要表示特定内存块不是对象(不再)而是空闲内存时,它将指针的最低位设置为 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
Run Code Online (Sandbox Code Playgroud)