395 Stimmen

Warum würden Sie jemals finalize() implementieren?

Ich habe viele Fragen von Anfängern in Java zu finalize() durchgelesen und finde es irgendwie verwirrend, dass niemand wirklich klargestellt hat, dass finalize() kein zuverlässiger Weg ist, Ressourcen aufzuräumen. Ich habe gesehen, wie jemand kommentiert hat, dass sie es verwenden, um Verbindungen zu bereinigen, was wirklich beängstigend ist, da der einzige Weg, um so nah wie möglich an eine Garantie zu kommen, dass eine Verbindung geschlossen ist, ist, try (catch) finally zu implementieren.

Ich wurde nicht in Informatik ausgebildet, aber ich programmiere seit fast einem Jahrzehnt professionell in Java und ich habe noch nie jemanden gesehen, der finalize() in einem Produktionssystem implementiert hat. Das bedeutet immer noch nicht, dass es keine Verwendung hat, oder dass die Leute, mit denen ich gearbeitet habe, es richtig gemacht haben.

Also frage ich mich, welche Anwendungsfälle es für die Implementierung von finalize() gibt, die nicht zuverlässiger über einen anderen Prozess oder eine andere Syntax innerhalb der Sprache behandelt werden können?

Bitte geben Sie spezifische Szenarien oder Ihre Erfahrung an, einfach das Java-Lehrbuch zu wiederholen oder die beabsichtigte Verwendung von finalize reicht nicht aus, da dies nicht der Zweck dieser Frage ist.

0 Stimmen

HI finalize () Methode sehr gut hier erklärt howtodoinjava.com/2012/10/31/…

5 Stimmen

Die meisten Anwendungs- und Bibliothekscodes werden finalize() niemals verwenden. Allerdings tut Plattformbibliothekcode, wie z.B. SocketInputStream, der native Ressourcen im Namen des Aufrufers verwaltet, dies, um das Risiko von Ressourcenlecks zu minimieren (oder verwendet äquivalente Mechanismen wie PhantomReference, die später hinzugefügt wurden). Daher werden sie im Ökosystem benötigt, obwohl 99,9999% der Entwickler niemals einen schreiben werden.

4 Stimmen

Aktualisierung: finalize ist ab Java 9 veraltet. Siehe die Frage, Warum ist die finalize() Methode in Java 9 veraltet?.

244voto

John M Punkte 12793

Sie könnten es als Absicherung für ein Objekt verwenden, das eine externe Ressource (Socket, Datei usw.) hält. Implementieren Sie eine close()-Methode und dokumentieren Sie, dass sie aufgerufen werden muss.

Implementieren Sie finalize() zur Durchführung der close()-Verarbeitung, wenn Sie feststellen, dass dies nicht erfolgt ist. Vielleicht mit etwas, das auf stderr ausgegeben wird, um darauf hinzuweisen, dass Sie nach einem fehlerhaften Aufrufer aufräumen.

Es bietet zusätzliche Sicherheit in einer außergewöhnlichen/fehlerhaften Situation. Nicht jeder Aufrufer wird jedes Mal das korrekte try {} finally {}-Zeug machen. Bedauerlicherweise ist das in den meisten Umgebungen wahr.

Ich stimme zu, dass es selten benötigt wird. Und wie Kommentatoren feststellen, geht es mit GC-Overhead einher. Verwenden Sie es nur, wenn Sie diese zusätzliche Sicherheit in einer lang laufenden Anwendung benötigen.

Ich sehe, dass mit Java 9 Object.finalize() veraltet ist! Sie verweisen uns auf java.lang.ref.Cleaner und java.lang.ref.PhantomReference als Alternativen.

3 Stimmen

Ich denke, ich dokumentiere im Allgemeinen gut und schreie dann Leute an, wenn sie die Dokumentation nicht lesen. Ich denke, das würde auch helfen. grinsen

50 Stimmen

Stellen Sie einfach sicher, dass durch finalize() niemals eine Ausnahme ausgelöst wird, da der Garbage Collector dann die Bereinigung dieses Objekts nicht fortsetzen wird und es zu einem Memory-Leak kommt.

17 Stimmen

Finalize wird nicht garantiert aufgerufen, also verlassen Sie sich nicht darauf, dass es eine Ressource freigibt.

187voto

Steve Jessop Punkte 264569

finalize() ist ein Hinweis an den JVM, dass es vielleicht schön wäre, Ihren Code zu einem unbestimmten Zeitpunkt auszuführen. Dies ist gut, wenn Sie möchten, dass der Code mysteriös nicht ausgeführt wird.

Es ist auch in drei Situationen gut, etwas Bedeutendes in Finalizern zu tun (im Grunde genommen alles außer Logging):

  • Sie möchten darauf wetten, dass andere finalisierte Objekte immer noch in einem Zustand sind, den der Rest Ihres Programms als gültig betrachtet.
  • Sie möchten viel Überprüfungscode zu allen Methoden aller Ihrer Klassen hinzufügen, die einen Finalizer haben, um sicherzustellen, dass sie sich nach der Finalisierung korrekt verhalten.
  • Sie möchten versehentlich finalisierte Objekte wiederbeleben und viel Zeit damit verbringen, herauszufinden, warum sie nicht funktionieren oder warum sie nicht finalisiert werden, wenn sie schließlich freigegeben werden.

