Wann wird die Methode finalize() in Java aufgerufen?

Lesezeit: 5 Minuten

Wann wird die Methode finalize in Java aufgerufen
Rajesh Kumar J

Ich muss wissen, wann die finalize() Methode wird in der aufgerufen JVM. Ich habe eine Testklasse erstellt, die in eine Datei schreibt, wenn die finalize() Methode wird aufgerufen, indem sie überschrieben wird. Es wird nicht ausgeführt. Kann mir jemand sagen, warum es nicht ausgeführt wird?

  • Nur als Randnotiz: Finalize ist in Java 9 als veraltet markiert

    – Reg.-Nr

    27. Oktober 2017 um 11:41 Uhr

  • Schau mal: infoq.com/news/2017/03/Java-Finalize-Deprecated

    – wleao

    3. Dezember 2017 um 11:38 Uhr

  • wenn irgendetwas einen Verweis auf Ihr Objekt oder sogar die Klasse hat. finalize() und Garbage Collection hat keine Auswirkungen.

    – ha9u63ar

    10. Januar 2018 um 22:31 Uhr

  • Es ist veraltet, wenn Java9 gestartet wird. docs.oracle.com/javase/9/docs/api/java/lang/…

    – srk

    25. Juni 2020 um 8:42 Uhr

1646629638 204 Wann wird die Methode finalize in Java aufgerufen
Joachim Sauer

Die finalize -Methode wird aufgerufen, wenn ein Objekt im Begriff ist, Garbage Collection zu erhalten. Das kann jederzeit sein, nachdem es für die Garbage-Collection geeignet geworden ist.

Beachten Sie, dass es durchaus möglich ist, dass ein Objekt niemals Garbage Collection erhält (und somit finalize wird nie aufgerufen). Dies kann passieren, wenn das Objekt nie für gc geeignet wird (weil es während der gesamten Lebensdauer der JVM erreichbar ist) oder wenn zwischen dem Zeitpunkt, zu dem das Objekt geeignet wird, und dem Zeitpunkt, zu dem die JVM aufhört, tatsächlich keine Garbage Collection ausgeführt wird (dies tritt häufig bei simple Testprogramme).

Es gibt Möglichkeiten, der JVM mitzuteilen, dass sie ausgeführt werden soll finalize auf Objekte, die noch nicht aufgerufen wurden, aber ihre Verwendung ist auch keine gute Idee (die Garantien dieser Methode sind auch nicht sehr stark).

