关闭资源的顺序
Posted
技术标签:
【中文标题】关闭资源的顺序【英文标题】:Order in closing resources 【发布时间】:2013-05-28 20:06:17 【问题描述】:我应该在连接之前关闭语句吗?和声明之前的结果集? 还是完全相反?
Connection conn = null;
Statement st = null;
Resultset rs = null;
try
// Do stuff
catch (SQLException e)
// Do stuff
finally
if (rs != null) rs.close();
if (st != null) st.close();
if (conn != null) conn.close();
或者
Connection conn = null;
Statement st = null;
Resultset rs = null;
try
// Do stuff
catch (SQLException e)
// Do stuff
finally
if (conn != null) conn.close();
if (st != null) st.close();
if (rs != null) rs.close();
【问题讨论】:
规则很简单:按打开的相反顺序关闭。关闭连接后,关闭语句将毫无意义。 注意:void close() 抛出 SQLException,每个 close() 必须在自己的 try/catch 中 一般情况下,您应该以 LIFO 的方式关闭资源——后进先出。因此,您打开的第一件事(连接)应该是最后关闭的。第一种方法更有意义。 理想情况下,当您关闭Connection
时,兼容的JDBC 驱动程序、连接池等将关闭ResultSet
、Statement
等;但不幸的是,现实情况并非总是如此。
@Aubin 或将关闭包装在一个方法中。如果您的程序正在终止并且它没有关闭数据库连接,这没什么大不了的,因为当 JVM 死掉时,该资源也会死掉。如果您的程序需要继续运行,这是一个问题,因为您泄露的资源将继续存在。
【参考方案1】:
关闭结果集,然后是语句,然后是连接。
换句话说,按照后进先出的原则关闭所有内容。
【讨论】:
AKA,也称为Stack
@SnakeDoc AKA 也称为也称为。
@Pescis 我必须达到最低炭化量;-P
虽然这确实回答了问题,但它无助于 OP 成为更好的程序员,也无助于获得更多知识。 OP,看看 A.R.M. / Try-With-Resources 块用于在现代 Java (Java 7+) 中执行此操作的正确方法。 docs.oracle.com/javase/tutorial/essential/exceptions/…【参考方案2】:
您应该按照与打开顺序相反的顺序关闭资源(就好像这些资源在堆栈上一样)。
使用 Java 7 try-with-resources,理想的方法是:
try (
Connection conn = somethingThatGetsAConnection();
Statement st = conn.createStatement();
Resultset rs = st.executeQuery("SELECT something");
)
// Do stuff
catch (SQLException e)
// Do stuff
Java 会为你处理好它,它会以相反的顺序关闭资源。另见Oracle tutorial on try-with-resources:
请注意,资源的“关闭”方法是按其创建的相反顺序调用的。
您可以在文章 Better Resource Management with Java SE 7: Beyond Syntactic Sugar 中找到对 try-with-resources 的更深入了解
14.20.3 部分提到的 Java 7 的 Java 语言规范:
资源按从左到右的顺序初始化。如果资源初始化失败(即,其初始化表达式抛出异常),则到目前为止由
try
-with-resources 语句初始化的所有资源都将关闭。如果所有资源初始化成功,try
块将正常执行,然后关闭try
-with-resources 语句的所有非空资源。资源以与初始化相反的顺序关闭。仅当资源初始化为非空值时才关闭资源。关闭一个资源的异常不会阻止关闭其他资源。
这也可以看作是一个明确的迹象,表明 Java 语言设计者考虑以与分配规范相反的顺序关闭资源。
【讨论】:
@Aubin 你错了。也请从此答案中删除您的 -1 。 ARM 块顺序无关紧要,JVM 会处理它。这比 OP 预期的更好地回答了 OP 的问题。 @Aubin 添加了对相反顺序的简短提及,但我认为 *** 并不总是要回答确切的问题,而是要为实际问题提供更好的答案。 try-with-resources 通过消除实际思考的需要来解决问题。 好的,现在是的,我已经删除了我的反对票。对 JLS 的引用将很好地完成此答案。 @Aubin 更新了我的答案,尽管在我阅读 JLS 时它明确提到了一次关闭中的异常,但不会阻止另一次关闭:“关闭一个资源的异常不会防止关闭其他资源。”(当然这可能意味着您尝试关闭的特定资源尚未关闭,但在没有 try-with-resources 的情况下也会发生这种情况【参考方案3】:ResultSet
、Statement
,然后是Connection
。 JDBC 连接和语句的黄金法则是以启动或打开的反向 顺序关闭。此外,ResultSet
依赖于Statement
的执行,Statement
依赖于Connection
实例。因此,关闭应按该顺序进行(ResultSet、Statement、Connection)。
【讨论】:
【参考方案4】:第一个例子是正确的方法。任何其他订单的问题是关闭Statement
也会自动关闭任何底层ResultSet
(Connection
也可能发生同样的情况) - 所以您需要先关闭层次结构中最低的一个。
@aubin 指出,close()
方法可能会抛出 SQLException
。解决这个问题的一个简单方法是使用 DBUtils
closeQuietly()
方法来关闭它们——然后你甚至不需要空检查!
【讨论】:
【参考方案5】:要以最小的努力解决这个问题,请尝试使用 Java 7 的新 A.R.M. (自动资源管理)块,也称为 Try-With-Resources。
try (Connection conn = null, Statement st = null, ResultSet rs = null)
// Do stuff
catch (SQLException e)
// Do stuff
没有丑陋的Finally
或担心正确的顺序,Java 会为您处理。
更多关于 ARM/Try-With-Resources 块的信息:http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
【讨论】:
关闭操作的顺序呢?这是问题,你不回答...... @Aubin 它更好地回答了他的问题。在 ARM 块中顺序无关紧要,发明了 ARM 块来解决这个确切的问题。请删除你的 -1 @SnakeDoc 在 ARM 中以分配的相反顺序调用关闭 @SnakeDoc 我正在阅读该教程,您还链接到其中明确提及它(请参阅我的回答中的引用)。 AFAIK 编译器实际上将 try-with-resources 转换为具有一些(复杂)异常处理的 finally 块;它只不过是语法糖。 在 try-with-resources 上也可以看到这个链接(尤其是最后的揭秘部分):oracle.com/technetwork/articles/java/…以上是关于关闭资源的顺序的主要内容,如果未能解决你的问题,请参考以下文章
高效 告别996,开启java高效编程之门 4-3传统方式关闭流资源