为什么在使用'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;
    }
}