Java UncaughtExceptionHandler 解析

问:说说你对 UncaughtExceptionHandler 的认识和理解?

答:在虚拟机中,当一个线程如果没有显式处理(即 try catch)异常而抛出时会将该异常事件报告给该线程对象的 java.lang.Thread.UncaughtExceptionHandler 进行处理,如果线程没有设置 UncaughtExceptionHandler,则默认会把异常栈信息输出到终端而使程序直接崩溃。所以如果我们想在线程意外崩溃时做一些处理就可以通过实现 UncaughtExceptionHandler 来满足需求。

为了让大家搞清其中接口方法的细节差异,下面给出核心源码解释(有删减):

public class Thread {
    ......
    /**
     * 当一个线程因未捕获的异常而即将终止时虚拟机将使用 Thread.getUncaughtExceptionHandler()
     * 获取已经设置的 UncaughtExceptionHandler 实例,并通过调用其 uncaughtException(...) 方
     * 法而传递相关异常信息。
     * 如果一个线程没有明确设置其 UncaughtExceptionHandler,则将其 ThreadGroup 对象作为其
     * handler,如果 ThreadGroup 对象对异常没有什么特殊的要求,则 ThreadGroup 会将调用转发给
     * 默认的未捕获异常处理器(即 Thread 类中定义的静态未捕获异常处理器对象)。
     *
     * @see #setDefaultUncaughtExceptionHandler
     * @see #setUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     */
    @FunctionalInterface
    public interface UncaughtExceptionHandler {
        /**
         * 未捕获异常崩溃时回调此方法
         */
        void uncaughtException(Thread t, Throwable e);
    }

    /**
     * 静态方法,用于设置一个默认的全局异常处理器。
     */
    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
         defaultUncaughtExceptionHandler = eh;
     }

    /**
     * 针对某个 Thread 对象的方法,用于对特定的线程进行未捕获的异常处理。
     */
    public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        checkAccess();
        uncaughtExceptionHandler = eh;
    }

    /**
     * 当 Thread 崩溃时会调用该方法获取当前线程的 handler,获取不到就会调用 group(handler 类型)。
     * group 是 Thread 类的 ThreadGroup 类型属性,在 Thread 构造中实例化。
     */
    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
        return uncaughtExceptionHandler != null ?
            uncaughtExceptionHandler : group;
    }

    /**
     * 线程全局默认 handler。
     */
    public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
        return defaultUncaughtExceptionHandler;
    }
    ......
}

通过上面源码可以看出,线程崩溃时异常抛出的顺序是先调用 ThreadgetUncaughtExceptionHandler() 查看是否有自己对象特有的 handler,如果有就直接处理,如果没有就调用 ThreadGroup (UncaughtExceptionHandler 在 JDK 的默认实现类),如果 ThreadGroup 没有特殊处理就会继续调用 ThreadgetDefaultUncaughtExceptionHandler() 获取 handler 进行处理,如果默认 handler 也没有处理就直接执行正常的异常流程使程序崩溃。

下面看下 ThreadGroup 的核心实现源码,如下:

//ThreadGroup 在 Thread 对象构造方法中实例化。
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
    ......
    public void uncaughtException(Thread t, Throwable e) {
        //默认情况下 parent 是 null。
        if (parent != null) {
            parent.uncaughtException(t, e);
        } else {
            //一般走进来,调用 Thread.setDefaultUncaughtExceptionHandler(...)
            //方法设置的全局 handler 进行处理。
            Thread.UncaughtExceptionHandler ueh =
                Thread.getDefaultUncaughtExceptionHandler();
            if (ueh != null) {
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
                //全局 handler 也不存在就输出异常栈。
                System.err.print("Exception in thread \""
                                 + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }
    ......
}

本文参考自 UncaughtExceptionHandler 相关问题解析

你可能感兴趣的:(Java UncaughtExceptionHandler 解析)