uncaughtExceptionHandler

uncaughtExceptionHandler

Thread.UncaughtExceptionHandler 声明,当处理未捕获异常的方法本身抛出异常时,该异常将被忽略:



但是,当我测试它时,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):



我发现的另一个奇怪之处是,我得到的输出不是来自System.err。它似乎完全来自另一个流。我通过将System.err重定向到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");
}

输出(粗线表示红色):



这些现象的解释是什么?

UncaughtExceptionHandler中引发的错误会如何处理?预期的(记录或保证的)行为是什么?

最佳答案

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具有误导性,最好加以修复。

08-17 04:04