@Yano
2017-08-06T10:00:45.000000Z
字数 3867
阅读 2252
Java
对于JDK源码分析的文章,仅仅记录我认为重要的地方。源码的细节实在太多,不可能面面俱到地写清每个逻辑。所以我的JDK源码分析,着重在JDK的体系架构层面,具体源码可以参考:博客园:如果天空不死-博客。
在开始研究异常的源码之前,首先看一下下面的示例:
@Testpublic 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 是所有 errors 和 exceptions 的父类,只有继承了 Throwable 才能被 Java 语句中的异常捕获。一个 Throwable 对象包含线程创建到执行至异常处的所有栈。同时也包括一个额外的 message 信息,来描述异常。
Exception 也并没有什么代码,基本上就是继承了 Throwable 而已!重要的是 Exception 可以被捕获,而 Error 不需要也不能被捕获!
Error 表示非常严重的错误,一个正常的程序不应该 catch 这个错误。这些错误是「非检查异常」,在编译期是无法发现的。
最重要的成员:
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 traces.println(this);StackTraceElement[] trace = getOurStackTrace();for (StackTraceElement traceElement : trace)s.println("\tat " + traceElement);// Print suppressed exceptions, if anyfor (Throwable se : getSuppressed())se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); // Print cause, if anyThrowable ourCause = getCause();if (ourCause != null)ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);}}
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 最重要的意义,在于 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即可!