搜索
写经验 领红包
 > 地理

java中的tycatchfially(Java中的Bea是什么)

导语:java中的try catch finally return

先上代码

public class TestReturn {    public int testReturn(int a) {        try {            return a;        } finally {            a++;        }    }    public static void main(String[] args) {        System.out.println(new TestReturn().testReturn(1));    }}

代码很简单,输出结果为啥呢?1 or 2?

这是一道经常在笔试中考的java基础问题,这次我们从字节码的角度来分析一下,return究竟return了啥。

我们用javap -v命令对class文件进行反编译,得到如下描述(抽取方法部分):

字节码其实就是用jvm的指令(200多个)对栈和局部变量表的操作。

继续分析字节码:

初始值:栈顶:空,局部变量表:[this,1,...]

第六行:0: iload_1,iload是一个操作指令,表示加载局部变量表下标为1的值到栈顶,因为是普通方法,0放的是this对象,1放的是第一个入参,i表示此参数为int类型,iload_1表示把第一个入参加载到栈顶。

栈顶:1,局部变量表:[this,1,...]

第七行:1: istore_2,istore也是一个jvm指令,把栈顶值弹出存放到局部变量表下标为2的位置。

栈顶:空,局部变量表:[this,1,1,...]

第八行:2: iinc 1, 1,iinc是一个自增指令, 是对局部变量表里的内容做自增,参数1, 1表示在局部变量表的下标为1的值+1。

栈顶:空,局部变量表:[this,2,1,...]

第九行:5: iload_2,加载局部变量表下标为2的值到栈顶。

栈顶:1,局部变量表:[this,2,1,...]

第十行:6: ireturn,栈顶弹出返回,此时栈顶的值为1,所以返回值为1。

程序的主体部分到这里就结束了,但是我们发现下面还有好几行指令是在干嘛呢?

Exception table:         from    to  target type             0     2     7   any

Exception table: from to target type 0 2 7 any

先来看看这个Exception table,我们源代码里并没有写catch,但是javac编译器却帮我们自动生成了异常表,from,to表示需要对哪部分指令做异常捕获,这里的值是0,2,意思就是在对:

 0: iload_1 1: istore_2 2: iinc          1, 1

这几个指令操作做捕获,如果这几个指令抛出了异常,程序跳到target 7,也就是第七行指令:

 7: astore_3 8: iinc          1, 1 11: aload_3 12: athrow

下面来分析一下抛异常的时候的执行指令:

astore_3:a表示是一个对象,此处为异常对象,把异常对象存储到局部变量表的3号下标位置。

栈顶:1,局部变量表:[this,1,1,exception...]

iinc 1, 1:对局部变量表1位置的值加1

栈顶:1,局部变量表:[this,2,1,exception...]

aload_3:加载局部变量表3位置的值到栈顶

栈顶:exception,局部变量表:[this,2,1,exception...]

athrow:弹出栈顶,并抛出栈顶的异常对象

整个流程用伪代码来说就像下面这样:

总结:

我们通过分析class文件可以很清楚的发现:

1,有try块的程序无论有没有catch,在字节码层面都会被拆解成2部分,正常部分和异常处理部分,finally块的程序会被分别插入到这2部分之中,所以finally关键字其实只是一个语法糖。

2,对于自增操作其实是操作的局部变量表,而返回值返回的是栈顶的值,关键点是要看局部变量表在函数返回之前有没有被load到栈顶。

本文内容由小舻整理编辑!