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. SpringCloud微服务(07):Zipkin组件,实现请求链路追踪

    本文源码:GitHub·点这里 || GitEE·点这里 一.链路追踪简介 1.Sleuth组件简介 Sleuth是SpringCloud微服务系统中的一个组件,实现了链路追踪解决方案.可以定位一个请 ...

  2. 通过idea将maven工程转为web项目

    前言 吐槽一下网上的各种转换教程..说的真的是吵来吵去,有用的东西极少.特此自己写一篇好使的. 转换过程 建好的maven工程 建好的maven工程长这个鬼样子~~,没有使用骨架.就是普通的建立方式. ...

  3. PlayJava Day012

    今日所学: /* 2019.08.19开始学习,此为补档. */ JPanel和JFrame 1.JFrame是最底层,JPanel是置于其面上,同一个界面只有一个JFrame,一个JFrame可以放 ...

  4. SSH框架之Struts2第三篇

    1.3相关知识点 : 1.3.1 OGNL的表达式 : 1.3.1.1 什么是OGNL OGNL是Object-Graph Navigation Language的编写,它是一种功能强大的表达式语言, ...

  5. 面试再问ThreadLocal,别说你不会

    转载自:公众号<Java知音> ThreadLocal是什么 以前面试的时候问到ThreadLocal总是一脸懵逼,只知道有这个哥们,不了解他是用来做什么的,更不清楚他的原理了.表面上看他 ...

  6. JVM从入门开始深入每一个底层细节

    1 官网 1.1 寻找JDK文档过程 www.oracle.com -> 右下角Product Documentation -> 往下拉选择Java -> Java SE docum ...

  7. 从华为“鸿蒙”备胎看IT项目建设

    别误会啊,本文并不在讲大家在做IT项目建设的时候学华为做一个备胎系统,以防正主系统崩掉之后能够及时替换到备胎系统里面,不影响业务. 前段时间华为被美帝制裁,然后各家组织对华为各种限制.然而华为整体布局 ...

  8. WebGL-3D地图大俯仰角的雾化处理

    腾讯位置服务Javascript API GL版,是基于WebGL技术打造的地图API库,使得浏览器环境下也可实现APP端的应用体验,提供2D/3D模式,运行流畅.当前版本提供地图展示.标记.信息窗口 ...

  9. springboot进入html

    话不多说,转载 https://blog.csdn.net/sinat_33889619/article/details/78339042 这个博客写的真好

  10. Django 模板变量之 forloop

    1. 模板变量之forloop.counter:从1开始自增1 模板代码如下: {% for row in v %} <tr> <td>{{forloop.counter}}& ...