(6)Hook线程及捕获线程执行异常

Hook线程

JVM 进程退出是由于 JVM 进程中没有活跃的非守护线程,或者收到了系统中断信号,向 JVM 程序注入一个 Hook 线程,在 JVM 进程退出的时候, Hook 线程会启动执行,通过 Runtime 可以为 JVM 注入多个 Hook 线程。

示例

    public static void main(String[] args) {
        Runtime.getRuntime().addShutdownHook(new Thread(()->{
            try {
                System.out.println("the hook thread 1 is running.");
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("the hook thread 1 will exit.");
        }));

        Runtime.getRuntime().addShutdownHook(new Thread(()->{
            try {
                System.out.println("the hook thread 2 is running.");
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("the hook thread 2 will exit.");
        }));
        System.out.println("The program will is stopping.");
    }

输出

The program will is stopping.
the hook thread 1 is running.
the hook thread 2 is running.
the hook thread 1 will exit.
the hook thread 2 will exit.

注意事项

  1. Hook 线程只有在收到退出信号的时候会被执行,如果在 kill 的时候使用了参数 -9,那么 Hook 线程不会得到执行,进程将会立即退出。
  2. Hook 线程中也可以执行一些资源释放的工作。
  3. 尽量不要再 Hook 线程中执行一些耗时非常长的操作,因为其会导致程序迟迟不能退出。

线程运行时异常

API

public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) //某个线程指定 UncaughtExceptionHandler 
public UncaughtExceptionHandler getUncaughtExceptionHandler() //获取该线程指定的UncaughtExceptionHandler 
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) //设置全局线程 UncaughtExceptionHandler 
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() //获取全局线程 UncaughtExceptionHandler 

UncaughtExceptionHandler

    @FunctionalInterface
    public interface UncaughtExceptionHandler {
        /**
         * Method invoked when the given thread terminates due to the
         * given uncaught exception.
         * <p>Any exception thrown by this method will be ignored by the
         * Java Virtual Machine.
         * @param t the thread
         * @param e the exception
         */
        void uncaughtException(Thread t, Throwable e);
    }

该接口会被 Thread 中的 dispatchUncaughtException 方法调用。dispatchUncaughtException 方法只会被 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);
    }

getUncaughtExceptionHandler 方法

public UncaughtExceptionHandler getUncaughtExceptionHandler() {
        return uncaughtExceptionHandler != null ?
            uncaughtExceptionHandler : group;
    }

其中 uncaughtExceptionHandler 变量为该线程指定的 UncaughtExceptionHandler,即调用 public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) 方法设置。

group 为线程组,其实现了 Thread.UncaughtExceptionHandler 接口。默认的 uncaughtException 方法为:

     public void uncaughtException(Thread t, Throwable e) {
        if (parent != null) {
            parent.uncaughtException(t, e);
        } else {
            Thread.UncaughtExceptionHandler ueh =
                Thread.getDefaultUncaughtExceptionHandler();
            if (ueh != null) {
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
                System.err.print("Exception in thread \""
                                 + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }

如果父线程组不为 null ,会一直获取执行父线程组的 uncaughtException 方法,如果父线程组为 null ,则获取默认的,如果默认的不为 null,则会执行默认。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值