Java中异常捕获的原理

本文详细解释了Java中异常捕获的实现机制,包括try-catch如何工作、异常表的作用,以及finally块的执行逻辑。它强调了编译期生成的异常表在处理异常时的关键作用,以及不同类型的异常如何匹配和处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        在Java中,程序遇到异常时会向外抛出,此时可以使用try-catch捕获异常的方式将异常捕获并继续让程序按程序员设计好的方式运行。

异常捕获机制的实现,需要借助于编译时生成的异常表

        

        异常表在编译期生成,存放的是代码中异常的处理信息,包含了异常捕获的生效范围以及异常发生后跳转到的字节码指令位置。

起始/结束PC:此条异常捕获生效的字节码起始/结束位置。

跳转PC:异常捕获之后,跳转到的字节码位置。

异常类型 : 需要捕获的异常具体类型

    public void test4() {
        int i = 0;
        try {
           i = 1;
        } catch (Exception e) {
            i = 2;
        }
    }

字节码如下 :

 0 iconst_0
 1 istore_1
 2 iconst_1
 3 istore_1
 4 goto 10 (+6)
 7 astore_2
 8 iconst_2
 9 istore_1
10 return

        在位置2到4字节码指令执行范围内,如果出现了Exception对象的异常或者子类对象异常,直接跳转到位置7的指令。也就是i = 2代码位置。

        程序运行中触发异常时,Java 虚拟机会从上至下遍历异常表中的所有条目。当触发异常的字节码的索引值在某个异常表条目的监控范围内,Java 虚拟机会判断所抛出的异常和该条目想要捕获的异常是否匹配。

1、如果匹配,跳转到“跳转PC”对应的字节码位置。

2、如果遍历完都不能匹配,说明异常无法在当前方法执行时被捕获,此方法栈帧直接弹出,在上一层的栈帧中进行异常捕获的查询。

        多个catch分支情况下,异常表会从上往下遍历,先捕获RuntimeException,如果捕获不了,再捕获Exception。

        finally的处理方式就相对比较复杂一点了,分为以下几个步骤:

1、finally中的字节码指令会插入到try 和 catch代码块中,保证在try和catch执行之后一定会执行finally中的代码。

如下,在i=1i=2两段字节码指令之后,都加入了finally下的字节码指令。

2、如果抛出的异常范围超过了Exception,比如Error或者Throwable,此时也要执行finally,所以异常表中增加了两个条目。覆盖了try和catch两段字节码指令的范围,any代表可以捕获所有种类的异常。

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值