printStackTrace()为什么是这个样子?「终于解决」

(49) 2023-06-14 13:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说printStackTrace()为什么是这个样子?「终于解决」,希望能够帮助你!!!。

文章目录

  • demo
  • e.printStackTrace()
    • s.println(this)
    • s.println("\tat " + traceElement)
    • se.printEnclosedStackTrace
    • ourCause.printEnclosedStackTrace
  • log.error("error, trace: ", e)

一个常见的报错异常栈如下:


printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第1张

所以,为什么异常栈是这个样子的?

demo

printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第2张

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();
    }
  }
}

运行结果:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第3张

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

printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第4张
注意,e.printStackTrace()默认使用的事System.err。
继续往下看:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第5张
4处print,分别看。
PS:都是println,自动换行。

s.println(this)

很明显,调用的就是Throwable的toString方法:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第6张
getClass()是继承自Object,getLocalizedMessage()是打印当前类的detailMessage属性:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第7张
所以以上代码的作用是:打印当前Exception类名,如果detailMessage不为null,则打印“类名:detalMessage”。
以demo的代码为例,断点来看:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第8张

所以:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第3张
中的第一行:

java.lang.Exception: outer exception

来源就有了。

s.println("\tat " + traceElement)

printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第10张
1)getOurStackTrace()
getOurStackTrace()用于获取当前完整的方法栈(具体实现涉及native方法,不再深入),每一个栈帧StackTraceElement有属性:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第11张
2)s.println(“\tat " + traceElement)
很明显,这里的s.println(”\tat " + traceElement)又默认调用了StackTraceElement.toString():
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第12张
依次是:类名.方法名(文件名 : 行号),断点:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第13张
对应到:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第3张
果然一一对应。

se.printEnclosedStackTrace

printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第15张
注释写的很清楚:打印suppressed exceptions,
关于suppressed exception可以看这里:suppressed exception(PS:用来解决finally 异常覆盖catch 异常的情况)。demo中我们专门e.addSuppressed:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第16张
看断点:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第17张
其中:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第18张
看实现:

源码太多,以后专门分析,现在先不看了,反正就是这个Suppressed效果:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第3张

ourCause.printEnclosedStackTrace

printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第20张
其中CAUSE_CAPTION:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第21张

注释写的很清楚:打印cause,其中casuse是new Exception传入的:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第22张
每个Throwable默认的cause都是它自己:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第23张
构造方法传入:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第24张
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第25张
而我们这样传入了一个:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第26张
再看一下:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第20张
而getCause()如果cause是自身就返回null:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第28张
即没有传入cause时,“Cause by”往后的就不用打了。
获取了Throwable ourCause之后,执行这个ourCause的printEnclosedStackTrace(又是它),先不看了,反正就是这个Cause by效果:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第3张
有关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

调用的方法:
printStackTrace()为什么是这个样子?「终于解决」_https://bianchenghao6.com/blog__第30张
后面源码太复杂了,不看了,反正还是调用了Throwable.printStackTrace()。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复