当前位置: 首页 > 知识库问答 >
问题:

为什么对uncaughtexception的处理似乎发生在发生异常行为的死线程中?

凌博实
2023-03-14
@Slf4j
public class Main {

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread() {

            public void run() {
                try {
                    //do some stuff
                    LOG.debug("about to throw a RE from a worker thead");
                } catch (Exception e) {
                    e.printStackTrace();
                }

                throw new RuntimeException("purposeful!");
            }

        };
        LOG.debug("in main thead");
        t.setUncaughtExceptionHandler(
                (thread, throwable) -> LOG.debug("in main thread; catching exception from worker. uncaught exception from worker thread: {} from {}",
                        throwable.getMessage(), thread.getName()));
        t.start();
        TimeUnit.SECONDS.sleep(10);
        LOG.debug("done-main thead");
    }
}

如果运行,将产生以下输出:

10:19:50.249 [main] DEBUG com.foo.services.search.Main - in main thead
10:19:50.258 [Thread-0] DEBUG com.foo.services.search.Main - about to throw a RE from a worker thead
10:19:50.258 [Thread-0] DEBUG com.foo.services.search.Main - in main thread; catching exception from worker. uncaught exception from worker thread: purposeful! from Thread-0
10:20:00.258 [main] DEBUG com.foo.services.search.Main - done-main thead

为什么当thread-0完成时,throwable-catching-activity似乎发生在这个完成的线程中?

共有1个答案

宦琪
2023-03-14

表单doc中,声明此方法仅由JVM调用:

    /**
     * Dispatch an uncaught exception to the handler. This method is
     * intended to be called only by the JVM.
     */
    private void dispatchUncaughtException(Throwable e) {
        getUncaughtExceptionHandler().uncaughtException(this, e);
    }

出于好奇,我找到了HotSpot的相关源代码:https://github.com/openjdk/jdk/blob/master/src/hotspot/share/runtime/thread.cpp

正如您在thread.cpp中看到的,当thread退出时会触发此逻辑:

// For any new cleanup additions, please check to see if they need to be applied to
// cleanup_failed_attach_current_thread as well.
void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
  // ........
  if (!destroy_vm) {
    if (uncaught_exception.not_null()) {
      EXCEPTION_MARK;
      // Call method Thread.dispatchUncaughtException().
      Klass* thread_klass = vmClasses::Thread_klass();
  //...
}
 类似资料:
  • 问题内容: 我已经创建了一个MS Access数据库并为其分配了DSN。我想通过我的Java应用程序访问它。 这就是我在做什么: 我在try块的第一行遇到了异常。那是;。为什么会有此异常? 问题答案: 对于Java 7,您可以仅省略该语句,因为它并不是真正需要的。 对于Java 8,您不能使用JDBC-ODBC Bridge,因为它已被删除。您将需要使用类似UCanAccess的名称。有关更多信息

  • 问题内容: 为什么在调用execute方法时将未处理的异常重新抛出在worker中?结果,将在下一次执行时创建新线程,以最大化线程数 问题答案: 为什么当RuntimeException发生时,java ThreadPoolExecutor杀死线程? 我只能猜测, 直接进行线程调用而不将其包装在a中的原因是,这样,即使您不在乎结果,也不会招致该线程的开销。 __ 如果您的线程抛出,这是很罕见的事情

  • 死锁描述了另外两个线程因为永远等待对方而被阻塞的情况。当死锁发生时,程序永远挂起,你唯一能做的就是杀死程序。 为什么在下面给出的示例生产者-消费者问题中没有发生死锁: 我想知道为什么当同步对象正在等待其他线程释放锁时,在同步块中调用等待方法不会导致死锁?

  • 我无法理解整数的Java常量池是如何工作的。 我理解字符串的行为,因此能够证明整数常量也是同样的情况。 因此,对于整数 (&A) 直到现在一切都在我脑海中浮现。 我不能理解的是,当我从127增加整数时,它的行为不同。此行为在127之后发生变化,下面是代码片段 有人能帮我理解一下吗?

  • 问题内容: 我有一个生成器和一个使用它的函数: 如果生成器引发异常,我想在使用者函数中处理该异常,然后继续使用迭代器,直到耗尽为止。请注意,我不想在生成器中有任何异常处理代码。 我想到了类似的东西: 但这对我来说看起来很尴尬。 问题答案: 这也是我不确定是否正确/优雅处理的事情。 我要做的是从生成器中获取一个,然后将其提升到其他位置。喜欢: 这样,我仍然继承了Exception而没有引发它,这将导

  • 问题内容: 我无法理解Java常量池常量的工作方式。 我了解字符串的行为,因此可以证明自己与整数常量也是如此。 所以,对于整数 和 直到这里一切都进入我的脑海。 我无法理解的是,当我从127增加整数时,它的行为有所不同。此行为在127之后发生变化,下面是代码段 有人可以帮我理解吗? 问题答案: 不,用于数字的常量池与用于字符串的方法不同。对于字符串,只保留编译时常量-而对于整数类型的包装器类型,如