Wenn Sie sich darauf verlassen finalize für den korrekten Betrieb Ihrer Anwendung, dann machen Sie etwas falsch. finalize sollte nur zur Bereinigung von (normalerweise Nicht-Java-)Ressourcen verwendet werden. Und das ist exakt weil die JVM das nicht garantiert finalize wird immer auf ein beliebiges Objekt aufgerufen.

  • @ Rajesh. Nein. Es geht nicht um die „Lebensdauer“. Sie können Ihr Programm (für Jahre) in eine Endlosschleife versetzen, und wenn der Garbage Collector nicht benötigt wird, wird er nie ausgeführt.

    – ChrisCantrell

    25. September 2013 um 22:28 Uhr

  • @VikasVerma: Der perfekte Ersatz ist nichts: Sie sollten sie nicht brauchen. Der einzige Fall, in dem es sinnvoll wäre, wäre, wenn Ihre Klasse eine externe Ressource verwaltet (wie eine TCP/IP-Verbindung, eine Datei … alles, was der Java GC nicht verarbeiten kann). In diesen Fällen die Closable Schnittstelle (und die Idee dahinter) ist wahrscheinlich das, was Sie wollen: machen .close() schließen/verwerfen Sie die Ressource und fordern Sie den Benutzer Ihrer Klasse auf, sie zur richtigen Zeit aufzurufen. Sie könnte möchte ein hinzufügen finalize Methode “nur um sicher zu sein”, aber das wäre eher ein Debugging-Tool als ein tatsächlicher Fix (weil es nicht zuverlässig genug ist).

    – Joachim Sauer

    13. Juni 2014 um 11:27 Uhr

  • @Dragonborn: Das ist eigentlich eine ganz andere Frage und sollte separat gestellt werden. Es gibt Shutdown-Hooks, aber sie sind nicht garantiert, wenn die JVM unerwartet heruntergefahren wird (auch bekannt als Absturz). Aber ihre Garantien sind wesentlich stärker als die für Finalizer (und sie sind auch sicherer).

    – Joachim Sauer

    13. Februar 2015 um 15:11 Uhr

  • Ihr letzter Absatz besagt, dass Sie es nur zum Bereinigen von Ressourcen verwenden sollen, obwohl es keine Garantie gibt, dass es jemals aufgerufen wird. Spricht dieser Optimismus? Ich würde davon ausgehen, dass etwas Unzuverlässiges auch nicht zum Bereinigen von Ressourcen geeignet wäre.

    – Jeroen Vannevel

    18. April 2015 um 12:20 Uhr

  • Finalizer können manchmal den Tag retten … Ich hatte einen Fall, in dem eine Bibliothek eines Drittanbieters einen FileInputStream verwendete und ihn nie schloss. Mein Code hat den Code der Bibliothek aufgerufen und dann versucht, die Datei zu verschieben, was fehlgeschlagen ist, weil sie noch geöffnet war. Ich musste den Anruf erzwingen System.gc() um FileInputStream::finalize() aufzurufen, dann könnte ich die Datei verschieben.

    – Elist

    8. August 2018 um 14:42 Uhr

Im Allgemeinen ist es am besten, sich nicht darauf zu verlassen finalize() irgendetwas aufräumen usw.

Entsprechend der Javadoc (was lesenswert wäre), es ist:

Wird vom Garbage Collector für ein Objekt aufgerufen, wenn Garbage Collection feststellt, dass keine weiteren Verweise auf das Objekt vorhanden sind.

Wie Joachim betonte, kann dies im Leben eines Programms niemals passieren, wenn das Objekt immer zugänglich ist.

Außerdem wird nicht garantiert, dass der Garbage Collector zu einem bestimmten Zeitpunkt ausgeführt wird. Im Allgemeinen versuche ich zu sagen finalize() ist wahrscheinlich nicht die beste Methode, die Sie im Allgemeinen verwenden können, es sei denn, Sie benötigen sie für etwas Bestimmtes.

  • Mit anderen Worten (nur zur Klarstellung für zukünftige Leser) wird die Hauptklasse niemals aufgerufen, da, wenn die Hauptklasse schließt, kein Müll eingesammelt werden muss. Das Betriebssystem bereinigt alles, was die App ohnehin verwendet.

    – Markus Hieronymus

    7. Mai 2012 um 7:05 Uhr


  • “nicht die beste Methode zu verwenden … es sei denn, Sie brauchen es für etwas Bestimmtes” – äh, dieser Satz gilt für 100% von allem, ist also nicht hilfreich. Die Antwort von Joachim Sauer ist viel besser

    – BT

    7. März 2013 um 21:37 Uhr

  • @Zom-B Ihr Beispiel ist zur Verdeutlichung hilfreich, aber um pedantisch zu sein, könnte es vermutlich in der Hauptklasse aufgerufen werden, wenn die Hauptklasse einen Nicht-Daemon-Thread erstellt und dann zurückkehrt?

    –Tom G

    15. Februar 2014 um 21:24 Uhr

  • Also, was sind die Situationen, wo finalize wäre nützlich?

    – nbro

    21. Mai 2015 um 17:28 Uhr

  • @MarkJeronimus – Eigentlich ist das irrelevant. Die finalize() Die Methode on für die Hauptklasse wird aufgerufen, wenn eine >>Instanz<< der Klasse der Garbage Collection unterzogen wird, nicht wenn die Hauptmethode beendet wird. Und außerdem die Hauptklasse könnten Garbage Collection durchgeführt werden, bevor die Anwendung abgeschlossen ist; zB in einer Multithread-App, wo der “Haupt”-Thread andere Threads erstellt und dann zurückkehrt. (In der Praxis wäre ein nicht standardmäßiger Classloader erforderlich ….)

    – Stefan C

    10. September 2016 um 7:51 Uhr


