如何通过 JVM 对象头 Mark Word 的动态位偏移理解重量级锁下的 ObjectMonitor 关联

雨明姑娘_4411

雨明姑娘_4411

2026-04-25

511人浏览

原创

重量级锁触发后mark word末3位为010仅是入口信号,真正标志是其余61位构成可解析的objectmonitor*地址;jol显示0x0000001000000000时末3位实为000,说明未膨胀,需确保真实线程竞争且禁用偏向锁。

如何通过 jvm 对象头 mark word 的动态位偏移理解重量级锁下的 objectmonitor 关联

重量级锁触发后 Mark Word 末 3 位变成 010,但真正关键的是它存的不是“锁状态”,而是 ObjectMonitor* 地址

很多人以为看到 010 就等于“锁已膨胀”,其实这只是入口信号。真正要确认是否进入重量级锁,得看这 8 字节(64 位)里除末 3 位外的其余位是否构成一个合法的内存地址——而且这个地址必须能被 HotSpot 解析为 ObjectMonitor 实例。

常见错误现象:JOL 打印出的十六进制值末三位是 010,但高位全是 0(比如 0x0000000000000010),这说明锁还没真正膨胀,只是刚尝试升级、尚未完成 Monitor 分配;或者 JVM 启用了 -XX:+UseBiasedLocking 但未禁用,导致偏向锁未及时撤销,阻塞了后续升级路径。

  • 必须确保测试中至少有两个线程对同一对象执行 synchronized,且存在真实竞争(例如加 Thread.sleep(1) 或循环等待)
  • 避免 JIT 编译优化掉同步块:用 volatile 引用对象、放入 List、或在同步块内外都调用 System.out
  • 64 位 JVM 默认开启指针压缩(-XX:+UseCompressedOops),此时 ObjectMonitor* 是 32 位压缩地址,需左移 3 位再还原为真实地址(JOL 不自动做这步,得手动处理)

用 ClassLayout.parseInstance(obj).toPrintable() 查到的十六进制值,怎么拆解出 Monitor 地址

JOL 默认只输出对象头的原始字节布局,不解释语义。比如打印出:

OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
    0     4        (object header)                           0x00000000
    4     4        (object header)                           0x00000010

这是 8 字节合并后的结果(小端序),实际应拼为 0x0000001000000000(注意高低位顺序)。取低 3 位得 000?不对——要按 HotSpot 源码约定,**从最低位开始数:bit0–bit2 是 lock bits**,所以 0x0000001000000000 的二进制末尾是 000?再检查:十六进制 00 对应二进制 00000000,末三位确实是 000。说明当前还不是重量级锁——你可能漏掉了竞争条件。

Publish Passwords
Publish Passwords

本地凭据保险库,集成操作系统密钥链,支持加密存储与会话级访问控制。

下载
  • 正确做法:把整个 8 字节转成 64 位二进制字符串,截取 substring(0, 61)(去掉末 3 位 lock bits),再转回 long,就是 Monitor 指针值(压缩地址需
  • 验证地址有效性:用 jhsdb jmap --pid <pid> --binaryheap</pid> 导出堆快照,搜索该地址是否落在 ObjectMonitor 实例范围内(需配合 hsdis 或调试版 JVM)
  • 若地址值极小(如 0x10、0x20)或为全 0,基本可判定 Monitor 尚未分配,锁仍卡在轻量级锁自旋阶段

ObjectMonitor 地址写入 Mark Word 的时机,比你想象中更“懒”

HotSpot 并不会在第一次检测到竞争时就立即分配 ObjectMonitor。它会先尝试自旋(spin)、再尝试轻量级锁重试,只有当自旋失败 + 多次重试失败 + 确认有线程进入 EntryList 阻塞时,才调用 ObjectSynchronizer::inflate() 分配 Monitor 并更新 Mark Word。

  • 这意味着:即使两个线程同时执行 synchronized(obj),只要其中一个快速退出,另一个可能全程走轻量级锁路径,Mark Word 始终保持 000(轻量级锁标志位)
  • 用 jstack -l <pid></pid> 查看线程栈,若看到 - waiting to lock ,且该地址与 JOL 打印出的高位一致,才是 Monitor 已生效的铁证
  • 禁用自旋(-XX:PreBlockSpin=0)和禁用偏向锁(-XX:-UseBiasedLocking)能加速膨胀过程,方便观察

为什么有时候 010 出现了,但 ObjectMonitor._owner 却是 null

这是最易被忽略的细节:Monitor 分配完成 ≠ 锁已被持有。ObjectMonitor 是一个独立结构体,包含 _owner、_EntryList、_WaitSet 等字段。Mark Word 写入 Monitor 地址,只是建立了对象与 Monitor 的关联;真正设置 _owner 是在 ObjectMonitor::enter() 中通过 CAS 完成的。

所以你会看到一种中间态:Mark Word 已含有效 Monitor 地址(末三位 010),但 _owner == NULL——说明 Monitor 已就位,但还没有线程成功获取它。此时新来的线程会直接进入 _EntryList 阻塞,而不是再去 inflate。

  • 用 jhsdb clhsdb 连上运行中的 JVM,执行 inspect <monitor_addr></monitor_addr> 可查看 _owner 字段值
  • 如果 _owner 是非空但指向一个已销毁线程(如 thread_id = 0),说明发生过锁竞争但 Owner 已退出,Monitor 处于“待回收”状态(HotSpot 会延迟回收以减少开销)
  • 这种分离设计正是锁升级机制的弹性所在:Monitor 分配与锁获取解耦,避免每次竞争都触发内存分配

真实场景下,Mark Word 和 ObjectMonitor 的联动不是原子的一锤定音,而是一组带状态跃迁的协作步骤。想靠一次 JOL 输出就断言“已重量级锁”,大概率会误判——重点不是末三位是不是 010,而是那个地址背后有没有活着的 ObjectMonitor,以及它里面有没有正在起作用的 _owner。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

10557

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

7682

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6692

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1144

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

928

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1376

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2769

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20091

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1235

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.7万人学习