printStackTrace()为什么是这个样子?


一个常见的报错异常栈如下:
在这里插入图片描述
所以,为什么异常栈是这个样子的?

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()。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值