简体   繁体   English

最终程序块何时相对于返回运行

[英]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. 昨天,我偶然发现了一个有趣的错误,并已解决该错误,但是今天早晨它仍然困扰着我,因此,我想看看是否有人可以对这个问题有所了解。

The code in question: 有问题的代码:

final ResultSet rs = prepStatement.executeQuery();
try
{
   if (!rs.next())
   {
      throw new IllegalStateException("Expected non-empty result");
   }
   return rs.getInt(0 + 1);
}
finally
{
   rs.close();
}

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. 偶尔,return语句将引发异常,指示已在封闭的ResultSet上调用了getInt(int)。 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. 这使我相信,以某种方式偶尔会在return语句之前执行finally块。 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. 我正在使用下面列出的Oracle JVM。

java version "1.7.0_45" Java版本“ 1.7.0_45”
Java(TM) SE Runtime Environment (build 1.7.0_45-b18) Java(TM)SE运行时环境(内部版本1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode) Java HotSpot(TM)64位服务器VM(内部版本24.45-b08,混合模式)

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 clarification 尝试捕获最终返回澄清
https://stackoverflow.com/questions/20164755/the-order-of-invoking-finally-block https://stackoverflow.com/questions/20164755/the-order-of-invoking-finally-block
Does finally always execute in Java? 最后是否总是用Java执行?

I wrote and compiled the following class 我编写并编译了以下课程

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();
        }
    }
}

with the following commands 使用以下命令

[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
}

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 . 如果遵循字节码指令 ,您将看到在28处调用rs.getInt(1)并将其值存储在33 The rs.close() is invoked at 35 . rs.close()35处调用。 The stored value is retrieved at 40 and returned at 41 . 40检索存储的值,并在41返回。

What you are experiencing must come from some other point in your code. 您正在体验的内容必须来自代码的其他方面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM