我正试图在我们的一个Java守护进程中捕获内存泄漏,在转储内存并通过Memory Analyzer Tool进行分析后,注意到大部分泄漏是由JDBC4Connection引起的:
10 instances of "com.mysql.jdbc.JDBC4Connection", loaded by "sun.misc.Launcher$AppClassLoader @ 0x2aaab620ed00" occupy 858,283,752 (81.55%) bytes. Biggest instances:
* com.mysql.jdbc.JDBC4Connection @ 0x2aaab64ad820 - 87,110,160 (8.28%) bytes.
* com.mysql.jdbc.JDBC4Connection @ 0x2aaab64af520 - 86,730,408 (8.24%) bytes.
* com.mysql.jdbc.JDBC4Connection @ 0x2aaab64ad0e0 - 86,584,048 (8.23%) bytes.
* com.mysql.jdbc.JDBC4Connection @ 0x2aaab64aede0 - 86,488,800 (8.22%) bytes.
* com.mysql.jdbc.JDBC4Connection @ 0x2aaab61f5320 - 85,752,872 (8.15%) bytes.
* com.mysql.jdbc.JDBC4Connection @ 0x2aaab64ae6a0 - 85,603,280 (8.13%) bytes.
* com.mysql.jdbc.JDBC4Connection @ 0x2aaab64adf60 - 85,270,440 (8.10%) bytes.
* com.mysql.jdbc.JDBC4Connection @ 0x2aaab61f4be0 - 85,248,592 (8.10%) bytes.
* com.mysql.jdbc.JDBC4Connection @ 0x2aaab64afc60 - 85,120,704 (8.09%) bytes.
* com.mysql.jdbc.JDBC4Connection @ 0x2aaab61f5a60 - 84,374,448 (8.02%) bytes.
Keywords
com.mysql.jdbc.JDBC4Connection
sun.misc.Launcher$AppClassLoader @ 0x2aaab620ed00
我很确定我们关闭了所有的MySQL资源,但是找不到导致这种情况的原因。
有没有什么好办法可以抓住它?你有没有经历过这个,并且可以建议我应该寻找什么?
P.S .: 通过MAT深入了解,我看到以下信息:
com.mysql.jdbc.JDBC4Connection @ 0x2aaab64ad820 | 1,856 | 87,110,160 | 8.28%
|- java.util.HashMap @ 0x2aaab62115a8 | 64 | 87,021,632 | 8.27%
| '- java.util.HashMap$Entry[16384] @ 0x2aaae182e970| 131,096 | 87,021,568 | 8.27%
似乎每个JDBC都包含大量的Hashmap条目(> 6000个对象),并且根本不会释放它们。
提前致谢!
答案 0 :(得分:6)
至于HashMap,我也看过了。我没有查看源代码,但我的印象是MySQL驱动程序在内部存储了HashMaps中的行(至少是行值)。
泄漏ResultSet非常容易。由于这个原因,我自己在JDK 7或8中处理这些可靠资源的想法真的很吸引我。
你可以在某个地方插入一个垫片类(比如连接)来记录每个打开/关闭的资源,看看你是否可以在没有直接读取所有源的情况下捕获泄漏的位置。
答案 1 :(得分:4)
我很确定我们关闭了所有MySQL资源
如果不是100%确定,请说明您是如何关闭连接的。
您使用的是连接池吗?是否会出现游泳池大小为10?
答案 2 :(得分:0)
听起来像您有一个具有10个连接的连接池,并且该池启用了语句缓存,而没有将缓存大小限制为正常值。