最终程序块何时相对于返回运行 [英] When Does the Finally Block Run Relative to the Return

查看:84
本文介绍了最终程序块何时相对于返回运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我昨天偶然发现了一个有趣的错误,并且已经解决了该错误,但是今天早晨它仍然困扰着我,所以我想看看是否有人可以对此问题有所了解.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