Java连接未在Java Application中关闭

时间:2010-09-22 20:11:17

标签: java oracle database-connection

我在一些不使用连接池的旧Java Web应用程序中发生了连接泄漏。 试图找到泄漏很难,因为IT不会授予我访问v $ session SELECT Count(*) FROM v$session;

的权限

所以我试图使用System.out语句进行调试。即使在我将conn打印到系统日志文件时关闭连接conn.close();,它也会为我提供连接对象名称。

try { 
    Connection conn;
    conn.close() 
    } 
catch (SQLException e) { }
finally { 
    if (conn != null) {
        try {
           System.out.println("Closing the connection"); 
           conn.close();
           }
        catch (Exception ex) 
            {
            System.out.println("Exception is " + ex); 
            }
     }
 }
// I then check conn and it is not null and I can print the object name.
    if (conn != null) {
            System.out.println("Connection is still open and is " + conn); 
    }

但是如果我还在conn = null;语句下添加conn.close();,则连接现在似乎已关闭。所以我的问题是conn.close();实际上释放我的连接或我也必须使它为null以真正释放我的连接。就像我说的那样,我很难确定连接是否实际发布而无法查询v $ session。是否有java代码片段可以给我打开连接?

此时可能很有教育意义,因为我计划重构这些应用程序以使用连接池,但我现在正在寻找快速绑定。

6 个答案:

答案 0 :(得分:6)

结束的重要部分是数据库方面正在发生的事情。这是必须关闭该连接的RDBMS。调用close()方法是将消息传递给数据库以关闭连接。

将连接设置为null不会指示RDBMS执行任何操作。

相同的逻辑适用于ResultSet,它是数据库端的游标和Statement。您需要以创建它们的相反顺序关闭创建它们的方法的finally块中的各个try / catch块中的那些块。否则,您将看到有关“超出最大游标数”的错误。

答案 1 :(得分:4)

将conn设置为null只会断开连接对象的引用链接,并且不会影响正在打开的连接。如果连接仍处于打开状态,则仍将从JDBC驱动程序/连接池等内部引用连接...

将变量设置为null更能说明垃圾收集器可以在需要时清理原始对象,而不是其他任何东西。

答案 2 :(得分:3)

正如其他人所说,这里有两个不同的概念:关闭连接并跟踪变量中的连接。

要关闭连接,请致电conn.close()。此不会将变量conn设置为null。您可以使用conn.isClosed()测试连接是否已打开。



如果您不想再跟踪代码中的连接,可以conn = null。此不会立即关闭连接。我相信连接将根据JDBC documentation

自动关闭
立即释放此Connection对象的数据库和JDBC资源,而不是等待它们自动释放。

如果您选择这条路线,请注意垃圾收集器可能无法尽快关闭您的连接,并且您可能看到资源泄漏;在连接被垃圾回收之前,不会释放保留的数据库锁。某些驱动程序(我不知道oracle是否为1)对一次可能存在的连接数施加了最大限制,因此保留打开的连接也可能导致连接失败,稍后在程序中。

答案 3 :(得分:1)

连接泄漏是最好的。我认为一个好的策略是在几个函数中包含连接的获取和释放,然后总是通过这些函数获取和释放连接。然后,您可以让这些函数维护所有打开的连接的列表,并在allocate函数的调用者上执行堆栈跟踪。然后有一个屏幕,显示所有打开的连接列表以及它们来自何处。在测试环境中运行,使用一堆屏幕运行,然后退出所有连接应该关闭,然后打开显示打开connectoins的屏幕,并显示恶棍。

答案 4 :(得分:0)

我在这里的解释是一个有根据的猜测。

作为一种练习,我总是在收盘后设置conn = null。我相信当你做conn.close()时,你告诉垃圾收集器它已经准备好被垃圾收集了。但是,将由垃圾收集过程决定何时这样做。

您也可以更改

  

如果(conn将!= NULL)

  

if(conn.isClosed())

...

答案 5 :(得分:0)

是否有Java代码片段可以为我提供开放式连接?

Statement smt = null;
    ResultSet rs = null;
    try { 
        // Create Statement from connection
        smt = conn.createStatement();
        // Execute Query in statement 
        rs = stmt.executeQuery("SELECT 1 FROM Dual");

        if (rs.next()) {
            return true; // connection is valid
        }
        catch (SQLException e) {
            // Some sort of logging
            return false;
        }
        finally {
            if (smt != null) smt.close();
            if (rs != null) rs.close();
        }

快速猜测,假设您使用的是Oracle。 Sugession:为什么不安装jboss并通过那里设置连接池?