java源码分析(7)-Throwable

原创 2016年06月01日 17:28:57


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();
    }





版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

JAVA编程——Throwable常见异常及源码详解

Throwable
  • RamProg
  • RamProg
  • 2015年08月16日 00:14
  • 864

Java源码侦探--异常体系解读Throwable

Throwable类是整个异常体系类的父级类,当然最终追根溯源到底的父类当然要归于Object类。Throwable类实现了Serializable接口,表示Throwable可以进行序列化,继承自O...

深入java.lang.Throwable

深入java.lang.Throwable java语言中,错误类的基类是java.lang.Error,异常类的基类是java.lang.Exception。 相同点:java.lang.Er...

java异常之Throwable源码

1 java异常类结构: 常用的CheckedException 常用的RuntimeException:

异常介绍、自定义异常、异常面试题

一、异常介绍 java.lang Class Exception java.lang.Object java.lang.Throwable jav...
  • hwshea
  • hwshea
  • 2015年11月18日 15:37
  • 630

Java中Throwable源码阅读

Throwable 源码阅读笔记 读的不是很懂,但是大致明白自定义异常中的那几个常用的参数的发源地了,这是项目中自定义异常经常使用的几个参数和方法,在Throwable中都可以查到影子: prote...
  • dzy21
  • dzy21
  • 2016年07月09日 17:00
  • 501

Throwable(一)源码分析

package java.lang; import java.io.*; /** * * Throwable是所有Error和Exceptiong的父类 * 注意它有四个构造函数: * Throwa...

java集合(7):TreeSet源码分析(jdk1.8)

前言TreeSet是基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法...

(7) java源码分析------之ArrayList (对应数据结构中线性表中的顺序表,JDK1.6)

ArrayList就是传说中的动态数组,就是Array的复杂版本,它提供了如下一些好处:动态的增加和减少元素、灵活的设置数组的大小......     认真阅读本文,我相信一定会对你有帮助。比如...

Java高并发程序设计笔记7之并发容器及典型源码分析

并发容器是针对多个线程并发访问而设计的,在jdk5.0引入了concurrent包, 其中提供了很多并发容器,极大的提升同步容器类的性能。 ConcurrentHashMap 我们知道HashM...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java源码分析(7)-Throwable
举报原因:
原因补充:

(最多只允许输入30个字)