Grundlegendes zu Javas Referenzklassen: SoftReference, WeakReference und PhantomReference

81

Kann jemand den Unterschied zwischen den drei Referenzklassen erklären (oder einen Link zu einer netten Erklärung posten)? SoftReference> WeakReference> PhantomReference, Aber wenn ich würde alle nutzen? Warum gibt es ein WeakHashMapaber nein SoftHashMapoder PhantomHashMap?

Und wenn ich den folgenden Code verwende ...

WeakReference<String> ref = new WeakReference<String>("Hello!");
if (ref != null) {                 // ref can get collected at any time...
    System.gc();                   // Let's assume ref gets collected here.
    System.out.println(ref.get()); // Now what?!
}

...was geschieht? Muss ich refvor jeder Anweisung überprüfen, ob null ist (dies ist falsch, aber was soll ich tun)? Entschuldigung für die Schnellfeuerfragen, aber ich habe Probleme, diese ReferenceKlassen zu verstehen ... Danke!

Haywood Jablomey
quelle
1
Warum gibt es eine WeakHashMapaber keine SoftHashMapoder PhantomHashMapausgezeichnete Frage, warum habe ich das vorher nicht bemerkt .. ??
Mehraj Malik
1
Die ref != nullPrüfung macht keinen Sinn. refwird niemals sein null.
Holger
Hinzufügen zum Q : strongRef --> weakRef --> objA. Jetzt wird objAGCed oder nicht, da es einen indirekten Verweis von hat strongRef.
Samshers

Antworten:

60

Die Java-Bibliotheksdokumentation für das java.lang.refPaket kennzeichnet die abnehmende Stärke der drei expliziten Referenztypen.

Sie verwenden a, SoftReferencewenn das referenzierte Objekt so lange am Leben bleiben soll, bis der Host-Prozess fast keinen Speicher mehr hat. Das Objekt kann erst gesammelt werden, wenn der Kollektor Speicher freigeben muss . Locker gesagt, ein SoftReferenceMittel binden , "Pin das Objekt, bis Sie nicht mehr können."

Verwenden WeakReferenceSie im Gegensatz dazu a, wenn Sie die Lebensdauer des referenzierten Objekts nicht beeinflussen möchten. Sie möchten lediglich eine separate Aussage über das referenzierte Objekt machen, solange es am Leben bleibt. Die Berechtigung des Objekts zur Sammlung wird nicht durch das Vorhandensein gebundener WeakReferences beeinflusst. So etwas wie eine externe Zuordnung von der Objektinstanz zu einer verwandten Eigenschaft, bei der die Eigenschaft nur aufgezeichnet werden muss, solange das verwandte Objekt lebt, ist eine gute Verwendung für WeakReferences und WeakHashMap.

Der letzte PhantomReferenceist schwerer zu charakterisieren. Eine WeakReferencesolche Bindung hat PhantomReferencekeinen Einfluss auf die Lebensdauer des referenzierten Objekts. Aber im Gegensatz zu den anderen Referenztypen kann man a nicht einmal dereferenzieren PhantomReference. In gewissem Sinne zeigt es nicht auf das, worauf es zeigt, soweit Anrufer dies beurteilen können. Es ermöglicht lediglich das Verknüpfen einiger verwandter Daten mit dem referenzierten Objekt - Daten, die später überprüft und bearbeitet werden können, wenn das Objekt PhantomReferencein der zugehörigen Warteschlange in die Warteschlange gestellt wird ReferenceQueue. Normalerweise leitet man einen Typ von PhantomReferencediesem abgeleiteten Typ ab und enthält einige zusätzliche Daten. Leider ist ein Downcasting erforderlich, um einen solchen abgeleiteten Typ zu verwenden.

In Ihrem Beispielcode kann nicht die refReferenz (oder, wenn Sie es vorziehen, "Variable") null sein. Es ist vielmehr der Wert, der durch Aufrufen erhalten wird Reference#get(), der null sein kann. Wenn sich herausstellt, dass es null ist, sind Sie zu spät. Das referenzierte Objekt ist bereits auf dem Weg, gesammelt zu werden:

final String val = ref.get();
if (null != val)
{
  // "val" is now pinned strongly.
}
else
{
  // "val" is already ready to be collected.
}
seh
quelle
Hinzufügen zum Q : strongRef --> weakRef --> objA. Jetzt wird objAGCed oder nicht, da es einen indirekten Verweis von hat strongRef.
Samshers
Wenn ich Ihre Frage richtig verstehe, kann @samshers objAals Müll gesammelt werden . Das Anheften eines WeakReferenceObjekts übt keinen Einfluss auf das Objekt aus, auf das dieses WeakReferencezeigt.
seh
Macht es keinen Unterschied, keinen starken Bezug in der Kette zu haben? Denn damit der objAMüll gesammelt wird, muss die schwache Referenz zuerst rechts entfernt werden. Und eine starke Referenz weist auf die schwache Referenz hin, die es dem schwachen Schiedsrichter
unmöglich macht
Nein, das WeakReferencemuss nicht abgeholt werden, damit objAes abgeholt werden kann. Das WeakReferencehält nicht objAam Leben. Es ist vielmehr eine Möglichkeit zu finden, objAwährend es lebt - ohne diese Lebensdauer zu beeinflussen - und zu erkennen, wann der Sammler es bereits weggenommen hat.
SEH
6

Ein Link: https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references

PhantomHashMapwürde nicht sehr gut funktionieren, da getimmer nullfür Phantomreferenzen zurückgegeben wird.

Caches sind schwierig und SoftHashMapfunktionieren möglicherweise nicht so gut, wie Sie vielleicht denken. Ich glaube jedoch, dass die Sammlungsbibliothek von Google eine allgemeine Referenzkartenimplementierung enthält.

Sie sollten immer überprüfen, ob getnicht zurückgegeben wird null. (Beachten Sie, dass nicht überprüft wird, ob die ReferenceReferenz selbst nicht ... ist null.) Bei internierten Zeichenfolgen wird dies immer der Fall sein, aber (wie immer) versuchen Sie nicht, "klug" zu sein.

Tom Hawtin - Tackline
quelle
Der Link ist abgelaufen.
Mehraj Malik
@MehrajMalik Link behoben.
Tom Hawtin - Tackline
Hinzufügen zum Q : strongRef --> weakRef --> objA. Jetzt wird objAGCed oder nicht, da es einen indirekten Verweis von hat strongRef.
Samshers
0
String str = new String("hello, world");
WeakReference<String> ref = new WeakReference<String>(str);
str = null;

if (ref != null) {                 
    System.gc(); 
    System.out.println(ref.get());
}

In diesem Fall wird null ausgegeben. Der Aufruf an System.gc()ist hier wichtig.

kopite
quelle