package java.lang;
import java.io.*;
/**
*
* Throwable是所有Error和Exceptiong的父类
* 注意它有四个构造函数:
* Throwable()
* Throwable(String message)
* Throwable(Throwable cause)
* Throwable(String message, Throwable cause)
*
*/
public class Throwable implements Serializable {
private static final long serialVersionUID = -3042686055658047285L; /**
* Native code saves some indication of the stack backtrace in this slot.
*/
private transient Object backtrace; /**
* 描述此异常的信息
*/
private String detailMessage; /**
* 表示当前异常由那个Throwable引起
* 如果为null表示此异常不是由其他Throwable引起的
* 如果此对象与自己相同,表明此异常的起因对象还没有被初始化
*/
private Throwable cause = this; /**
* 描述异常轨迹的数组
*/
private StackTraceElement[] stackTrace; /**
* 构造函数,起因对象没有被初始化可以在以后使用initCause进行初始化
* fillInStackTrace可以用来初始化它的异常轨迹的数组
*/
public Throwable() {
fillInStackTrace();
} /**
* 构造函数
*/
public Throwable(String message) {
//填充异常轨迹数组
fillInStackTrace();
//初始化异常描述信息
detailMessage = message;
} /**
* 构造函数,cause表示起因对象
*/
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);
} /**
* 初始化起因对象,这个方法只能在未被初始化的情况下调用一次
*/
public synchronized Throwable initCause(Throwable cause) {
//如果不是未初始化状态则抛出异常
if (this.cause != this)
throw new IllegalStateException("Can't overwrite cause"); //要设置的起因对象与自身相等则抛出异常
if (cause == this)
throw new IllegalArgumentException("Self-causation not permitted"); //设置起因对象
this.cause = cause;
//返回设置的起因的对象
return this;
} /**
* 字符串表示形式
*/
public String toString() {
String s = getClass().getName();
String message = getLocalizedMessage();
return (message != null) ? (s + ": " + message) : s;
} /**
* 打印出错误轨迹
*/
public void printStackTrace() {
printStackTrace(System.err);
} /**
* 打印出错误轨迹
*/
public void printStackTrace(PrintStream s) {
synchronized (s) {
//调用当前对象的toString方法
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);
}
} /**
* 打印起因对象的信息
* @param s 打印的流
* @param causedTrace 有此对象引起的异常的异常轨迹
*/
private void printStackTraceAsCause(PrintStream s,
StackTraceElement[] causedTrace)
{
//获得当前的异常轨迹
StackTraceElement[] trace = getOurStackTrace();
//m为当前异常轨迹数组的最后一个元素位置,
//n为当前对象引起的异常的异常轨迹数组的最后一个元素
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"); //获得此对象的起因对象,并递归打印出信息
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);
} /**
* 填充异常轨迹
*/
public synchronized native Throwable fillInStackTrace(); /**
* 返回当前的异常轨迹的拷贝
*/
public StackTraceElement[] getStackTrace() {
return (StackTraceElement[]) getOurStackTrace().clone();
} /**
* 获取当前的异常轨迹
*/
private synchronized StackTraceElement[] getOurStackTrace() {
//如果第一次调用此方法则初始化异常轨迹数组
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;
} /**
* 异常轨迹的深度,0表示无法获得
*/
private native int getStackTraceDepth(); /**
* 获取指定位标的异常轨迹
*/
private native StackTraceElement getStackTraceElement(int index); private synchronized void writeObject(java.io.ObjectOutputStream s)
throws IOException
{
getOurStackTrace();
s.defaultWriteObject();
}
}

