Подтвердить что ты не робот

Восстанавливается ли EDT или нет, когда генерируется исключение?

(приведенный ниже примерный код является самодостаточным и выполнимым, вы можете попробовать его, это не приведет к сбою вашей системы:)

Tom Hawtin прокомментировал здесь вопрос: Почему люди запускают графический интерфейс Java в очереди событий

что

Неверно, что 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

и для меня это исключение, исключающее исключение?

Вы можете видеть, что идентификатор потока увеличивается каждый раз, когда вы запускаете сбой.

Итак, EDT автоматически перезапускается каждый раз, когда выбрано исключенное исключение или исключены исключения "пойманы, сброшены и поток продолжается", как прокомментировал Том Хотин?

Что здесь происходит?

4b9b3361

Ответ 1

Для справки: "Особое поведение этого механизма зависит от реализации." Например, идентификатор потока остается неизменным на моей платформе. Чистый эффект, обсуждаемый в AWT Threading Issues, заключается в том, что "JVM не будет выходить, пока есть хотя бы один отображаемый компонент".

Ответ 2

Интересный вопрос. Я бы подумал, что исключения были пойманы и что поток продолжался, но после некоторых исследований я не уверен.

Я продлил вашу программу с помощью

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

в котором я собрал все "замеченные" awt-потоки, и размер набора увеличивается каждый раз, когда я нажимаю кнопку "throw exception", что, по-видимому, предполагает, что новый поток инициализируется в случае исключения.

Наконец, я нашел этот комментарий в реализации 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.
 */

Реализация полного метода выполнения выглядит так:

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);
        }
    }
}

Ответ 3

В разделе "Диспетчер событий" есть по умолчанию UncaughtExceptionHandler, который печатает исключение в System.out, а затем продолжается в потоке.