原书:《Java 并发编程的艺术第2版》 | 作者:方腾飞 魏鹏 程晓明 | 2023 年 9 月 | 机械工业出版社
1.3.1 volatile 和 synchronized 关键字 | 13 页
|
|
查看字节码 javap -c Synchronized.class
|
|
为什么有 2 个 monitorexit 指令? AI 提供
两个 monitorexit 指令确保了正常、异常路径的锁都能被释放
- 第一个 monitorexit(第 9 行)是在正常执行路径上退出同步代码块。
- 第二个 monitorexit(第 15 行)位于 Exception table 中,对应异常处理路径。当在同步代码块内抛出异常时,JVM会确保在异常处理完毕后仍然释放监视器(即执行 monitorexit),以保证同步资源的正确释放。
Monitor
使用 javap -v Synchronized.class
查看 ACC_SYNCHRONIZED
|
|
AI:对于同步方法,ACC_SYNCHRONIZED 标志使得 JVM 能够隐式地在方法调用前后执行 monitorenter 和 monitorexit 指令(这些指令不会出现在字节码中,而是由 JVM 自动插入)。 monitorexit 指令确保了即使方法执行过程中抛出异常,监视器也能得到释放,避免了死锁的发生。
在上面的 class 信息中,对于同步块的实现使用了 monitorenter
和 monitorexit
指令。
而同步方法则是依靠方法修饰符上的 ACC_SYNCHRONIZED 完成的。
两种方式的本质都是对一个对象的监视器(monitor)进行获取,获取过程是排他的。
同一时刻只能有一个线程获取到由 synchronized 保护的对象的监视器。
任意一个对象都拥有自己的监视器,当这个对象由同步块或者同步方法调用时,执行方法的线程必须先获取该对象的监视器,才能进入同步块或同步方法。
没有获取到监视器的线程会被阻塞在同步块和同步块方法的入口处,进入BLOCKED 状态。
javap 命令 AI 提供
javap
是 Java 虚拟机的一个工具,用于反编译 Java 类文件。它能够将 Java 字节码文件转换为 Java 源代码的伪代码表示,从而帮助开发者理解字节码的底层结构。
要使用 javap
,你需要首先确保它已经安装在你的系统中。在大多数 Java 开发环境中,javap
通常已经作为 Java 开发工具包(JDK)的一部分安装好了。
以下是 javap
的一些基本用法:
- 查看类的字节码信息:这个命令会输出指定类(
1
javap -verbose ClassName
ClassName
)的字节码信息,包括常量池、类访问标志、类索引、父类索引、接口索引等。 - 查看类的属性:这个命令会输出指定类(
1
javap -private ClassName
ClassName
)的私有成员变量和私有方法。 - 查看类的字节码指令:这个命令会输出指定类(
1
javap -c ClassName
ClassName
)的字节码指令,但不包括常量池和属性信息。 - 查看类的源代码:这个命令会输出指定类(
1
javap -s ClassName
ClassName
)的源代码的伪代码表示。 - 查看类的属性:这个命令会输出指定类(
1
javap -p ClassName
ClassName
)的私有成员变量和私有方法。 - 查看类的完整信息:这个命令会输出指定类(
1
javap -v ClassName
ClassName
)的详细信息,包括字节码指令、常量池、属性等。 例如,如果你想查看名为MyClass
的类的字节码信息,你可以使用以下命令:
|
|
请注意,使用 javap
工具反编译的代码只是字节码的伪代码表示,并不是真正的 Java 源代码。因此,反编译出来的代码可能与原始的 Java 源代码存在差异。此外,使用 javap
反编译可能会违反某些软件的许可协议,因此在使用之前应确保你有权反编译该软件。