Können Sie sich darauf verlassen, dass .finalize () aufgerufen wird?

8

Ich habe versucht, etwas von meinem Java-Code zu instrumentieren, um sicherzustellen, dass Objekte korrekt gesammelt werden, und ich stellte fest, dass er überraschenderweise nicht so oft aufgerufen wurde, wie ich es erwartet hatte.

Ich frage mich jetzt, ob dies an einer fehlerhaften Instrumentierung oder einem tatsächlichen Speicherleck liegt, das ich lösen muss. der VisualVM-Profiler scheint den ersten anzuzeigen.

Die Besorgnis erregende Situation besteht darin, dass ich einen Thread habe, der Anfragen bearbeitet und in der Anfrage Tausende von temporären Objekten erzeugt. Manchmal wird der Socket, in den dieser Thread schreibt, unerwartet geschlossen und der Thread trifft eine Ausnahme und stirbt.

Wenn der Thread stirbt, scheint es nicht so zu sein, dass .finalize () für diese Objekte jemals aufgerufen wird. Ist das ein Grund, meiner Instrumentierung nicht zu vertrauen?

    
Kevin Dolan 24.10.2011, 17:27
quelle

4 Antworten

2

Nein. Es gibt keine Garantie, dass es angerufen wird. Es wird jedoch normalerweise aufgerufen. Es kann sein, dass Sie Ihre Objekte nicht ordnungsgemäß freigeben oder der Garbage Collector nicht ausgeführt wurde oder der Finalizer-Thread auf eine lange Ausführungszeit wartet.

Sie können darüber in der Finalisierung von Klasseninstanzen nachlesen Teil der Sprachspezifikation.

    
Clint 24.10.2011, 17:35
quelle
4

Finalize () ist nicht die Lösung. Sie können nicht wissen, wann der Finalizer aufgerufen wird. Wenn dein Problem eine Ausnahme ist, benutze try/catch/finally blocks und schließe / lösche alle Sachen, die du schließen willst, um sie zu blockieren. Dies garantiert, dass in beiden Fällen alles bereinigt wird: Die Logik wird normal beendet oder es wurde eine Ausnahme ausgelöst.

    
AlexR 24.10.2011 17:37
quelle
1

Nach allem, was ich über Java-Grundlagen lese, sollte man niemals darauf vertrauen, dass finalize ausgeführt wird. finalize () ist kein Destruktor , den Sie vielleicht aus anderen Sprachen kennen.

Aus java.lang.Object javadoc:

%Vor%

Ссылка ()

Wie ich Dinge sehe, sollte und sollte das gefürchtete Finalize nur dann verwendet werden, wenn Sie in Ihrer App nativen Code enthalten. Aber selbst dann solltest du dich nicht darauf verlassen.

    
MarianP 24.10.2011 17:37
quelle
0

Ihre Verwirrung scheint zu sein, ob es ein Speicherleck gibt oder nicht. Sie versuchen, dies festzustellen, indem Sie prüfen, ob finalize() aufgerufen wurde oder nicht. Wenn das so ist, dann ist es nicht die richtige zu überprüfen, ob es ein Speicherleck gibt oder nicht.

Nur so sind wir in Java klar Speicherlecks bedeuten versteckte Verweise auf Objekte, die Sie nicht brauchen.

Zweck von finalize() , dem Entwickler eine Möglichkeit zu geben, sein eigenes Durcheinander zu bereinigen (Verbindungen, Streams, ...). Der Speicher soll JVMs Chaos / Kopfschmerz sein und durch GC aufgeräumt werden.

Kurz gesagt, die Tatsache, dass " GC garantiert, dass finalize() vorher aufgerufen wird, befreit den Speicher ", sollte nicht als " interpretiert werden, wenn finalize() nicht aufgerufen wird Speicherverlust ". Es könnte einfach sein, dass dieses Objekt nicht noch Garbage Collection ist.

Wenn Sie nach einem Speicherleck suchen, verwenden Sie ein Tool. Siehe Optionen:

Kashyap 24.10.2011 18:15
quelle

Tags und Links