Hotspot中Java对象头markOop的3位promo_bits作用是什么?
Hotspot markOop结构说明
Hotspot源码中对象头的markword被定义为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)
两种表述的差异说明
你看到的两种markOop结构表述不存在冲突,对应完全不同的运行场景:
- 源码中CMS promoted object是GC晋升过程中的临时状态,仅在GC执行的极短时间窗口内存在,此时对象不处于正常业务运行的加锁流程中
- 锁升级相关的结构是对象处于正常运行、被加锁时的状态,低2位锁标记对应轻量级/重量级锁的编码,和GC晋升临时状态的低3位编码完全不同,二者不会同时出现
3位promo_bits的作用
当对象使用ParNew+CMS的GC组合,从新生代晋升到老年代时,原新生代对象的markOop会被临时修改为CMS promoted object结构,3位promo_bits的作用分别为:
- 第一位是晋升完成标记:标识该对象已经完成到老年代的复制,GC线程扫描到该标记时,会直接通过
PromotedObject*指针访问新地址的对象,避免重复复制 - 第二位是并行幂等校验位:多GC线程并行执行晋升逻辑时,用来标记该对象已经被处理,避免多个线程重复复制同一个对象导致的内存错误
- 第三位是GC批次校验位:记录该对象对应的GC执行批次,防止跨GC周期的无效指针访问,尤其在CMS并发标记阶段触发增量GC时做合法性校验
内容的提问来源于stack exchange,提问作者Wiggin
相关产品推荐
相关产品推荐

