既然Throwable是异常处理机制的核心,那么,我们就来分析下它的源码来看看它是如何实现的。

进行分析前,我们可以先想想如果让我们实现一个异常处理机制,我们需要它做什么?

  1. 发生异常终止程序执行,

  2. 选择备选方案继续程序执行,

  3. 可以显示程序出现具体位置。

 异常终止,跳转等这些都是虚拟机来进行管理的,通过关键字,我们无从更深的考究。但是,异常的输出,我们可以通过源码来看看他的过程。

首先我们需要获取发生异常的具体位置信息。虚拟机的本地方法栈为我们提供了获取某个线程执行的方法调用深度以及方法信息和执行位置信息接口。

 /**
* Returns the number of elements in the stack trace (or 0 if the stack
* trace is unavailable).
*
* package-protection for use by SharedSecrets.
*/
native int getStackTraceDepth(); /**
* Returns the specified element of the stack trace.
*
* package-protection for use by SharedSecrets.
*
* @param index index of the element to return.
* @throws IndexOutOfBoundsException if {@code index < 0 ||
* index >= getStackTraceDepth() }
*/
native StackTraceElement getStackTraceElement(int index);

printStackTrace方法具体实现

    private void printStackTrace(PrintStreamOrWriter s) {
// Guard against malicious overrides of Throwable.equals by
// using a Set with identity equality semantics.
Set<Throwable> dejaVu =
Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
dejaVu.add(this); synchronized (s.lock()) {
// Print our stack trace
s.println(this);
StackTraceElement[] trace = getOurStackTrace();
for (StackTraceElement traceElement : trace)
s.println("\tat " + traceElement); // Print suppressed exceptions, if any
for (Throwable se : getSuppressed())
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); // Print cause, if any
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
}
}

从中我们可以看到主要设计到三部分的输出,第一个是执行过程位置信息,第二个是提供的异常信息输出,第三个就是异常信息输出。

⚠️ 红线部分可以看出通过使用自带输出工具显示需要加锁,可以看出使用自带异常输出效率是很低的。

执行过程信息:

 private synchronized StackTraceElement[] getOurStackTrace() {
// Initialize stack trace field with information from
// backtrace if this is the first call to this method
if (stackTrace == UNASSIGNED_STACK ||
(stackTrace == null && backtrace != null) /* Out of protocol state */) {
int depth = getStackTraceDepth();
stackTrace = new StackTraceElement[depth];
for (int i=0; i < depth; i++)
stackTrace[i] = getStackTraceElement(i);
} else if (stackTrace == null) {
return UNASSIGNED_STACK;
}
return stackTrace;
}

提供的异常信息:

 public final synchronized void addSuppressed(Throwable exception) {
if (exception == this)
throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE, exception); if (exception == null)
throw new NullPointerException(NULL_CAUSE_MESSAGE); if (suppressedExceptions == null) // Suppressed exceptions not recorded
return; if (suppressedExceptions == SUPPRESSED_SENTINEL)
suppressedExceptions = new ArrayList<>(1); suppressedExceptions.add(exception);
}

异常信息:

 public synchronized Throwable getCause() {
return (cause==this ? null : cause);
}

好处:

   通过对源码分析我们可以更加直观知道异常信息是怎么输出的,这样如果我们想基于异常信息进行一些程序的个性化定制也成为一重可能,比如日志搜集的使用。