protected void finalize() throws Throwable {}
  • jede Klasse erbt die finalize() Methode aus java.lang.Object
  • Die Methode wird vom Garbage Collector aufgerufen, wenn festgestellt wird, dass keine weiteren Verweise auf das Objekt vorhanden sind
  • Die Methode Object finalize führt keine Aktionen aus, kann aber von jeder Klasse überschrieben werden
  • Normalerweise sollte es außer Kraft gesetzt werden, um Nicht-Java-Ressourcen zu bereinigen, dh eine Datei zu schließen
  • wenn überschrieben finalize() Es ist gute Programmierpraxis, eine try-catch-finally-Anweisung zu verwenden und immer aufzurufen super.finalize(). Dies ist eine Sicherheitsmaßnahme, um sicherzustellen, dass Sie nicht versehentlich das Schließen einer Ressource verpassen, die von der Objekte aufrufenden Klasse verwendet wird

    protected void finalize() throws Throwable {
         try {
             close();        // close open files
         } finally {
             super.finalize();
         }
     }
    
  • jede Ausnahme, die von geworfen wird finalize() während der Garbage Collection hält die Finalisierung an, wird aber ansonsten ignoriert

  • finalize() wird nie mehr als einmal auf einem Objekt ausgeführt

Zitiert aus: http://www.janeg.ca/scjp/gc/finalize.html

Sie können auch diesen Artikel lesen:

  • Der JavaWorld-Artikel, auf den Sie verlinken, stammt aus dem Jahr 1998 und enthält einige interessante Ratschläge, insbesondere den Vorschlag, System.runFinalizersOnExit() aufzurufen, um sicherzustellen, dass Finalizer ausgeführt werden, bevor die JVM beendet wird. Diese Methode ist derzeit veraltet, mit dem Kommentar „Diese Methode ist von Natur aus unsicher. Dies kann dazu führen, dass Finalizer für Live-Objekte aufgerufen werden, während andere Threads diese Objekte gleichzeitig manipulieren, was zu fehlerhaftem Verhalten oder Deadlock führt.’ Also werde ich das nicht tun.

    – Greg Chabala

    14. Juni 2011 um 17:12 Uhr

  • Da runFinalizerOnExit() NICHT Thread-sicher ist, könnte man Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { destroyMyEnclosingClass(); } }); im Konstruktor der Klasse.

    – Ustaman Sangat

    24. Juli 2012 um 21:49 Uhr


  • @Ustaman Sangat Das ist eine Möglichkeit, aber denken Sie daran, dass dies einen Verweis auf Ihre Instanz aus dem shutdownHook setzt, was so ziemlich garantiert, dass Ihre Klasse niemals von einer Garbage Collection erfasst wird. Mit anderen Worten, es ist ein Speicherleck.

    – Pieroxy

    18. Juni 2013 um 16:32 Uhr

  • @pieroxy, obwohl ich allen anderen hier zustimme, finalize() für nichts zu verwenden, verstehe ich nicht, warum es eine Referenz vom Shutdown-Hook geben müsste. Man könnte eine weiche Referenz haben.

    – Ustaman Sangat

    19. Juni 2013 um 21:42 Uhr

1646629639 33 Wann wird die Methode finalize in Java aufgerufen
Ha Deng

Siehe Effektives Java, 2. Auflage, Seite 27.
Punkt 7: Vermeiden Sie Finalizer

Finalizer sind unvorhersehbar, oft gefährlich und im Allgemeinen unnötig. Führen Sie niemals etwas Zeitkritisches in einem Finalizer durch. Verlassen Sie sich niemals auf einen Finalizer, um den kritischen persistenten Zustand zu aktualisieren.

