parent
aa3418b879
commit
fb91866b4c
@ -0,0 +1,55 @@ |
|||||||
|
--- |
||||||
|
异常 |
||||||
|
--- |
||||||
|
|
||||||
|
#### 目录 |
||||||
|
|
||||||
|
1. 思维导图 |
||||||
|
2. 概述 |
||||||
|
3. 异常处理 |
||||||
|
4. 实现原理 |
||||||
|
5. 参考 |
||||||
|
|
||||||
|
#### 思维导图 |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 概述 |
||||||
|
|
||||||
|
在 Java 语言规范中,所有异常都是 Throwable 类或者其子类的实例。Throwable 有两大直接子类。第一个是 Error,涵盖程序不应捕获的异常,当程序触发 Error 时,它的执行状态已经无法恢复,需要中止线程甚至是中止虚拟机。第二个是 Exception,涵盖程序可能需要捕获并且处理的异常。Exception 又可以分为受检异常和非受检异常,受检异常是指需要显式捕获或声明的异常,非受检异常则是指 RuntimeException。 |
||||||
|
|
||||||
|
![](https://i.loli.net/2019/01/27/5c4da2c221a34.png) |
||||||
|
|
||||||
|
#### 异常处理 |
||||||
|
|
||||||
|
异常处理的两大组成要素是抛出异常和捕获异常,这两大要素共同实现程序控制流的非正常转移。 |
||||||
|
|
||||||
|
##### 抛出异常 |
||||||
|
|
||||||
|
抛出异常可以分为显式和隐式两种,显式抛异常的主体是应用程序,它指的是程序中使用 throw 关键字,手动将异常实例抛出。 |
||||||
|
|
||||||
|
隐式抛异常的主体则是 Java 虚拟机,它指的是 Java 虚拟机在执行过程中,碰到无法继续执行的异常状态,自动抛出异常。通常都是运行时异常。 |
||||||
|
|
||||||
|
##### 捕获异常 |
||||||
|
|
||||||
|
捕获异常设计 try-catch-final 语句块。 |
||||||
|
|
||||||
|
try 代码块用来标记需要进行异常监控的代码,catch 代码块跟在 try 代码块之后,用来捕获 try 代码块中触发的某种指定类型的异常。除了声明所捕获异常的类型之外,catch 代码块还定义了针对该异常类型的异常处理器。在 Java 中,try 代码块后面可以跟着多个 catch 代码块,来捕获不同类型的异常。Java 虚拟机会从上到下匹配异常处理器。因此,前面的 catch 代码块所捕获的异常类型不能覆盖后面的,否则编译器会报错。finally 代码块,跟在 catch 代码块之后,用来声明一段必定运行的代码。它的设计初衷是为了避免跳过某些关键的清理代码,例如关闭已打开的系统资源。 |
||||||
|
|
||||||
|
在某些不幸的情况下,catch 代码块也触发了异常,那么 finally 代码块同样会运行,并会抛出 catch 代码块触发的异常。在某些极端不幸的情况下,finally 代码块也触发了异常,那么只好中断当前 finally 代码块的执行,并往外抛异常。 |
||||||
|
|
||||||
|
#### 实现原理 |
||||||
|
|
||||||
|
异常实例的构造十分昂贵。这是由于在构造异常实例时,Java 虚拟机便需要生成该异常的栈轨迹(stack trace)。该操作会逐一访问当前线程的 Java 栈帧,并且记录下各种调试信息,包括栈帧所指向方法的名字,方法所在的类名、文件名,以及在代码中的第几行触发该异常。 |
||||||
|
|
||||||
|
那么 Java 虚拟机是如何捕获异常的? |
||||||
|
|
||||||
|
在编译生成的字节码中,每个方法都附带一个异常表。异常表中的每一个条目代表一个异常处理器,并且由 from 指针、to 指针、target 指针以及所捕获的异常类型构成。这些指针的值是字节码索引,用以定位字节码。 |
||||||
|
|
||||||
|
其中,from 指针和 to 指针标示了该异常处理器所指控的范围,即 try 代码块所覆盖的范围。target 指针则指向异常处理器的初始位置,例如 catch 代码块的起始位置。 |
||||||
|
|
||||||
|
当程序触发异常时,Java 虚拟机会从上至下遍历异常表中的所有条目。当触发异常的字节码的索引值在某个异常表条目的监控范围内,Java 虚拟机会判断所抛出的异常和该条目想要捕获的异常是否匹配。Java 虚拟机会将控制流转移至该条目 target 指针指向的字节码。 |
||||||
|
|
||||||
|
#### 参考 |
||||||
|
|
||||||
|
[JVM是如何处理异常的?](https://time.geekbang.org/column/article/12134) |
After Width: | Height: | Size: 195 KiB |
Loading…
Reference in new issue