JAVA异常处理分析高级进界(下)的更多相关文章

  1. JAVA异常处理分析(中)

    在使用java异常处理机制时候我们会发现有些异常抛出后可以不需要进行抓取处理,而有些异常必须要进行抓取处理,这是个什么情况呢? 设计理念猜想:      有一些场景的异常,是可以不需要处理或是经常不会 ...

  2. java异常处理机制

    本文从Java异常最基本的概念.语法开始讲述了Java异常处理的基本知识,分析了Java异常体系结构,对比Spring的异常处理框 架,阐述了异常处理的基本原则.并且作者提出了自己处理一个大型应用系统 ...

  3. Java异常处理机制难点解惑-用代码说话

    是否需要看这篇文章? 下面的例子中,如果正常执行返回值多少? 如果出现了ArithmeticException返回值多少? 如果出现非ArithmeticException(如NullPointerE ...

  4. 谈谈你对Java异常处理机制的理解

    先谈谈我的理解:异常处理机制可以说是让我们编写的程序运行起来更加的健壮,无论是在程序调试.运行期间发生的异常情况的捕获,都提供的有效的补救动作,任何业务逻辑都会存在异常情况,这时只需要记录这些异常情况 ...

  5. 引用面试官文章 :如何准备Java初级和高级的技术面试

    本人最近几年一直在做java后端方面的技术面试官,而在最近两周,又密集了面试了一些java初级和高级开发的候选人,在面试过程中,我自认为比较慎重,遇到问题回答不好的候选人,我总会再三从不同方面提问,只 ...

  6. 深入探索 高效的Java异常处理框架

    转载自:http://www.sunwei.org/archives/196 摘要:本文从Java异常最基本的概念.语法开始讲述了Java异常处理的基本知识,分析了Java异常体系结构,对比Sprin ...

  7. Java异常处理的9个最佳实践

    无论你是新手还是资深程序员,复习下异常处理的实践总是一件好事,因为这能确保你与你的团队在遇到问题时能够处理得了它. 在 Java 中处理异常并不是一件易事.新手觉得处理异常难以理解,甚至是资深开发者也 ...

  8. Java异常处理的基础知识

    Java中的异常捕获语句 Try{ //可能发生运行错误的代码: } catch(异常类型 异常对象引用){ //用于处理异常的代码 } finally{ //用于“善后” 的代码 } Java 中所 ...

  9. 札记:Java异常处理

    异常概述 程序在运行中总会面临一些"意外"情况,良好的代码需要对它们进行预防和处理.大致来说,这些意外情况分三类: 交互输入 用户以非预期的方式使用程序,比如非法输入,不正当的操作 ...

随机推荐

  1. java利用poi 把ppt转化为图片,

    导入jar包: poi-3.8.jar poi-ooxml-3.9.jar poi-scratchpad-3.8.jar 代码: package test4; import java.awt.Dime ...

  2. zabbix 部署 jmx 监控tomcat

    zabbix提供了一个java gateway的应用去监控jmx(Java Management Extensions,即Java管理扩展)是一个为应用程序.设备.系统等植入管理功能的框架.JMX可以 ...

  3. Yii 各种url地址写法

    echo Url::home(); 生成入口地址/yii2test/frontend/web/index.php: echo  Url::base();生成入口文件夹地址:/yii2test/fron ...

  4. CH1809匹配统计【KMP】

    1809 匹配统计 0x18「基本数据结构」练习 描述 阿轩在纸上写了两个字符串,分别记为A和B.利用在数据结构与算法课上学到的知识,他很容易地求出了“字符串A从任意位置开始的后缀子串”与“字符串B” ...

  5. vitess基础镜像构建流程Centos

    以下列出了构建vitess使用的Centos镜像的简单流程,由于较早基础版本是Centos7.2的,重新构建可以基于最新的Centos版本构建 1.基础镜像拉取 #拉取官方版本 docker pull ...

  6. nginx+lua构建简单waf网页防火墙

    需求背景 类似于论坛型的网站经常会被黑掉,除了增加硬件防护感觉效果还是不太好,还会偶尔被黑,waf的功能正好实现了这个需求. waf的作用: 防止sql注入,本地包含,部分溢出,fuzzing测试,x ...

  7. java 并查集

    并查集代码 并查集优化⼀ 并查集优化⼆ 实战题⽬目1. https://leetcode.com/problems/number-of-islands/2. https://leetcode.com/ ...

  8. Git学习-->如何通过Shell脚本实现 监控Gitlab备份整个过程并且通过邮件通知得到备份结果?

    一.背景 Git学习–>如何通过Shell脚本自动定时将Gitlab备份文件复制到远程服务器? http://blog.csdn.net/ouyang_peng/article/details/ ...

  9. IScroll5中文API整理,用法与参考

    IScroll是移动页面上被使用的一款仿系统滚动插件.IScroll5相对于之前的IScroll4改进了许多,使得大家可以更方便的定制所需的功能了. 做项目的时候正好用到了这个插件,自己做了一下总结, ...

  10. tp基础补充

    ThinkPHP php框架 真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维护项目,十分 ...