Wenn Sie glauben, dass Sie finalize() benötigen, ist das, was Sie wirklich wollen, manchmal eine Phantomreferenz (die im gegebenen Beispiel einen harten Verweis auf eine Verbindung halten könnte, die von ihrem Referenten verwendet wird, und diese nach dem Einreihen der Phantomreferenz schließen könnte). Dies hat auch die Eigenschaft, dass es möglicherweise mysteriöserweise nie ausgeführt wird, aber zumindest kann es keine Methoden auf finalisierten Objekten aufrufen oder sie wieder beleben. Also ist es genau richtig für Situationen, in denen Sie diese Verbindung nicht unbedingt sauber schließen müssen, aber Sie möchten es gerne, und die Clients Ihrer Klasse können es nicht oder wollen es nicht selbst schließen (was eigentlich fair genug ist - was ist der Sinn eines Garbage Collectors, wenn Sie Schnittstellen entwerfen, die erfordern, dass eine bestimmte Aktion vor der Sammlung durchgeführt wird? Das bringt uns nur zurück in die Zeiten von malloc/free.)

Manchmal benötigen Sie die Ressource, die Sie verwalten zu glauben, robuster zu sein. Warum müssen Sie z.B. diese Verbindung schließen? Es muss letztendlich auf irgendeiner Art von E/A beruhen, die vom System bereitgestellt wird (Socket, Datei, usw.), also warum können Sie sich nicht darauf verlassen, dass das System sie für Sie schließt, wenn die niedrigste Ebene der Ressource gesammelt wird? Wenn der Server am anderen Ende unbedingt verlangt, dass Sie die Verbindung sauber schließen, anstatt einfach den Socket zu schließen, was passiert dann, wenn jemand über das Netzkabel des Geräts stolpert, auf dem Ihr Code läuft, oder das Netzwerk dazwischen ausfällt?

Haftungsausschluss: Ich habe in der Vergangenheit an einer JVM-Implementierung gearbeitet. Ich hasse Finalizer.

82 Stimmen

Upvoten für extreme Sarkasmus Gerechtigkeit.

32 Stimmen

Das beantwortet nicht die Frage; es nennt nur alle Nachteile von finalize(), ohne zu erklären, warum jemand es wirklich verwenden möchte.

0 Stimmen

Waren Finalisierer und Phantomreferenzen beide Teil der ursprünglichen JVM-Spezifikation? Wenn man Phantomreferenzen hatte und wenn es eine systemdefinierte Phantomreferenz-Benachrichtigungswarteschlange gab, die jedes Objekt benachrichtigen würde, das auf bequemer Basis GC'ed wurde, würden diese (zusammen mit WeakReference) nahezu alles tun, was Code sollte mit finalize machen [Wiederauferstehung ist möglicherweise nicht möglich, aber ich bin mir nicht sicher, ob das eine schlechte Sache wäre].

51voto

skaffman Punkte 389758

Die einzige Zeit, in der ich finalize in Produktionscode verwendet habe, war, um eine Überprüfung zu implementieren, ob die Ressourcen eines bestimmten Objekts freigegeben wurden, und falls nicht, dann eine sehr laute Meldung zu protokollieren. Es hat tatsächlich nicht versucht, es selbst zu tun, es hat nur viel geschrien, wenn es nicht ordnungsgemäß erledigt wurde. Hat sich als ziemlich nützlich erwiesen.

0 Stimmen

Das ist die einzige gültige Verwendung. Sie können almson-refcount zu diesem Zweck verwenden, da die korrekte und effiziente Implementierung knifflig ist.

40voto

Paul Tomblin Punkte 172816

Ich arbeite seit 1998 professionell mit Java und habe finalize() noch nie implementiert. Nicht einmal.

0 Stimmen

Wie zerstöre ich das öffentliche Klassenobjekt? Es verursacht Probleme in ADF. Grundsätzlich soll die Seite neu geladen werden (um frische Daten von einer API zu erhalten), aber sie verwendet das alte Objekt und zeigt die Ergebnisse an.

2 Stimmen

@InfantPro'Aravind' Aufrufen von finalize entfernt das Objekt nicht. Es handelt sich um eine Methode, die Sie implementieren, die die JVM wählen kann, um aufzurufen, wenn sie Ihren Gegenstand entsorgt.

0 Stimmen

@PaulTomblin, ohk danke für dieses Detail. Irgendwelche Vorschläge zum Aktualisieren einer Seite auf ADF?

6voto

Bill the Lizard Punkte 384619

Sie sollten sich nicht darauf verlassen, dass finalize() Ihre Ressourcen für Sie aufräumt. finalize() wird erst ausgeführt, wenn die Klasse eingesammelt wird, falls überhaupt. Es ist daher besser, die Ressourcen explizit freizugeben, wenn Sie sie nicht mehr benötigen.

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