方法签名中有或没有 synchronized 关键字的方法的相同字节码
Same bytecode for method with or without synchronized keyword in method signature
对于以下 2 类 得到了相同的 Java 字节码。
java版本:
java version "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, mixed mode)
javac 和 javap 版本:
1.8.0_181
我的疑惑是
带有 synchronized 关键字的方法不应该有不同的字节码,正如我们在 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
}
我只是想增加对javaw.r.t的理解。字节码。
如果我的方法有误或问题太琐碎,请通过评论告诉我。
除以下内容外,我们欢迎任何与文档相关的参考:
https://en.wikipedia.org/wiki/Java_bytecode
https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
方法上的 synchronized
修饰符被编译到方法 header 中的 ACC_SYNCHRONIZED 标志中。不影响生成的字节码指令;进入和退出监视器的代码是 JVM 在看到该标志时隐式添加的。
有关方法 header 中标志的完整列表及其含义,请参阅 JVM specification。
对于以下 2 类 得到了相同的 Java 字节码。
java版本:
java version "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, mixed mode)
javac 和 javap 版本:
1.8.0_181
我的疑惑是
带有 synchronized 关键字的方法不应该有不同的字节码,正如我们在 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
}
我只是想增加对javaw.r.t的理解。字节码。
如果我的方法有误或问题太琐碎,请通过评论告诉我。
除以下内容外,我们欢迎任何与文档相关的参考:
https://en.wikipedia.org/wiki/Java_bytecode
https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
方法上的 synchronized
修饰符被编译到方法 header 中的 ACC_SYNCHRONIZED 标志中。不影响生成的字节码指令;进入和退出监视器的代码是 JVM 在看到该标志时隐式添加的。
有关方法 header 中标志的完整列表及其含义,请参阅 JVM specification。