什么是调查Java中数据库连接使用情况的好工具?
开发人员正在支持一个复杂的Java程序,该程序偶尔会耗尽可用的数据库连接数。由于问题是零星的,因此知道哪个线程打开了与数据库的多个连接以将精力集中在该区域中将是有用的。
最后,正确的修复似乎是重写程序以重用连接而不是每个线程打开多个连接。
我问,开发人员应该在他的工具箱中使用哪些工具来调查资源,即线程分配的数据库连接。
什么是调查Java中数据库连接使用情况的好工具?
开发人员正在支持一个复杂的Java程序,该程序偶尔会耗尽可用的数据库连接数。由于问题是零星的,因此知道哪个线程打开了与数据库的多个连接以将精力集中在该区域中将是有用的。
最后,正确的修复似乎是重写程序以重用连接而不是每个线程打开多个连接。
我问,开发人员应该在他的工具箱中使用哪些工具来调查资源,即线程分配的数据库连接。
不是特定工具,而是用于跟踪哪些代码负责打开连接或其他资源的调试技术。
我假设你在java端使用一致的方法来获得数据库连接(合并或不合并)。
我们的想法是在您的连接工厂/池或其他任何地方创建一个非常轻的包装类。包装器将实现任何有意义的jdbc接口,因此您可以将其交换为普通连接对象,但大多数方法只是透明地调用/返回底层连接。
如果您正在使用某种IoC框架(例如spring),您应该能够在配置级别轻松交换连接/工厂类。现在你所有的java代码都将使用你的新数据库连接包装器。
如果您正在使用游泳池,那么请致电 connection.close()
通常只是将对象返回到池而不是破坏连接。所以这种技术适用于正常的连接泄漏或只是“没有返回池(池耗尽)”泄漏。
现在我们只需要记录有趣的位并为泄漏的连接设置陷阱。
在连接包装器的构造函数或工厂方法中创建一个新的 Throwable
对象并将其存储为包装器中的局部变量以供日后使用。我们用一个 Throwable
因为它比使用更快/更便宜 Thread.currentThread().getStackTrace()
。
实施 finally
包装器类中的方法。这是一个清理方法,当对象被销毁时由GC调用,因为它不再使用。
该 finally
方法应检查“我是否关闭?”。如果已经关闭,那么一切都很好......但是如果连接正在进行GC并且尚未关闭......那么这是一个“泄露”的连接。
现在 Throwable
重新回归。我们可以抓住 Throwable
并输出一条很好的日志消息,上面写着:“我是一个泄漏的连接,这里是一个涉及我的创建者的堆栈跟踪。”
该方法可适用于各种情况。您当然可以在包装器中保留其他类型的数据,以便对特定问题进行故障排除。例如创建时间。然后,您可以轮询长期连接并再次暗示创建者。或者您可以轮询现有连接并解析 Throwable
堆栈跟踪以获取有关哪些代码随时间使用多少连接的数据。
可能有一个现成的工具也可以做这些类型的事情,但在大多数情况下应用这种技术所需的代码量非常少(假设您有一种简单的方法来交换我们的数据库连接工厂而不用搜索 - 替换整个代码库)。
看一下 log4jdbc。它使您可以查看jdbc上的所有内容,包括打开/关闭连接以及连接编号信息。
有人给我看了 ConnLeakFinder 最近,“一个简单的工具来查明java代码中的jdbc连接泄漏”。到目前为止,我还没有自己测试过,但它应该允许你 看看谁在使用后没有关闭连接。看到 连接+泄漏+如何+ Find.htm。
但事实上,你应该使用连接池(例如 C3P0)。
连接池可以为您提供一些诊断。例如,检查C3P0连接池的debugUnreturnedConnectionStackTraces属性:
http://www.mchange.com/projects/c3p0/index.html#debugUnreturnedConnectionStackTraces
P6SPY 是一个开源框架,支持拦截和可选修改数据库语句的应用程序。
从 http://www.p6spy.com/about.html
P6Spy发行版包括以下模块:
不是特定工具,而是用于跟踪哪些代码负责打开连接或其他资源的调试技术。
我假设你在java端使用一致的方法来获得数据库连接(合并或不合并)。
我们的想法是在您的连接工厂/池或其他任何地方创建一个非常轻的包装类。包装器将实现任何有意义的jdbc接口,因此您可以将其交换为普通连接对象,但大多数方法只是透明地调用/返回底层连接。
如果您正在使用某种IoC框架(例如spring),您应该能够在配置级别轻松交换连接/工厂类。现在你所有的java代码都将使用你的新数据库连接包装器。
如果您正在使用游泳池,那么请致电 connection.close()
通常只是将对象返回到池而不是破坏连接。所以这种技术适用于正常的连接泄漏或只是“没有返回池(池耗尽)”泄漏。
现在我们只需要记录有趣的位并为泄漏的连接设置陷阱。
在连接包装器的构造函数或工厂方法中创建一个新的 Throwable
对象并将其存储为包装器中的局部变量以供日后使用。我们用一个 Throwable
因为它比使用更快/更便宜 Thread.currentThread().getStackTrace()
。
实施 finally
包装器类中的方法。这是一个清理方法,当对象被销毁时由GC调用,因为它不再使用。
该 finally
方法应检查“我是否关闭?”。如果已经关闭,那么一切都很好......但是如果连接正在进行GC并且尚未关闭......那么这是一个“泄露”的连接。
现在 Throwable
重新回归。我们可以抓住 Throwable
并输出一条很好的日志消息,上面写着:“我是一个泄漏的连接,这里是一个涉及我的创建者的堆栈跟踪。”
该方法可适用于各种情况。您当然可以在包装器中保留其他类型的数据,以便对特定问题进行故障排除。例如创建时间。然后,您可以轮询长期连接并再次暗示创建者。或者您可以轮询现有连接并解析 Throwable
堆栈跟踪以获取有关哪些代码随时间使用多少连接的数据。
可能有一个现成的工具也可以做这些类型的事情,但在大多数情况下应用这种技术所需的代码量非常少(假设您有一种简单的方法来交换我们的数据库连接工厂而不用搜索 - 替换整个代码库)。
看一下 log4jdbc。它使您可以查看jdbc上的所有内容,包括打开/关闭连接以及连接编号信息。
有人给我看了 ConnLeakFinder 最近,“一个简单的工具来查明java代码中的jdbc连接泄漏”。到目前为止,我还没有自己测试过,但它应该允许你 看看谁在使用后没有关闭连接。看到 连接+泄漏+如何+ Find.htm。
但事实上,你应该使用连接池(例如 C3P0)。
连接池可以为您提供一些诊断。例如,检查C3P0连接池的debugUnreturnedConnectionStackTraces属性:
http://www.mchange.com/projects/c3p0/index.html#debugUnreturnedConnectionStackTraces
P6SPY 是一个开源框架,支持拦截和可选修改数据库语句的应用程序。
从 http://www.p6spy.com/about.html
P6Spy发行版包括以下模块: