最终程序块何时相对于返回运行 [英] When Does the Finally Block Run Relative to the Return
问题描述
我昨天偶然发现了一个有趣的错误,并且已经解决了该错误,但是今天早晨它仍然困扰着我,所以我想看看是否有人可以对此问题有所了解.
I stumbled across an interesting error yesterday and have since fixed it, but it still was bothering me this morning, so I would like to see if anyone can shed some light on the issue.
相关代码:
final ResultSet rs = prepStatement.executeQuery();
try
{
if (!rs.next())
{
throw new IllegalStateException("Expected non-empty result");
}
return rs.getInt(0 + 1);
}
finally
{
rs.close();
}
现在开始不做的部分.偶尔,return语句将引发异常,指示已在封闭的ResultSet上调用了getInt(int).我验证了准备好的语句没有在代码中的任何位置被关闭,并且如果数据库正在关闭,我也会看到其他错误.这使我相信,有时以某种方式,在return语句之前执行了finally块.我唯一能想到的是,热点编译器并不总是正确.我正在使用下面列出的Oracle JVM.
Now for the part that doesn't make since. Every once in a while, the return statement will throw an exception indicating that getInt(int) has been called on a closed ResultSet. I verified that the prepared statement is not being closed anywhere in the code, and if the database was closing, I would see other errors as well. This leads me to believe that somehow, occasionally, the finally block is being executed before the return statement. The only thing I can think of is that the hotspot compiler doesn't always get this right. I'm using the Oracle JVM listed below.
java版本"1.7.0_45"
Java(TM)SE运行时环境(内部版本1.7.0_45-b18)
Java HotSpot(TM)64位服务器VM(内部版本24.45-b08,混合模式)
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
我想应该提一提,我已经看到许多其他有关此顺序的问题,但是它们似乎都表明它是一成不变的,在这里我似乎见证了一些不同的事情.
I feel like I should mention that I have seen the host of other questions about this ordering, but they all seem to indicate that it is set in stone, where I seem to be witnessing something different.
Try-catch-finally-return澄清
https://stackoverflow.com/questions/20164755/the-order-of-invoking-最终阻止
最终是否总是用Java执行?
Try-catch-finally-return clarification
https://stackoverflow.com/questions/20164755/the-order-of-invoking-finally-block
Does finally always execute in Java?
推荐答案
我编写并编译了以下类
public class Examples {
public int answer(PreparedStatement prepStatement) throws SQLException {
final ResultSet rs = prepStatement.executeQuery();
try {
if (!rs.next()) {
throw new IllegalStateException("Expected non-empty result");
}
return rs.getInt(1);
} finally {
rs.close();
}
}
}
使用以下命令
[s_delima@ml-l-sotiriosd Downloads]$ java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
[s_delima@ml-l-sotiriosd Downloads]$ javac Examples.java
[s_delima@ml-l-sotiriosd Downloads]$ /usr/java/latest/bin/javap -c Examples
Compiled from "Examples.java"
public class Examples {
public Examples();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public int answer(java.sql.PreparedStatement) throws java.sql.SQLException;
Code:
0: aload_1
1: invokeinterface #2, 1 // InterfaceMethod java/sql/PreparedStatement.executeQuery:()Ljava/sql/ResultSet;
6: astore_2
7: aload_2
8: invokeinterface #3, 1 // InterfaceMethod java/sql/ResultSet.next:()Z
13: ifne 26
16: new #4 // class java/lang/IllegalStateException
19: dup
20: ldc #5 // String Expected non-empty result
22: invokespecial #6 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
25: athrow
26: aload_2
27: iconst_1
28: invokeinterface #7, 2 // InterfaceMethod java/sql/ResultSet.getInt:(I)I
33: istore_3
34: aload_2
35: invokeinterface #8, 1 // InterfaceMethod java/sql/ResultSet.close:()V
40: iload_3
41: ireturn
42: astore 4
44: aload_2
45: invokeinterface #8, 1 // InterfaceMethod java/sql/ResultSet.close:()V
50: aload 4
52: athrow
Exception table:
from to target type
7 34 42 any
42 44 42 any
}
如果您遵循字节代码说明,您会在28
看到它,调用rs.getInt(1)
并将其值存储在33
中. rs.close()
在35
处调用.在40
处检索存储的值,并在41
处返回.
If you follow along with byte code instructions, you will see that at 28
, the rs.getInt(1)
is invoked and its value is stored at 33
. The rs.close()
is invoked at 35
. The stored value is retrieved at 40
and returned at 41
.
您遇到的问题必须来自代码中的其他地方.
What you are experiencing must come from some other point in your code.
这篇关于最终程序块何时相对于返回运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!