JDK1.8源码之 Throwable

1,580 阅读3分钟

概述

在Java语言中,Throwable 是所有error和exception的父类。只有Throwable类的实例才能被Java虚拟机或者Java的throw语句抛出。只有该类或者该类的子类才能成为catch语句的参数。

一个throwable 包含了它被创建时,线程执行堆栈的一个快照。也可以包含一条包含错误相关信息的消息字符串。一个throwable可以阻止其他throwable冒泡。其他throwable可以导致该throwable被创建。由此导致链式反应。 大概的意思,举个例子,在内层抛出NullPointerException,是可以导致外层的Exception的。内层抛出的异常都会在该层进行捕获和处理。

继承关系

public class Throwable implements Serializable 实现了 Serializable 接口

成员属性

  • private String detailMessage; 包含了本次Throwable的详细信息。例如,FileNotFoundException包含了无法被找到的文件名。

  • private Throwable cause = this; 异常原因

  • private StackTraceElement[] stackTrace = UNASSIGNED_STACK; 堆栈信息

  • private List suppressedExceptions = SUPPRESSED_SENTINEL; 把被抑制的Exception记录在该变量。

构造器

使用message和cause来创建一个Throwable

public Throwable(String message, Throwable cause) {
    fillInStackTrace();
    detailMessage = message;
    this.cause = cause;
}

还有3个重载方法

public Throwable(String message) {
    fillInStackTrace();
    detailMessage = message;
}
public Throwable() {
    fillInStackTrace();
}
public Throwable(Throwable cause) {
    fillInStackTrace();
    detailMessage = (cause==null ? null : cause.toString());
    this.cause = cause;
}

关键方法

getMessage()

获取异常的信息

public String getMessage()
getLocalizedMessag()

获取异常信息

public String getLocalizedMessage() {
    return getMessage();
}
getCause()

获取异常原因

public synchronized Throwable getCause() {
    return (cause==this ? null : cause);
}
initCause()

初始化异常原因。

public synchronized Throwable initCause(Throwable cause) {
    if (this.cause != this)
        throw new IllegalStateException("Can't overwrite cause with " +
                                        Objects.toString(cause, "a null"), this);
    if (cause == this)
        throw new IllegalArgumentException("Self-causation not permitted", this);
    this.cause = cause;
    return this;
}
printStackTrace()

打印堆栈信息

public void printStackTrace() {
    printStackTrace(System.err);
}
public void printStackTrace(PrintStream s) {
    printStackTrace(new WrappedPrintStream(s));
}
private void printStackTrace(PrintStreamOrWriter s)
public void printStackTrace(PrintWriter s) {
    printStackTrace(new WrappedPrintWriter(s));
}
fillInStackTrace()

填充堆栈信息。

private native Throwable fillInStackTrace(int dummy);
public synchronized Throwable fillInStackTrace() {
    if (stackTrace != null ||
        backtrace != null /* Out of protocol state */ ) {
        fillInStackTrace(0);
        stackTrace = UNASSIGNED_STACK;
    }
    return this;
}
getStackTrace()

获取堆栈信息。

public StackTraceElement[] getStackTrace() {
    return getOurStackTrace().clone();
}
setStackTrace()

设置堆栈信息

public void setStackTrace(StackTraceElement[] stackTrace) {
    // Validate argument
    StackTraceElement[] defensiveCopy = stackTrace.clone();
    for (int i = 0; i < defensiveCopy.length; i++) {
        if (defensiveCopy[i] == null)
            throw new NullPointerException("stackTrace[" + i + "]");
    }

    synchronized (this) {
        if (this.stackTrace == null && // Immutable stack
            backtrace == null) // Test for out of protocol state
            return;
        this.stackTrace = defensiveCopy;
    }
}
addSuppressed()

添加被抑制的异常。

public final synchronized void addSuppressed(Throwable exception) {
    if (exception == this)
        throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE, exception);

    if (exception == null)
        throw new NullPointerException(NULL_CAUSE_MESSAGE);

    if (suppressedExceptions == null) // Suppressed exceptions not recorded
        return;

    if (suppressedExceptions == SUPPRESSED_SENTINEL)
        suppressedExceptions = new ArrayList<>(1);

    suppressedExceptions.add(exception);
}
getSuppressed()

当一个异常被抛出的时候,可能有其他异常因为该异常而被抑制住,从而无法正常抛出。这时可以通过addSuppressed方法把这些被抑制的方法记录下来。被抑制的异常会出现在抛出的异常的堆栈信息中,也可以通过getSuppressed方法来获取这些异常。这样做的好处是不会丢失任何异常,方便开发人员进行调试。

public final synchronized Throwable[] getSuppressed() {
    if (suppressedExceptions == SUPPRESSED_SENTINEL ||
        suppressedExceptions == null)
        return EMPTY_THROWABLE_ARRAY;
    else
        return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
}
要点分析

该类是Exception 和 Error的父类。只有该类可以被作为catch的参数。

希望和大家多多交流


我16年毕业以后,做的是前端,目前打算深入学习java开发。内容有任何问题,欢迎各位小伙伴们指正,也希望小伙伴们给我点赞和关注,给我留言,一起交流讨论,共同进步。