JDK源码解析之 java.lang.Throwable
在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性。
一、类定义
public class Throwable implements Serializable {}
- Serializable:可被序列化的标志接口
二、成员变量
//静态变量
//这两个变量主要用于序列化
private static class SentinelHolder {public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL =new StackTraceElement("", "", null, Integer.MIN_VALUE);public static final StackTraceElement[] STACK_TRACE_SENTINEL =new StackTraceElement[] {STACK_TRACE_ELEMENT_SENTINEL};
}
//一个空的StackTraceElement[]数组,用来初始化或者作为返回值。
private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0];
//一个空的只读List,同样用于初始化
private static final List<Throwable> SUPPRESSED_SENTINEL =Collections.unmodifiableList(new ArrayList<Throwable>(0));
//前两个用于作为错误信息,后两个作为printStackTrace方法的说明前缀使用
private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
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: ";
//用作getSuppressed方法的返回值(当suppressedExceptions没有元素时)
private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];//实例变量
//用来保存栈信息的轨迹
private transient Object backtrace;
//描述这个异常的信息
private String detailMessage;
//描述这个异常由哪个Throwable导致,默认是this。
private Throwable cause = this;
//异常抛出位置的栈信息,每个StackTraceElement代表一个栈信息,默认指向静态常量UNASSIGNED_STACK,代表栈信息为空。
private StackTraceElement[] stackTrace = UNASSIGNED_STACK;
//JDK 1.7引入的新特性。该List用来保存被屏蔽的异常对象,在try-catch语句中,如果try中抛出了异常,在执行流程转移到方法栈上一层之前,finally语句块会执行,但是,如果在finally语句块中又抛出了一个异常,那么这个异常会覆盖掉之前抛出的异常,这点很像finally中return的覆盖。
private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;
三、构造方法
public Throwable() {fillInStackTrace();
}
/*** @param message 异常描述信息,该参数直接赋值给实例变量detailMessage*/
public Throwable(String message) {fillInStackTrace();detailMessage = message;
}
/*** @param message 异常描述信息,该参数直接赋值给实例变量detailMessage* @param cause 描述当前异常由哪个异常引发*/
public Throwable(String message, Throwable cause) {fillInStackTrace();detailMessage = message;this.cause = cause;
}
/*** @param cause 描述当前异常由哪个异常引发*/
public Throwable(Throwable cause) {fillInStackTrace();detailMessage = (cause==null ? null : cause.toString());this.cause = cause;
}
/*** @param message 异常描述信息,该参数直接赋值给实例变量detailMessage* @param cause 描述当前异常由哪个异常引发* @param enableSuppression 是否支持Suppress异常消息* @param writableStackTrace 是否调用fillInStackTrace使堆栈信息可以写入*/
protected Throwable(String message, Throwable cause,boolean enableSuppression, boolean writableStackTrace) {if (writableStackTrace) {fillInStackTrace();} else {stackTrace = null;}detailMessage = message;this.cause = cause;if (!enableSuppression)suppressedExceptions = null;
}
Throwable
提供了4个public
构造器和1个protected
构造器(该构造器由JDK1.7引入)。4个public
构造器共同点就是都调用了fillInStackTrace
方法。
fillInStackTrace
会首先判断stackTrace
是不是为null
,如果不为null
则会调用native
方法fillInStackTrace
获取当前堆栈信息。那么什么时候为null
呢,答案是上面的protected
构造器可以指定writableStackTrace
为false
,这样stackTrace
就为null
了,就不会调用fillInStackTrace
获取堆栈信息。如果你不需要异常的栈信息,你也可以重写这个方法,让它直接返回this
,毕竟异常的爬栈是一个开销比较大的操作。
四、常用方法
1、printStackTrace方法
printStackTrace
把传入的输入流用内部类WrappedPrintStream
或WrappedPrintWriter
包装,主要用来实现printStackTrace
方法在打印堆栈信息时的线程安全。
public void printStackTrace() {printStackTrace(System.err);
}public void printStackTrace(PrintStream s) {printStackTrace(new WrappedPrintStream(s));
}public void printStackTrace(PrintWriter s) {printStackTrace(new WrappedPrintWriter(s));
}private void printStackTrace(PrintStreamOrWriter s) {Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());dejaVu.add(this);synchronized (s.lock()) {s.println(this);StackTraceElement[] trace = getOurStackTrace();for (StackTraceElement traceElement : trace)s.println("\tat " + traceElement);for (Throwable se : getSuppressed())se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);Throwable ourCause = getCause();if (ourCause != null)ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);}
}
}
printStackTrace
把传入的输入流用内部类WrappedPrintStream
或WrappedPrintWriter
包装,主要用来实现printStackTrace
方法在打印堆栈信息时的线程安全。
2、getMessage()和getLocalizedMessage()
默认条件下可以调用getMessage
或getLocalizedMessage
方法获取detailMessage
public String getMessage() {return detailMessage;
}
public String getLocalizedMessage() {return getMessage();
}
3、getCause()和initCause()
通过构造器自定义cause。构造完成后,可以通过getCause
方法访问获取,如果没有指定cause
,则返回null
。
在构造完成后,也可通过initCause方法修改:修改cause
的前提是必须在构造方法中没有指定别的cause
(即默认条件下cause
为this
),否则会抛出IllegalStateException
异常。另外也不能修改cause
为this
。
public synchronized Throwable getCause() {return (cause == this ? null : cause);
}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;
}
五、拓展
1.处理异常机制
在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。
抛出异常:当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。throws,throw
捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适 的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适 的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。try…catch
对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同。
由于运行时异常的不可查性,为了更合理、更容易地实现应用程序,Java规定,运行时异常将由Java运行时系统自动抛出,允许应用程序忽略运行时异常。
对于方法运行中可能出现的Error,当运行方法不欲捕捉时,Java允许该方法不做任何抛出声明。因为,大多数Error异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。
对于所有的可查异常,Java规定:一个方法必须捕捉,或者声明抛出方法之外。也就是说,当一个方法选择不捕捉可查异常时,它必须声明将抛出异常。
能够捕捉异常的方法,需要提供相符类型的异常处理器。所捕捉的异常,可能是由于自身语句所引发并抛出的异常,也可能是由某个调用的方法或者Java运行时 系统等抛出的异常。也就是说,一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。
任何Java代码都可以抛出异常,如:自己编写的代码、来自Java开发环境包中代码,或者Java运行时系统。无论是谁,都可以通过Java的throw语句抛出异常。
从方法中抛出的任何异常都必须使用throws子句。
捕捉异常通过try-catch语句或者try-catch-finally语句实现。
总体来说,Java规定:对于可查异常必须捕捉、或者声明抛出。允许忽略不可查的RuntimeException和Error。
try { // 可能会发生异常的程序代码
} catch (Type1 id1){ // 捕获并处置try抛出的异常类型Type1
}
catch (Type2 id2){ //捕获并处置try抛出的异常类型Type2
}
JDK源码解析之 java.lang.Throwable相关推荐
- JDK源码解析之 java.lang.Exception
异常.是所有异常的基类,用于标识一般的程序运行问题.这些问题通常描述一些会被应用程序捕获的反常情况. 一.源码部分 //继承了java.lang.Throwable public class Exce ...
- JDK源码解析之 java.lang.Error
java.lang.Error 错误.是所有错误的基类,用于标识严重的程序运行问题.这些问题通常描述一些不应被应用程序捕获的反常情况. 一.源码部分 //继承了java.lang.Throwable ...
- JDK源码解析之 java.lang.Thread
位于java.lang包下的Thread类是非常重要的线程类,它实现了Runnable接口,今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知识:线程的几种状态.上下文切换 ...
- JDK源码解析之 Java.lang.Object
Object类是Java中其他所有类的祖先,没有Object类Java面向对象无从谈起.作为其他所有类的基类,Object具有哪些属性和行为,是Java语言设计背后的思维体现. Object类位于ja ...
- JDK源码解析之 java.lang.Integer
teger 基本数据类型int 的包装类 Integer 类型的对象包含一个 int 类型的字段 一.类定义 public final class Integer extends Number imp ...
- JDK源码解析之 java.lang.System
一个和系统环境进行交互的类. System不允许被实例化, 而且是一个final类 一.不能实例化 private System() {} 二.成员变量 public final static Inp ...
- JDK源码解析之 Java.lang.Compiler
Compiler类提供支持Java到本机代码编译器和相关服务.在设计上,它作为一个占位符在JIT编译器实现. 一.源码部分 public final class Compiler {private C ...
- JDK源码解析之 Java.lang.Byte
byte,即字节,由8位的二进制组成.在Java中,byte类型的数据是8位带符号的二进制数,以二进制补码表示的整数 取值范围:默认值为0,最小值为-128(-27);最大值是127(27-1) By ...
- JDK源码解析之 Java.lang.String
String 类代表字符串.Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现. 字符串是常量:它们的值在创建之后不能更改.字符串缓冲区支持可变的字符串.因 ...
最新文章
- python的pandas_python之pandas(一)
- 亚马逊手机端测评软件/PC端测评软件各有什么优缺点?
- Mysql的timestamp与datetime
- HTML之position:absolute relative static fixed的区别和理解
- 树的距离(牛客网树上主席树+dfs序)
- 使用Java中的equals()和compareTo()方法比较字符串
- Unittest方法 -- 测试固件(TestFixture)
- android plugin 镜像,cordova-plugin-screen-orientation
- triz矛盾矩阵_TRIZ—创新性问题解决理论与实务培训
- C#学生管理系统源代码
- hua图软件 mac_实用电脑绘图软件~推荐_mac_微软怎么样_智能_魅可怎么样_圣诞节去哪玩_ipad_绘图软件_科技数码_应用推荐...
- pytorch 中的 forward 的使用与解释
- 如何查看mysql的gtid_mode_配置MHA开启主从同步的时候会提示从库gtid_mode为ON的状态...
- 6.10力扣 10号出去逛街了,11号补上! 打印n位数
- 最新Z-blog黑色极简风格文章博客主题模板源码
- java中四大层次结构
- 大学计算机专业实习报告
- python 自行安装第三方库包
- 电子设计数字钟,multisim仿真·
- 超有用的电脑配置知识!!以后买电脑就不会被忽悠啦!终身受用!
热门文章
- ajax将数据显示在class为content的标签中_利用selenium实现自动翻页爬取某鱼数据
- 什么是java枚举_什么是java枚举
- Python基础教程学习目录 - Python入门教程
- 计算机用户 图片存储位置,手机相册在哪个文件夹,详细教您手机图片存放在哪里...
- oracle undo管理机制,Oracle UNDO数据概念和管理
- wamp怎么安装mysql服务器_用wamp的mysq安装pythonmysql
- 软件测试技术qtp,51Testing独家连载:(四十一)精通QTP——自动化测试技术领航
- lua_path环境变量设置linux,ubuntu16.04安装lua环境
- php毕设,php毕设
- c语言内容逆置程序设计,C语言程序设计练习题含程序及参考答案.docx