Java MySQL JDBC内存泄漏

时间:2011-04-23 18:14:34

标签: java mysql jdbc memory-leaks

好的,所以我有这个程序有很多(~300)个线程,每个线程都与一个中央数据库通信。我创建了一个与数据库的全局连接,然后每个线程都会创建业务创建语句并执行它们。

在某个地方,我有一个巨大的内存泄漏。在分析堆转储后,我看到com.mysql.jdbc.JDBC4Connection对象是70 MB,因为它在“openStatements”(哈希映射)中有800,000个项目。在某个地方它没有正确地关闭我创建的语句,但我不能为我的生活弄清楚在哪里(每次打开一个,我也关闭它)。有什么想法可能会发生这种情况吗?

4 个答案:

答案 0 :(得分:22)

我有完全相同的问题。我需要为3个线程保持1个连接活动,同时每个线程必须执行大量语句(100k的顺序)。我非常小心,我使用try .... finally ...算法关闭了每个语句和每个结果集。这样,即使代码以某种方式失败,语句和结果集也始终关闭。运行代码8小时后,我惊讶地发现必要的内存从最初的35MB到500MB。我生成了一个内存转储,我用Eclipse的Mat Analyzer进行了分析。事实证明,一个com.mysql.jdbc.JDBC4Connection对象占用了445MB的内存,保留了一些openStatements对象,而这些对象又可以保留135k个hashmap条目,可能来自所有结果集。因此,即使您关闭所有语句和结果集,如果不关闭连接,它也会保留对它们的引用,并且GarbageCollector无法释放资源。

我的解决方案:经过长时间的搜索,我发现MySQL的人发表了这样的声明:

“快速测试是在您的JDBC URL中添加” dontTrackOpenResources = true “。如果内存泄漏 消失了,你的应用程序中的一些代码路径不是关闭语句和结果集。“

以下是链接:http://bugs.mysql.com/bug.php?id=5022。所以我试过了,猜猜怎么着? 8小时后,对于相同的数据库操作,我需要大约40MB的内存。 也许连接池是可取的,但如果这不是一个选项,这是我遇到的下一个最好的事情。

答案 1 :(得分:0)

曾几何时,每当我的代码看到“服务器消失”时,它就会打开一个新的数据库连接。如果错误发生在正确(错误!)的地方,我会留下一些非自由()d孤儿记忆。像这样的东西可以说明你所看到的吗?你是如何处理错误的?

答案 2 :(得分:0)

除非MySQL这样说,否则JDBC连接不是线程安全的。除非使用连接池,否则不能跨线程共享它们。另外,正如所指出的那样,您应该尝试/最终保证所有语句,结果集和连接都已关闭。

答案 3 :(得分:0)

如果没有看到你的代码(我确信它是巨大的),你应该考虑某种更正式的线程池机制,例如Apache Commons池框架,Spring的JDBC框架等。恕我直言,这是一个更简单的方法,因为其他人已经想出如何有效地管理这些类型的情况。