你的假设是正确的。synchronized
Java 语言中的块是用monitorenter
和monitorexit
指令实现的。您可以在此处查看 JVM 规范详细信息。
Java 虚拟机中的同步是通过监视器进入和退出来实现的,无论是显式的(通过使用 monitorenter 和 monitorexit 指令)还是隐式的(通过方法调用和返回指令)。
编译器生成的字节码将处理synchronized
体内抛出的所有异常,因此您的 try-finally 方法在这里可以正常工作。
声明规范finally
并没有说明发布监视器的任何内容。synchronized
第一个链接中提供的示例显示了包装在块中的简单方法的字节码。如您所见,处理任何可能的异常以确保执行 monitorexit 指令。您应该在编译器中实现相同的行为(编写将在 finally 语句中释放监视器的代码)。
void onlyMe(Foo f) {
synchronized(f) {
doSomething();
}
}
Method void onlyMe(Foo)
0 aload_1 // Push f
1 dup // Duplicate it on the stack
2 astore_2 // Store duplicate in local variable 2
3 monitorenter // Enter the monitor associated with f
4 aload_0 // Holding the monitor, pass this and...
5 invokevirtual #5 // ...call Example.doSomething()V
8 aload_2 // Push local variable 2 (f)
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
Exception table:
From To Target Type
4 10 13 any
13 16 13 any