try-finally 字节码分析

时间:2021-11-24 17:09:43

我们都知道下面的代码返回值为8,下面通过字节码看下是怎么返回8的.

public int tryFinally(){
        int i = 0;
        try{
            i++;
            return i;
        }finally {
            i = 8;
            return i;
        }
    }

通过javap -v  命令输出字节码

public int tryFinally();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=4, args_size=1
         0: iconst_0               //表示将常量0加载到操作数栈
         1: istore_1               //表示将栈顶数据存储到index为1的局部变量中, 我们姑且记做local1=0
         2: iinc          1, 1     //将index为1的局部变量的值做自增操作,local1=1
         5: iload_1                //将index为1的局部变量的值加载到操作数栈,即常量1入栈
         6: istore_2               //将栈顶数据存储到index为2的局部变量, local2=1
         7: bipush        8        //将常量8入栈
         9: istore_1               //将栈顶值8存储到index为1的局部变量, local1=8
        10: iload_1                //将index为1的局部变量的值加载到操作数栈,即8入栈
        11: ireturn                //正常返回(没有异常发生), 返回栈顶值8
        12: astore_3               //从下面的异常表,可以看出,如果2~7发生异常,那么从12开始执行.此时将栈顶值存储到局部变量3
        13: bipush        8        //常量值8入栈
        15: istore_1               //将常量值8存储到局部变量1,即local1=8
        16: iload_1                //局部变量1值加载到操作数栈,及常量8入栈
        17: ireturn                //返回栈顶值8
      Exception table:             //异常表
         from    to  target type
             2     7    12   any   //表示如果2~7发生异常,那么从12开始执行
            12    13    12   any   //表示如果12~13发生异常,那么从12开始执行

从字节码我们可以看出无论try语句是否出现异常,finally语句块都会执行,根据字节码我们可以看出,最终返回的值无论是否发生异常都是返回8

加载指令

load

将一个局部变量加载到操作数栈的指令有:

  iload, iload_<n>,lload,lload_<n>,fload,fload_<n>,dload,dload_<n>,aload,aload_<n>

  其中load前面的i,l,f,d,a分别表示数值类型为i,long,float,double,引用类型.n表示在局部变量表中下标为n的局部变量

      iload_1表示将局部变量表中下标为1的局部变量的值加载到操作数栈

 

常量入栈的jvm指令有:

  bipush, sipush, ldc, ldc_w, ldc2_2,aconst_null, iconst_m1,iconst_<i>,lconst_<l>,fconst_<f>,dconst_<d>

  iconst_m1 表示将常量-1入栈

  iconst_<i> 表示将常量0~5入栈,iconst_0 表示将常量0入栈

  bipush 表示将-128~127的整数入栈

  sipush 表示将-32768~32767的整数入栈

  lconst_<l>表示将long类型数常量入栈

  fconst_<l>表示将flost类型常量入栈

  dconst_<d>表示将double类型常量入栈

  ldc 表示将字符串或者数值类型常量入栈

存储指令

store

将一个数值从操作数栈存储到局部变量表的指令有:

  istore、istore_<n>、lstore、lstore_<n>、fstore、fstore_<n>、dstore、dstore_<n>、astore、astore_<n>

  如istore_2 表示将操作数栈顶值存储到局部变量表中下标为2的类型为int的局部变量