【发布时间】:2014-05-17 13:39:57
【问题描述】:
我看到了一个关于finally的Java难题,然后返回
int i = 0;
try {
return i;
} finally {
i++;
}
这个函数的返回值是多少,我知道它会返回0,我测试另一个代码
StringBuffer sb = new StringBuffer("11");
try {
return sb;
} finally {
sb.append("22");
}
发生了奇怪的事情,它返回“1122” 这是我的第一个问题:为什么它返回“1122”?
我反编译了这两个java代码,
0: iconst_0 put 0 to the stack
1: istore_0 store the stack top into index 0
2: iload_0 put index 0 to the stack
3: istore_1 store the stack top into index 1
4: iinc 0, 1 inc the index 0 with 1
7: iload_1 put index 1 to the stack
8: ireturn return the top of stack
// what's the below bytecode mean? because the index 0 has incremented, why increment again?
9: astore_2
10: iinc 0, 1
13: aload_2
这是我的第二个问题为什么 9 - 13 行字节码是什么意思?并且索引 0 增加了,wy 再次增加?
0: new #2; //class java/lang/StringBuffer
3: dup
4: ldc #3; //String 11
6: invokespecial #4; //Method java/lang/StringBuffer."<init>":(Ljava/lang/String;)V
9: astore_0
10: aload_0
11: astore_1
12: aload_0
13: ldc #5; //String 22
15: invokevirtual #6; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
18: pop
19: aload_1
// like the above, this seems should return the value in the index 1, it should be "11"??
20: areturn
21: astore_2
22: aload_0
23: ldc #5; //String 22
25: invokevirtual #6; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
28: pop
29: aload_2
30: athrow
这是我的第三个问题,似乎应该是索引中的值,应该是“11”??
【问题讨论】:
-
docs.oracle.com/javase/tutorial/essential/exceptions/… - finally 块总是在 try 块退出时执行。
-
它与引用与原始数据类型有关。第一种情况是原始数据类型,因此它将返回堆栈上的面值。第二种情况是一个引用,所以它会在
finally块执行后返回引用指向的任何东西。 -
所以从字节码的方式来说,astore_0,astore_1,存储引用,所以load_0,然后修改,那么index 1就会看到修改结果。对吗?
-
以后,请每个问题问一个问题。这应该是三个独立的问题。
-
我认为重复的代码路径用于处理“正常”和“异常”情况。
标签: java jvm return java-bytecode-asm try-catch-finally