Mark Word是JVM对象头中动态复用的8字节关键字段,存储哈希码、锁状态、GC年龄等信息;哈希码延迟计算并受锁状态影响;锁状态含无锁、偏向、轻量级、重量级及GC标记五种编码;分代年龄与锁位存在竞争,重量级锁会覆盖age;可通过JOL工具验证。

对象头中的 Mark Word 是 JVM 对象内存布局中非常关键的一部分,它在 64 位 HotSpot 虚拟机中通常占 8 字节(未开启指针压缩时),用于紧凑存储多个动态信息:对象哈希码、锁状态、GC 分代年龄、偏向线程 ID 等。这些信息并非同时存在,而是通过位域复用,依据对象当前状态动态解释。
哈希码的延迟计算与存储
Object.hashCode() 返回的哈希码默认由 JVM 生成,并非对象创建时立即计算。首次调用时,JVM 会基于某种随机或时间相关的算法生成一个 31 位整数,写入 Mark Word 的低 31 位(高 1 位用于标识是否已设置哈希)。若对象已加锁(如轻量级锁、重量级锁),哈希码会被移出 Mark Word,暂存于对应锁记录或对象监视器中,解锁后不再恢复——这意味着加锁后调用 hashCode() 可能触发锁膨胀并迁移哈希值。
锁状态的五种编码形式
Mark Word 利用最低 2–3 位表示锁标志位,配合高位组合表达不同锁状态:
- 无锁状态:最后 2 位为 01,高位存哈希码或分代年龄
- 偏向锁:最后 2 位为 01,第 3 位为 1,高位存偏向线程 ID 和 epoch
- 轻量级锁:最后 2 位为 00,高位存指向栈中锁记录的指针
- 重量级锁:最后 2 位为 10,高位存指向 ObjectMonitor 的指针
- GC 标志(如 CMS/ G1 的 mark word 复用):最后 2 位为 11,表示该对象正在被 GC 标记或需特殊处理
GC 分代年龄与锁状态的位域竞争
在未启用偏向锁(-XX:-UseBiasedLocking)或偏向锁关闭后,Mark Word 中原本存放偏向线程 ID 的 54 位可复用于存储 分代年龄(age)。此时 age 占 4 位(最大 15),配合锁标志位共同编码。例如:对象每经历一次 Minor GC 且存活,age 加 1;当 age ≥ 阈值(默认 15,可通过 -XX:MaxTenuringThreshold 设置),对象晋升至老年代。注意:一旦对象进入重量级锁状态,age 信息即被覆盖,GC 不再依赖 Mark Word 中的 age 字段做晋升决策,而是通过其他机制(如 TLAB 分配位置、卡表标记等)跟踪。
实际调试与验证建议
可通过 JOL(Java Object Layout)工具查看对象头布局:
- 运行
new Object()后打印其对象头,观察初始 Mark Word 值(通常含随机哈希或全 0) - 调用
System.identityHashCode()后再次查看,确认哈希位是否写入 - 在同步块中执行同一对象,观察 Mark Word 末位变化(00 / 10)及高位指针变化
- 配合 -XX:+PrintGCDetails 和 -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly(需 hsdis)分析锁升级与 GC 交互细节

















