OpenJDK怎么在字节码层面实现synchronized

风静酱_8682

风静酱_8682

2026-10-26

623人浏览

原创

synchronized代码块通过monitorenter和monitorexit指令实现,编译器自动插入并确保配对;同步方法则依赖ACC_SYNCHRONIZED标志,由JVM隐式处理锁逻辑。

openjdk怎么在字节码层面实现synchronized

monitorenter 和 monitorexit 指令是核心

synchronized 的字节码实现不依赖函数调用,而是由 JVM 直接插入 monitorenter 与 monitorexit 指令。这两条指令控制 Monitor 的获取与释放,不是 Java 方法,无法被重写或拦截。

编译器(如 javac)在遇到 synchronized 代码块时,会在块入口插入一条 monitorenter,在所有可能的出口(正常结束、异常跳转)插入对应数量的 monitorexit。JVM 运行时据此执行锁逻辑。

  • 每个 monitorenter 必须配对至少一个 monitorexit,否则校验失败,类加载会抛出 VerifyError
  • 同步方法不显式生成这两条指令,而是通过方法标志位 ACC_SYNCHRONIZED 标记,JVM 在调用该方法前自动执行等效的 monitorenter,返回前执行 monitorexit
  • 异常出口的 monitorexit 不靠手动编写,而是由编译器根据异常表(exception table)自动生成,确保不会漏解锁

同步代码块 vs 同步方法的字节码差异

两者语义一致,但字节码表现不同,直接影响你用 jclasslib 或 javap -v 查看时的观察结果:

  • synchronized(obj) { ... }:你会在字节码中明确看到 monitorenter 和 monitorexit 指令,操作数栈顶必须是锁对象引用(即 obj)
  • public synchronized void m() { ... }:方法属性里有 ACC_SYNCHRONIZED 标志,字节码中**看不到**任何 lock 相关指令——锁行为完全由 JVM 调用机制隐式完成
  • 静态同步方法同样走 ACC_SYNCHRONIZED,但锁对象是 Demo.class,不是 this;这点在字节码里也完全不体现,只靠方法签名和修饰符推断

为什么不能靠字节码判断“锁的是谁”

字节码本身不记录锁对象的身份信息,只记录“如何取锁”。真正决定锁对象的是 Java 源码上下文,而非指令操作数:

  • monitorenter 指令本身不携带“this”或“Demo.class”的硬编码,它只是弹出栈顶引用并尝试对该对象加锁
  • 所以你在 javap 输出里看到 monitorenter,但不知道它锁的是 this、lock 还是 getClass(),必须回溯到源码中那行 synchronized(...) 的括号内容
  • 同理,ACC_SYNCHRONIZED 标志不区分实例/静态——它是方法级标记,锁对象类型(实例 or Class)由方法是否为 static 决定,而这个信息在常量池的 Methodref 或方法描述符中,不在标志位里

容易忽略的细节:异常路径下的 monitorexit 是怎么插进去的

很多人以为只要写个 try-finally 就能模拟 synchronized,但 JVM 的异常处理机制比手写更严密:

  • 编译器为每个 synchronized 块生成的异常表(exception table)会覆盖所有可能抛出异常的字节码范围,并将控制流导向一个专门的 monitorexit 序列
  • 哪怕方法里用了 return、break、continue 或未捕获的 RuntimeException,JVM 都能保证对应 monitorexit 执行,这是字节码验证器强制保障的
  • 手写 try-finally + Lock.lock()/unlock() 时,如果 lock() 抛异常,unlock() 根本不会执行——而 monitorenter 失败时根本不会进入同步块,也就没有 monitorexit 可执行,不存在“加锁失败却要解锁”的问题

真正难的不是看懂 monitorenter,而是理解它背后绑定的 Monitor 生命周期、对象头 Mark Word 的状态切换,以及这些如何被 JIT 编译器进一步优化。字节码只是起点,不是终点。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

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

2023.06.15

11257

6

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

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

2023.07.05

8362

9

java自学难吗
java自学难吗

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

2023.07.31

7212

8

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

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

2023.08.01

1204

3

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

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

2023.08.02

968

3

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

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

2023.08.02

1456

5

java有什么用
java有什么用

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

2023.08.02

2969

5

java在线网站
java在线网站

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

2023.08.03

20231

3

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

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

2023.08.03

1295

8

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
OpenJDK项目Wiki
OpenJDK项目Wiki

共0课时 | 0人学习

OpenJDK构建指南
OpenJDK构建指南

共0课时 | 0人学习

OpenJDK官网文档
OpenJDK官网文档

共0课时 | 0人学习