文章目录
一个常见的报错异常栈如下:
所以,为什么异常栈是这个样子的?
demo
public class Main{
public static void in() throws Exception {
throw new Exception("inner exception");
}
public static void out() throws Exception{
try{
in();
}catch(Exception e){
throw new Exception("outer exception", e);
}
}
public static void main(String[] args){
try{
out();
}catch (Throwable e){
e.addSuppressed(new Exception("test suppressed exception"));
e.printStackTrace();
}
}
}
运行结果:
java.lang.Exception: outer exception
at Main.out(Main.java:14)
at Main.main(Main.java:19)
Suppressed: java.lang.Exception: test suppressed exception
at Main.main(Main.java:21)
Caused by: java.lang.Exception: inner exception
at Main.in(Main.java:7)
at Main.out(Main.java:12)
... 1 more
为什么是这种结果呢?
e.printStackTrace()
注意,e.printStackTrace()默认使用的事System.err。
继续往下看:
4处print,分别看。
PS:都是println,自动换行。
s.println(this)
很明显,调用的就是Throwable的toString方法:
getClass()是继承自Object,getLocalizedMessage()是打印当前类的detailMessage属性:
所以以上代码的作用是:打印当前Exception类名,如果detailMessage不为null,则打印“类名:detalMessage”。
以demo的代码为例,断点来看:
所以:
中的第一行:
java.lang.Exception: outer exception
来源就有了。
s.println("\tat " + traceElement)
1)getOurStackTrace()
getOurStackTrace()用于获取当前完整的方法栈(具体实现涉及native方法,不再深入),每一个栈帧StackTraceElement有属性:
2)s.println(“\tat " + traceElement)
很明显,这里的s.println(”\tat " + traceElement)又默认调用了StackTraceElement.toString():
依次是:类名.方法名(文件名 : 行号),断点:
对应到:
果然一一对应。
se.printEnclosedStackTrace
注释写的很清楚:打印suppressed exceptions,
关于suppressed exception可以看这里:suppressed exception(PS:用来解决finally 异常覆盖catch 异常的情况)。demo中我们专门e.addSuppressed:
看断点:
其中:
看实现:
源码太多,以后专门分析,现在先不看了,反正就是这个Suppressed效果:
ourCause.printEnclosedStackTrace
其中CAUSE_CAPTION:
注释写的很清楚:打印cause,其中casuse是new Exception传入的:
每个Throwable默认的cause都是它自己:
构造方法传入:
而我们这样传入了一个:
再看一下:
而getCause()如果cause是自身就返回null:
即没有传入cause时,“Cause by”往后的就不用打了。
获取了Throwable ourCause之后,执行这个ourCause的printEnclosedStackTrace(又是它),先不看了,反正就是这个Cause by效果:
有关printEnclosedStackTrace,可见专题:Throwable.printEnclosedStackTrace()
log.error("error, trace: ", e)
log一般来自SLF4J:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Logger log = LoggerFactory.getLogger(Main.class);
log.error("error, trace: ", e);
结果:
[ERROR 2021-07-20 10:42:04,617] [main Main] - error, trace:
java.lang.Exception: outer exception
at Main.out(Main.java:14)
at Main.main(Main.java:19)
Suppressed: java.lang.Exception: test suppressed exception
at Main.main(Main.java:21)
Caused by: java.lang.Exception: inner exception
at Main.in(Main.java:7)
at Main.out(Main.java:12)
... 1 more
调用的方法:
后面源码太复杂了,不看了,反正还是调用了Throwable.printStackTrace()。