Зачем заморачиваться с настройкой свойства sun.awt.exception.handler?

Вот некоторый код, который перехватывает исключение, созданное в потоке отправки событий:

package com.ndh.swingjunk;

import java.awt.EventQueue;

import javax.swing.JFrame;

public class EntryPoint {

    public static void main(String[] args) {
        Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());
//      System.setProperty("sun.awt.exception.handler", MyExceptionHandler.class.getName());

        EventQueue.invokeLater(new Runnable() 
        {
            public void run() 
            {
                new SomeWindow("foo").setVisible(true);
            }
        });
    }
}

class SomeWindow extends JFrame {
    public SomeWindow(String title) {
        this.setTitle(title);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        throw new RuntimeException("hello");
    }
}

Я видел предупреждения о том, что исключения, созданные в потоке отправки событий, не обрабатываются UncaughtExceptionHandler, но, похоже, это не относится к моему примеру; он работает одинаково независимо от того, закомментирована ли строка регистрации или оставлена. Мой пример как-то запутался, или регистрация обработчика исключений с помощью sun.awt.exception.handler больше не нужна?


person Nathan Hughes    schedule 26.04.2011    source источник


Ответы (2)


Класс EDT (java.awt.EventDispatchThread, не ищите его в javadoc, это приватный класс) сильно изменился с момента появления AWT.

В JDK6 вы можете видеть, что этот класс теперь может правильно обрабатывать исключения, возникающие внутри EDT. Обработка исключений в текущей версии немного сложна:

  • если вы установили свойство sun.awt.exception.handler, то ваш обработчик будет вызываться для каждого исключения, созданного кодом разработчика, вызванным внутри EDT (совместимость с предыдущими версиями JDK обеспечена).
  • в противном случае любое исключение будет повторно создано, поэтому текущий EDT остановится, и любой UncaughtExceptionHandler по умолчанию сможет его перехватить, как показано в вашем фрагменте кода.

НО (и это очень важно), если вы внимательно посмотрите на код EDT, то увидите, что этот механизм не сработает, если исключение возникнет в EDT во время отображения модального диалога (я думаю, это связано с тем, что управление EDT и EventQueue довольно сложное, и я бы даже осмелился сказать "запутанный": большая часть кода выглядит как хаки там).

В этой конкретной ситуации исключения будут регистрироваться в System.err, за исключением случаев, когда вы установили свойство sun.awt.exception.handler. Наличие по умолчанию UncaughtExceptionHandler не поможет.

Итак, я считаю, что ДА, вы все равно должны возиться со свойством sun.awt.exception.handler, за исключением случаев, когда вы можете точно сказать, что ваше приложение не использует модальные диалоги (не забывайте, что диалоги JOptionPane также модальный).

person jfpoilpret    schedule 27.04.2011
comment
К вашему сведению, это свойство было удалено в Java7. Модальные диалоги теперь правильно используют Thread.UncaughtExceptionHandler: bugs.sun.com/view_bug.do?bug_id =6727884 - person Gili; 10.07.2011

Вы позвонили setDefaultUncaughtExceptionHandler вместо setUncaughtExceptionHandler. (Если присутствует SecurityManager: для первого требуется RuntimePermission setDefaultUncaughtExceptionHandler, для второго — SecurityManager.checkAccess(Thread).)

person Tom Hawtin - tackline    schedule 26.04.2011
comment
Хотин, я хочу, чтобы мой пользовательский интерфейс JavaFX показывал всплывающее окно сообщения при обнаружении неперехваченной ошибки. Не могли бы вы уточнить, какой вызов мне следует использовать? - person likejudo; 16.01.2013
comment
@Anil Если это ненадежное приложение PlugIn/WebStart, оно должно быть setUncaughtExceptionHandler. Теоретически я считаю, что вы должны использовать JavaFX только в потоке событий, поэтому вам нужно будет установить его только один раз (но убедитесь, что в правильном потоке). AWT EDT может выйти и быть заменен другим потоком, если нет реализованных компонентов, поэтому существует потенциальный риск того, что этого будет недостаточно, если это имеет значение. - person Tom Hawtin - tackline; 16.01.2013
comment
Hawtin JavaFX также использует Tasks и Workers в качестве фоновых потоков, и я использую их. Я не знаю, правильно ли это, но вот что я сделал: в потоке Controller — UI я вызвал `Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t , Throwable e) { OkCancelController okc = null; okc = replaceSceneContent(okc, ok_cancel.fxml, в приложении произошла ошибка: + e.getMessage()); } });` - person likejudo; 16.01.2013