関連するJLS セクションを読んだ後、JLSには、メソッド定義に含まれることstatic
を禁止するものは何もありません。関連する JVM 仕様native
によると:
メソッドレベルの同期は、メソッドの呼び出しと戻りの一部として暗黙的に実行されます (§2.11.8)。同期されたメソッドは、ランタイム定数プールの method_info 構造体 (§4.6) で、メソッド呼び出し命令によってチェックされる ACC_SYNCHRONIZED フラグによって区別されます。ACC_SYNCHRONIZED が設定されているメソッドを呼び出すと、実行中のスレッドはモニターに入り、メソッド自体を呼び出し、メソッド呼び出しが正常に完了するか突然完了するかに関係なく、モニターを終了します。実行中のスレッドがモニターを所有している間、他のスレッドはモニターに入ることができません。同期メソッドの呼び出し中に例外がスローされ、同期メソッドが例外を処理しない場合、同期メソッドから例外が再スローされる前に、メソッドのモニターが自動的に終了します。
このため、生成されるバイトコードには、ブロックのようにmonitorenter
ormonitorexit
命令はありません。synchronized
この場合に生成されるのはinvokestatic
、静的メソッドを呼び出すために だけです。static native synchronized
この命令は、メソッド、static native
メソッド、またはメソッドを呼び出すと生成されますstatic
。
生成されたバイトコードを使用したサンプル コードを次に示します。
public static void main( String[] args ){
doSomething1();
System.out.println("Now do 2");
doSomething2();
System.out.println("native java");
doSomethingJava();
String s = "test";
synchronized ( s ){
int x = 9 + 5;
}
}
public static native void doSomething1();
public static synchronized native void doSomething2();
public static synchronized void doSomethingJava(){
System.out.println("synchronized");
}
生成されたバイトコード:
Compiled from "test.java"
class test {
test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #2 // Method doSomething1:()V
3: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
6: ldc #4 // String Now do 2
8: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
11: invokestatic #6 // Method doSomething2:()V
14: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
17: ldc #7 // String native java
19: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: invokestatic #8 // Method doSomethingJava:()V
25: ldc #9 // String test
27: astore_1
28: aload_1
29: dup
30: astore_2
31: monitorenter
32: bipush 14
34: istore_3
35: aload_2
36: monitorexit
37: goto 47
40: astore 4
42: aload_2
43: monitorexit
44: aload 4
46: athrow
47: return
Exception table:
from to target type
32 37 40 any
40 44 40 any
public static native void doSomething1();
public static synchronized native void doSomething2();
public static synchronized void doSomethingJava();
Code:
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #10 // String synchronized
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}