java代码中的finally块,在字节码层面的变化

java代码中的finally块,会在字节码层面上多加一层对于any异常的处理

结论

不论在方法上显式抛出异常了,还是在代码块中try-catch了,如果代码块中存在finally块,当前方法的Code属性中就会出现异常表信息,且Code属性中bytecode部分会多出一套对any异常的处理

这篇文章部分细节不会说明

对比加和不加finally块

首先是不加finally块的

public class Study3 {

	public void test() {
		try {
			InputStream in = new FileInputStream("AAA"); 
			ServerSocket socket = new ServerSocket(9999);
			socket.accept();
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
}

我们使用javap -verbose 来反编译我们写的类
其他部分我们不关注,只关注 test方法这一块
在这里插入图片描述
我们在上图中 关注红框部分,首先是max_locals= 3最大局部变量slot占据数量是3,我们知道非静态方法中,jvm会将对当前类对象引用隐式传入方法中,我们看局部变量表部分,我们catch的异常e和try中变量in共用了同一个1号slot,原因是因为try 和catch的域不同,出现异常被catch捕获了,try里面变量生命周期结束,所以catch中e可以占用之前try里面变量的slot
如果可以请读一下Code中byteCode部分,加finally之后会发生变化
注意此时异常表 Exception table里面存在是我们定义的对 Exception异常的捕获

然后我们加上finally块(注意finally块里面必须有代码,若没有代码则跟等同于没有finally块)

public void test() {
		try {
			InputStream in = new FileInputStream("AAA"); 
			ServerSocket socket = new ServerSocket(9999);
			socket.accept();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("aaa");
		}
	}

在这里插入图片描述
在这里插入图片描述
加finally块之后最显著变化,我们max_locals变成了4,在Code属性中byteCode体现在多了一部分对any异常处理的代码,看图中红框部分 , astore_3 将对除Exception以外的any异常抓出并存储到本地slot是3的变量里面 ,在这里就跟我们正常catch中异常处理不同了,因为catch里面异常变量会存储在我们已有的slot内,而加finally额外多出对any异常处理的异常变量则会额外占用一个slot位置,这个局部变量不会体现在局部变量表 LocalVariableTable里面,所以我们在局部变量表里面看到最大的索引是2

在显式抛出异常的方法中加finally块我就不演示了,显式抛出异常的方法中如果没有finally块,反编译结果中只会有Exceptions属性,不会有Exception table异常表信息,如果加了finally块,就会多出异常表信息,里面是对any异常做的处理,大家可以自己试一下

不喜勿喷,有问题请留言

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值