从字节码看try catch finally的return如何执行

1,031 阅读2分钟

一、finally语句不会被执行的情况,至少有如下两种

  1. try语句没有执行到,如在try语句之前就返回了,就这样finally语句就不会执行,说明finally语句被执行的前提是相应的try语句被执行到。
  2. 在try块中有System.exit(0)(是终止java虚拟机JVM的);语句,连JVM都停止了,所有都结束了,finally也不会被执行到。

二、return语句的关系

  1. finally语句在return语句执行之后return返回之前执行

public class FinallyReturnTest {    public static void main(String[] args) {        System.out.println(test());    }    public static String test() {        try {            System.out.println("try block");            return getResult();        } finally {            System.out.println("finally block");        }    }    public static String getResult() {        System.out.println("get result");        return "result";    }}

返回结果

try block
get result
finally block
result

Process finished with exit code 0

2.try中的返回值可能因为finally里的修改也可能不变

test1:

public class FinallyReturnTest1 {    public static void main(String[] args) {        System.out.println(test());    }    public static int test() {        int b = 20;        try {            System.out.println("try block");            return b += 80;        } catch (Exception e) {            System.out.println("catch block");        } finally {            System.out.println("finally block");            if (b > 25) {                System.out.println("b>25, b = " + b);            }            b = 150;        }        return 2000;    }}

返回结果

try block
finally block
b>25, b = 100
100

test2:

public class FinallyReturnTest2 {    public static void main(String[] args) {        System.out.println(getMap().get("KEY"));    }    public static Map<String, String> getMap() {        Map<String, String> map = new HashMap<>();        map.put("KEY", "INIT");        try {            map.put("KEY", "TRY");            return map;        }        catch (Exception e) {            map.put("KEY", "CATCH");        }        finally {            map.put("KEY", "FINALLY");            map = null;        }        return map;    }}

返回结果

FINALLY

Process finished with exit code 0

3、try块里的return语句在异常的情况下不会被执行,这样具体返回哪个看情况

①catch和finally块里无返回语句,返回finally外的return语句。

②如果catch块里无返回语句,finally里有返回语句,返回finally的return语句。

③如果catch块里有return语句,执行的情况和try一样,finally有返回语句,执行finally中的返回语句。

三、字节码角度理解

 public int get();

    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=4, args_size=1
         0: iconst_0 将int型0推送至栈顶(操作数栈)         1: istore_1 将栈顶int型数值存入第二个本地变量(局部变量表)         2: iconst_2 将int型2推送至栈顶         3: ireturn 从当前方法返回int,返回finally中的return值 2         4: astore_1 将栈顶引用型数值存入第二个变量(出现异常,将Exception存入局部变量表)         5: aload_1 将第二个引用型本地变量推送至栈顶         6: invokevirtual #3// Method java/lang/Exception.printStackTrace:()V 调用Exception实例方法         9: iconst_1 将int型1推送至栈顶        10: istore_2 将栈顶int型数值存入第三个本地变量        11: iconst_2 将int型2推送至栈顶        12: ireturn  从当前方法返回int,返回finally中的return值        13: astore_3  将栈顶引用型数值存入第四个变量        14: iconst_2 将int型2推送至栈顶        15: ireturn 从当前方法返回int,返回finally中的return值 2      Exception table:         from    to  target type             0     2     4   Class java/lang/Exception             0     2    13   any             4    11    13   any      LineNumberTable:        line 7: 0        line 12: 2        line 8: 4        line 9: 5        line 10: 9        line 12: 11