use*_*415 2 java bytecode synchronized
// the java source code
public class Demo {
private final Object lock = new Object();
public void read() {
synchronized (lock) {
// more code here ...
}
}
}
// the decompiled .class file
public class Demo {
private final Object lock = new Object();
public void read() {
// Why Java compiler add this line? Is the 'read this.lock' redundant?
Object var1 = this.lock;
synchronized(this.lock) {
// more code here ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
字节码在这里:javap -l -p -s demo.class
public void read();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=1
0: aload_0
1: getfield #3 // Field lock:Ljava/lang/Object;
4: dup
5: astore_1
6: monitorenter
7: aload_1
8: monitorexit
9: goto 17
12: astore_2
13: aload_1
14: monitorexit
15: aload_2
16: athrow
17: return
Exception table:
from to target type
7 9 12 any
12 15 12 any
LineNumberTable:
line 15: 0
line 16: 7
line 17: 17
LocalVariableTable:
Start Length Slot Name Signature
0 18 0 this Lxechoz/vipshop/com/demo/thread/Demo;
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 12
locals = [ class xechoz/vipshop/com/demo/thread/Demo, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
Run Code Online (Sandbox Code Playgroud)
我认为线 1: getfield #3 // Field lock:Ljava/lang/Object;
对应于Object var1 = this.lock;。
我知道编译器会通过添加或删除一些代码来优化代码。
但是,为什么编译器在synced块之前添加read语句。
为什么需要这个?还是为什么要进行优化?
Java虚拟机中的同步是通过监视器的进入和退出来实现的,显式地(通过使用monitorenter和monitorexit指令)或隐式地(通过方法调用和返回指令)来实现。
为确保monitorexit始终执行,编译器为添加了一个隐式catch子句Throwable。
为了在突然的方法调用完成时强制正确配对Monitorenter和MonitorExit 指令,编译器生成异常处理程序(第2.10节),该异常处理程序将匹配任何异常,并且其关联代码执行必要的MonitorExit指令。
使用时,javap -c Demo您可以在偏移量12-16处看到此附加字节码
0: aload_0
1: getfield #3 // Field lock:Ljava/lang/Object;
4: dup
5: astore_1
6: monitorenter
7: aload_1
8: monitorexit
9: goto 17
12: astore_2
13: aload_1
14: monitorexit
15: aload_2
16: athrow
17: return
Exception table:
from to target type
7 9 12 any
12 15 12 any
Run Code Online (Sandbox Code Playgroud)
生成的代码为伪代码
Object var1 = this.lock;
try {
monitorenter(var1);
// more code here ...
monitorexit(var1);
} catch (Throwable t) {
monitorexit(var1);
throw t;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
157 次 |
| 最近记录: |