Throwable 源碼閱讀

Throwable

  • 屬性說明
/**
 *  Java 語言中所有錯誤和異常的基類,此類及其子類才能通過 throws 被 JVM 虛擬機拋出。
 * @since 1.0
 */
public class Throwable implements Serializable {
    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -3042686055658047285L;

    /**
     *  JVM 會保存一些棧回溯信息到此對象上
     */
    private transient Object backtrace;

    /**
     *  異常的細節信息
     */
    private String detailMessage;

    /**
     *  共享的空堆棧信息
     */
    private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0];

    /**
     *  引起此 Throwable 拋出的源 Throwable 對象
     * @since 1.4
     */
    private Throwable cause = this;

    /**
     *  此 Throwable 關聯的堆棧信息
     * @serial
     * @since 1.4
     */
    private StackTraceElement[] stackTrace = UNASSIGNED_STACK;

    /**
     *  棧回溯的深度
     */
    private transient int depth;

    // Setting this static field introduces an acceptable
    // initialization dependency on a few java.util classes.
    private static final List<Throwable> SUPPRESSED_SENTINEL = Collections.emptyList();

    /**
     *  被抑制的異常對象列表
     * @serial
     * @since 1.7
     */
    private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;

    /** 用於抑制空指針異常的消息 */
    private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";

    /** Message for trying to suppress oneself. */
    private static final String SELF_SUPPRESSION_MESSAGE = "Self-suppression not permitted";

    /** 導致異常堆棧跟蹤的標題信息 */
    private static final String CAUSE_CAPTION = "Caused by: ";

    /** 被抑制的異常堆棧跟蹤的標題信息 */
    private static final String SUPPRESSED_CAPTION = "Suppressed: ";
  • 實例化
    /**
     *  創建一個無描述信息的 Throwable 對象
     */
    public Throwable() {
        fillInStackTrace();
    }

    /**
     *  創建一個持有指定描述信息 message 的 Throwable 對象
     * @param   message 詳細的信息
     */
    public Throwable(String message) {
        fillInStackTrace();
        detailMessage = message;
    }

    /**
     *  創建一個持有詳細信息和異常來源的 Throwable 對象
     * @param  message  詳細描述信息
     * @param  cause    引起此 Throwable 的源 Throwable 對象
     * @since  1.4
     */
    public Throwable(String message, Throwable cause) {
        fillInStackTrace();
        detailMessage = message;
        this.cause = cause;
    }

    /**
     *  創建一個持有源 Throwable 實例的 Throwable 對象
     *
     * @param  cause    源 Throwable 對象
     * @since  1.4
     */
    public Throwable(Throwable cause) {
        fillInStackTrace();
        detailMessage = cause==null ? null : cause.toString();
        this.cause = cause;
    }

    /**
     *  填充此 Throwable 實例的堆棧跟蹤信息
     */
    public synchronized Throwable fillInStackTrace() {
        if (stackTrace != null ||
                backtrace != null /* Out of protocol state */ ) {
            fillInStackTrace(0);
            stackTrace = UNASSIGNED_STACK;
        }
        return this;
    }

    private native Throwable fillInStackTrace(int dummy);
  • 打印異常堆棧
    /**
     *  將異常堆棧信息輸出到標準錯誤流
     */
    public void printStackTrace() {
        printStackTrace(System.err);
    }

    /**
     *  將此 Throwable 的堆棧信息輸出到指定的 PrintStream s 中
     *
     * @param s 用於輸出的目標 {@code PrintStream}
     */
    public void printStackTrace(PrintStream s) {
        printStackTrace(new WrappedPrintStream(s));
    }

    private void printStackTrace(PrintStreamOrWriter s) {
        final Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
        dejaVu.add(this);

        synchronized (s.lock()) {
            // 打印此 Throwable 的信息
            s.println(this);
            // 打印相關的堆棧信息
            final StackTraceElement[] trace = getOurStackTrace();
            for (final StackTraceElement traceElement : trace) {
                s.println("\tat " + traceElement);
            }

            // 打印抑制的異常信息
            for (final Throwable se : getSuppressed()) {
                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
            }

            // 打印異常原因
            final Throwable ourCause = getCause();
            if (ourCause != null) {
                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
            }
        }
    }

    /**
     *  將此 Throwable 的堆棧信息打印到 PrintWriter s 中
     *
     * @param s 用於輸出的 {@code PrintWriter}
     * @since   1.1
     */
    public void printStackTrace(PrintWriter s) {
        printStackTrace(new WrappedPrintWriter(s));
    }

    /**
     *  封裝 PrintStream and PrintWriter
     */
    private abstract static class PrintStreamOrWriter {
        /** Returns the object to be locked when using this StreamOrWriter */
        abstract Object lock();

        /** Prints the specified string as a line on this StreamOrWriter */
        abstract void println(Object o);
    }

    private static class WrappedPrintStream extends PrintStreamOrWriter {
        private final PrintStream printStream;

        WrappedPrintStream(PrintStream printStream) {
            this.printStream = printStream;
        }

        @Override
        Object lock() {
            return printStream;
        }

        @Override
        void println(Object o) {
            printStream.println(o);
        }
    }

    private static class WrappedPrintWriter extends PrintStreamOrWriter {
        private final PrintWriter printWriter;

        WrappedPrintWriter(PrintWriter printWriter) {
            this.printWriter = printWriter;
        }

        @Override
        Object lock() {
            return printWriter;
        }

        @Override
        void println(Object o) {
            printWriter.println(o);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章