Java异常学习一:Throwable源码
一.java异常类结构
常用的CheckedException
常用的RuntimeException
二.Throwable类源码
- StackTraceElement。一个final类,代表栈轨迹中的元素,一个异常可能有多个元素。
public final class StackTraceElement implements java.io.Serializable { // Normally initialized by VM (public constructor added in 1.5) private String declaringClass;//com.jyz.study.jdk.exception.ExceptionTest private String methodName;//equals private String fileName;//ExceptionTest.java private int lineNumber;//17 //可以看到 native方法lineNumber=-2 public boolean isNativeMethod() { return lineNumber == -2; } //com.jyz.study.jdk.exception.ExceptionTest.equals(ExceptionTest.java:17) public String toString() { return getClassName() + "." + methodName + (isNativeMethod() ? "(Native Method)" : (fileName != null && lineNumber >= 0 ? "(" + fileName + ":" + lineNumber + ")" : (fileName != null ? "("+fileName+")" : "(Unknown Source)"))); } }
- Throwable。java里所有错误和异常的基类。
public class Throwable implements Serializable { //异常详细信息 private String detailMessage; //初始化异常原因case为本身 private Throwable cause = this; //栈轨迹中的元素 private StackTraceElement[] stackTrace; //一般也就四个构造函数 public Throwable() { fillInStackTrace(); } public Throwable(String message) { fillInStackTrace(); detailMessage = message; } public Throwable(String message, Throwable cause) { fillInStackTrace(); detailMessage = message; this.cause = cause; } public Throwable(Throwable cause) { fillInStackTrace(); detailMessage = (cause==null ? null : cause.toString()); this.cause = cause; } //自定义异常时 可以重写此方法 public String getMessage() { return detailMessage; } //也可以重写此方法,比喻绑定国际化资源 public String getLocalizedMessage() { return getMessage(); } //if cause == null return null public Throwable getCause() { return (cause==this ? null : cause); } //构造异常链 public synchronized Throwable initCause(Throwable cause) { if (this.cause != this)//一旦通过初始化或者initCause设置了cause,就不能再次设置了 throw new IllegalStateException("Can't overwrite cause"); if (cause == this)//如果 cause 是此 throwable。(throwable 不能是它自己的 cause。) throw new IllegalArgumentException("Self-causation not permitted"); this.cause = cause; return this; } public void printStackTrace() { printStackTrace(System.err); } //先打印thia,再打印方法调用的栈轨迹,最后打印cause public void printStackTrace(PrintStream s) { synchronized (s) { s.println(this); StackTraceElement[] trace = getOurStackTrace(); for (int i=0; i < trace.length; i++) s.println("\tat " + trace[i]); Throwable ourCause = getCause(); if (ourCause != null) ourCause.printStackTraceAsCause(s, trace); } } //迭代打印cause private void printStackTraceAsCause(PrintStream s, StackTraceElement[] causedTrace) { // assert Thread.holdsLock(s); // Compute number of frames in common between this and caused StackTraceElement[] trace = getOurStackTrace(); int m = trace.length-1, n = causedTrace.length-1; while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) { m--; n--; } int framesInCommon = trace.length - 1 - m; s.println("Caused by: " + this); for (int i=0; i <= m; i++) s.println("\tat " + trace[i]); if (framesInCommon != 0) s.println("\t... " + framesInCommon + " more"); // Recurse if we have a cause Throwable ourCause = getCause(); if (ourCause != null) ourCause.printStackTraceAsCause(s, trace); } public void printStackTrace(PrintWriter s) { //...同上 } private void printStackTraceAsCause(PrintWriter s, StackTraceElement[] causedTrace) { //...同上} public StackTraceElement[] getStackTrace() { return (StackTraceElement[]) getOurStackTrace().clone(); } //native方法获取方法调用的栈轨迹 一个Throwable的stackTrace是固定的 private synchronized StackTraceElement[] getOurStackTrace() { // Initialize stack trace if this is the first call to this method if (stackTrace == null) { int depth = getStackTraceDepth(); stackTrace = new StackTraceElement[depth]; for (int i=0; i < depth; i++) stackTrace[i] = getStackTraceElement(i); } return stackTrace; } native int getStackTraceDepth(); native StackTraceElement getStackTraceElement(int index); } }