异常处理类-Throwable源码详解的更多相关文章

  1. JUC锁:核心类AQS源码详解

    目录 1 疑点todo和解疑 2 AbstractQueuedSynchronizer学习总结 2.1 AQS要点总结 2.2 细节分析 2.2.1 插入节点时先更新prev再更新前驱next 2.2 ...

  2. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  3. Shiro 登录认证源码详解

    Shiro 登录认证源码详解 Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加 ...

  4. Activiti架构分析及源码详解

    目录 Activiti架构分析及源码详解 引言 一.Activiti设计解析-架构&领域模型 1.1 架构 1.2 领域模型 二.Activiti设计解析-PVM执行树 2.1 核心理念 2. ...

  5. 源码详解系列(七) ------ 全面讲解logback的使用和源码

    什么是logback logback 用于日志记录,可以将日志输出到控制台.文件.数据库和邮件等,相比其它所有的日志系统,logback 更快并且更小,包含了许多独特并且有用的特性. logback ...

  6. RocketMQ源码详解 | Producer篇 · 其二:消息组成、发送链路

    概述 在上一节 RocketMQ源码详解 | Producer篇 · 其一:Start,然后 Send 一条消息 中,我们了解了 Producer 在发送消息的流程.这次我们再来具体下看消息的构成与其 ...

  7. RocketMQ源码详解 | Broker篇 · 其一:线程模型与接收链路

    概述 在上一节 RocketMQ源码详解 | Producer篇 · 其二:消息组成.发送链路 中,我们终于将消息发送出了 Producer,在短暂的 tcp 握手后,很快它就会进入目的 Broker ...

  8. RocketMQ源码详解 | Consumer篇 · 其一:消息的 Pull 和 Push

    概述 当消息被存储后,消费者就会将其消费. 这句话简要的概述了一条消息的最总去向,也引出了本文将讨论的问题: 消息什么时候才对被消费者可见? 是在 page cache 中吗?还是在落盘后?还是像 K ...

  9. 条件随机场之CRF++源码详解-预测

    这篇文章主要讲解CRF++实现预测的过程,预测的算法以及代码实现相对来说比较简单,所以这篇文章理解起来也会比上一篇条件随机场训练的内容要容易. 预测 上一篇条件随机场训练的源码详解中,有一个地方并没有 ...

随机推荐

  1. 配置, 映射WebDAV, 并通过IIS网站访问

    服务端 0. 服务端安装IIS时, 选中WebDAV发布, Windows身份验证, 安装完毕后, 打开IIS管理器(inetmgr); 1. 新建网站或使用默认网站, 创建虚拟目录, 虚拟目录物理路 ...

  2. Selenium(二):选择元素的基本方法

    1. 选择元素的基本方法 对于百度搜索页面,如果我们想自动化输入爱编程的小灰灰,怎么做呢? 这就是在网页中,操控界面元素. web界面自动化,要操控元素,首先需要选择界面元素 ,或者说定位界面元素 就 ...

  3. Java生鲜电商平台-订单模块状态机架构设计

    Java生鲜电商平台-订单模块状态机架构设计 说明:在Java生鲜电商平台中订单的状态流转业务        我们知道 一个订单会有很多种状态:临时单.已下单.待支付.待收货.待评价.已完成,退货中等 ...

  4. Java 反射机制 初探*

    反射机制初探 * 走进沼泽 在正常的程序中,先有类,然后再有对象. 取得Class对象(类对象) public final Class<?> getClass() ; 实例观察: publ ...

  5. kali安装vmtool后依旧无法拖拽文件,复制粘贴,解决办法

    本文链接:https://blog.csdn.net/Key_book/article/details/80310235命令行下 执行 apt-get install open-vm-tools-de ...

  6. python升级带来的yum异常(解决错误File "/usr/bin/yum", line 30 except KeyboardInterrupt, e:)

    解决错误File "/usr/bin/yum", line 30 except KeyboardInterrupt, e: 错误: 原因: 这是因为yum采用python作为命令解 ...

  7. ffmpeg-python 任意提取视频帧

    ▶ 环境准备 1.安装 FFmpeg 音/视频工具 FFmpeg 简易安装文档 2.安装 ffmpeg-python pip3 install ffmpeg-python 3.[可选]安装 openc ...

  8. 原生JS无缝轮播图

    (1)原理介绍 (2)静态布局 <!DOCTYPE html> <html> <head> <meta charset="utf-8"&g ...

  9. LEETCODE 1254 统计封闭岛屿的数目 Number of Closed Islands

    地址 https://leetcode-cn.com/contest/weekly-contest-162/problems/number-of-closed-islands/ 有一个二维矩阵 gri ...

  10. 第05组 Beta冲刺(4/4)

    第05组 Beta冲刺(4/4) 队名:天码行空 组长博客连接 作业博客连接 团队燃尽图(共享): GitHub当日代码/文档签入记录展示(共享): 组员情况: 组员1:卢欢(组长) 过去两天完成了哪 ...