Home > Software design >  Why Does the treatment of an uncaughtexception appear to be happening in the dead thread, in which t
Why Does the treatment of an uncaughtexception appear to be happening in the dead thread, in which t

Time:11-22

I borrowed this from another question:

@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");
    }
}

If it runs, the following output is produced:

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

Why, when thread-0 is finished, does the throwable-catching-activity appear to be occurring inside this completed thread?

CodePudding user response:

Form doc of JDK, it is stated that this method is only called by the 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);
    }

Out of curiosity, I found the relevant source code for hotspot: https://github.com/openjdk/jdk/blob/master/src/hotspot/share/runtime/thread.cpp

As you can see in the thread.cpp, this logic is triggered when thread exit:

// 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();
  //...
}
  • Related