异常是怎么被处理的?这题的答案不在源码里面。 (中)

简介: 异常是怎么被处理的?这题的答案不在源码里面。 (中)

也就是告诉 JVM,如果出异常了,请从这里开始处理。

最后,看 catch_type 参数,对应的是 Exception table 里面的 type。

这里就是程序捕获的异常。

比如我把程序修改为这样,捕获三种类型的异常:

image.png

image.png

image.png

别问,问就是语法规定。

具体是啥语法规定呢?

就在异常表的这个地方:

image.png

编译器会检查该类是否是 Throwable 或 Throwable 的子类。

关于 Throwable、Exception、Error、RuntimeException 就不细说了,生成一个继承关系图给大家看就行了:

image.png

所以,上面的消息汇总一下:

  • from:可能发生异常的起始点指令索引下标(包含)
  • to:可能发生异常的结束点指令索引下标(不包含)
  • target:在from和to的范围内,发生异常后,开始处理异常的指令索引下标
  • type:当前范围可以处理的异常类信息

知道了异常表之后,可以回答这个问题了:异常怎么被抛出的?

JVM 通过异常表,帮我们抛出来的。

异常表里面有啥?

前面我说了,不再赘述。

异常表怎么用呢?

简单描述一下:

1.如果出现异常了,JVM 会在当前的方法中去寻找异常表,查看是否该异常被捕获了。

2.如果在异常表里面匹配到了异常,则调用 target 对应的索引下标的指令,继续执行。

好,那么问题又来了。如果匹配不到异常怎么办呢?

我在官网文档的这里找到了答案:

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-3.html#jvms-3.12

它的示例代码是这样的:

image.png

然后下面有这样的一句描述:

image.png

意思就是如果抛出的值与 catchTwo 的任何一个 catch 子句的参数不匹配,Java虚拟机就会重新抛出该值,而不调用 catchTwo 的任何一个 catch 子句中的代码。

什么意思?

说白了就是反正我处理不了,我会把异常扔给调用方。

这是编程常识,大家当然都知道。

但是当常识性的东西,以这样的规范的描述展示在你面前的时候,感觉还是挺奇妙的。

当别人问你,为什么是这样的调用流程的时候,你说这是规定。

当别人问你,规定在哪的时候,你能把官网文档拿出来扔他脸上,指着说:就是这里。

虽然,好像没啥卵用。



稍微特殊的情况


这一趴再简单的介绍一下有 finally 的情况:

public class MainTest {
   public static void main(String[] args) {
       try {
           int a = 1 / 0;
       } catch (Exception e) {
           e.printStackTrace();
       } finally {
           System.out.println("final");
       }
   }
}

经过 javap 编译后,异常表部分出现了三条记录:


image.png


第一条认识,是我们主动捕获的异常。

第二三条都是 any,这是啥玩意?

答案在这:

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-3.html#jvms-3.13


image.png


主要看我画线的地方:

一个带有 finally 子句的 try 语句被编译为有一个特殊的异常处理程序,这个异常处理程序可以处理在 try 语句中抛出的(any)任何异常。

所有,翻译一下上面的异常表就是:

  • 如果 0 到 4 的指令之间发生了 Exception 类型的异常,调用索引为 15 的指令,开始处理异常。
  • 如果 0 到 4 的指令之间,不论发生了什么异常,都调用索引为 31 的指令(finally 代码块开始的地方)
  • 如果 15 到 20 的指令之间(也就是 catch 的部分),不论发生了什么异常,都调用索引为 31 的指令。

接着,我们把目光放到这一部分:

image.png


目录
相关文章
|
2月前
|
存储
关于递归处理,应该怎么处理,思路是什么?
本文讨论了如何使用递归处理将嵌套对象中的所有名称(name)属性转换为标签(label)属性的问题,提供了详细的递归函数实现思路和代码示例。
29 0
关于递归处理,应该怎么处理,思路是什么?
|
5月前
|
存储 算法 数据挖掘
【模拟面试问答】力扣165题:比较版本号(逐个比较与双指针法详解及模拟面试问答)
【模拟面试问答】力扣165题:比较版本号(逐个比较与双指针法详解及模拟面试问答)
循环初级一(附小练习和详细代码答案)
循环初级一(附小练习和详细代码答案)
110 0
|
11月前
|
存储 C++
数据的存储练习题 -- (解题思路+代码)
数据的存储练习题 -- (解题思路+代码)
62 0
|
前端开发 JavaScript
循环初级二(附小练习及其代码答案)
循环初级二(附小练习及其代码答案)
65 0
|
IDE 程序员 开发工具
一道面试题的最终答案
一道面试题的最终答案
115 1
|
存储 算法 C语言
想要去欺负Leetcode的这些年——第二次,看看咱们是怎么把数组玩转,把数列理解透彻的~
想要去欺负Leetcode的这些年——第二次,看看咱们是怎么把数组玩转,把数列理解透彻的~
144 0
想要去欺负Leetcode的这些年——第二次,看看咱们是怎么把数组玩转,把数列理解透彻的~
AnswerGame答案解析
AnswerGame答案解析
63 0