12

(以下のコード例は自己完結型で実行可能です。試してみてください。システムがクラッシュすることはありません:)

Tom Hawtin は、ここの質問についてコメントしました:なぜ人々はイベント キューで Java GUI を実行するのですか?

それ:

EDT がクラッシュする可能性は低いです。EDT ディスパッチでスローされた未チェックの例外がキャッチされ、ダンプされ、スレッドが続行されます。

誰かがここで何が起こっているのか説明してもらえますか ( 「チェックされていない例外をスローする」ボタンをクリックするたびに、意図的にゼロ除算が実行されます):

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class CrashEDT extends JFrame {

    public static void main(String[] args) {
        final CrashEDT frame = new CrashEDT();
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing( WindowEvent e) {
                System.exit(0);
            }
        });
        final JButton jb = new JButton( "throw an unchecked exception" );
        jb.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
                System.out.println( "Thread ID:" + Thread.currentThread().getId() );
                System.out.println( 0 / Math.abs(0) );
            }
        } );
        frame.add( jb );
        frame.setSize(300, 150);
        frame.setVisible(true);
    }

}

次のメッセージが表示されます(これは私が期待するものです):

Exception in thread "AWT-EventQueue-0" java.lang.ArithmeticException: / by zero

私にとって、これは未チェックの例外ですよね?

クラッシュをトリガーするたびに、スレッド ID が増加していることがわかります。

では、チェックされていない例外がスローされるたびに EDT が自動的に再起動されますか、またはTom Hawtin がコメントしたように、チェックされていない例外が「キャッチされ、ダンプされ、スレッドが続行されます」 ?

ここで何が起こっているのですか?

4

3 に答える 3

5

興味深い質問です。例外がキャッチされ、スレッドが続行されたと思っていたでしょうが、いくつかの調査の後、よくわかりません。

私はあなたのプログラムを

Set<Thread> seenAwtThreads = new HashSet<Thread>();

「見た」すべての awt スレッドを収集し、「例外をスロー」ボタンをクリックするたびにセットのサイズが増加します。これは、例外が発生した場合に新しいスレッドが初期化されることを示唆しているようです。

run最後に、の実装でこのコメントを見つけましたEventDispatchThread:

/*
 * Event dispatch thread dies in case of an uncaught exception. 
 * A new event dispatch thread for this queue will be started
 * only if a new event is posted to it. In case if no more
 * events are posted after this thread died all events that 
 * currently are in the queue will never be dispatched.
 */

完全な run メソッドの実装は次のようになります。

public void run() {
    try {
        pumpEvents(new Conditional() {
            public boolean evaluate() {
                return true;
            }
        });     
    } finally {
        /*
         * This synchronized block is to secure that the event dispatch 
         * thread won't die in the middle of posting a new event to the
         * associated event queue. It is important because we notify
         * that the event dispatch thread is busy after posting a new event
         * to its queue, so the EventQueue.dispatchThread reference must
         * be valid at that point.
         */
        synchronized (theQueue) {
            if (theQueue.getDispatchThread() == this) {
                theQueue.detachDispatchThread();
            }
            /*
             * Event dispatch thread dies in case of an uncaught exception. 
             * A new event dispatch thread for this queue will be started
             * only if a new event is posted to it. In case if no more
             * events are posted after this thread died all events that 
             * currently are in the queue will never be dispatched.
             */
            /*
             * Fix for 4648733. Check both the associated java event
             * queue and the PostEventQueue.
             */
            if (theQueue.peekEvent() != null || 
                !SunToolkit.isPostEventQueueEmpty()) { 
                theQueue.initDispatchThread();
            }
            AWTAutoShutdown.getInstance().notifyThreadFree(this);
        }
    }
}
于 2010-06-11T07:17:01.087 に答える
4

参考までに、「この機械の特定の動作は実装に依存します。」たとえば、私のプラットフォームではスレッド ID は変更されません。AWT Threading Issuesで説明されている最終的な影響は、「少なくとも 1 つの表示可能なコンポーネントがある間は JVM が終了しない」ことです。

于 2010-06-11T07:28:55.003 に答える
0

イベント ディスパッチ スレッドには、デフォルトのUncaughtExceptionHandlerが設定されています。これは、例外を System.out に出力し、スレッドで続行します。

于 2011-02-02T18:33:38.040 に答える