it-swarm.com.de

Wann wird die finalize () -Methode in Java aufgerufen?

Ich muss wissen, wann die finalize() -Methode in der JVM aufgerufen wird. Ich habe eine Testklasse erstellt, die in eine Datei schreibt, wenn die finalize()-Methode durch Überschreiben aufgerufen wird. Es wird nicht ausgeführt. Kann mir jemand den Grund nennen, warum es nicht ausgeführt wird?

292
Rajesh Kumar J

Im Allgemeinen ist es am besten, dass Sie sich nicht auf finalize() verlassen, um Aufräumarbeiten usw. durchzuführen.

Nach dem Javadoc (das wäre es wert, gelesen zu werden), ist es:

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

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

Es ist auch nicht garantiert, dass der Garbage Collector zu einem bestimmten Zeitpunkt ausgeführt wird. Im Allgemeinen möchte ich sagen, dass finalize() wahrscheinlich nicht die beste Methode ist, im Allgemeinen zu verwenden, es sei denn, es gibt etwas Bestimmtes, für das Sie es benötigen.

247
user7094

Die finalize-Methode wird aufgerufen, wenn ein Objekt im Begriff ist, Müll zu sammeln. Dies kann jederzeit geschehen, nachdem es für die Müllabfuhr geeignet ist.

Beachten Sie, dass es durchaus möglich ist, dass für ein Objekt niemals Müll gesammelt wird (und daher finalize nie aufgerufen wird). Dies kann vorkommen, wenn das Objekt niemals für gc in Frage kommt (weil es während der gesamten Lebensdauer der JVM erreichbar ist) oder wenn zwischen dem Zeitpunkt, zu dem das Objekt in Frage kommt, und dem Zeitpunkt, zu dem die JVM beendet wird, tatsächlich keine Speicherbereinigung ausgeführt wird (dies tritt häufig bei simple auf Testprogramme).

Es gibt verschiedene Möglichkeiten, der JVM mitzuteilen, finalize für Objekte auszuführen, für die sie noch nicht aufgerufen wurde. Die Verwendung dieser Objekte ist jedoch keine gute Idee (die Garantien dieser Methode sind ebenfalls nicht sehr stark).

Wenn Sie für den korrekten Betrieb Ihrer Anwendung auf finalize angewiesen sind, machen Sie etwas falsch. finalize sollte only für die Bereinigung von Ressourcen (normalerweise nicht Java) verwendet werden. Und das ist genau, weil die JVM nicht garantiert, dass finalize jemals für ein Objekt aufgerufen wird.

354
Joachim Sauer
protected void finalize() throws Throwable {}
  • jede Klasse erbt die finalize()-Methode von Java.lang.Object
  • Die Methode wird vom Garbage Collector aufgerufen, wenn sie bestimmt Keine weiteren Verweise auf das Objekt existieren
  • die Object finalize-Methode führt keine Aktionen aus, kann jedoch von .__ überschrieben werden. jede Klasse
  • normalerweise sollte es außer Kraft gesetzt werden, Nicht-Java-Ressourcen zu bereinigen, dh .__ zu schließen. eine Datei
  • wenn Sie finalize() überschreiben, ist es eine gute Programmiermethode, eine .__ zu verwenden. try-catch-finally-Anweisung und an Rufen Sie immer super.finalize() auf. Diese ist eine Sicherheitsmaßnahme, um sicherzustellen, dass Sie dies tun verpassen Sie nicht versehentlich ein Ressource, die von den aufrufenden Objekten verwendet wird Klasse 

    protected void finalize() throws Throwable {
         try {
             close();        // close open files
         } finally {
             super.finalize();
         }
     }
    
  • jede Ausnahme, die während der Speicherbereinigung von finalize() ausgelöst wird, stoppt die Finalisierung wird aber sonst ignoriert

  • finalize() wird niemals mehr als einmal für ein Objekt ausgeführt

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

Sie können diesen Artikel auch überprüfen:

68
XpiritO

Die Java-Methode finalize() ist kein Destruktor und sollte nicht zur Verarbeitung von Logik verwendet werden, von der Ihre Anwendung abhängig ist. Die Java-Spezifikation besagt, dass es keine Garantie gibt, dass die Methode finalize während der Lebensdauer der Anwendung überhaupt aufgerufen wird.

Wahrscheinlich möchten Sie eine Kombination aus finally und einer Bereinigungsmethode, wie in:

MyClass myObj;

try {
    myObj = new MyClass();

    // ...
} finally {

    if (null != myObj) {
        myObj.cleanup();
    }
}
22
rsp

