Выполняется ли перезапуск EDT при возникновении исключения?

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

Том Хотин прокомментировал вопрос здесь: Почему люди запускают графический интерфейс 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 автоматически перезапускается каждый раз, когда генерируется непроверенное исключение или когда непроверенное исключение "поймано, выгружено и поток продолжается", как прокомментировал Том Хотин?

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


person NoozNooz42    schedule 11.06.2010    source источник
comment
Интересное примечание по совершенно другому вопросу: вам не нужно выполнять Math.abs (0), чтобы заставить компилятор принять его. 0/0 - правильное выражение, которое также вызовет исключение. подробнее ...   -  person aioobe    schedule 11.06.2010
comment
@aioobe: он хе, я знаю, я знаю, я читал это обсуждение ... Но если бы написали 0/0 или 1/0, люди бы спросили, что это вообще компилируется :)   -  person NoozNooz42    schedule 11.06.2010
comment
хахаха ... хороший момент :-)   -  person aioobe    schedule 11.06.2010
comment
Глядя на EventDispatchThread.pumpOneEventForFilters, в текущей реализации это сложно. Очевидно, разные реализации могут отличаться. Перед выходом из EDT, когда не было реализованных окон, по-видимому, всегда обнаруживались исключения.   -  person Tom Hawtin - tackline    schedule 11.06.2010


Ответы (3)


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

person trashgod    schedule 11.06.2010
comment
@trashgod: пока что пробовал только в системе Debian Linux :) +1, и это java.sun.com/javase/6/docs/api/java/awt/doc-files/ отличный материал! - person NoozNooz42; 11.06.2010
comment
Ага. Я использую ubuntu, использую java 6. Какую систему вы используете на trashgod? - person aioobe; 11.06.2010
comment
@ NoozNooz42: В то время как Mac OS X сохраняет тот же идентификатор, я вижу, как вы увеличиваете свой отчет в Ubuntu 10.04. - person trashgod; 11.06.2010
comment
@trashgod: да, только что попробовал на OS X 10.4 / Tiger / Java 1.5 и OS X 10.6 / Snow Leopard / Java 1.6, и на обоих ID остается одинаковым. Я думаю, что в OS X после отпускания кнопки кнопка не перерисовывается правильно (после сбоя это как если бы событие отпускания мыши было потеряно), в то время как в Linux отпускание кнопки учитывается правильно (не уверен что сказал). - person NoozNooz42; 11.06.2010
comment
@ NoozNooz42: Я использовал Java 1.6 как в Mac OS X 10.5.8, так и в Ubuntu 10.04. Источник eMac идентичен источнику, показанному @aioobe. - person trashgod; 11.06.2010
comment
@ NoozNooz42: Да, я тоже это вижу. Подсветка кнопки остается установленной (серой) до тех пор, пока мышь не выйдет из кнопки. - person trashgod; 11.06.2010

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

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

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.
 */

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

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);
        }
    }
}
person aioobe    schedule 11.06.2010
comment
@ NoozNooz42, нет, я думаю, 6. Дайте мне знать, если вы обнаружите, что в java 7 это изменилось :-) - person aioobe; 11.06.2010
comment
Приносим извинения за задержку с ответом. Я использовал Java 1.6 как в Mac OS X 10.5.8, так и в Ubuntu 10.04. Источник Mac идентичен показанному вами. - person trashgod; 11.06.2010

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

person keuleJ    schedule 02.02.2011