java - 方法签名中带或不带同步关键字的方法的相同字节码
问题描述
对于以下 2 个类,它们具有相同的 Java 字节码。
爪哇版:
java 版本“1.8.0_181” Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13,混合模式)
javac 和 javap 版本:
1.8.0_181
我的疑问是
不应该使用synchronized关键字的方法有不同的字节码,正如我们在同步块中看到的那样
monitorenter
,monitorexit
或者让我们假设我不应该混合同步块和同步方法JVM 如何以不同的方式处理这两种方法?
public class MySingleton1 { private MySingleton1() {} private static MySingleton1 ourInstance; public static MySingleton1 getInstance() { if (ourInstance == null) { ourInstance = new MySingleton1(); } return ourInstance; } }
和
public class MySingleton2 { private MySingleton2() {} private static MySingleton2 ourInstance; public static synchronized MySingleton2 getInstance() { if (ourInstance == null) { ourInstance = new MySingleton2(); } return ourInstance; } }
字节码如下:
$javac MySingleton1.java
$javap -c MySingleton1
$javac MySingleton2.java
$javap -c MySingleton2
各个文件的字节码:
Compiled from "MySingleton1.java"
public class MySingleton1 {
public static MySingleton1 getInstance();
descriptor: ()LMySingleton1;
Code:
0: getstatic #2 // Field ourInstance:LMySingleton1;
3: ifnonnull 16
6: new #3 // class MySingleton1
9: dup
10: invokespecial #4 // Method "<init>":()V
13: putstatic #2 // Field ourInstance:LMySingleton1;
16: getstatic #2 // Field ourInstance:LMySingleton1;
19: areturn
}
和
Compiled from "MySingleton2.java"
public class MySingleton2 {
public static synchronized MySingleton2 getInstance();
descriptor: ()LMySingleton2;
Code:
0: getstatic #2 // Field ourInstance:LMySingleton2;
3: ifnonnull 16
6: new #3 // class MySingleton2
9: dup
10: invokespecial #4 // Method "<init>":()V
13: putstatic #2 // Field ourInstance:LMySingleton2;
16: getstatic #2 // Field ourInstance:LMySingleton2;
19: areturn
}
我只是想增加我对 java wrt 字节码的理解。
如果我的方法错误或问题太琐碎,请让我知道作为评论。
任何与文档相关的参考都是非常受欢迎的,但以下内容除外:
https://en.wikipedia.org/wiki/Java_bytecode
https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
解决方案
方法上的synchronized
修饰符被编译到方法头中的 ACC_SYNCHRONIZED 标志中。它不影响生成的字节码指令;进入和退出监视器的代码由 JVM 在看到该标志时隐式添加。
有关方法标头中标志的完整列表及其含义,请参阅JVM 规范。
推荐阅读
- java - How do I make my gradle plugin value depend on whether or not I execute another task?
- javascript - 如何从存储过程中获取分区键范围?
- utf-8 - UniData / CentOS - 指南和修复文件导致语言组错误
- kerberos - Chrome-headless 不喜欢 kerberos 票
- azure - 使用 azure-sdk-for-python 将节点部署到 AKS 群集
- c# - .Net Core 2.1 似乎忽略了 modelBuilder.Entity
().HasData - mysql - 如何正确关闭 NodeJS 到 MySQL 的连接?
- python - 将 2 级 multiidex 系列重新组合为数据框,以便二级索引成为名称?
- android - 从免安装应用升级到完整应用的最佳实践
- python-3.x - Python3中的CSV文件比较算法