Check out Effective Java, 2. Ausgabe, Seite 27 . Punkt 7: Finalizer vermeiden

Finalisierer sind unvorhersehbar, oft gefährlich und im Allgemeinen überflüssig. mache niemals etwas Zeitkritisches in einem Finalizer. noch nie zum Aktualisieren des kritischen persistenten Status von einem Finalizer abhängig.

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
}
18
Hao Deng

Wann wird die finalize()-Methode in Java aufgerufen?

Die Finalize-Methode wird aufgerufen, nachdem der GC erkannt hat, dass das Objekt nicht mehr erreichbar ist, und bevor der von dem Objekt belegte Speicher tatsächlich beansprucht wird.

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

  • Wenn der GC nicht läuft, kann finalize() niemals aufgerufen werden. (Normalerweise wird der GC nur ausgeführt, wenn die JVM entscheidet, dass wahrscheinlich genug Müll vorhanden ist, um es lohnenswert zu machen.)

  • Es kann mehr als einen GC-Zyklus dauern, bis der GC feststellt, dass ein bestimmtes Objekt nicht erreichbar ist. (Java-GCs sind in der Regel "Generationskollektoren" ...)

  • Sobald der GC feststellt, dass ein Objekt nicht erreichbar und finalisierbar ist, wird es in eine Finalisierungswarteschlange gestellt. Die Finalisierung erfolgt normalerweise asynchron mit der normalen GC.

(Die JVM-Spezifikation führt tatsächlich erlaubt eine JVM aus, um niemals Finalizer auszuführen, sofern sie nicht den von den Objekten verwendeten Speicherplatz freigibt. Eine JVM, die auf diese Weise implementiert wurde, wäre dies verkrüppelt/nutzlos, aber dieses Verhalten ist "erlaubt".)

Das Ergebnis ist, dass es unklug ist, sich auf die Fertigstellung zu verlassen, um Dinge zu tun, die in einem bestimmten Zeitrahmen erledigt werden müssen. Es ist "Best Practice", sie überhaupt nicht zu verwenden. Es sollte einen besseren (d. H. Zuverlässigeren) Weg geben, um das zu tun, was Sie in der finalize()-Methode zu tun versuchen. 

Die einzige legitime Verwendung für die Finalisierung ist das Bereinigen von Ressourcen, die mit Objekten verknüpft sind, die durch Anwendungscode verloren gegangen sind. Selbst dann sollten Sie versuchen, den Anwendungscode so zu schreiben, dass er die Objekte nicht an erster Stelle verliert. (Verwenden Sie beispielsweise Java 7+ try-with-resources, um sicherzustellen, dass close() immer aufgerufen wird ...)


Ich habe eine Testklasse erstellt, die in eine Datei schreibt, wenn die finalize () -Methode durch Überschreiben aufgerufen wird. Es wird nicht ausgeführt. Kann mir jemand den Grund nennen, warum es nicht ausgeführt wird?

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

  • Bei dem Objekt wird kein Müll gesammelt, da er noch erreichbar ist.
  • Bei dem Objekt wird kein Müll gesammelt, 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. Die Finalisierung wird jedoch nicht abgeschlossen, bevor der Test abgeschlossen ist.
16
Stephen C

Da beim Aufruf der finalize () -Methode durch JVM eine Ungewissheit besteht (nicht sicher, ob finalize (), die überschrieben wird, ausgeführt werden würde oder nicht), ist zu Studienzwecken der bessere Weg zu beobachten, was passiert, wenn finalize () aufgerufen wird zwingen Sie die JVM, die Garbage Collection mit dem Befehl System.gc() aufzurufen.

Insbesondere wird finalize () aufgerufen, wenn ein Objekt nicht mehr verwendet wird. Wenn wir jedoch versuchen, es durch das Erstellen neuer Objekte aufzurufen, gibt es keine Gewissheit über seinen Aufruf. Zur Sicherheit erstellen wir also ein null-Objekt c, das offensichtlich keine zukünftige Verwendung hat, daher sehen wir den finalize-Aufruf des Objekts c.

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.

Hinweis - Auch nach dem Drucken von bis zu 70 und nachdem Objekt b nicht im Programm verwendet wird, besteht die Unsicherheit, dass b von JVM gelöscht wird oder nicht, da "Finalized-Methode in Klasse Bike aufgerufen ..." nicht gedruckt wird .

10
techloris_109

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);
}

main

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 das erste 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
5
user1623624

