深入理解Java虚拟机(四)

深入理解Java虚拟机(四)

synchronized 字节码分析

我们先来看一下一个简单的方法

/**
* @Author: cuzz
* @Date: 2019/3/4 13:34
* @Description:
*/
public class MyTest02 {
int x = 0;

public void setX(int x) {
this.x = x;
}
}

使用 javap -v com.cuzz.jvm.bytecode.MyTest02 命令,找到 setX 方法

public void setX(int);
descriptor: (I)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: putfield #2 // Field x:I
5: return
LineNumberTable:
line 12: 0
line 13: 5
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/cuzz/jvm/bytecode/MyTest02;
0 6 1 x I

如果我们在方法中添加 synchronzied 关键字

public class MyTest02 {
int x = 0;

public synchronized void setX(int x) {
this.x = x;
}
}

我们再反编译一下

public synchronized void setX(int);
descriptor: (I)V
flags: ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: putfield #2 // Field x:I
5: return
LineNumberTable:
line 12: 0
line 13: 5
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/cuzz/jvm/bytecode/MyTest02;
0 6 1 x I

对比这两个反编译的结果,我们发现在 flags 中多了 ACC_SYNCHRONIZED,不会出现 monitorenter 和 monitorexit。

如果我们是在方法体重添加 synchronized 关键字

public class MyTest02 {
String lock = "lock";
int x = 0;

public int getX() {
synchronized (lock) {
return x;
}
}
}

我们反编译一下 找到 getX 方法

public int getX();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=1
0: aload_0
1: getfield #3 // Field lock:Ljava/lang/String;
4: dup
5: astore_1
6: monitorenter
7: aload_0
8: getfield #4 // Field x:I
11: aload_1
12: monitorexit
13: ireturn
14: astore_2
15: aload_1
16: monitorexit
17: aload_2
18: athrow
Exception table:
from to target type
7 13 14 any
14 17 14 any
LineNumberTable:
line 17: 0
line 18: 7
line 19: 14
LocalVariableTable:
Start Length Slot Name Signature
0 19 0 this Lcom/cuzz/jvm/bytecode/MyTest02;
StackMapTable: number_of_entries = 1
frame_type = 255 /* full_frame */
offset_delta = 14
locals = [ class com/cuzz/jvm/bytecode/MyTest02, class java/lang/Object ]
stack = [ class java/lang/Throwable ]

在 6 中出现 monitorenter,在 16 中出现 moniterexit

Comments