Phantomreferenzen in Java

1. Übersicht

In diesem Artikel werfen wir einen Blick auf das Konzept einer Phantomreferenz - in der Java-Sprache.

2. Phantomreferenzen

Phantomreferenzen unterscheiden sich in zwei wesentlichen Punkten von weichen und schwachen Referenzen.

Wir können keinen Referenten einer Phantomreferenz erhalten. Auf den Referenten kann niemals direkt über die API zugegriffen werden. Aus diesem Grund benötigen wir eine Referenzwarteschlange, um mit dieser Art von Referenzen arbeiten zu können.

Der Garbage Collector fügt einer Referenzwarteschlange eine Phantomreferenz hinzu, nachdem die Finalisierungsmethode seines Referenten ausgeführt wurde . Dies bedeutet, dass sich die Instanz noch im Speicher befindet.

3. Anwendungsfälle

Es gibt zwei gängige Anwendungsfälle, für die sie verwendet werden.

Die erste Technik besteht darin, zu bestimmen, wann ein Objekt aus dem Speicher entfernt wurde , um speicherempfindliche Aufgaben zu planen. Zum Beispiel können wir warten, bis ein großes Objekt entfernt wurde, bevor wir ein anderes laden.

Die zweite Praxis ist mit dem vermeiden finalize - Methode und die Verbesserung der Finalisierung .

3.1. Beispiel

Lassen Sie uns nun den zweiten Anwendungsfall implementieren, um praktisch herauszufinden, wie diese Art von Referenzen funktioniert.

Zunächst benötigen wir eine Unterklasse der PhantomReference- Klasse, um eine Methode zum Löschen von Ressourcen zu definieren:

public class LargeObjectFinalizer extends PhantomReference { public LargeObjectFinalizer( Object referent, ReferenceQueue q) { super(referent, q); } public void finalizeResources() { // free resources System.out.println("clearing ..."); } }

Jetzt werden wir eine verbesserte feinkörnige Finalisierung schreiben:

ReferenceQueue referenceQueue = new ReferenceQueue(); List references = new ArrayList(); List largeObjects = new ArrayList(); for (int i = 0; i < 10; ++i) { Object largeObject = new Object(); largeObjects.add(largeObject); references.add(new LargeObjectFinalizer(largeObject, referenceQueue)); } largeObjects = null; System.gc(); Reference referenceFromQueue; for (PhantomReference reference : references) { System.out.println(reference.isEnqueued()); } while ((referenceFromQueue = referenceQueue.poll()) != null) { ((LargeObjectFinalizer)referenceFromQueue).finalizeResources(); referenceFromQueue.clear(); } 

Zuerst initialisieren wir alle erforderlichen Objekte: referenceQueue - um die in der Warteschlange befindlichen Referenzen zu verfolgen, Referenzen - um anschließend Reinigungsarbeiten durchzuführen, largeObjects - um eine große Datenstruktur zu imitieren.

Als Nächstes erstellen wir diese Objekte mit den Klassen Object und LargeObjectFinalizer .

Bevor wir den Garbage Collector aufrufen, geben wir große Datenmengen manuell frei, indem wir die Liste der großen Objekte dereferenzieren . Beachten Sie, dass wir eine Verknüpfung für die Anweisung Runtime.getRuntime (). Gc () verwendet haben , um den Garbage Collector aufzurufen.

Es ist wichtig zu wissen, dass System.gc () die Speicherbereinigung nicht sofort auslöst - es ist lediglich ein Hinweis für JVM, den Prozess auszulösen.

Die for- Schleife zeigt, wie sichergestellt wird, dass alle Referenzen in die Warteschlange gestellt werden. Sie wird für jede Referenz als wahr ausgegeben .

Schließlich haben wir eine while- Schleife verwendet, um die in der Warteschlange befindlichen Referenzen abzufragen und für jede von ihnen Reinigungsarbeiten durchzuführen.

4. Fazit

In diesem kurzen Tutorial haben wir Javas Phantomreferenzen vorgestellt.

Wir haben in einigen einfachen und auf den Punkt gebrachten Beispielen gelernt, was dies ist und wie sie nützlich sein können.