Um eine Ressource zu beenden, verwenden Sie stattdessen try-finally:

// try-finally block guarantees execution of termination method
Foo foo = new Foo(...);
try {
    // Do what must be done with foo
    ...
} finally {
    foo.terminate(); // Explicit termination method
}

  • @Anatoly die Bearbeitung ist falsch, es fehlt die Situation, in der die MyClass() Der Konstruktor löst die Ausnahme aus. Dies löst in der neuen Version des Beispiels eine NPE aus.

    – bzw

    27. November 2020 um 14:07 Uhr

1646629639 626 Wann wird die Methode finalize in Java aufgerufen
Stefan C

Wann ist der finalize() Methode in Java aufgerufen?

Die Finalize-Methode wird aufgerufen, nachdem der GC festgestellt hat, dass das Objekt nicht mehr erreichbar ist, und bevor er den vom Objekt verwendeten Speicher tatsächlich zurückfordert.

  • Wenn ein Objekt niemals unerreichbar wird, finalize() wird nie darauf angerufen.

  • Wenn der GC dann nicht läuft finalize() dürfen nie angerufen werden. (Normalerweise wird der GC nur ausgeführt, wenn die JVM entscheidet, dass wahrscheinlich genug Datenmüll vorhanden ist, damit es sich lohnt.)

  • Es kann mehr als einen GC-Zyklus dauern, bevor der GC feststellt, dass ein bestimmtes Objekt nicht erreichbar ist. (Java GCs sind typischerweise “Generations”-Sammler …)

  • Sobald der GC erkennt, dass ein Objekt unerreichbar und finalisierbar ist, wird es in eine Finalisierungswarteschlange gestellt. Die Finalisierung erfolgt in der Regel asynchron mit der normalen GC.

(Eigentlich die JVM-Spezifikation erlaubt eine JVM zu noch nie run finalizers … vorausgesetzt, dass es nicht den von den Objekten belegten Speicherplatz zurückfordert. Eine so implementierte JVM wäre lahmgelegt / nutzlos, aber dieses Verhalten ist “erlaubt”.)

Das Ergebnis ist, dass es unklug ist, sich auf die Finalisierung zu verlassen, um Dinge zu erledigen, die in einem bestimmten Zeitrahmen erledigt werden müssen. Es ist „Best Practice“, sie überhaupt nicht zu verwenden. Es sollte einen besseren (dh zuverlässigeren) Weg geben, alles zu tun, was Sie in der zu tun versuchen finalize() Methode.

Die einzige legitime Verwendung für die Finalisierung besteht darin, Ressourcen zu bereinigen, die Objekten zugeordnet sind, die durch den Anwendungscode verloren gegangen sind. Selbst dann sollten Sie versuchen, den Anwendungscode so zu schreiben, dass die Objekte gar nicht erst verloren gehen. (Verwenden Sie beispielsweise Java 7+ Versuch-mit-Ressourcen um sicherzustellen, dass close() heißt immer …)


Ich habe eine Testklasse erstellt, die in eine Datei schreibt, wenn die Methode finalize() aufgerufen wird, indem sie überschrieben wird. Es wird nicht ausgeführt. Kann mir jemand sagen, warum es nicht ausgeführt wird?

Es ist schwer zu sagen, aber es gibt ein paar Möglichkeiten:

  • Das Objekt wird nicht von der Garbage Collection erfasst, da es noch erreichbar ist.
  • Das Objekt wird nicht von der Garbage Collection erfasst, da der GC nicht ausgeführt wird, bevor der Test abgeschlossen ist.
  • Das Objekt wird vom GC gefunden und vom GC in die Finalisierungswarteschlange gestellt, aber die Finalisierung wird nicht abgeschlossen, bevor Ihr Test abgeschlossen ist.

Wann wird die Methode finalize in Java aufgerufen
cst1992

