java - UncaughtExceptionHandler 中抛出的错误是否被吞没?

标签 java exception-handling jvm uncaught-exception uncaughtexceptionhandler

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

void uncaughtException(Thread t, Throwable e):

Method invoked when the given thread terminates due to the given uncaught exception.

Any exception thrown by this method will be ignored by the Java Virtual Machine.

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

Exception: java.lang.RuntimeException thrown from the UncaughtExceptionHandler in thread "main"

我发现的另一个奇怪之处是我得到的输出不是来自 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");
}

输出(粗体表示红色):

true

this is black color

java.lang.Error: test stacktrace color at asf.df.main(df.java:13)

Exception: java.lang.RuntimeException thrown from the UncaughtExceptionHandler in thread "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 具有误导性,最好修复。

关于java - UncaughtExceptionHandler 中抛出的错误是否被吞没?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24834702/

相关文章:

java - 从未调用过 valueChangeListener

java 服务器到服务器通信框架 (json)

java - 如何在Java中使用字符串为变量赋值(不是评估)

java - 每次创建新的 Java 对象或重用一个

c++ - 从构造函数中捕获异常意味着我的实例之后超出了范围

haskell - 如果 JVM 语言编译过程有一个像 Haskell 一样的 STG 阶段,会有什么变化?

Java 内存感知缓存

JavaFX System.setProperty 管理员权限

.net - 为什么.net 异常没有被捕获?

c# - 在任务中抛出异常 - "await"vs Wait()