JDK源码分析 异常

说明

对于JDK源码分析的文章,仅仅记录我认为重要的地方。源码的细节实在太多,不可能面面俱到地写清每个逻辑。所以我的JDK源码分析,着重在JDK的体系架构层面,具体源码可以参考:http://www.cnblogs.com/skywang12345/category/455711.html

例子

在开始研究异常的源码之前,首先看一下下面的示例:

@Test
public void testThrowable() {
    try {
        int a = 1 / 0;
    } catch (Exception e) {
        System.out.println(e.getMessage());
        System.out.println(e.getCause());
        e.printStackTrace();
    }
}

输出

/ by zero
null
java.lang.ArithmeticException: / by zero
    at test.jdk.testThrowable(jdk.java:383)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    ...

调试信息

异常的框架

Throwable

Throwable 是所有 errors 和 exceptions 的父类,只有继承了 Throwable 才能被 Java 语句中的异常捕获。一个 Throwable 对象包含线程创建到执行至异常处的所有栈。同时也包括一个额外的 message 信息,来描述异常。

Exception

Exception 也并没有什么代码,基本上就是继承了 Throwable 而已!重要的是 Exception 可以被捕获,而 Error 不需要也不能被捕获!

Error

Error 表示非常严重的错误,一个正常的程序不应该 catch 这个错误。这些错误是「非检查异常」,在编译期是无法发现的。

Throwable 源码分析

最重要的成员:

private StackTraceElement[] stackTrace = UNASSIGNED_STACK;

其中一个StackTraceElement代表一个栈帧,最顶端的StackTraceElement代表异常抛出地点,其余每个StackTraceElement都表示一个方法调用。

源码如下:

/**
 * An element in a stack trace, as returned by {@link
 * Throwable#getStackTrace()}.  Each element represents a single stack frame.
 * All stack frames except for the one at the top of the stack represent
 * a method invocation.  The frame at the top of the stack represents the
 * execution point at which the stack trace was generated.  Typically,
 * this is the point at which the throwable corresponding to the stack trace
 * was created.
 *
 * @since  1.4
 * @author Josh Bloch
 */
public final class StackTraceElement implements java.io.Serializable {
    // Normally initialized by VM (public constructor added in 1.5)
    private String declaringClass;
    private String methodName;
    private String fileName;
    private int    lineNumber;

UNASSIGNED_STACK 是一个空数组,用来表示未赋值的状态。

private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0];

主要看一个经常用到的用于打印堆栈信息的函数: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);
    }
}

Exception 源码分析

Exception 没有什么代码,只是继承了Throwable而已!

/**
 * The class {@code Exception} and its subclasses are a form of
 * {@code Throwable} that indicates conditions that a reasonable
 * application might want to catch.
 *
 * <p>The class {@code Exception} and any subclasses that are not also
 * subclasses of {@link RuntimeException} are <em>checked
 * exceptions</em>.  Checked exceptions need to be declared in a
 * method or constructor's {@code throws} clause if they can be thrown
 * by the execution of the method or constructor and propagate outside
 * the method or constructor boundary.
 *
 * @author  Frank Yellin
 * @see     java.lang.Error
 * @jls 11.2 Compile-Time Checking of Exceptions
 * @since   JDK1.0
 */
public class Exception extends Throwable {

Error 源码分析

Error 最重要的意义,在于 JVM 对它的约定。Error表示非常重要的错误,在编译期是无法检查出来的,程序不应该抛出Error。

/**
 * An {@code Error} is a subclass of {@code Throwable}
 * that indicates serious problems that a reasonable application
 * should not try to catch. Most such errors are abnormal conditions.
 * The {@code ThreadDeath} error, though a "normal" condition,
 * is also a subclass of {@code Error} because most applications
 * should not try to catch it.
 * <p>
 * A method is not required to declare in its {@code throws}
 * clause any subclasses of {@code Error} that might be thrown
 * during the execution of the method but not caught, since these
 * errors are abnormal conditions that should never occur.
 *
 * That is, {@code Error} and its subclasses are regarded as unchecked
 * exceptions for the purposes of compile-time checking of exceptions.
 *
 * @author  Frank Yellin
 * @see     java.lang.ThreadDeath
 * @jls 11.2 Compile-Time Checking of Exceptions
 * @since   JDK1.0
 */
public class Error extends Throwable {

总结

《Java编程思想》中提到:对于异常来说,最重要的是它的名字。异常的作用就是:用名字描述清楚所发生的错误,最好能够见名知意。用法也很简单:继承Exception即可!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏进击的君君的前端之路

知识点梳理

1102
来自专栏蘑菇先生的技术笔记

探索c#之不可变数据类型

2094
来自专栏佳爷的后花媛

java学习要点

作为一个程序员,在找工作的过程中,都会遇到笔试,而很多笔试里面都包括java,尤其是作为一个Android开发工程师,java是必备技能之一.所以为了笔试过程中...

3425
来自专栏搜云库

BTA 常问的 Java基础40道常见面试题及详细答案

最近看到网上流传着,各种面试经验及面试题,往往都是一大堆技术题目贴上去,而没有答案。

6016
来自专栏我是攻城师

Apache Pig学习笔记之内置函数(三)

4424
来自专栏个人分享

JAVA 几种引用类型学习

1、对象的强、软、弱和虚引用     在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及(re...

3452
来自专栏阿杜的世界

【译】Java 8的新特性—终极版1. 简介2. Java语言的新特性3. Java编译器的新特性4. Java官方库的新特性5. 新的Java工具6. JVM的新特性7. 结论8. 参考资料

前言: Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级。在Java Code Geeks上已经有很多介绍Java 8新特性的文章,...

1174
来自专栏纯洁的微笑

Java 8的新特性—终极版

1. 简介 毫无疑问,Java 8是Java自Java 5(发布于2004年)之后的最重要的版本。这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特...

4226
来自专栏WindCoder

JSON中关于对双向关联的支持

本文原文:Bidirectional Relationship Support in JSON

1862
来自专栏企鹅号快讯

不想再被鄙视?那就看进来!一文搞懂 Python 2 字符编码

来源:xybaby自荐投稿 www.cnblogs.com/xybaby/p/7814299.html 程序员都自视清高,觉得自己是创造者,经常鄙视不太懂技术的...

3436

扫码关注云+社区

领取腾讯云代金券