Da beim Aufrufen der Methode finalize() durch JVM eine Unsicherheit besteht (nicht sicher, ob das überschriebene finalize() ausgeführt wird oder nicht), ist es zu Studienzwecken besser, zu beobachten, was passiert, wenn finalize() aufgerufen wird Zwingen Sie die JVM, die Garbage Collection per Befehl aufzurufen System.gc().

Insbesondere wird finalize() aufgerufen, wenn ein Objekt nicht mehr verwendet wird. Aber wenn wir versuchen, es zu rufen, indem wir neue Objekte schaffen, gibt es keine Gewissheit über seinen Ruf. Zur Sicherheit erstellen wir also a null Objekt c die offensichtlich keine zukünftige Verwendung hat, daher sehen wir das Objekt cAnruf beenden.

Beispiel

class Car {

    int maxspeed;

    Car() {
        maxspeed = 70;
    }

    protected void finalize() {

    // Originally finalize method does nothing, but here we override finalize() saying it to print some stmt
    // Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection

        System.out.println("Called finalize method in class Car...");
    }
}

class Bike {

    int maxspeed;

    Bike() {
        maxspeed = 50;
    }

    protected void finalize() {
        System.out.println("Called finalize method in class Bike...");
    }
}

class Example {

    public static void main(String args[]) {
        Car c = new Car();
        c = null;    // if c weren`t null JVM wouldn't be certain it's cleared or not, null means has no future use or no longer in use hence clears it
        Bike b = new Bike();
        System.gc();    // should clear c, but not b
        for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) {
            System.out.print("\t" + b.maxspeed);
            if (b.maxspeed > 50) {
                System.out.println("Over Speed. Pls slow down.");
            }
        }
    }
}

Ausgabe

    Called finalize method in class Car...
            1       2       3       4       5       6       7       8       9
    10      11      12      13      14      15      16      17      18      19
    20      21      22      23      24      25      26      27      28      29
    30      31      32      33      34      35      36      37      38      39
    40      41      42      43      44      45      46      47      48      49
    50      51Over Speed. Pls slow down.
            52Over Speed. Pls slow down.
            53Over Speed. Pls slow down.
            54Over Speed. Pls slow down.
            55Over Speed. Pls slow down.
            56Over Speed. Pls slow down.
            57Over Speed. Pls slow down.
            58Over Speed. Pls slow down. 
            59Over Speed. Pls slow down.
            60Over Speed. Pls slow down.
            61Over Speed. Pls slow down.
            62Over Speed. Pls slow down.
            63Over Speed. Pls slow down.
            64Over Speed. Pls slow down.
            65Over Speed. Pls slow down.
            66Over Speed. Pls slow down.
            67Over Speed. Pls slow down.
            68Over Speed. Pls slow down.
            69Over Speed. Pls slow down.
            70Over Speed. Pls slow down.

Notiz – Selbst nach dem Drucken von bis zu 70 und nachdem Objekt b nicht im Programm verwendet wird, besteht Unsicherheit darüber, ob b von JVM gelöscht wird oder nicht, da “Called finalize method in class Bike…” nicht gedruckt wird.

1646629640 617 Wann wird die Methode finalize in Java aufgerufen
OnaBai

finalize gibt die Anzahl für die Klassenerstellung aus.

protected void finalize() throws Throwable {
    System.out.println("Run F" );
    if ( checkedOut)
        System.out.println("Error: Checked out");
        System.out.println("Class Create Count: " + classCreate);
}

hauptsächlich

while ( true) {
    Book novel=new Book(true);
    //System.out.println(novel.checkedOut);
    //Runtime.getRuntime().runFinalization();
    novel.checkIn();
    new Book(true);
    //System.runFinalization();
    System.gc();

Wie du siehst. Die folgende Ausgabe zeigt, dass der GC zum ersten Mal ausgeführt wurde, wenn die Klassenanzahl 36 beträgt.

C:\javaCode\firstClass>java TerminationCondition
Run F
Error: Checked out
Class Create Count: 36
Run F
Error: Checked out
Class Create Count: 48
Run F

963020cookie-checkWann wird die Methode finalize() in Java aufgerufen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy