[英]Oracle connection not closing in Java Application
我在一些不使用连接池的旧Java Web应用程序中发生连接泄漏。 试图找到泄漏很难,因为IT不会授予我访问v $ session SELECT Count(*) FROM v$session;
所以我试图使用System.out语句进行调试。 即使在关闭连接conn.close();
当我将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 = null;
在conn.close();
下面conn.close();
声明连接现在似乎已关闭。 所以我的问题是conn.close(); 实际上释放我的连接或我也必须使它为null以真正释放我的连接。 就像我说的那样,我很难确定连接是否实际发布而无法查询v $ session。 有没有java代码片段可以给我打开连接?
这可能是教育性的,因为我计划重构这些应用程序以使用连接池,但我现在正在寻找一个快速的绑定。
关闭的重要部分是数据库方面正在发生的事情。 这是必须关闭该连接的RDBMS。 调用close()方法是将消息传递给数据库以关闭连接的方法。
将连接设置为null不会指示RDBMS执行任何操作。
相同的逻辑适用于ResultSet,它是数据库端的游标和Statement。 您需要以创建它们的相反顺序关闭创建它们的方法的finally块中的各个try / catch块中的那些块。 否则,您将看到有关“超出最大游标数”的错误。
将conn设置为null只会断开连接对象的引用链接,并且不会影响正在打开的连接。 如果连接仍处于打开状态,则仍将从JDBC驱动程序/连接池等内部引用连接...
将变量设置为null更能说明垃圾收集器可以在需要时清除原始对象,而不是其他任何东西。
正如其他人所说,这里有两个不同的概念:关闭连接并跟踪变量中的连接。
要关闭连接,请调用conn.close()
。 这不会将变量conn设置为null。 您可以使用conn.isClosed()
测试连接是否已打开。
如果您不再需要跟踪代码中的连接,则可以conn = null
。 这不会立即关闭连接。 我相信连接将根据JDBC 文档自动关闭:
立即释放此Connection对象的数据库和JDBC资源,而不是等待它们自动释放。
如果您选择这条路线,请注意垃圾收集器可能无法尽快关闭您的连接,并且您可能看到资源泄漏; 在连接被垃圾回收之前,不会释放保留的数据库锁。 某些驱动程序(我不知道oracle是否为1)对一次可能存在的连接数施加了最大限制,因此保留打开的连接也会导致程序中的连接失败。
连接泄漏是最好的。 我认为一个好的策略是在几个函数中包含连接的获取和释放,然后总是通过这些函数获取和释放连接。 然后,您可以让这些函数维护所有打开的连接的列表,并在allocate函数的调用者上执行堆栈跟踪。 然后有一个屏幕,显示所有打开的连接列表以及它们来自何处。 在测试环境中运行它,使用一堆屏幕运行,然后全部退出以便所有连接应该关闭,然后调出显示打开connectoins的屏幕,并显示反派。
我在这里的解释是一个有根据的猜测。
作为一种做法,我总是在收盘后设置conn = null。 我相信当你做conn.close()时,你告诉垃圾收集器它已经准备好被垃圾收集了。 但是,将由垃圾收集过程决定何时这样做。
你也可以改变你的
如果(参数conn!= NULL)
至
if(conn.isClosed())
..
是否有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并通过那里设置连接池?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.