在Thread中有四种处理运行时异常的API
- setUncaughtExceptionHandler(UncaughtExceptionHandler eh)为某个特定线程指定UncaughtExceptionHandler
- setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)设置全局的UncaughtExceptionHandler
- getUncaughtExceptionHandler 获取特定线程的UncaughtExceptionHandler
- getDefaultUncaughtExceptionHandler 获取全局的UncaughtExceptionHandler
线程在执行过程中不允许抛出checked异常,而且线程是运行在自己的上下文中,派生他的线程无法直接获得他运行中出现的异常信息,当线程在运行过程中出现异常时会回调UncaughtExceptionHandler接口,从而得知是哪个线程在运行时出错。
没有向线程注入UncaughtExceptionHandler回调接口的情况下,线程出现了异常又将如何处理?
- getUncaughtExceptionHandler方法会首先判断当前线程是否设置了handler,如果有则执行线程自己的uncaughtException方法,否则就到所在的ThreadGroup中去获取,ThreadGroup同样也实现了UncaughtExceptionHandler接口
- 该ThreadGroup如果有父ThreadGroup则直接调用父Group的UncaughtException方法
-如果设置了全局默认的UncaughtExceptionHandler,则调用UncaughtException方法 - 如果既没有父ThreadGroup也没有设置全局默认的UncaughtExceptionHandler,则会直接将异常的堆栈信息定向到System.err中
Hook线程介绍
Jvm进程的退出是由于Jvm进程中没有活跃的非守护线程,或者收到了系统中断信号,向Jvm程序中注入了一个Hook线程,在Jvm进程退出的时候,Hook线程会启动执行,通过Runtime可以为Jvm注入多个Hook线程,如下:
public class HookThread {
public static void main(String[] args){
//为应用程序注入钩子线程
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("The hook Thread 1 is Running");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("The hook Thread 1 will exit");
}
}));
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("The hook Thread 2 is Running");
try {
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 2 is Running
The hook Thread 1 is Running
The hook Thread 1 will exit
The hook Thread 2 will exit
给java程序注入了两个hook线程,在main线程中结束,也就是Jvm中没有了活动的非守护线程,Jvm进程即将退出时,两个Hook线程会被启动并且运行。