FinalReference -Zitat
Diese Klasse ist ein Paketyp, der angibt, dass es sich nicht um einen öffentlichen Teil handelt und von Referenz erbringt, was bedeutet, dass es sich auch um einen bestimmten Referenztyp handelt. Daher wird es vor dem Recycling jedes Objekts in das angegebene Referqyebcequeueue platziert.
Dieses Referenzobjekt wird speziell für die Klasse mit Abschlussmethoden verwendet. Es ist zu verstehen, dass jedes Objekt mit entsprechenden Methoden als FinalReferce -Objekt eingekapselt wird.
Da die Abschlussmethode durch Objekt definiert wird, ist die Standardimplementierung leer. Wenn diese Methode dann neu geschrieben wird, ist der Methodekörper definitiv nicht leer. Dieser Unterschied kann dadurch gemacht werden. Solange die Abschlussmethode eine nicht leere Klasse implementiert, müssen die generierten Objekte in FinalReferce registriert werden.
Dieser Schritt kann entsprechend registriert werden, indem die Objekt -Standard -Konstruktor -Methode während der Newinstance aufgerufen wird.
Finalizer#Register -Methode
Wenn diese Methode hauptsächlich aufgerufen wird, wird das entsprechende Finalizer -Objekt generiert und das Finalizer -Objekt wird von FinalReference geerbt. Diese Methode wird wie folgt deklariert:
/ * Aufgerufen von vm */static void Register (Object Finalizee) {New Finalizer (Finalizee);} Wie aus den obigen Kommentaren ersichtlich ist, wird diese Methode von JVM zu einem bestimmten Zeitraum aufgerufen.
Wechseln Sie dann wie unten gezeigt zum Konstruktor des Finalizers:
private Finalizer (Object Finalizee) {Super (Finalizee, Warteschlange); hinzufügen();} Es ist ersichtlich, dass das entsprechende Referenzobjekt durch die Warteschlange zurückgerufen wird. Die Funktion von Add besteht darin, alle Objekte zu speichern, die die Methode noch nicht abgeschlossen haben und sie am Endsystem aufrufen System.shutdown . Stellen Sie es durch Runtime#runFinalizersOnExit ein.
Referenzqueue
Diese Referenzwarteschlange wird in dieser Warteschlange platziert, bevor die internen Objekte des entsprechenden Referenzobjekts recycelt werden (die detaillierte Beschreibung wird in einem anderen Artikel über die Referenz erläutert), da nur das entsprechende Objekt aus dieser Warteschlange erhalten werden muss, dann ist dieses Objekt definitiv bereit, recycelt zu werden.
Rufen Sie dann die entsprechende Abschlussmethode vor dem Recycling auf.
FinalizerThread -Thread
Dieser Thread erhält immer wieder Daten aus der Warteschlange und ruft dann die entsprechende Abschlussmethode auf. Der entsprechende Code lautet wie folgt:
für (;;) {try {Finalizer f = (Finalizer) queue.remove (); f.runfinalizer (JLA); } catch (InterruptedException x) {// Ignorieren und fortzusetzen}}}Der entsprechende Runfinalizer lautet wie folgt:
synchronisiert (this) {if (hasBeenFinalized ()) return; remove ();} try {Object Finalize = this.get (); if (finalizee! / * Löschen Sie den Stapelschlitz, der diese Variable enthält, um die Wahrscheinlichkeit einer falschen Retention mit einem konservativen GC */ Finalizee = null zu verringern; }} catch (throwable x) {} super.clear ();In der obigen Logik entfernen Sie es zuerst, und entfernen Sie es von der Finalisation. Diese Methode soll sicherstellen, dass die Finalierung jedes Objekts nur einmal aufgerufen wird, dh der aktuelle Anruf wird abgeschlossen. Es wird im entsprechenden Zustand aufgezeichnet, dh Hasbeenfinalized Returns REICH (in der Tat bedeutet es, den nächsten Zeiger in sich selbst zu zeigen.
Als nächstes rufen Sie die entsprechende Abschlussmethode auf. jla.invokeFinalize besteht tatsächlich darin, die Abschlussmethode des entsprechenden Objekts aufzurufen. In diesem Prozess wird das ursprüngliche Objekt zuerst durch GET erhalten. Im gesamten JVM -Prozess wird die Referenz nicht vor dem Recycling für die endgültige Erstellung auf Null gesetzt. Denn hier kann das entsprechende Referenzobjekt immer erhalten werden.
Nach der Verarbeitung wird schließlich der entsprechende Clear aufgerufen, um die entsprechende Referenz zu löschen. Dies erreicht den Effekt der endgültigen Referenz mit keinem anderen Objekt zur Referenz.
In der obigen Verarbeitung gibt es keine Begrenzung für die Zeit zum Aufrufen von Abschluss. Sobald die Fertigstellung eines Objekts langsam aufgerufen wird, wird die Ausführung der gesamten Recyclingkette beeinflusst, und eine entsprechende OOM -Ausnahme wird erzeugt. Schreiben Sie daher nicht in besonderen Fällen die Finalisierung neu. Es sollte andere Methoden geben, um die entsprechenden Szenarien zu verarbeiten. Zum Beispiel FinalizizableReference in Guava.
Finalizer startet den Thread
Im obigen Thread wird es während des entsprechenden Prozessstarts gestartet. Es ist zu verstehen, dass das Objekt die Initialisierung der Finalizer -Klasse durch Aufrufen register(object) auslöst. Im statischen Initialisierungsblock wird dann der entsprechende Recycling -Thread gestartet. Der entsprechende Initialisierungscode lautet wie folgt:
static {ThreadGroup tg = thread.currentThread (). GetThreadGroup (); für (Threadgroup TGN = TG; TGN! = NULL; TG = TGN, TGN = tg.getParent ()); Thread Finalizer = New FinalizerThread (TG); Finalizer.SetPriority (Thread.max_Priority - 2); Finalizer.SetDaemon (true); Finalizer.start ();}Das obige statische oben ist ein statischer Initialisierungsblock, dh, solange der Klasse -Finalizer verwendet wird, wird der entsprechende Aufruf ausgelöst. Die hier verwendete Thread -Gruppe ist eine System -Thread -Gruppe, und die Priorität ist immer noch relativ hoch und ist als Hintergrund -Thread konfiguriert.
Wenn Sie JStack zum Drucken von Threads verwenden, werden die unten gezeigten Threads hier angezeigt. Wie in der Abbildung unten gezeigt
Zusammenfassen
Der gesamte Finalizer arbeitet durch FinalReference durch die JVM und die entsprechenden Java -Klassen zusammen. Es wird nicht alles von JVM implementiert, sodass es nicht zugrunde liegende, sondern die entsprechende Semantik implementieren kann. Alles wird von normalem Java gemacht und von JVM zusammengearbeitet. Das Verständnis des gesamten Prozesses ist auch ein Verständnis des Laufmechanismus von Java selbst.