Mark Word 是 JVM 锁优化的核心字段,64 位下低 3 位标识锁状态:001 无锁、000 轻量级锁、010 重量级锁、101 偏向锁;状态变更通过 CAS 原子替换整个 Mark Word 实现。

Java 对象头中的 Mark Word 是 JVM 实现轻量级锁、偏向锁等优化机制的核心字段,它在 32 位和 64 位虚拟机中长度不同(分别为 32 位和 64 位),但都通过复用同一段内存、按位域(bit field)方式动态编码不同状态信息。锁状态不是独立字段,而是嵌入在 Mark Word 的低几位中,配合其他位共同表达当前锁的类型和归属。
Mark Word 中锁状态位的布局与含义
以 HotSpot 64 位 JVM(开启指针压缩,默认使用 32 位 Klass Pointer)为例,Mark Word 共 64 位,其中低 3 位(bit 0–2)固定为 lock state bits,直接标识锁的当前状态:
- 001:无锁状态(Normal/Unlocked)——此时 Mark Word 存储对象哈希码、分代年龄、是否为偏向锁等信息(具体分布取决于是否启用偏向锁)
- 000:轻量级锁(Lightweight Locked)——Mark Word 存储指向栈中 Lock Record 的指针(即 Displaced Mark Word 的地址)
- 010:重量级锁(Heavyweight Locked / Monitor Locked)——Mark Word 存储指向 ObjectMonitor 对象的指针
- 101:偏向锁(Biased Locked)——Mark Word 存储偏向线程 ID、偏向时间戳、分代年龄等复合信息(需结合高位判断)
注意:011 和 111 等组合在当前主流 JDK(如 JDK 8–17)中未被使用;JDK 15+ 默认关闭偏向锁,因此 101 状态实际很少出现。
锁升级过程中 Mark Word 的动态更新过程
锁状态变化本质是 Mark Word 内容的原子性替换(通常用 CAS 操作完成),不是简单修改某几个 bit:
立即学习“Java免费学习笔记(深入)”;
- 从无锁(001)到偏向锁(101):JVM 在第一次调用 synchronized 且满足条件时,尝试用 CAS 将线程 ID、epoch、age 等写入 Mark Word,并将锁状态位设为 101
- 从偏向锁撤销为无锁(001):发生竞争时,持有偏向锁的线程需将 Mark Word 恢复为原始无锁状态(可能含 hashcode 或 age),并设置为 001
- 从无锁/偏向锁升级为轻量级锁:线程在栈中创建 Lock Record,将对象原 Mark Word(Displaced Mark Word)存入其中,再用 CAS 将 Mark Word 替换为该 Lock Record 地址,并设状态为 000
- 从轻量级锁膨胀为重量级锁:当自旋失败,JVM 分配 ObjectMonitor,将 Mark Word 改为指向该 monitor 的指针,并设状态为 010
如何验证 Mark Word 的实际值
可通过 JOL(Java Object Layout) 工具查看对象内存布局及 Mark Word 内容:
- 添加依赖:
org.openjdk.jol:jol-core - 代码示例:
System.out.println(ClassLayout.parseInstance(obj).toPrintable()); - 输出中 “mark:” 行即为 Mark Word 十六进制值,结合 JVM 参数(如
-XX:+UseBiasedLocking、-XX:-UseBiasedLocking)可观察不同锁状态下的变化 - 注意:必须在对象未被 GC 回收、且未被 JIT 过度优化(如逃逸分析消除锁)的前提下测试
关键细节与常见误区
Mark Word 的锁状态记录高度依赖 JVM 实现和运行时条件:
- 32 位 JVM 下 Mark Word 为 32 位,锁状态位仍占低 3 位,但其余字段布局有差异(如无指针压缩时 Klass Pointer 占 32 位)
- 对象未被锁定时,Mark Word 可能存储 identity hashcode —— 若调用过
System.identityHashCode(),后续无法进入偏向锁状态 - GC 过程中(如 CMS、ZGC 的并发标记阶段),部分 GC 算法会临时修改 Mark Word 高位用于标记,但这与锁状态无关,属于 GC 专用位
- 锁状态位只是“提示”,真正决定行为的是 JVM 根据这些位 + 当前上下文(如线程栈、monitor 状态)所执行的逻辑


















