反编译方法
对 .class
文件进行反编译
-
javap -c ***.class
:-c
对代码进行反汇编 -
javap -v ***.class
:-v -verbose
输出附加信息(包括行号、本地变量表,反汇编等详细信息)
Synchronized 同步代码块
正常代码块
Java 源码
LockSyncDemo.java
public class LockSyncDemo {
Object object = new Object();
public void m1() {
synchronized (object) {
System.out.println("-----hello synchronized code block");
}
}
public static void main(String[] args) {
}
}
反编译源码
Terminal
leam@Leam-MacBook-Pro locks % javap -c ./LockSyncDemo.class
Compiled from "LockSyncDemo.java"
public class dev.matrixlab.juc.locks.LockSyncDemo {
java.lang.Object object;
public dev.matrixlab.juc.locks.LockSyncDemo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #2 // class java/lang/Object
8: dup
9: invokespecial #1 // Method java/lang/Object."<init>":()V
12: putfield #3 // Field object:Ljava/lang/Object;
15: return
public void m1();
Code:
0: aload_0
1: getfield #3 // Field object:Ljava/lang/Object;
4: dup
5: astore_1
6: monitorenter
7: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
10: ldc #5 // String -----hello synchronized code block
12: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
15: aload_1
16: monitorexit
17: goto 25
20: astore_2
21: aload_1
22: monitorexit
23: aload_2
24: athrow
25: return
Exception table:
from to target type
7 17 20 any
20 23 20 any
public static void main(java.lang.String[]);
Code:
0: return
}
总结
Java
实现使用的是monitorenter
和monitorexit
指令- 32 行(m1() 方法的 code 22 行)
monitorexit
指令释放锁是防止同步代码块中异常后能正常释放锁 34行(m1() 方法的 code 24 行)athrow
指令。
异常代码块
java 源码
LockSyncDemo.java
public class LockSyncDemo {
Object object = new Object();
public void m1() {
synchronized (object) {
System.out.println("-----hello synchronized code block");
throw new RuntimeException("-----exp");
}
}
public static void main(String[] args) {
}
}
反编译源码
Terminal
leam@Leam-MacBook-Pro locks % javap -c ./LockSyncDemo.class
Compiled from "LockSyncDemo.java"
public class dev.matrixlab.juc.locks.LockSyncDemo {
java.lang.Object object;
public dev.matrixlab.juc.locks.LockSyncDemo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #2 // class java/lang/Object
8: dup
9: invokespecial #1 // Method java/lang/Object."<init>":()V
12: putfield #3 // Field object:Ljava/lang/Object;
15: return
public void m1();
Code:
0: aload_0
1: getfield #3 // Field object:Ljava/lang/Object;
4: dup
5: astore_1
6: monitorenter
7: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
10: ldc #5 // String -----hello synchronized code block
12: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
15: new #7 // class java/lang/RuntimeException
18: dup
19: ldc #8 // String -----exp
21: invokespecial #9 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
24: athrow
25: astore_2
26: aload_1
27: monitorexit
28: aload_2
29: athrow
Exception table:
from to target type
7 28 25 any
public static void main(java.lang.String[]);
Code:
0: return
}
总结
只有一个 monitorexit
指令,但是出现两个 athrow
指令。
Synchronized 普通同步方法
Java 源码
LockSyncDemo.java
public class LockSyncDemo {
Object object = new Object();
public synchronized void m2() {
System.out.println("-----hello synchronized method-----");
}
public static void main(String[] args) {
}
}
反编译源码
Terminal
leam@Leam-MacBook-Pro locks % javap -v ./LockSyncDemo.class
Classfile /xxxxx/juc/target/classes/dev/matrixlab/juc/locks/LockSyncDemo.class
Last modified Jan 23, 2024; size 766 bytes
SHA-256 checksum b90ba9cb95fc7391329f44b636c9f4243ab9865fa05308db31ac8806939dbb57
Compiled from "LockSyncDemo.java"
public class dev.matrixlab.juc.locks.LockSyncDemo
minor version: 0
major version: 52
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #7 // dev/matrixlab/juc/locks/LockSyncDemo
super_class: #2 // java/lang/Object
interfaces: 0, fields: 1, methods: 3, attributes: 1
Constant pool:
#1 = Methodref #2.#25 // java/lang/Object."<init>":()V
#2 = Class #26 // java/lang/Object
#3 = Fieldref #7.#27 // dev/matrixlab/juc/locks/LockSyncDemo.object:Ljava/lang/Object;
#4 = Fieldref #28.#29 // java/lang/System.out:Ljava/io/PrintStream;
#5 = String #30 // -----hello synchronized method-----
#6 = Methodref #31.#32 // java/io/PrintStream.println:(Ljava/lang/String;)V
#7 = Class #33 // dev/matrixlab/juc/locks/LockSyncDemo
#8 = Utf8 object
#9 = Utf8 Ljava/lang/Object;
#10 = Utf8 <init>
#11 = Utf8 ()V
#12 = Utf8 Code
#13 = Utf8 LineNumberTable
#14 = Utf8 LocalVariableTable
#15 = Utf8 this
#16 = Utf8 Ldev/matrixlab/juc/locks/LockSyncDemo;
#17 = Utf8 m2
#18 = Utf8 main
#19 = Utf8 ([Ljava/lang/String;)V
#20 = Utf8 args
#21 = Utf8 [Ljava/lang/String;
#22 = Utf8 MethodParameters
#23 = Utf8 SourceFile
#24 = Utf8 LockSyncDemo.java
#25 = NameAndType #10:#11 // "<init>":()V
#26 = Utf8 java/lang/Object
#27 = NameAndType #8:#9 // object:Ljava/lang/Object;
#28 = Class #34 // java/lang/System
#29 = NameAndType #35:#36 // out:Ljava/io/PrintStream;
#30 = Utf8 -----hello synchronized method-----
#31 = Class #37 // java/io/PrintStream
#32 = NameAndType #38:#39 // println:(Ljava/lang/String;)V
#33 = Utf8 dev/matrixlab/juc/locks/LockSyncDemo
#34 = Utf8 java/lang/System
#35 = Utf8 out
#36 = Utf8 Ljava/io/PrintStream;
#37 = Utf8 java/io/PrintStream
#38 = Utf8 println
#39 = Utf8 (Ljava/lang/String;)V
{
java.lang.Object object;
descriptor: Ljava/lang/Object;
flags: (0x0000)
public dev.matrixlab.juc.locks.LockSyncDemo();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #2 // class java/lang/Object
8: dup
9: invokespecial #1 // Method java/lang/Object."<init>":()V
12: putfield #3 // Field object:Ljava/lang/Object;
15: return
LineNumberTable:
line 3: 0
line 5: 4
LocalVariableTable:
Start Length Slot Name Signature
0 16 0 this Ldev/matrixlab/juc/locks/LockSyncDemo;
public synchronized void m2();
descriptor: ()V
flags: (0x0021) ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=1, args_size=1
0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #5 // String -----hello synchronized method-----
5: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 8: 0
line 9: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Ldev/matrixlab/juc/locks/LockSyncDemo;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 13: 0
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 args [Ljava/lang/String;
MethodParameters:
Name Flags
args
}
SourceFile: "LockSyncDemo.java"
总结
调用指令将会检查方法的 ACC_SYNCHRONIZED
访问标志是否被设置。
如果设置了,执行线程会将先持有 monitor
然后再执行方法,
最后在方法完成(无论是正常完成还是非正常完成)时释放 monitor
Synchronized 静态同步方法
Java 源码
LockSyncDemo.java
public class LockSyncDemo {
Object object = new Object();
public synchronized void m2() {
System.out.println("-----hello synchronized method-----");
}
public static synchronized void m3() {
System.out.println("-----hello static synchronized method-----");
}
public static void main(String[] args) {
}
}
反编译源码
Terminal
leam@Leam-MacBook-Pro locks % javap -v ./LockSyncDemo.class
Classfile /xxxxx/juc/target/classes/dev/matrixlab/juc/locks/LockSyncDemo.class
Last modified Jan 23, 2024; size 870 bytes
SHA-256 checksum 622741fdbd5e164c92c92f9f610c613e8e5ac46e2bdda9bbd41064b51c6bfa66
Compiled from "LockSyncDemo.java"
public class dev.matrixlab.juc.locks.LockSyncDemo
minor version: 0
major version: 52
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #8 // dev/matrixlab/juc/locks/LockSyncDemo
super_class: #2 // java/lang/Object
interfaces: 0, fields: 1, methods: 4, attributes: 1
Constant pool:
#1 = Methodref #2.#27 // java/lang/Object."<init>":()V
#2 = Class #28 // java/lang/Object
#3 = Fieldref #8.#29 // dev/matrixlab/juc/locks/LockSyncDemo.object:Ljava/lang/Object;
#4 = Fieldref #30.#31 // java/lang/System.out:Ljava/io/PrintStream;
#5 = String #32 // -----hello synchronized method-----
#6 = Methodref #33.#34 // java/io/PrintStream.println:(Ljava/lang/String;)V
#7 = String #35 // -----hello static synchronized method-----
#8 = Class #36 // dev/matrixlab/juc/locks/LockSyncDemo
#9 = Utf8 object
#10 = Utf8 Ljava/lang/Object;
#11 = Utf8 <init>
#12 = Utf8 ()V
#13 = Utf8 Code
#14 = Utf8 LineNumberTable
#15 = Utf8 LocalVariableTable
#16 = Utf8 this
#17 = Utf8 Ldev/matrixlab/juc/locks/LockSyncDemo;
#18 = Utf8 m2
#19 = Utf8 m3
#20 = Utf8 main
#21 = Utf8 ([Ljava/lang/String;)V
#22 = Utf8 args
#23 = Utf8 [Ljava/lang/String;
#24 = Utf8 MethodParameters
#25 = Utf8 SourceFile
#26 = Utf8 LockSyncDemo.java
#27 = NameAndType #11:#12 // "<init>":()V
#28 = Utf8 java/lang/Object
#29 = NameAndType #9:#10 // object:Ljava/lang/Object;
#30 = Class #37 // java/lang/System
#31 = NameAndType #38:#39 // out:Ljava/io/PrintStream;
#32 = Utf8 -----hello synchronized method-----
#33 = Class #40 // java/io/PrintStream
#34 = NameAndType #41:#42 // println:(Ljava/lang/String;)V
#35 = Utf8 -----hello static synchronized method-----
#36 = Utf8 dev/matrixlab/juc/locks/LockSyncDemo
#37 = Utf8 java/lang/System
#38 = Utf8 out
#39 = Utf8 Ljava/io/PrintStream;
#40 = Utf8 java/io/PrintStream
#41 = Utf8 println
#42 = Utf8 (Ljava/lang/String;)V
{
java.lang.Object object;
descriptor: Ljava/lang/Object;
flags: (0x0000)
public dev.matrixlab.juc.locks.LockSyncDemo();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #2 // class java/lang/Object
8: dup
9: invokespecial #1 // Method java/lang/Object."<init>":()V
12: putfield #3 // Field object:Ljava/lang/Object;
15: return
LineNumberTable:
line 3: 0
line 5: 4
LocalVariableTable:
Start Length Slot Name Signature
0 16 0 this Ldev/matrixlab/juc/locks/LockSyncDemo;
public synchronized void m2();
descriptor: ()V
flags: (0x0021) ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=1, args_size=1
0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #5 // String -----hello synchronized method-----
5: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 8: 0
line 9: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Ldev/matrixlab/juc/locks/LockSyncDemo;
public static synchronized void m3();
descriptor: ()V
flags: (0x0029) ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=0, args_size=0
0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #7 // String -----hello static synchronized method-----
5: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 12: 0
line 13: 8
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 17: 0
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 args [Ljava/lang/String;
MethodParameters:
Name Flags
args
}
SourceFile: "LockSyncDemo.java"
总结
ACC_STATIC
,ACC_SYNCHRONIZED
访问标志区分该方法是否静态同步方法