あなたの仮定は正しいです。synchronized
Java 言語のブロックは、monitorenter
およびmonitorexit
命令で実装されます。JVM 仕様の詳細は、こちらで確認できます。
Java 仮想マシンでの同期は、モニターの開始と終了によって、明示的に (monitorenter と monitorexit 命令を使用して)、または暗黙的に (メソッド呼び出しと return 命令で) 実装されます。
コンパイラは、本体内でスローされたすべての例外を処理するバイトコードを生成する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