Java 在什么情况下该资源会泄漏?

Java 在什么情况下该资源会泄漏?,java,eclipse,Java,Eclipse,Eclipse4发出警告,表示stmt可能未关闭并导致资源泄漏: class Test { public void test() { PreparedStatement stmt = null; try { stmt = HibernateSession.instance().connection().prepareStatement(""); } catch (final SQLException e) {

Eclipse4发出警告,表示stmt可能未关闭并导致资源泄漏:

class Test {
    public void test() {
        PreparedStatement stmt = null;
        try {
            stmt = HibernateSession.instance().connection().prepareStatement("");
        } catch (final SQLException e) {
            e.printStackTrace();
        } finally {
            if (stmt != null)
                try {
                    stmt.close();
                } catch (final SQLException e) {
                    e.printStackTrace();
                }
        }
    }
}

在什么情况下会发生这种情况?

您需要使用Java 7的try with resources或try finally块:

try(stmt = HibernateSession.instance().connection().prepareStatement("")) {


}
此警告将在继承自
AutoCloseable
但不保证关闭的类型上生成。(或者可能是
可关闭的
,我忘了是哪个)

现在我明白了您的要求,只需编写不那么复杂的代码

Foo f = null; // don't do this, but it's what you're doing
f = new Foo();
这就是你正在做的,你发现了其中一种情况,你实际上必须为这项无关的工作支付罚款

此外,您的
try/finally
应该是干净的
.close()
不能抛出,为什么要捕获

try { // don't do this
    stmt.close();
}
catch(SQLException exc) {

}

应该生成一个Eclipse警告,告诉您正在捕获未抛出的内容。这甚至可能是一个编译错误,不确定,但听起来您将受益于使用Eclipse>Preferences>Compiler并查看哪些警告是智能的。如果你不明白一个警告,谷歌一下,看看它是否对你有帮助,不要跳过它。(有点像您对这一块所做的)。

如果在
finally
块中调用
stmt.close()
时引发异常,则可能会发生泄漏。

问题是在
finally
块中可能会发生异常,这将阻止
stmt
关闭

一种解决方法是,您可以将
finally
块中的所有内容替换为:

JDBCUtilities.close(stmt);
请参阅JDBCUtilities的。关闭。如您所见,使用此实用工具方法不会引发任何异常,因此您不必担心资源泄漏。另一个好处是,该实用程序方法还处理
stmt
null
情况,因此我们不需要自己编写代码


实际上,它是使用JDBCUtilities

我想这里的结论是:这是一个Eclipse bug?

这不是最糟糕的Eclipsebug@OlegMikheev这不是一个bug,这是一个特性。我不是讽刺地说,这实际上是一个有用的功能。这里有许多重复的功能之一:我看不出
stmt
怎么会不关闭,但连接永远不会关闭。Eclipse并不比你聪明,仅此而已。谢谢,这将使代码更加清晰。我希望我的雇主能采用jdk 1.7。@OlegMikheev我的错,我暗自认为自动关闭类的设计是正确的(我以前在Java中犯过这个错误)。那么如何处理这样的泄漏呢?它会让Eclipse更加困惑,因为Eclipse不可能知道
JDBCUtilities.close(stmt)
的作用是什么。@Unreputable如何处理?Eclipse只检查语法错误、检查异常等。我认为它不关心或不理解业务逻辑。在
finally
块中,我们想要关闭
stmt
,这正是
jdbculities.close
所做的。Eclipse不知道
jdbculities.close(stmt)
调用
stmt.close()
@不可修复我认为Eclipse不需要知道这一点。你能举一个它可能抱怨的例子吗?我的意思是Eclipse会发出同样的警告,因为它不知道stmt是否确实关闭了。在我看来,这像是一个Eclipse bug。可能Eclipse看到有一条路径通过
finally
(当
stmt
为null时)导致不调用
stmt.close()