JVM 中的异常处理

Java 发表评论

 通常来说在JVM中构建一个异常实例是一个十分昂贵的动作。 因为在构建异常的时候,JVM就需要生成一个异常栈轨迹(stack trace)。这个操作会逐一访问当前线程的Java 栈帧,并且记录下调试的各种信息,比如:所在的方法名,方法所在的类,文件名,以及具体在什么代码行。(抛出异常的时候可见)

 

JVM具体是怎么抛出异常的

首先JVM在编译的时候,每个方法都会附带一个异常表(异常表会声明会被抛出的异常,而不是可能抛出的异常,包括catch里面自定义的异常)。异常表中每一个条目代表一个异常发生器,异常发生器由 From指针,To指针,Target指针和应该捕获的异常类型构成。 其中From指针和To指针该异常处理器所监控的范围,例如在try{}里面。 而target指针则指向异常处理器的起始位置。例如catch代码块的起始位置。

 

上面是转载郑雨迪老师的测试用例。从字节码中可以看出,索引3 是From指向的位置,索引6是To指针的位置。它们正好涵盖了try代码块。表示异常处理器所监视的范围。接下来索引位置7则代表Target指针所指向的地方。它代表异常处理器开始的位置。

但是finally代表块较为复杂。现在版本使用的方法是复制。相当于在所有Try{} ,catch{}的正常出口方向都复制一个finnaly 代码块。如下图:

每一个target相当于我指向这份复制的finnaly代码块。但是在最后原始的finnaly代码块 还是会在抛出一遍异常。这里有一个问题是如果在Catch异常的时候不幸的又发生了另外一个异常,这时候只会抛出在 catch 时候的异常,另外一个异常将会被抑制。这个时候我们可以用Throwable.getSuppressed方法找回被压抑的异常。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

昵称 *