Es gibt 4 Arten von Referenzen in Java: StrongReference, SoftReference, WeakReference und PhantomReference (die legendäre Geisterreferenz, haha).
Diese vier Arten von Referenzen stehen in engem Zusammenhang mit GC. Schauen wir uns ihre Definitionen und Verwendungsszenarien einzeln an:
1. Starke Referenz
StrongReference ist die Standardreferenzimplementierung von Java. Sie bleibt so lange wie möglich in der JVM bestehen, wenn kein Objekt darauf verweist.
Java-Code
Kopieren Sie den Codecode wie folgt:
@Prüfen
public void strongReference() {
Objektreferenz = neues Objekt();
/**
* Erstellen Sie StrongReference durch Zuweisung
*/
Objekt strongReference = referent;
behauptenSame(referent, strongReference);
referent = null;
System.gc();
/**
* StrongReference wird nach der GC nicht recycelt
*/
behauptenNotNull(strongReference);
}
2. WeakReference und WeakHashMap
WeakReference ist, wie der Name schon sagt, eine schwache Referenz. Wenn das referenzierte Objekt in der JVM keine starke Referenz mehr hat, wird die schwache Referenz nach der GC automatisch recycelt.
Kopieren Sie den Codecode wie folgt:
@Prüfen
public void schwachReference() {
Objektreferenz = neues Objekt();
WeakReference<Object> schwachReference = new WeakReference<Object>(referent);
behauptenSame(referent, schwachRerference.get());
referent = null;
System.gc();
/**
* Sobald keine starke Referenz auf den Referenten verweist, wird die schwache Referenz nach der GC automatisch recycelt
*/
behauptenNull(weakReference.get());
}
WeakHashMap verwendet WeakReference als Schlüssel. Sobald kein starker Verweis auf den Schlüssel vorliegt, löscht WeakHashMap den relevanten Eintrag nach der GC automatisch.
Kopieren Sie den Codecode wie folgt:
@Prüfen
public void schwachHashMap() wirft InterruptedException {
Map<Object, Object> schwachHashMap = new WeakHashMap<Object, Object>();
Objektschlüssel = neues Objekt();
Objektwert = neues Objekt();
schwachHashMap.put(key, value);
behauptenTrue(weakHashMap.containsValue(value));
Schlüssel = null;
System.gc();
/**
* Warten Sie, bis ungültige Einträge in die ReferenceQueue gelangen, damit sie beim nächsten Aufruf von getTable gelöscht werden können
*/
Thread.sleep(1000);
/**
* Sobald kein starker Verweis auf den Schlüssel vorliegt, löscht WeakHashMap den entsprechenden Eintrag nach der GC automatisch
*/
behauptenFalse(weakHashMap.containsValue(value));
}
3.SoftReference
SoftReference hat im Grunde die gleichen Eigenschaften wie WeakReference. Der größte Unterschied besteht darin, dass SoftReference die Referenz so lange wie möglich behält, bis der Speicher der JVM aufgebraucht ist, bevor sie recycelt wird (Garantie einer virtuellen Maschine). Diese Funktion macht SoftReference sehr gut für Caching-Anwendungen geeignet.
Kopieren Sie den Codecode wie folgt:
@Prüfen
public void softReference() {
Objektreferenz = neues Objekt();
SoftReference<Object> softReference = new SoftReference<Object>(referent);
behauptenNotNull(softRerference.get());
referent = null;
System.gc();
/**
* Soft-Referenzen werden nur vor jvm OutOfMemory recycelt und eignen sich daher sehr gut für Caching-Anwendungen
*/
behauptenNotNull(softRerference.get());
}
4. PhantomReferenz
Als Protagonist dieses Artikels unterscheidet sich Phantom Reference stark von WeakReference und SoftReference, da seine get()-Methode immer null zurückgibt, woher auch der Name stammt.
Java-Code
Kopieren Sie den Codecode wie folgt:
@Prüfen
public void phantomReferenceAlwaysNull() {
Objektreferenz = neues Objekt();
PhantomReference<Object> phantomReference = new PhantomReference<Object>(referent, new ReferenceQueue<Object>());
/**
* Die get-Methode der Phantomreferenz gibt immer null zurück
*/
behauptenNull(phantomReference.get());
}
Sie fragen sich vielleicht, welchen Nutzen eine Referenz hat, die immer null zurückgibt. Bitte achten Sie beim Erstellen von PhantomReference auf den zweiten Parameter ReferenceQueue (tatsächlich können auch WeakReference und SoftReference diesen Parameter haben).
Die einzige Verwendung von PhantomReference besteht darin, zu verfolgen, wann der Referent in die ReferenceQueue eingereiht wird.
5. Relevanzwarteschlange
Wenn eine schwache Referenz anfängt, Null zurückzugeben, kann das Objekt, auf das sie verweist, recycelt werden. Zu diesem Zeitpunkt können einige entsprechende Bereinigungsarbeiten an den Konstruktor einer Referenz, der virtuellen Maschine, durchgeführt werden Das Objekt wird automatisch in die ReferenceQueue eingefügt. WeakHashMap verwendet die ReferenceQueue, um Einträge zu löschen, deren Schlüssel keine starken Referenzen mehr haben.
Java-Code
Kopieren Sie den Codecode wie folgt:
@Prüfen
public void referenceQueue() wirft InterruptedException {
Objektreferenz = neues Objekt();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
WeakReference<Object> schwachReference = new WeakReference<Object>(referent, referenceQueue);
behauptenFalse(weakReference.isEnqueued());
Reference<? erweitert Object> polled = referenceQueue.poll();
behauptenNull(abgefragt);
referent = null;
System.gc();
behauptenTrue(weakReference.isEnqueued());
Referenz<? erweitert Objekt> Removed = referenceQueue.remove();
behauptenNotNull(entfernt);
}
6. PhantomReference vs. WeakReference
PhantomReference hat zwei Vorteile: Erstens können wir genau wissen, wann das Objekt aus dem Speicher gelöscht wird. Diese Funktion kann für einige spezielle Anforderungen verwendet werden (z. B. Distributed GC, XWork und Google-Guice haben auch einige Reinigungsarbeiten durchgeführt).
Zweitens können einige grundlegende Probleme vermieden werden, die durch die Finalisierung verursacht werden. Wie oben erwähnt, besteht die einzige Funktion von PhantomReference darin, zu verfolgen, wann der Referent in die ReferenceQueue eingereiht wird. Was ist jedoch der Unterschied zwischen den beiden?
Hier geht es um die finalize-Methode von Object. Diese Methode wird aufgerufen, bevor gc ausgeführt wird. Wenn ein Objekt die finalize-Methode absichtlich überlädt und innerhalb der Methode einen starken Verweis auf sich selbst erstellt, führt dies dazu, dass diese GC-Runde nicht ausgeführt werden kann Dieses Objekt kann dazu führen, dass in der JVM viel Müll vorhanden ist. Dieses Problem kann durch die Verwendung von PhantomReference vermieden werden Es wird nach der Ausführung der Methode recycelt, was bedeutet, dass es zu diesem Zeitpunkt unmöglich ist, die ursprüngliche Referenz abzurufen, sodass das oben genannte Problem nicht auftritt. Dies ist natürlich ein sehr extremes Beispiel und tritt im Allgemeinen nicht auf.
7. Vergleich
Weiche vs. schwache vs. Phantom-Referenzen | ||||
---|---|---|---|---|
Typ | Zweck | Verwenden | Bei GCed | Implementierende Klasse |
Starke Referenz | Eine gewöhnliche Referenz hält Objekte am Leben, solange sie referenziert werden. | normale Referenz. | Jedes Objekt, auf das nicht verwiesen wird, kann zurückgefordert werden. | Standard |
Weiche Referenz | Hält Objekte am Leben, sofern genügend Speicher vorhanden ist. | um Objekte auch dann am Leben zu erhalten, wenn Clients ihre Referenzen (speicherempfindliche Caches) entfernt haben, für den Fall, dass Clients erneut per Schlüssel nach ihnen fragen. | Nach einem ersten GC-Durchlauf entscheidet die JVM, dass sie noch mehr Speicherplatz zurückgewinnen muss. | java.lang.ref.SoftReference |
Schwache Referenz | Hält Objekte nur dann am Leben, wenn sie von Clients verwendet (erreichbar) werden. | Container, die nicht mehr verwendete Objekte automatisch löschen. | Nachdem GC festgestellt hat, dass das Objekt nur schwach erreichbar ist | java.lang.ref.WeakReference java.util.WeakHashMap |
Phantomreferenz | Ermöglicht das Aufräumen nach der Finalisierung, aber bevor der Speicherplatz zurückgewonnen wird (ersetzt oder erweitert die Verwendung von offinalize()) | Spezielle Reinigungsverarbeitung | Nach der Finalisierung. | java.lang.ref.PhantomReference |
8. Zusammenfassung
Allgemeine Anwendungen erfordern keine Referenzprogrammierung, aber das Verständnis dieses Wissens wird hilfreich sein, um das Funktionsprinzip von GC und Leistungsoptimierung zu verstehen. Ich hoffe, dass dieser Artikel hilfreich sein kann.