为什么在使用'synchronized'关键字时需要调用两次'monitorexit'指令?
Why do we need to call 'monitorexit' instruction twice when we use 'synchronized' keyword?
根据JVM Specification, paragraph 3.14 Synchronization,JVM调用monitorexit指令两次。
我想知道为什么 JVM 需要这样的行为?
为什么我们调用这条指令2次,而不是3或4或N次?
可能与同步锁的类型有某种联系?
如果您查看代码,它应该在第 10 行之后结束,它转到 return 语句
9 monitorexit // Exit the monitor associated with f
10 goto 18 // Complete the method normally
13 astore_3 // In case of any throw, end up here
14 aload_2 // Push local variable 2 (f)
15 monitorexit // Be sure to exit the monitor!
16 aload_3 // Push thrown value...
17 athrow // ...and rethrow value to the invoker
18 return // Return in the normal case
但它会在 return 再次调用失败时添加额外的警告检查 monitorexit
该代码不是"calling" monitorexit
指令的两次。它在两个不同的代码路径上执行一次。
- 第一个代码路径用于
synchronized
块中的代码正常退出时。
- 第二个代码路径在隐式异常处理路径中,用于块异常终止的情况。
您可以将示例中的字节码编写为 pseudo-code,如下所示:
void onlyMe(Foo f) {
monitorEntry(f);
try {
doSomething();
monitorExit();
} catch (Throwable any) {
monitorExit();
throw any;
}
}
根据JVM Specification, paragraph 3.14 Synchronization,JVM调用monitorexit指令两次。
我想知道为什么 JVM 需要这样的行为? 为什么我们调用这条指令2次,而不是3或4或N次?
可能与同步锁的类型有某种联系?
如果您查看代码,它应该在第 10 行之后结束,它转到 return 语句
9 monitorexit // Exit the monitor associated with f 10 goto 18 // Complete the method normally 13 astore_3 // In case of any throw, end up here 14 aload_2 // Push local variable 2 (f) 15 monitorexit // Be sure to exit the monitor! 16 aload_3 // Push thrown value... 17 athrow // ...and rethrow value to the invoker 18 return // Return in the normal case
但它会在 return 再次调用失败时添加额外的警告检查 monitorexit
该代码不是"calling" monitorexit
指令的两次。它在两个不同的代码路径上执行一次。
- 第一个代码路径用于
synchronized
块中的代码正常退出时。 - 第二个代码路径在隐式异常处理路径中,用于块异常终止的情况。
您可以将示例中的字节码编写为 pseudo-code,如下所示:
void onlyMe(Foo f) {
monitorEntry(f);
try {
doSomething();
monitorExit();
} catch (Throwable any) {
monitorExit();
throw any;
}
}