//测试类
public class TestPrintStackTrace {
public static void main(String[] args) {try {
f();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void f() throws Exception {
throw new Exception("出问题啦!");
}
}
//查看e.printStackTrace();源码
public class Throwable implements Serializable{
//因为System.err是PrintStream类型,所以调用了public void printStackTrace(PrintStream s)函数
public void printStackTrace() {
printStackTrace(System.err);
}
//此处的s=System.err,构造了WrappedPrintStream(s)后直接走private void printStackTrace(PrintStreamOrWriter s)
public void printStackTrace(PrintStream s) {
printStackTrace(new WrappedPrintStream(s));
}
//这里就是e.printStackTrace()实现的底层代码,有些看不懂没事,抓住主干代码看,看他如何抛出异常的
private void printStackTrace(PrintStreamOrWriter s) {
// Guard against malicious overrides of Throwable.equals by
// using a Set with identity equality semantics.
Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
dejaVu.add(this);
synchronized (s.lock()) {
// Print our stack trace
s.println(this);//此处的this是mian方法中的new Exception("出问题啦!"),所以此处默认调用toString方法
/*public String toString() {
String s = getClass().getName();
String message = getLocalizedMessage();
return (message != null) ? (s + ": " + message) : s;
}*/
//toString方法中s=文件名,message=出问题啦!
//形如:
//此处便是用for循环输出每个出错位置,getOurStackTrace()获取每个出错的位置复制给trace,然后用增强for遍历,到此就是全部过程
StackTraceElement[] trace = getOurStackTrace();
for (StackTraceElement traceElement : trace)
s.println("\tat " + traceElement);
// Print suppressed exceptions, if any
for (Throwable se : getSuppressed())
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
// Print cause, if any
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
}
}
//WrappedPrintStream类
private static class WrappedPrintStream extends PrintStreamOrWriter {
private final PrintStream printStream;
//此处的printStream=System.err
WrappedPrintStream(PrintStream printStream) {
this.printStream = printStream;
}
Object lock() {
return printStream;
}
void println(Object o) {
printStream.println(o);
}
}
}