源码
下面代码的返回结果是1不是2,下面从字节码的角度分析一下原因
public class Start {
public static void main(String[] args) {
int demo = demo();
System.out.println(demo);
}
public static int demo() {
int x = 1;
try {
return x;
} finally {
x = 2;
}
}
}
代码字节码分析
获取方法的字节码命令为
javap -v xxx.class
上面代码的字节码部分如下图所示(其中红色的字为解析,下面会对详细内容进行解释)
首先要明确该段代码中有一个操作数栈和局部变量表,如下图所示
当程序执行 int x = 1,时会有两个操作,常量1会压入操作数栈栈顶,然后弹出栈顶元素赋值为局部变量表的x的位置,对应字节码中的0: iconst_1 , 1: istore_0 ,如下图所示
然后执行try-catch-finally中的方法,用到x,所以执行字节码 2: iload_0,命令,把局部变量表中的0号位置数据加载到操作数栈栈顶。如下图所示。
接下来执行 3: istore_1 方法,把操作数栈顶元素保存到局部变量表1号位置,如下图所示
接下来执行4: iconst_2 , 5: istore_0 字节码,即x = 2的代码,把2压入到操作数栈栈顶中,把栈顶元素保存到局部变量表0号位置中,如下图所示。
最后执行 6: iload_1 , 7: ireturn 字节码,把局部变量表1号位置上数据压入到操作数栈栈顶,返回操作数栈顶元素,如下图所示
源码拓展
如果代码想返回2,可以有如下操作
public static int demo() {
int x = 1;
try {
return x;
} finally {
x = 2;
return x;
}
}
或者
public static int demo() {
int x = 1;
try {
} finally {
x = 2;
}
return x;
}
字节码命令部分介绍
iconst_n
把n压入到操作数栈栈顶,n为表示具体的操作值,比如int x =5,则执行iconst_5命令。 不过也有其他的命令,当int取值-1~ 5采用iconst指令,取值-128~ 127采用bipush指令,取值-32768~ 32767采用sipush指令,取值-2147483648~2147483647采用 ldc 指令。
int x =1;
int y =11;
对应的字节码如下图所示
istore_n
把操作数栈栈顶元素保存到局部变量表n号位置
iload_n
把局部变量表n号位置的数据压入到操作数栈栈顶
参考
https://mp.weixin.qq.com/s/4tBjAt-lTh6-zmhW-44S6A https://www.imooc.com/wenda/detail/440500