[关闭]
@Yano 2017-08-06T10:00:45.000000Z 字数 3867 阅读 1707

JDK源码分析 异常

Java


说明

对于JDK源码分析的文章,仅仅记录我认为重要的地方。源码的细节实在太多,不可能面面俱到地写清每个逻辑。所以我的JDK源码分析,着重在JDK的体系架构层面,具体源码可以参考:博客园:如果天空不死-博客

例子

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

  1. @Test
  2. public void testThrowable() {
  3. try {
  4. int a = 1 / 0;
  5. } catch (Exception e) {
  6. System.out.println(e.getMessage());
  7. System.out.println(e.getCause());
  8. e.printStackTrace();
  9. }
  10. }

输出

/ 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都表示一个方法调用。

源码如下:

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

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

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

主要看一个经常用到的用于打印堆栈信息的函数:printStackTrace。

  1. private void printStackTrace(PrintStreamOrWriter s) {
  2. // Guard against malicious overrides of Throwable.equals by
  3. // using a Set with identity equality semantics.
  4. Set<Throwable> dejaVu =
  5. Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
  6. dejaVu.add(this);
  7. synchronized (s.lock()) {
  8. // Print our stack trace
  9. s.println(this);
  10. StackTraceElement[] trace = getOurStackTrace();
  11. for (StackTraceElement traceElement : trace)
  12. s.println("\tat " + traceElement);
  13. // Print suppressed exceptions, if any
  14. for (Throwable se : getSuppressed())
  15. se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
  16.  // Print cause, if any
  17. Throwable ourCause = getCause();
  18. if (ourCause != null)
  19. ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
  20. }
  21. }

Exception 源码分析

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

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

Error 源码分析

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

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

总结

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

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注