2013-04-04 16 views
6

私はJDK 1.7.0_03を開くために、OracleのJDK 1.6から切り替えた、と私は終了時に、むしろ注目すべきデッドロックヒットしました:LinuxではSystem.exitはスレッドセーフではありませんか?

java.lang.Thread.State: WAITING (on object monitor) 
at java.lang.Object.wait(Native Method) 
at java.lang.Thread.join(Thread.java:1258) 
- locked <0x8608dda0> (a sun.awt.X11.XToolkit$1$1) 
at java.lang.Thread.join(Thread.java:1332) 
at java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:106) 
at java.lang.ApplicationShutdownHooks$1.run(ApplicationShutdownHooks.java:46) 
at java.lang.Shutdown.runHooks(Shutdown.java:123) 
at java.lang.Shutdown.sequence(Shutdown.java:167) 
at java.lang.Shutdown.exit(Shutdown.java:212) 
- locked <0x8603df28> (a java.lang.Class for java.lang.Shutdown) 
at java.lang.Runtime.exit(Runtime.java:107) 
at java.lang.System.exit(System.java:960) 

をあなたがAWTからのSystem.exitを呼び出す必要がありますことが表示されますイベントキュー。これは本当ですか? Sun docsにスレッド要件のドキュメントはありませんRuntime.exit

AWTツリーロックを取得する必要があるのはLinuxのみですが、これはケーキを取ります。これはバグですか?またはドキュメントに何かが欠けていますか?

+2

は、デッドロックを実証SSCCE(http://sscce.org/)を手に入れましたか? – NPE

+0

'System.exit'メソッドは、Java仮想マシン内のすべてのスレッドの強制終了を強制します。 System.exitを使用して前述のデッドロック問題を解決していない場合、デッドロックが発生する前にプログラムを停止しています。あなたが正常に停止すると、他のスレッドはメインスレッドの助けを借りずに続行され、明らかにそれらなしでは実行できません。 –

答えて

1

runHooksメソッドは、Runtime.addShutdownHookによって登録されたフックスレッドを開始し、それらが終了するのを待ちます。フックスレッドのいずれかが、AWTイベントスレッドが必要とするリソースをロックしている場合、デッドロックが発生する可能性があります。

あなたはAWTイベントスレッドではSystem.exitを呼び出すようにしている場合、私は好きですが、別のスレッドでそれを呼び出す勧め:これは知らなくても、ランタイムでのバグであるかどうかを言うことは不可能である

new Thread(){ 
      public void run() { 
       System.exit(0); 
      } 
    }.start(); 
+0

私はこのスニペットが大好きです。それは本当に美しさです。ありがとう。 –

1

アプリケーションの動作の詳細(理想的にはSSCCEの形式)。

たとえば、次の例は、System.exit()を含む同様のデッドロックを示しています。しかし、それはないSystem.exit()で、明確にアプリケーションのバグです:

public class OhNo { 

    final static Object lock = new Object(); 

    public static void main(String[] args) { 
     new Thread(new Runnable() { 
      public void run() { 
       synchronized (lock) { 
        for (;;) { 
        } 
       } 
      } 
     }).start(); 
     Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 
      public void run() { 
       synchronized (lock) { 
        System.out.println("in shutdown hook"); 
       } 
      } 
     })); 
     System.out.println("about to call System.exit()"); 
     System.exit(0); 
    } 
} 
+0

AWT-EventQueue-0が私を呼び出しています。オブジェクトOのロックを取得しています.Oはビジー状態なので、AWT-EventQueue-0は待機をブロックされます。 OはSystem.exit()を呼び出していますが、LinuxではこれがAWTツリーロックを待っています。これはもちろんOで待機しています。したがって、デッドロックです。とにかく、私は奇妙なことをすることができるこれらのシャットダウンフックがあると思う、右の答えはSpring.Rushによって示唆されるように、シャットダウンする新しいスレッドを作成することです。それは非常に堅牢なようです。 –

関連する問題