java源码分析(7)-Throwable


Throwable

1.Throwable类

Throwable类实现了Serializable 接口,此类可用于序列化

public class Throwable implements Serializable {
    private transient Object backtrace;
    private String detailMessage;//用于存放异常的详细信息
    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();
    }
    public Throwable getCause() {
        return (cause==this ? null : cause);//若cause为本身,即初始化时没有赋值,返回null,若已赋值,则返回值
    }

2.initCause

初始化cause,一个Throwable类只能设置一次cause

public synchronized Throwable initCause(Throwable cause) {
        if (this.cause != this)//已设置过cause,则抛异常,意思为只能设置一次
cause属性
            throw new IllegalStateException("Can't overwrite cause");
        if (cause == this)//若参数cause等于本身,抛异常
            throw new IllegalArgumentException("Self-causation not permitted");
        this.cause = cause;
        return this;
    }

3.打印错误信息

//遍历出错的原因轨迹
    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);
        }
    }
    private void printStackTraceAsCause(PrintStream s,
                                        StackTraceElement[] causedTrace)
    {
        StackTraceElement[] trace = getOurStackTrace();//获得当前的异常轨迹数组
        int m = trace.length-1, n = causedTrace.length-1;
        //m为当前异常轨迹数组的最后一个元素的下标
        //n为当前对象引起的异常的异常轨迹数组的最后一个元素的下标
        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) {
        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);
        }
    }
    private void printStackTraceAsCause(PrintWriter 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);
    }

4.fillInStackTrace

 public synchronized native Throwable fillInStackTrace();//native方法获得方

法执行的栈轨迹

5.余下的一些功能

 public StackTraceElement[] getStackTrace() {
        return (StackTraceElement[]) getOurStackTrace().clone();
    }
    private synchronized StackTraceElement[] getOurStackTrace() {
        //只有第一次调用才会执行if模块中的代码
        if (stackTrace == null) {
            int depth = getStackTraceDepth();
            stackTrace = new StackTraceElement[depth];
            for (int i=0; i < depth; i++)
                stackTrace[i] = getStackTraceElement(i);
        }
        return stackTrace;
    }
    //设置异常的轨迹
    public void setStackTrace(StackTraceElement[] stackTrace) {
        StackTraceElement[] defensiveCopy =
            (StackTraceElement[]) stackTrace.clone();
        for (int i = 0; i < defensiveCopy.length; i++)
            if (defensiveCopy[i] == null)
                throw new NullPointerException("stackTrace[" + i + "]");

        this.stackTrace = defensiveCopy;
    }
    native int getStackTraceDepth();
    native StackTraceElement getStackTraceElement(int index);//获得特定下标的异

常轨迹
    //序列化对象
    private synchronized void writeObject(java.io.ObjectOutputStream s)
        throws IOException
    {
        getOurStackTrace();
        s.defaultWriteObject();
    }





阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29346449/article/details/51557634
文章标签: java 源码
个人分类: java源码
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

java源码分析(7)-Throwable

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