Делать ошибки в UncaughtExceptionHandler пропасть?
Thread.UncaughtExceptionHandler заявляет, что когда метод, который обрабатывает необработанные исключения, сам создает исключение, это исключение будет проигнорировано:
пустота uncaughtException(поток t, Throwable e):
метод вызывается, когда данный поток завершается из-за данного неперехваченное исключение.
любое исключение, вызванное этим методом, будет проигнорировано Java Виртуальный Машина.
однако, когда я тестировал его, JVM не игнорировал исключения, обработанные обработчиком необработанных исключений`:
public static void main(final String args[]) {
    Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread arg0, Throwable arg1) {
            throw new java.lang.RuntimeException("e2");
        }
    });
    throw new RuntimeException("e1");
}
выход консоли Eclipse (jre 1.7):
исключение: java.ленг.Исключение RuntimeException, созданное из UncaughtExceptionHandler в потоке "main"
еще одна странность, которую я обнаружил, заключается в том, что выход, который я получаю, не исходит от System.err. Кажется, он совсем из другого потока. Я проверено перенаправлением System.err to System.out, но я все еще получаю "красный" выход:
public static void main(final String[] args) {
    System.setErr(System.out);
    System.out.println(System.err == System.out);
    System.err.println("this is black color");
    try {
        throw new Error("test stacktrace color");
    } catch (Throwable e) {
        e.printStackTrace();
    }
    try {
        Thread.sleep(2500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            throw new RuntimeException("from handler");
        }
    });
    throw new RuntimeException("from main");
}
вывод (жирным шрифтом обозначается красный цвет):
правда
это черный цвет
java.ленг.Ошибка: тестовый цвет stacktrace в asf.пеленгатор.main (df.java: 13)
исключение: java.ленг.RuntimeException, выброшенное из UncaughtExceptionHandler в потоке "main"
что объяснение этих феноменов?
что происходит с ошибками, брошенными в UncaughtExceptionHandler? Каково ожидаемое (задокументированное или гарантированное) поведение?
2 ответов
HotSpot JVM печатает исключения, выброшенные из UncaughtExceptionHandler. См.JavaThread:: exit
    if (HAS_PENDING_EXCEPTION) {
      ResourceMark rm(this);
      jio_fprintf(defaultStream::error_stream(),
            "\nException: %s thrown from the UncaughtExceptionHandler"
            " in thread \"%s\"\n",
            pending_exception()->klass()->external_name(),
            get_thread_name());
      CLEAR_PENDING_EXCEPTION;
    }
JVM печатает эти исключения непосредственно на stderr независимо от System.err состояние-было ли оно перенаправлено или нет.
Ну, это предупреждение не влияет на приложение - в этом смысле исключение "игнорируется". Но вы правы, такое поведение не очевидно. Javadoc вводит в заблуждение и лучше быть зафиксированный.
исключения игнорируются, и обработка продолжается при выбрасывании из неосновного потока.
если он брошен в main, возвращаемый код ошибки не равен нулю.
необработанные исключения регистрируются через syserr.
public static void main(final String[] args) {
    final Thread myThread = new Thread(new Runnable() {
        @Override
        public void run() {
            Thread.currentThread()
                .setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
                    @Override
                    public void uncaughtException(final Thread t, final Throwable e) {
                        System.out.println("In child UncaughtExceptionHandler at " + java.time.Instant.now());
                        throw new RuntimeException("From child thread UncaughtExceptionHandler"
                                + java.time.Instant.now());
                    }
                });
            throw new RuntimeException("from runnable");
        }
    });
    Thread.currentThread()
    .setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(final Thread t, final Throwable e) {
                System.out.println("In main UncaughtExceptionHandler " + java.time.Instant.now());
                throw new RuntimeException("From main thread UncaughtExceptionHandler" + java.time.Instant.now());
        }
    });
    myThread.start();
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
    System.out.println("After child thread: " + java.time.Instant.now());
    //Will result in a non-zero return code
    throw new RuntimeException("from main");
}
выход:
in child UncaughtExceptionHandler at 2014-07-19T04:10: 46.184 Z
исключение: java.ленг.Исключение RuntimeException, брошенное из UncaughtExceptionHandler в потоке " поток-0" После дочерняя нить: 2014-07-19T04:10:48.197 Z В основном UncaughtExceptionHandler 2014-07-19T04:10: 48.197 Z
исключение: java.ленг.RuntimeException, выброшенное из UncaughtExceptionHandler в потоке "main"
