Java 应用程序中 Oracle 连接未关闭

发布于 2024-09-24 12:34:48 字数 1021 浏览 2 评论 0原文

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

因此,我尝试使用 System.out 语句进行调试。即使在关闭连接之后,当我将 conn 打印到系统日志文件时,它也会为我提供连接对象名称。

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.close(); 语句下方添加 conn = null;,则连接现在似乎已关闭。所以我的问题是 conn.close(); 吗?实际释放我的连接还是我还必须将其设置为空才能真正释放我的连接。就像我说的,在无法查询 v$session 的情况下,我真的很难确定连接是否真的被释放。有没有java代码片段可以给我开放的连接?

这可能是有教育意义的,因为我计划重构这些应用程序以使用连接池,但我现在正在寻找一个快速的创可贴。

I have a connection leak in some older Java web applications which do not utilize connection pooling.
Trying to find the leak is hard because IT will not grant me access to v$session SELECT Count(*) FROM v$session;

So instead I am trying to debug with System.out statements. Even after closing the connection conn.close(); when I print conn to the System log file it gives me the connection object name.

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); 
    }

however if I also add conn = null; below the conn.close(); statement the connection now seems closed. So my question is does conn.close(); actually release my connection or do I also have to make it null to really release my connection. Like I said it is really hard for me to determine if the connection is actually released without being able to query v$session. Is there snippet of java code which can give me my open connections??

It's probably educational at this point because I plan to refactor these applications to use connection pooling but I'm looking for a quick bandaid for now.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

箹锭⒈辈孓 2024-10-01 12:34:49

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

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

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

The important part of the close is what's happening on the database side. It's the RDBMS that has to close that connection. Calling the close() method is what communicates the message to the database to close the connection.

Setting the connection to null doesn't instruct RDBMS to do anything.

Same logic applies to ResultSet, which is a cursor on the database side, and Statement. You need to close those in individual try/catch blocks in the finally block of the method that created them, in reverse order of creation. Otherwise you'll see errors about "Max cursors exceeded".

随心而道 2024-10-01 12:34:49

将 conn 设置为 null 只会中断对连接对象的引用链接,对连接是否打开没有影响。如果连接仍然打开,那么仍然会从 JDBC 驱动程序/连接池等内部引用该连接...

将变量设置为 null 可以更多地告诉垃圾收集器可以在需要时清理原始对象比什么都重要。

Setting the conn to null only breaks the reference link to the connection object, and has no influence on the connection being open or not. If the connection is still open then the connection will still be referred to from inside the JDBC driver/connection pool etc...

Setting a variable to null is more telling the garbage collector that it is ok to clean up the original object when it wants to than anything else.

一袭水袖舞倾城 2024-10-01 12:34:49

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

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

如果您不想再在代码中跟踪连接,可以conn = null。这不会立即关闭连接。我相信连接将自动关闭,基于 JDBC 文档

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

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

As others are saying, you've got two different concepts here: closing the connecting and tracking the connection in a variable.

To close the connection, call conn.close(). This will not set the variable conn to null. You can test if the connection is open with conn.isClosed().

If you don't care to track the connection in your code any more, you can conn = null. This does not immediately close the connection. I believe the connection will be automatically closed, based on the JDBC documentation :

Releases this Connection object's database and JDBC resources immediately instead of waiting for them to be automatically released.

If you choose to go this route, be aware that the garbage collector may not close your connection as quickly as you want, and you may have what appears to be a resource leak; reserved database locks won't be released until the connection is garbage collected. Certain drivers (I don't know if oracle is one) impose maximum limit to the number of connections that may exist at one time, so leaving open connections can also cause failures to connect, later in the program.

各自安好 2024-10-01 12:34:49

连接泄漏是最好的。我认为一个好的策略是将连接的获取和释放包装在几个函数中,然后始终通过这些函数获取和释放连接。然后,您可以让这些函数维护所有打开连接的列表,并对分配函数的调用者进行堆栈跟踪。然后有一个屏幕显示所有打开的连接及其来源的列表。在测试环境中运行它,使用一堆屏幕运行,然后退出所有屏幕,以便所有连接都应该关闭,然后调出显示打开连接的屏幕,并且应该揭露恶棍。

Connection leaks are a best. I think a good strategy is to wrap the getting and releasing of connections in a couple of functions and then always get and release your connections through those functions. Then you can have those functions maintain a list of all open connections, and do a stack trace on the caller of the allocate function. Then have a screen that shows a list of all open connections and where they came from. Run this in a test environment, run around using a bunch of screens, then exit them all so all the connections SHOULD close, then bring up the screen that shows open connectoins, and the villain should be revealed.

穿透光 2024-10-01 12:34:49

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

作为一种实践,我总是在关闭后设置 conn=null 。我相信当您执行 conn.close() 时,您是在告诉垃圾收集器它已准备好进行垃圾收集。但是,何时执行此操作将由垃圾收集过程决定。

您也可以更改您的

if(conn!=null)

if (conn.isClosed())

..

My explanation here is an educated guess.

As a practice I have always set conn=null after the close. I believe when you do conn.close() you are telling the garbage collector that it's ready to be garbage collected. However, it will be up to the garbage collection process to determine when to do so.

Also you can change your

if(conn!=null)

to

if (conn.isClosed())

..

意犹 2024-10-01 12:34:49

是否有 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,请快速猜测一下。
建议:为什么不安装 jboss 并通过那里设置连接池?

Is there snippet of Java code which can give me my open connections?

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();
        }

Just a quick guess, assuming you are using Oracle.
Sugession: Why don't you install jboss and set up connection pooling through there?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文