Mark Word 是 JVM 实现锁机制的核心动态结构,通过复用比特位记录锁状态、线程ID、GC年龄等信息;其布局随锁状态(无锁/偏向/轻量级/重量级/GC)变化,不同状态下各字段语义互斥。

Java 对象头中的 Mark Word 是 JVM 实现轻量级锁、偏向锁、重量级锁等同步机制的核心数据结构,它在对象内存布局中占据固定位置(通常 8 字节或 16 字节,取决于平台和 JVM 参数),通过复用同一段二进制位来动态记录锁状态、线程 ID、GC 分代年龄、哈希码等信息。
Mark Word 的结构随锁状态动态变化
Mark Word 不是静态存储锁状态的“字段”,而是根据当前锁所处阶段,重新解释其内部比特位的含义。JVM 通过对象监视器(ObjectMonitor)与 Mark Word 协同工作,在加锁/解锁过程中修改 Mark Word 的内容,并依据特定标志位识别当前锁类型。
- 未锁定状态(无锁):存储对象哈希码(如果已计算)、GC 分代年龄、是否为偏向锁标记(biased_lock=0)
- 偏向锁状态:biased_lock=1,且 epoch、thread ID、age 等字段有效;若线程重入,不修改 Mark Word
- 轻量级锁状态:biased_lock=0,lock=01;Mark Word 被替换为指向当前线程栈中 Lock Record 的指针(Displaced Mark Word 存于该记录中)
- 重量级锁状态:biased_lock=0,lock=10;Mark Word 存储指向 ObjectMonitor 的指针(monitor pointer)
- GC 标记状态(如 CMS 或 G1 并发标记阶段):lock=11,mark=00/01/10 等,表示对象处于特殊 GC 状态,此时不能加锁
锁升级过程中的 Mark Word 修改时机与方式
锁状态变化不是自动触发的,而是在 synchronized 进入/退出、或发生竞争时由 JVM 运行时检测并执行相应操作:
- 偏向锁获取:首次进入 synchronized 块时,JVM 检查对象头是否允许偏向(未被锁定 + 偏向启用 + 未批量撤销)、线程 ID 是否匹配;若满足,则 CAS 将当前线程 ID 写入 Mark Word,并设置 biased_lock=1、age 等
- 偏向锁撤销:当另一线程尝试获取已偏向对象的锁,会触发偏向撤销 —— JVM 暂停持有线程(安全点),将 Mark Word 恢复为未锁定状态(可能带原始哈希码),再升级为轻量级锁
- 轻量级锁加锁:线程在栈帧中创建 Lock Record,将对象当前 Mark Word 复制到 record 的 Displaced Mark Word 字段;再 CAS 将 Mark Word 替换为指向该 record 的指针;成功则加锁完成
- 锁膨胀(升级为重量级锁):轻量级锁下发生多线程自旋失败(超过阈值,默认 10 次),JVM 将 Mark Word 改为指向 ObjectMonitor 的指针,同时将所有等待线程挂起,交由操作系统互斥量管理
关键细节:Mark Word 是“复用”而非“叠加”存储
同一个 Mark Word 在不同锁状态下,各比特位代表完全不同的语义,不存在“同时存线程 ID 和 monitor 地址”的情况。例如:
立即学习“Java免费学习笔记(深入)”;
- 偏向锁时:bit 0–1 = 01(锁标志位),bit 2 = 1(biased_lock),高位存 thread ID
- 轻量级锁时:bit 0–1 = 00(lock=00 表示轻量级锁),高位存栈中 Lock Record 地址
- 重量级锁时:bit 0–1 = 10(lock=10),高位存 ObjectMonitor* 地址
- 注意:JDK 10+ 默认关闭偏向锁(-XX:+UseBiasedLocking=false),且部分 HotSpot 版本已移除偏向锁逻辑;实际行为需结合具体 JDK 版本和启动参数确认
如何观察 Mark Word 变化?
可通过 JOL(Java Object Layout)工具打印对象头布局,配合调试或延迟触发锁操作来对比:
- 添加依赖:<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.17</version></dependency>
- 代码示例:
System.out.println(ClassLayout.parseInstance(obj).toPrintable()); - 配合 -XX:+PrintGCDetails、-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly(需 hsdis)可进一步分析底层指令,但需注意 Mark Word 是瞬态的,打印时刻可能已变更


















