为什么使用“ synchronized”关键字时需要两次调用“ monitorexit”指令?

时间:2019-06-12 06:00:30

标签: java jvm bytecode synchronized specifications

根据JVM Specification, paragraph 3.14 Synchronization,JVM两次调用 monitorexit 指令。

我想知道为什么JVM需要这种行为? 为什么我们调用此指令2次,而不是3次,4次或N次?

可能与同步锁的类型有关吗?

2 个答案:

答案 0 :(得分:2)

该代码没有两次“调用” monitorexit指令。它在两个不同的代码路径上执行一次。

  • 第一个代码路径用于synchronized块中的代码正常退出时。
  • 对于块异常终止的情况,第二个代码路径位于隐式异常处理路径中。

您可以在示例中将字节码写为 pseudo-code ,如下所示:

void onlyMe(Foo f) {
    monitorEntry(f);

    try {
        doSomething();
        monitorExit();
    } catch (Throwable any) {
        monitorExit();
        throw any;
    }
}

答案 1 :(得分:0)

如果您看一下代码,它应该在第10行后的goto 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

但是如果再次失败返回电话,monitorexit

则增加了额外的警告检查。