try catch finally执行流程原理分析

try catch finally语句执行流程原理分析

碰到一道讨人try catch语句的面试题,代码如下:

package test;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(test.testTryCatch());
	}
	
	public static int testTryCatch() {
		int x = 1;
		
		try {
			return x;
		}
		finally {
			++ x;
		}
	}

}

这道题的输出是1,最开始碰到的时候,我以为答案应该是2,因为finally语句块肯定会执行啊!执行了的话那为啥值还不增加呢?后来查了一些博客,发现一篇用虚拟机的字节码指令来解释try catch执行流程的博客,但是觉得解释的不是很清楚(这里就不列出来了啊!懒得去翻了 = =),然后自己也去实验了一下,用jdk 自带的javap程序查看上述代码的class文件(注意加上参数-c),可得到下面的指令序列(这里就列出testTryCatch方法的指令序列了)

在这里插入图片描述
上面指令是可在Wiki百科上查阅具体作用,这里就不累赘了。

下面说一下为什么会是输出1。

首先,第零条和第一条指令对应函数中的那条x=1语句,效果就是先把int型的1常量push入操作数栈里,然后又pop出放入局部变量表中的第零个slot(在深入理解java虚拟机书中说第零个slot默认应该是用来放该方法所属对象实例的引用,但是我们这里的testTryCatch是声明为了静态方法,所以就把第一个局部变量放入了第零个slot)。
第二条,第三条,第七条和第八条对应try块里那条return语句,这里说明return语句执行有两步:第一步是把return后面的要返回的值计算出并放入局部变量表特定的位置(一般是放到要用到的变量之后的一个slot),第二步就是把之前局部变量表中要返回的值推入栈顶,并执行ireturn指令,将栈顶的值出栈并返回。第一步和第二步之间就是执行的finally语句快中的代码,如第四条指令iinc,这条指令对应的是++x这条语句,就是把x所在的第零个slot中的值自增1。
ireturn指令之后的第九条到第十四条指令是出现异常后的执行路径,这里就简单说一下:大体就是,把生成的异常对象的引用放入第一个slot,然后再执行finally块里的代码,然后使用athrow抛出保存的那个引用,实际上跟正常执行的流程是差不多的

这里try catch finally语句算是讲清楚了,总的来说就是总共try catch finally语句有一条正常执行路径,一条未声明异常的处理路径,加上已经显示声明的catch语句数量的路径,就像异常表里描述的那样。然后每条路径的Treturn 或 athrow都是有两步,分别为保存值和返回值,两部中间是执行finally代码块。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值