Ich habe einen Heap-Dump für mein Programm durchgeführt. Als ich ihn mit dem Speicheranalysetool öffnete, stellte ich fest, dass die java.lang.ref.Finalizer
para org.logicalcobwebs.proxool.ProxyStatement
hat viel Speicherplatz in Anspruch genommen. Warum ist das so?
Antworten
Zu viele Anzeigen?Einige Klassen implementieren die Object.finalize()
Methode. Objekte, die diese Methode überschreiben, müssen von einem Hintergrund-Thread-Call-Finalizer aufgerufen werden, und sie können erst dann bereinigt werden. Wenn diese Aufgaben kurz sind und man nicht viele davon verwirft, funktioniert alles gut. Wenn Sie jedoch viele dieser Objekte erstellen und/oder ihre Finalisierer lange brauchen, baut sich die Warteschlange der zu finalisierenden Objekte auf. Es ist möglich, dass diese Warteschlange den gesamten Speicher verbraucht.
Die Lösung lautet
- Verwenden Sie nach Möglichkeit keine finalize()d-Objekte (wenn Sie die Klasse für das Objekt schreiben)
- Machen Sie finalize sehr kurz (wenn Sie es verwenden müssen)
- werfen Sie solche Objekte nicht jedes Mal weg (versuchen Sie, sie wiederzuverwenden)
Die letzte Option ist wahrscheinlich die beste für Sie, da Sie eine bestehende Bibliothek verwenden.
Soweit ich das beurteilen kann, ist Proxool ein Verbindungspool für JDBC-Verbindungen. Das deutet für mich darauf hin, dass das Problem darin besteht, dass Ihre Anwendung den Verbindungspool missbraucht. Statt eines Aufrufs von close
auf den Anweisungsobjekten, lässt Ihr Code sie und/oder ihre übergeordneten Verbindungen wahrscheinlich fallen. Das Proxool verlässt sich auf Finalizer, um die zugrundeliegenden treiberimplementierten Objekte zu schließen ... aber dafür sind diese Finalizer-Instanzen erforderlich. Es könnte auch bedeuten, dass Sie die Verbindung dazu veranlassen, (echte) Datenbankverbindungen häufiger als nötig zu öffnen/schließen, und das wäre schlecht für die Leistung.
Ich schlage also vor, dass Sie Ihren Code auf durchgesickerte ResultSet-, Statement- und/oder Connection-Objekte überprüfen und sicherstellen, dass Sie sie in finally
Blöcke.
Wenn Sie sich den Speicherauszug ansehen, fragen Sie sich sicher, wohin die 898.527.228 Bytes gehen. Der überwiegende Teil wird vom Finalizer-Objekt mit der ID 2aab07855e38
. Wenn Sie die Dump-Datei noch haben, sehen Sie sich an, was dass Finalizer
bezieht sich auf. Es sieht problematischer aus als die Proxool-Objekte.
Es kann spät sein, aber ich hatte ein ähnliches Problem und fand heraus, dass wir die Garbage Collectors abstimmen müssen, kann nicht serielle und parallele GC halten, und G1 GC war auch nicht richtig funktionieren. Aber bei der Verwendung von concurrentMarkSweep GC waren wir in der Lage, den Aufbau dieser Warteschlange zu groß zu stoppen.