73 Stimmen

ist ein Speicherleck? warum java.lang.ref.Finalizer so viel Speicher verbraucht

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?

screenshot

76voto

Peter Lawrey Punkte 511323

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.

11voto

Stephen C Punkte 665668

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.

0voto

Nirbhay Mishra Punkte 1539

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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X