2010-12-02 13 views
5

Ich versuche, ein Speicherleck in einem unserer Java-Daemons zu fangen, und nach dem Auslagern des Speichers und Analysieren über Memory Analyzer Tool, bemerkte, dass der größte Teil der Leckage durch die JDBC4Connection verursacht wird:Speicherleck in 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 

Ich bin ziemlich sicher, dass wir alle MySQL-Ressourcen schließen, aber nicht finden können, was das verursacht.

Gibt es einen guten Weg, es zu fangen? Hast du das in der Vergangenheit erlebt und kannst beraten, wonach ich suchen soll?

PS: Blick tiefer mit MAT, sehe ich die folgenden Informationen:

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%

Es scheint, als jeder JDBC eine riesige Menge an HashMap Einträge hält (> 6000 Objekte), und sie nicht befreien überhaupt.

Vielen Dank im Voraus!

Antwort

6

Duffymo ist fast sicher richtig. In der Vergangenheit, als wir Speicherlecks hatten, ist es praktisch immer der MySQL JDBC-Treiber. Ich vergesse nur, ein kleines ResultSet oder eine Connection oder Statement irgendwo zu schließen. Ich habe die gesamte Codebasis für jedes Mal auditiert, wenn wir diese verwendet haben, um das Problem zu finden und sicherzustellen, dass sie geschlossen werden.

Wie für die HashMap habe ich das auch gesehen. Ich habe die Quelle nicht angeschaut, aber mein Eindruck war, dass der MySQL-Treiber die Zeilen (mindestens Zeilenwerte) intern in HashMaps gespeichert hat.

Undichte ResultSets ist leider einfach. Die Idee, dass sich die knappen Ressourcen, die sich darum kümmern, selbst in JDK 7 oder 8 zu finden, gefällt mir deshalb sehr.

Sie könnten irgendwo eine Shim-Klasse einfügen (etwa für Connection), um jede geöffnete/geschlossene Ressource zu protokollieren, um zu sehen, ob Sie das Leck lokalisieren können, ohne direkt alle Quellen zu lesen.

+0

Eine etwas naive Frage. aber gibt es eine Chance, dass dies ein Problem in JDBC-Treiber selbst ist, und die Aktualisierung würde helfen? Oder muss das etwas streng in meinem Code sein? – SyBer

+0

Danke für die Shim-Klasse-Idee, werde es versuchen. – SyBer

+1

Die JDBC-Treiber können undicht sein. Wenn Sie die Versionshinweise lesen, werden diese als behoben angezeigt. Das heißt, in 3-4 Jahren, in denen ich mit diesem Zeug gearbeitet habe, muss ich noch ein Leck finden, das nicht unsere Schuld war, egal wie sicher ich sonst gewesen wäre. – MBCook

4

Ich bin mir ziemlich sicher, dass wir alle die MySQL Ressourcen

Wenn nicht 100% sicher zu schließen, bitte zeigen, wie Sie Ihre Verbindungen sind zu schließen.

Verwenden Sie einen Verbindungspool? Würde es eine Poolgröße von 10 haben?

+1

Ja, wir verwenden den BoneCP-Pool. – SyBer