天天看点

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

文章目录

    • 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,则会执行默认。

继续阅读