Nachdem ich in letzter Zeit mit Finalizer-Methoden gerungen habe (um Verbindungspools während des Testens zu entsorgen), muss ich sagen, dass dem Finalizer viele Dinge fehlen. Durch die Verwendung von VisualVM zur Beobachtung sowie die Verwendung schwacher Referenzen zur Verfolgung der tatsächlichen Interaktion habe ich festgestellt, dass die folgenden Dinge in einer Java 8-Umgebung (Oracle JDK, Ubuntu 15) zutreffen:

  • Finalize wird nicht sofort aufgerufen, wenn der Finalizer (GC-Teil) die Referenz einzeln besitzt
  • Der standardmäßige Garbage Collector fasst nicht erreichbare Objekte zusammen
  • Finalize wird in Massen aufgerufen und zeigt auf ein Implementierungsdetail, dass der Garbage Collector in einer bestimmten Phase die Ressourcen freigibt.
  • Das Aufrufen von System.gc () führt häufig nicht dazu, dass Objekte häufiger finalisiert werden. Es führt lediglich dazu, dass der Finalizer schneller auf ein nicht erreichbares Objekt aufmerksam wird
  • Das Erstellen eines Thread-Dumps führt fast immer dazu, dass der Finalizer aufgrund eines hohen Heap-Overheads während des Heap-Dumps oder eines anderen internen Mechanismus ausgelöst wird
  • Die Finalisierung scheint entweder an den Speicherbedarf (mehr Speicherplatz) gebunden zu sein oder durch die Liste der Objekte, die für das Finalisieren eines bestimmten internen Grenzwerts markiert werden. Wenn Sie also viele Objekte finalisieren, wird die Finalisierungsphase häufiger und früher ausgelöst, verglichen mit nur wenigen
  • Es gab Umstände, unter denen ein System.gc () ein Finalisieren direkt auslöste, jedoch nur, wenn die Referenz lokal und von kurzer Dauer war. Dies könnte generationsbezogen sein.

Letzter Gedanke

Die Finalisierungsmethode ist unzuverlässig, kann jedoch nur für eine Sache verwendet werden. Sie können sicherstellen, dass ein Objekt vor dem Sammeln von Müll geschlossen oder entsorgt wurde. Dies ermöglicht die Implementierung eines Ausfallsicherungsschutzes, wenn Objekte mit einem komplexeren Lebenszyklus, die eine Aktion am Lebensende umfassen, korrekt behandelt werden. Das ist der einzige Grund, aus dem ich mir vorstellen kann, dass es sich lohnt, es zu überschreiben.

4
Martin Kersten

Wenn ein Objekt zerstört wird, muss es manchmal eine Aktion ausführen. Wenn ein Objekt beispielsweise über eine Nicht-Java-Ressource verfügt, z. B. ein Dateihandle oder eine Schriftart, können Sie überprüfen, ob diese Ressourcen freigegeben werden, bevor Sie ein Objekt zerstören. Um solche Situationen zu bewältigen, bietet Java einen Mechanismus namens "Finalisieren". Durch das Finalisieren können Sie bestimmte Aktionen definieren, die ausgeführt werden, wenn ein Objekt aus dem Garbage Collector entfernt werden soll .. Um einen Finalizer zu einer Klasse hinzuzufügen, definieren Sie einfach die finalize () - Methode. Die Java-Ausführungszeit ruft diese Methode immer dann auf, wenn ein Objekt dieser Klasse gelöscht wird. In finalize method () legen Sie Aktionen fest, die ausgeführt werden müssen, bevor ein Objekt zerstört wird .. Der Garbage Collector wird regelmäßig nach Objekten durchsucht, die sich nicht mehr auf einen laufenden Status oder indirekt auf ein anderes Objekt mit Referenz beziehen. Bevor ein Asset freigegeben wird, ruft die Java-Laufzeitumgebung die Methode finalize () für das Objekt auf. Die finalize () -Methode hat die folgende allgemeine Form:

protected void finalize(){
    // This is where the finalization code is entered
}

Mit dem Schlüsselwort protected wird der Zugriff auf finalize () durch Code außerhalb seiner Klasse verhindert .. _ Es ist wichtig zu verstehen, dass finalize () direkt vor der Garbage Collection aufgerufen wird . Es wird nicht aufgerufen, wenn ein Objekt beispielsweise den Gültigkeitsbereich verlässt. Dies bedeutet, dass Sie nicht wissen können, wann finalize () ausgeführt wird. Folglich muss das Programm andere Mittel bereitstellen, um Systemressourcen oder andere vom Objekt verwendete Ressourcen freizugeben. Für den normalen Programmablauf sollten Sie sich nicht auf finalize () verlassen.

