【问题标题】:How do I track orphaned JDBC connections that are not closed?如何跟踪未关闭的孤立 JDBC 连接?
【发布时间】:2010-12-10 04:11:19
【问题描述】:

我们在旧代码中发现了一个未关闭连接的错误。这是一个简单的修复,但我想知道我们如何证明它已修复。可以选择是否使用连接池。对于池的使用,添加对池的监控很容易,但是当不使用连接池时,我们如何跟踪那些未关闭的孤立连接?和其他内存泄漏一样吗?

这个错误看起来基本上是一个剪切和粘贴错误。我们有一些管理数据库连接的类,所以大致如下所示:

OurDBConn conn1 = ConnectionManager.getConnection();
try {
  // business logic
} catch () {
  //
} finally {
  ConnectionManager.returnConnection(conn1);
}

/// and then later in the same method
OurDBConn conn2 = ConnectionManager.getConnection();
try {
  // business logic
} catch () {
  //
} finally {
  ConnectionManager.returnConnection(conn1); // NOTE Error: conn1 should be conn2
}

我不知道为什么早期的编码人员不只是重用原始连接,但事实就是这样

(开始编辑/追加)

是的,连接代码也是我们的,所以我可以使用给出的答案。

但是,尽管下面的答案回答了我提出的问题,但我认为我没有提出正确的问题。我不确定stackoverflow 的正确做法是什么;问另一个问题,还是编辑这个?

我应该问的一个问题是:这些孤立的、未关闭的连接如何在系统性能中体现出来?另外,既然这些连接对象只存在于某个方法的范围内,那么这些连接难道不符合垃圾回收的条件吗?然后如果它们被 gc'ed,那么打开的连接被 gc'ed 有什么影响?

(结束编辑)

【问题讨论】:

  • 我会密切关注这一点,我们的几个项目中都存在非常相似的问题。
  • 作为记录,我需要有一个非常好的理由不将其移至成熟的连接池实现,例如 DBCP 或 C3PO - 如果你有机会 - 也许你应该考虑这样做?

标签: java jdbc connection-pooling


【解决方案1】:

您可以实现自定义迷你框架或使用现有的迷你框架作为 JDBC 操作的精简包装器。例如,有一个 spring-jdbc 模块 (mavenized) 涵盖了开发人员提供的所有容易出错的样板代码。

您可以检查它的usage examples 并看到客户端代码根本没有初始化/清理!它使用 '模板方法' 模式,即您只需编写基本的数据处理,而无需担心连接/语句/结果集的创建和关闭。所以,你一开始说的问题就没法介绍了。

【讨论】:

    【解决方案2】:

    假设连接管理器也是您自己的代码,您可以将初始化的连接(连同堆栈跟踪)存储在连接管理器内的映射中,然后在它们返回时将其删除。因此,在任何时候,映射的键集都是未返回的连接集,您可以在映射中查找该值,以找到创建它们但从未释放它们的代码有罪的部分。 (如果连接不是合适的映射键,您可能可以使用某种唯一 ID 或连接编号或其他任何东西 - 实际值与其存在无关)。

    然后只需添加一些适当的方式来按需访问此地图即可。根据您的环境,添加一个将映射内容转储到文件的关闭挂钩,和/或添加一个 JConsole 接口以在运行代码中查找未关闭的连接集,都是不错的选择。

    如果连接管理器不是您的代码,您仍然可以使用方面实现相同的目标。

    【讨论】:

    • 我们使用的连接池做的事情很像这样;我相信它会包装它返回的连接,并跟踪它们的使用时间。如果连接未使用的时间超过我们在配置中指定的特定时间,则连接将自动终止,并且在连接打开时记录的堆栈跟踪将打印到日志中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    相关资源
    最近更新 更多