可能平时朋友们都好奇,为什么没有进行try catch的处理,当我们抛出异常时还是能打印出异常堆栈信息:
public static void main(String[] args) throws Exception {
throw new RuntimeException("error");
}
其实通过debug,可以发现线程会执行如下方法, 通过注释可以知道,当异常未被代码捕获时,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()方法
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
private ThreadGroup group;
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
该方法会进行判断,若设置了uncaughtExceptionHandler,则使用uncaughtExceptionHandler的uncaughtException()方法,否则使用
group的。
而我们可以通过如下方法来为线程设置该Handler。
Thread.currentThread().setUncaughtExceptionHandler();
然后我们再看uncaughtException()方法,若我们没有设置handler,则使用ThreadGroup的方法。
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);
}
}
}
通过源码可以发现, 当!(e instanceof ThreadDeath)时,将异常堆栈信息输出到控制台上,于是谜底揭晓!
---------------------------------------------------------------------------分割线----------------------------------------------------------------------------------------------------
使用自定义的UncaughtExceptionHandler的小demo
public static void main(String[] args) throws Exception {
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("线程" + t.getName() + "发生异常");
System.out.println(e.toString());
System.out.println("异常类型为:" + e.getClass());
}
});
throw new RuntimeException("error");
}