2
Amarildo

Ein Objekt kann für die Garbage Collection oder GC verwendet werden, wenn es nicht von Live Threads oder statischen Hinweisen erreichbar ist. Mit anderen Worten: Sie können sagen, dass ein Objekt für die Garbage Collection in Frage kommt, wenn alle Referenzen null sind. Zyklische Abhängigkeiten werden nicht als Verweis gezählt. Wenn Objekt A einen Verweis auf Objekt B hat und Objekt B einen Verweis auf Objekt A hat und keine anderen Live-Verweise vorhanden sind, sind beide Objekte A und B für die Garbage Collection geeignet. In der Regel kann ein Objekt in den folgenden Fällen für die Garbage Collection in Java verwendet werden:

  1. Alle Referenzen dieses Objekts werden explizit auf null gesetzt, z. object = null
  2. Das Objekt wird in einem Block erstellt, und der Referenzbereich verlässt den Bereich, sobald die Steuerung diesen Block verlässt.
  3. Übergeordnetes Objekt auf null gesetzt, wenn ein Objekt den Verweis auf ein anderes Objekt enthält und wenn Sie das Referenzobjekt des Containerobjekts auf null setzen, wird das untergeordnete Objekt oder das enthaltene Objekt automatisch für die Garbage Collection ausgewählt.
  4. Wenn ein Objekt nur über Live-Verweise über WeakHashMap verfügt, kann es für die Garbage Collection verwendet werden. 
2
Tushar Trivedi

finalize Die Methode wird nicht garantiert. Diese Methode wird aufgerufen, wenn das Objekt für GC geeignet ist. Es gibt viele Situationen, in denen die Objekte möglicherweise nicht gesammelt werden.

2
giri

Klasse, in der wir die finalize-Methode überschreiben

public class TestClass {    
    public TestClass() {
        System.out.println("constructor");
    }

    public void display() {
        System.out.println("display");
    }
    @Override
    public void finalize() {
        System.out.println("destructor");
    }
}

Die Chancen, dass die Methode finalize aufgerufen wird

public class TestGarbageCollection {
    public static void main(String[] args) {
        while (true) {
            TestClass s = new TestClass();
            s.display();
            System.gc();
        }
    }
}

wenn der Speicher mit Dump-Objekten überladen ist, ruft der gc die Methode finalize auf

rufen Sie die Konsole auf, in der Sie nicht feststellen, dass die Finalize-Methode häufig aufgerufen wird. Wenn der Speicher überlastet wird, wird die Finalize-Methode aufgerufen. 

1
pradeep

finalize() wird unmittelbar vor der Garbage Collection aufgerufen. Es wird nicht aufgerufen, wenn ein Objekt den Gültigkeitsbereich verlässt. Dies bedeutet, dass Sie nicht wissen können, wann oder nicht, ob finalize() ausgeführt wird.

Beispiel:

Wenn Ihr Programm endet, bevor der Garbage Collector auftritt, wird finalize() nicht ausgeführt. Daher sollte es als Sicherungsverfahren verwendet werden, um den ordnungsgemäßen Umgang mit anderen Ressourcen oder für Anwendungen mit besonderer Verwendung sicherzustellen, nicht als Mittel, die Ihr Programm im normalen Betrieb verwendet.

0
AyukNayr

Java ermöglicht es Objekten, eine Methode namens finalize () .__ zu implementieren. das könnte gerufen werden.

die finalize () -Methode wird aufgerufen, wenn der Garbage Collector versucht, sammle das Objekt.

Wenn der Garbage Collector nicht ausgeführt wird, wird die Methode nicht aufgerufen.

Wenn der Garbage Collector das Objekt nicht erfasst und versucht, es auszuführenwieder wird die Methode nicht beim zweiten Mal aufgerufen.

In der Praxis ist es sehr unwahrscheinlich, dass Sie es in echten Projekten einsetzen.

Denken Sie daran, dass es möglicherweise nicht angerufen wird und dass es definitiv wird nicht zweimal angerufen. Die finalize () -Methode kann Null oder Eins ausführen Zeit.

Im folgenden Code erzeugt die Methode finalize () keine Ausgabe, wenn wir Führen Sie es aus, da das Programm beendet wird, bevor die .__ ausgeführt werden muss. Müllsammler.

Quelle

0
JavaDev