2013-02-12 152 views
3

我跟着把一个close()最终块的做法:java.sql.Connection对象在垃圾回收时会自动关闭吗?

void foo() { 
    Connection conn; 
    try { 
     conn = getConnection(); 
     // .. 
    } final { 
     try { 
      conn.close() 
     } catch(Exception e) { 
     } 
    } 
} 

是否真的需要调用连接上close(),或将垃圾收集器会自动做呢?

我确定垃圾收集会带来额外的延迟,我只是不希望连接永远保持打开状态。

+4

它是您的责任,当您完成它的关闭连接。垃圾收集器不会为你做。 – Perception 2013-02-12 23:01:16

+0

也许这回答你的问题:http://stackoverflow.com/questions/8652336/jdbc-garbage-collection 总结:你需要关闭连接,以防止各种泄漏,不能依靠GC为你做。 – 2013-02-12 23:01:35

+1

您可能会在连接完成之前耗尽连接。没有结束就不可靠。你可能喜欢尝试执行周围的习语。 (由于你的代码显然是编写的,你似乎会放弃关闭的异常(可能是因为失败获取而导致的NPE) - 您可能想要从那里抛出某种异常,类似于获取连接所抛出的异常。对于Java SE 7,您可以使用新的尝试资源语法来粗略地做正确的事情,但是执行周围仍然胜利。) – 2013-02-12 23:02:13

回答

5

是真的有必要调用close()连接

是上。

或垃圾收集器会自动做到这一点?

未指定。也许有些实现会这样做。你不能依靠它。

我确定GC会产生额外的延迟。

GC可能永远不会发生。你无限可以吗?

我只是不想让连接永远保持打开状态。

你不希望他们保持打开时间超过必要的时间。他们是稀缺资源。不要浪费他们。 "It is recommended that programmers explicitly close all connections (with the method Connection.close) and statements (with the method Statement.close) as soon as they are no longer needed, thereby freeing DBMS resources as early as possible."

1

是的,有必要调用close()。有一些JDBC包装器可以自动完成这种类型的事情(例如Tomcat连接池),但总的来说,在涉及资源的任何地方都可以清理干净。

1

一些JDBC连接实现将在垃圾收集时执行close()。 Postgres JDBC驱动程序的finalize()方法(代码为here)就是一个例子。但是,并不能保证情况如此。

但是......

有没有办法知道什么时候该连接对象的垃圾回收将发生。垃圾收集器不了解JDBC资源,仅仅关于内存。这意味着GC只能在需要释放内存时才会发生。如果你有60个连接,但是仍然有空闲的内存,GC不会运行,你最终将无法连接。

也可能发生某种JDBC连接池。这意味着您获得的Connection对象不是实际连接,而是包含在池化逻辑中的一个连接。如果你没有这些连接,池不会知道你已经完成了它们,并且不能够重用它们用于其他请求,并且连接池将被耗尽。

所以总是close()你的连接明确如果你创建它们。

1

由于数据库连接不应该保持打开状态并且Garbage Collecting可能无法关闭它,因此使用Try with Resources的Java 7“项目硬币”语法很有帮助。任何实施AutoCloseable的东西都可以按照下面的说明使用。

void foo() { 
    try(Connection conn = getConnection()) { 
     // Do your Database code 
    } catch(SQLException e) { 
     //Handle the exception 
    } 
} //conn is closed now since it implements AutoCloseable.