objectmonitor 是 hotspot jvm 用 c++ 实现的锁核心类,位于 native heap,懒加载、不可继承、java 层不可见;其关键字段包括 _owner、_entrylist、_waitset、_recursions 等,synchronized 底层通过 monitorenter/monitorexit 调用 enter()/exit() 方法驱动锁竞争与线程状态切换。

synchronized 的底层不是 Java 代码写的,而是 HotSpot JVM 用 C++ 实现的 ObjectMonitor 类。它不暴露给开发者,也不在 Java 堆里,而是在 JVM 的本地内存(native heap)中动态分配。
ObjectMonitor 是什么
它是 HotSpot 源码中定义的一个 C++ 类(位于 src/share/vm/runtime/objectMonitor.hpp),每个 Java 对象在发生真实锁竞争或调用 wait/notify 时,才会被“膨胀”并关联一个 ObjectMonitor 实例。
- 不是每个对象一创建就配一个 Monitor,而是懒加载:首次需要重量级锁时才初始化
- 它和 Java 对象本身解耦——对象头 Mark Word 中存的只是一个指向它的指针(升级后)
- 不能 new,不能继承,Java 层完全感知不到它的存在
核心字段都在 C++ 里定义
从 OpenJDK 11 源码看,ObjectMonitor 主要字段包括:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- _owner:void* 类型,存当前持有锁的线程指针,用 CAS 原子更新
- _EntryList:ObjectWaiter* 链表,挂等待获取锁的线程(BLOCKED 状态)
- _WaitSet:ObjectWaiter* 链表,挂调用 wait() 后释放锁并休眠的线程(WAITING 状态)
- _recursions:int 类型,记录重入次数,支持可重入
- _count:volatile int,统计锁竞争次数,用于锁优化决策
- _cxq:竞争队列(Contention Queue),配合 _EntryList 做快速入队
加锁动作本质是调用 C++ 成员函数
当你写 synchronized(obj),编译后生成 monitorenter 指令,JVM 执行时会调用 ObjectMonitor::enter();退出时调用 ObjectMonitor::exit()。
- enter() 先尝试轻量级路径(CAS 修改 Mark Word),失败再走重量级:把当前线程封装成 ObjectWaiter,插入 _EntryList,然后调用 pthread_cond_wait 进入内核态等待
- exit() 会检查 _WaitSet 是否有线程在等 notify,有则唤醒;否则从 _EntryList 挑一个线程唤醒让它重试抢锁
- 所有线程状态切换(BLOCKED/WAITING/TIMED_WAITING)都由这些 C++ 函数驱动
锁升级过程就是 Monitor 的“上线”时机
偏向锁和轻量级锁阶段,ObjectMonitor 并未启用:
- 偏向锁:只改 Mark Word 中的线程 ID 和偏向标志位,不碰 Monitor
- 轻量级锁:在栈上建 Lock Record,用 CAS 替换 Mark Word,仍绕过 Monitor
- 只有自旋失败、发生竞争或调用 wait/notify,才会触发 inflate(),真正创建并绑定 ObjectMonitor
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










