关于UncaughtException
问1:
如下代码
try {
//代码块
} catch (Throwable e) {
e.printStackTrace();
}
可以捕获代码块中的所有exception吗?
答:不是,当代码块调用子线程执行时候报错的时候,run方法内抛出的异常(前提是run内部未捕获)。
原因:run方法是不抛出任何异常的。
问2:
那么这部分异常怎么处理呢?
答:见Thread.java 源码1830行
/***
* 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);
}
也就是说当run方法内部有异常的时候,JVM会将该无法捕获的异常交为UncaughtExceptionHandler处理,默认UncaughtExceptionHandler为空null。
问3:如何编写UncaughtExceptionHandler及使用?
前提是继承Thread类。
public class UncaughtExceptionHandlerImpl implements UncaughtExceptionHandler{
@Override
public void uncaughtException(Thread t, Throwable e) {
//可以记录日志
//可以释放资源
//。。。。。。
System.out.println(e);
}
}
public class TestThread extends Thread{
@Override
public void run() {
int i = 1/0;
System.out.println(i);
}
public static void main(String[] args) {
TestThread t = new TestThread();
t.setUncaughtExceptionHandler(new UncaughtExceptionHandlerImpl());
t.start();
}
}
问4:UncaughtExceptionHandler 仅抓exception的异常?
答:不是,这个命名有些迷惑人,实际上大家看源码就知道uncaughtException(Thread t, Throwable e )
入参是Throwable接口,所以java.lang.Error和java.lang.Exception都会捕获。
同时因为工程对其他中心或是项目引用比较多,经常会有java.lang.NoClassDefFoundError: Could not initialize class
等类似问题,所以try catch的时候捕获Throwable比较好
结束语:鉴于上述知识点,建议将所有重要子线程设置UncaughtExceptionHandler,在主线程获取子线程日志,否则有问题子线程内部未捕获,有问题将会石沉大海,无法定位。