Java MySQL JDBC内存泄漏

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

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

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

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

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

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

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

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

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