Was ist der Unterschied zwischen java.lang.ref.WeakReference
und java.lang.ref.SoftReference
?
Was ist der Unterschied zwischen java.lang.ref.WeakReference
und java.lang.ref.SoftReference
?
Antworten:
Aus dem Verständnis schwacher Referenzen , von Ethan Nicholas:
Schwache Referenzen
Eine schwache Referenz ist einfach ausgedrückt eine Referenz, die nicht stark genug ist, um ein Objekt zu zwingen, im Speicher zu bleiben. Mit schwachen Referenzen können Sie die Fähigkeit des Garbage Collectors nutzen, die Erreichbarkeit für Sie zu bestimmen, sodass Sie dies nicht selbst tun müssen. Sie erstellen eine schwache Referenz wie folgt:
WeakReference weakWidget = new WeakReference(widget);
und dann an anderer Stelle im Code können Sie
weakWidget.get()
das eigentlicheWidget
Objekt abrufen. Natürlich ist die schwache Referenz nicht stark genug, um die Speicherbereinigung zu verhindern. Daher werden Sie möglicherweise feststellen (wenn keine starken Referenzen auf das Widget vorhanden sind), dassweakWidget.get()
plötzlich eine Rückkehr erfolgtnull
....
Weiche Referenzen
Eine weiche Referenz ist genau wie eine schwache Referenz, nur dass sie weniger darauf aus ist, das Objekt, auf das sie sich bezieht, wegzuwerfen. Ein Objekt, das nur schwach erreichbar ist (die stärksten Verweise darauf sind
WeakReferences
), wird beim nächsten Speicherbereinigungszyklus verworfen, aber ein Objekt, das nur schwach erreichbar ist, bleibt im Allgemeinen eine Weile bestehen.
SoftReferences
sind nicht erforderlich anders zu verhalten , alsWeakReferences
, aber solange Speicher ist reichlich vorhanden leise erreichbare Objekte im Allgemeinen beibehalten wird in der Praxis. Dies macht sie zu einer hervorragenden Grundlage für einen Cache wie den oben beschriebenen Bildcache, da Sie dem Garbage Collector die Möglichkeit geben können, sich darüber Gedanken zu machen, wie erreichbar die Objekte sind (ein stark erreichbares Objekt wird niemals aus dem Cache entfernt) und wie schlecht es ist braucht den Speicher, den sie verbrauchen.
Und Peter Kessler fügte in einem Kommentar hinzu:
Die Sun JRE behandelt SoftReferences anders als WeakReferences. Wir versuchen, an einem Objekt festzuhalten, auf das von einer SoftReference verwiesen wird, wenn der verfügbare Speicher nicht unter Druck steht. Ein Detail: Die Richtlinien für die JREs "-client" und "-server" sind unterschiedlich: Die JRE -client versucht, Ihren Footprint klein zu halten, indem sie lieber SoftReferences löscht, als den Heap zu erweitern, während die JRE -server versucht, Ihre zu behalten Hohe Leistung, indem der Heap lieber erweitert wird (wenn möglich) als SoftReferences gelöscht wird. Eine Größe passt nicht allen.
Schwache Referenzen werden eifrig gesammelt. Wenn GC feststellt, dass ein Objekt schwach erreichbar ist (nur über schwache Referenzen erreichbar), werden die schwachen Referenzen auf dieses Objekt sofort gelöscht. Als solche eignen sie sich gut, um einen Verweis auf ein Objekt zu behalten, für das Ihr Programm auch irgendwo (stark referenzierte) "zugehörige Informationen" speichert, z. B. zwischengespeicherte Reflexionsinformationen über eine Klasse oder einen Wrapper für ein Objekt usw. Alles, was dazu beiträgt Es macht keinen Sinn, das Objekt zu behalten, dem es zugeordnet ist. Wenn die schwache Referenz gelöscht wird, wird sie in eine Referenzwarteschlange eingereiht, die Ihr Code irgendwo abfragt, und die zugehörigen Objekte werden ebenfalls verworfen. Das heißt, Sie behalten zusätzliche Informationen zu einem Objekt bei, aber diese Informationen werden nicht benötigt, sobald das Objekt, auf das es sich bezieht, verschwindet. Tatsächlich, In bestimmten Situationen können Sie sogar WeakReference unterordnen und die zugehörigen zusätzlichen Informationen zum Objekt in den Feldern der WeakReference-Unterklasse aufbewahren. Eine andere typische Verwendung von WeakReference ist die Verwendung von Maps zum Speichern kanonischer Instanzen.
SoftReferences hingegen eignen sich zum Zwischenspeichern externer, wiederherstellbarer Ressourcen, da der GC das Löschen normalerweise verzögert. Es ist jedoch garantiert, dass alle SoftReferences gelöscht werden, bevor OutOfMemoryError ausgelöst wird, sodass sie theoretisch kein OOME [*] verursachen können.
Ein typisches Anwendungsfallbeispiel ist das Beibehalten einer analysierten Form eines Inhalts aus einer Datei. Sie würden ein System implementieren, in dem Sie eine Datei laden, analysieren und eine SoftReference für das Stammobjekt der analysierten Darstellung beibehalten würden. Wenn Sie die Datei das nächste Mal benötigen, versuchen Sie, sie über die SoftReference abzurufen. Wenn Sie es abrufen können, haben Sie sich ein weiteres Laden / Parsen erspart, und wenn der GC es in der Zwischenzeit gelöscht hat, laden Sie es neu. Auf diese Weise nutzen Sie freien Speicher für die Leistungsoptimierung, riskieren jedoch kein OOME.
Nun zum [*]. Das Beibehalten einer SoftReference kann kein OOME an sich verursachen. Wenn Sie andererseits fälschlicherweise SoftReference für eine Aufgabe verwenden, für die eine WeakReference verwendet werden soll (dh Sie behalten die mit einem Objekt verknüpften Informationen bei, auf die irgendwie stark verwiesen wird, und verwerfen sie, wenn das Referenzobjekt gelöscht wird), können Sie auf OOME as stoßen Ihr Code, der die ReferenceQueue abfragt und die zugehörigen Objekte verwirft, wird möglicherweise nicht rechtzeitig ausgeführt.
Die Entscheidung hängt also von der Verwendung ab. Wenn Sie Informationen zwischenspeichern, deren Erstellung teuer ist, die jedoch aus anderen Daten rekonstruierbar sind, verwenden Sie weiche Verweise. Wenn Sie einen Verweis auf eine kanonische Instanz einiger Daten beibehalten oder dies möchten Verwenden Sie eine schwache Referenz, wenn Sie einen Verweis auf ein Objekt haben, ohne es zu "besitzen" (wodurch verhindert wird, dass es GC-fähig wird).
WeakReference
ist, dass an Orten, an denen man es verwenden sollte, die Tatsache, dass man nach dem Erlöschen des Verweises für eine Weile gültig bleiben kann, tolerierbar sein kann, aber nicht wünschenswert ist.
WeakReference
, um GC-Läufe zu beobachten. Siehe Ausarbeitung: stackoverflow.com/a/46291143/632951
In Java ; Reihenfolge vom stärksten zum schwächsten gibt es: Stark, Weich, Schwach und Phantom
Eine starke Referenz ist eine normale Referenz, die das referenzierte Objekt vor der Erfassung durch GC schützt. dh Niemals sammelt sich Müll.
Eine Soft-Referenz kann vom Garbage Collector erfasst werden, wird jedoch wahrscheinlich erst erfasst, wenn ihr Speicher benötigt wird. dh Müll sammelt sich vorher OutOfMemoryError
.
Eine schwache Referenz ist eine Referenz, die ein referenziertes Objekt nicht vor der Erfassung durch GC schützt. dh Müll sammelt sich, wenn keine starken oder weichen Refs vorhanden sind.
Ein Phantom Referenz ist eine Referenz auf ein Objekt wird phantomly verwiesen , nachdem er fertig gestellt wurde, aber vor dem zugewiesenen Speicher zurückgewonnen wurde.
Analogie: Angenommen, eine JVM ist ein Königreich, Object ist ein König des Königreichs und GC ist ein Angreifer des Königreichs, der versucht, den König (Objekt) zu töten.
until memory is available
macht keinen Sinn. Meinst du is eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use
?
Schwache Referenz http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
Prinzip: weak reference
bezieht sich auf die Speicherbereinigung. Normalerweise kann ein Objekt mit einem oder mehreren Objekten reference
nicht zur Speicherbereinigung verwendet werden.
Das obige Prinzip ist nicht anwendbar, wenn es ist weak reference
. Wenn ein Objekt nur eine schwache Referenz zu anderen Objekten hat, ist es für die Speicherbereinigung bereit.
Schauen wir uns das folgende Beispiel an: Wir haben ein Map
with Objects, bei dem Key auf ein Objekt verweist.
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> aMap = new
HashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
System.out.println("Size of Map" + aMap.size());
}
}
Nun, während der Ausführung des Programms haben wir gemacht emp = null
. Das Map
Halten des Schlüssels macht hier so wie es ist keinen Sinn null
. In der obigen Situation wird das Objekt nicht durch Müll gesammelt.
WeakHashMap
WeakHashMap
In key-to-value mappings
diesem Fall werden die Einträge ( ) entfernt, wenn sie nicht mehr von der abgerufen werden können Map
.
Lassen Sie mich das obige Beispiel mit WeakHashMap zeigen
import java.util.WeakHashMap;
public class Test {
public static void main(String args[]) {
WeakHashMap<Employee, EmployeeVal> aMap =
new WeakHashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
int count = 0;
while (0 != aMap.size()) {
++count;
System.gc();
}
System.out.println("Took " + count
+ " calls to System.gc() to result in weakHashMap size of : "
+ aMap.size());
}
}
Ausgang: Nahm 20 calls to System.gc()
zu Folge in aMap size
der: 0.
WeakHashMap
hat nur schwache Verweise auf die Schlüssel, keine starken Verweise wie andere Map
Klassen. Es gibt Situationen, auf die Sie achten müssen, wenn der Wert oder Schlüssel stark referenziert wird, obwohl Sie ihn verwendet haben WeakHashMap
. Dies kann vermieden werden, indem das Objekt in eine WeakReference eingeschlossen wird .
import java.lang.ref.WeakReference;
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> map =
new HashMap<Employee, EmployeeVal>();
WeakReference<HashMap<Employee, EmployeeVal>> aMap =
new WeakReference<HashMap<Employee, EmployeeVal>>(
map);
map = null;
while (null != aMap.get()) {
aMap.get().put(new Employee("Vinoth"),
new EmployeeVal("Programmer"));
System.out.println("Size of aMap " + aMap.get().size());
System.gc();
}
System.out.println("Its garbage collected");
}
}
Weiche Referenzen.
Soft Reference
ist etwas stärker als die schwache Referenz. Die weiche Referenz ermöglicht die Speicherbereinigung, bittet den Speicherbereiniger jedoch, sie nur zu löschen, wenn keine andere Option vorhanden ist.
Der Garbage Collector sammelt nicht wie bei schwach erreichbaren Objekten aggressiv erreichbare Objekte aggressiv, sondern nur dann, wenn er den Speicher wirklich "benötigt". Weiche Referenzen sind eine Möglichkeit, dem Garbage Collector zu sagen: "Solange der Speicher nicht zu eng ist, möchte ich dieses Objekt behalten. Aber wenn der Speicher sehr knapp wird, sammeln Sie es und ich werde mich darum kümmern." damit." Der Garbage Collector muss alle weichen Referenzen löschen, bevor er werfen kann OutOfMemoryError
.
NullPointerException
in bekommen aMap.get().put(...)
.
WeakHashMap
Beispiel (da dies das erste ist, das ein schwaches Verhalten zeigt). Suchen Sie im Dokument nach "WeakHashMap": "An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. "
Der gesamte Sinn der Verwendung von WeakHashMap besteht darin, dass Sie keine WeakReference deklarieren / übergeben müssen. Die WeakHashMap erledigt das intern für Sie. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html
WeakHashMap
Aktion mit einer Beispiel-App, die zeigt, wie Einträge erst nach Ausführung der Garbage Collection entfernt werden, finden Sie unter Meine Antwort auf die Frage: Wächst die WeakHashMap ständig oder werden die Garbage Keys gelöscht? .
Der einzige wirkliche Unterschied zwischen einer weichen Referenz und einer schwachen Referenz besteht darin, dass
Der Garbage Collector verwendet Algorithmen, um zu entscheiden, ob ein leicht erreichbares Objekt zurückgefordert werden soll oder nicht, er fordert jedoch immer ein schwach erreichbares Objekt zurück.
SoftReference
ist für Caches konzipiert. Wenn festgestellt wird, dass ein WeakReference
Objekt auf ein ansonsten nicht erreichbares Objekt verweist, wird es sofort gelöscht. SoftReference
kann so belassen werden wie es ist. In der Regel gibt es einen Algorithmus, der sich auf die Menge des freien Speichers und die zuletzt verwendete Zeit bezieht, um zu bestimmen, ob dieser gelöscht werden soll. Der aktuelle Sun-Algorithmus löscht die Referenz, wenn sie nicht in so vielen Sekunden verwendet wurde, wie auf dem Java-Heap Megabyte Speicher frei sind (konfigurierbar, Server-HotSpot prüft gegen den maximal möglichen Heap, wie von festgelegt -Xmx
). SoftReference
s wird gelöscht, bevor OutOfMemoryError
es geworfen wird, sofern nicht anders erreichbar.
java.lang
. Ein solcher Missbrauch von Synonymen nützt niemandem etwas.
Dieser Artikel kann sehr hilfreich sein, um starke, weiche, schwache und Phantomreferenzen zu verstehen.
Um Ihnen eine Zusammenfassung zu geben,
Wenn Sie nur schwache Verweise auf ein Objekt haben (ohne starke Verweise), wird das Objekt im nächsten GC-Zyklus von GC zurückgefordert.
Wenn Sie nur weiche Verweise auf ein Objekt haben (ohne starke Verweise), wird das Objekt von GC nur dann zurückgefordert, wenn JVM nicht mehr über genügend Speicher verfügt.
Man kann also sagen, dass starke Referenzen die ultimative Kraft haben (können von GC niemals gesammelt werden).
Weiche Referenzen sind leistungsfähiger als schwache Referenzen (da sie dem GC-Zyklus entgehen können, bis JVM nicht mehr über genügend Speicher verfügt).
Schwache Referenzen sind noch weniger leistungsfähig als weiche Referenzen (da sie keinen GC-Zyklus entziehen können und zurückgefordert werden, wenn das Objekt keine andere starke Referenz hat).
Restaurant Analogie
Wenn Sie ein starker Kunde sind (analog zu einer starken Referenz), werden Sie Ihren Tisch (den Speicherbereich auf dem Haufen) niemals verlassen, selbst wenn ein neuer Kunde ins Restaurant kommt oder was auch immer passiert. Der Kellner hat kein Recht, Ihnen zu sagen (oder Sie sogar zu bitten), das Restaurant zu verlassen.
Wenn Sie ein weicher Kunde sind (analog zur weichen Referenz), werden Sie vom Kellner nicht aufgefordert, den Tisch zu verlassen, wenn kein neuer Kunde in das Restaurant kommt, es sei denn, es ist kein anderer leerer Tisch mehr vorhanden, um den neuen Kunden aufzunehmen. (Mit anderen Worten, der Kellner fordert Sie auf, den Tisch nur zu verlassen, wenn ein neuer Kunde eintritt und für diesen neuen Kunden kein anderer Tisch mehr vorhanden ist.)
Wenn Sie ein schwacher Kunde sind (analog zu einer schwachen Referenz), kann der Kellner Sie nach seinem Willen (zu jedem Zeitpunkt) auffordern, das Restaurant zu verlassen: P.
Per doc , lose WeakReferences muss von einem laufenden GC gelöscht werden.
Per doc , lose SoftReferences muss vor OOM gelöscht werden ausgelöst.
Das ist der einzige wirkliche Unterschied. Alles andere ist nicht Vertragsbestandteil. (Ich gehe davon aus, dass die neuesten Dokumente vertraglich sind.)
SoftReferences sind nützlich. Speicherempfindliche Caches verwenden SoftReferences, keine WeakReferences.
weak_ref.get()
. Wenn dies der null
Fall ist, erfahren Sie, dass der GC zwischen dieser Dauer ausgeführt wurde.
Bei falscher Verwendung von WeakReference ist die Liste endlos:
Ein mieser Hack, um eine Prioritäts-2-Softreferenz so zu implementieren, dass Sie keine schreiben müssen, aber sie funktioniert nicht wie erwartet, da der Cache bei jedem GC-Lauf gelöscht wird, selbst wenn freier Speicher vorhanden ist. Phails finden Sie unter https://stackoverflow.com/a/3243242/632951 . (Außerdem, was ist, wenn Sie mehr als 2 Ebenen der Cache-Priorität benötigen? Sie müssten immer noch eine echte Bibliothek dafür benötigen.)
ein lausiger Hack zu assoziieren Daten mit einem Objekt einer vorhandenen Klasse, doch sie schafft ein Speicherleck (OutOfMemoryError) , wenn der GC eine Pause nach dem weakreferences geschaffen nehmen entscheidet. Außerdem ist es mehr als hässlich: Ein besserer Ansatz ist die Verwendung von Tupeln.
Ein mieser Hack, um Daten einem Objekt einer vorhandenen Klasse zuzuordnen, bei dem die Klasse den Nerv hat, sich selbst nicht unterklassifizierbar zu machen, und der in einem vorhandenen Funktionscode verwendet wird, den Sie aufrufen müssen. In einem solchen Fall besteht die richtige Lösung darin, entweder die Klasse zu bearbeiten und sie unterklassifizierbar zu machen oder die Funktion zu bearbeiten und eine Schnittstelle anstelle einer Klasse zu verwenden oder eine alternative Funktion zu verwenden.
equals()
nur die Objektidentität ist? Weiche Referenzen scheinen dort eine Verschwendung zu sein, denn sobald ein Schlüsselobjekt nicht mehr gut erreichbar ist, wird niemand mehr diese Zuordnung nachschlagen.
Die sechs Arten von Objekterreichbarkeitszuständen in Java:
Für weitere Informationen: https://www.artima.com/insidejvm/ed2/gc16.html «Zusammenbruch
Man sollte sich bewusst sein, dass ein schwach referenziertes Objekt nur dann erfasst wird, wenn es NUR schwache Referenzen hat. Wenn es nur eine starke Referenz hat, wird es nicht gesammelt, egal wie viele schwache Referenzen es hat.
Um einen Aspekt der Speichernutzung in Aktion zu geben, habe ich ein Experiment mit starken, weichen, schwachen und Phantomreferenzen unter starker Last mit schweren Objekten durchgeführt, indem ich sie bis zum Ende des Programms beibehalten habe. Dann überwacht Heap - Nutzung & GC Verhalten . Diese Metriken können von Fall zu Fall variieren, bieten aber sicherlich ein hohes Verständnis. Nachfolgend finden Sie Ergebnisse.
Heap & GC Verhalten unter starker Last
Hier erhalten Sie detailliertere Grafiken, Statistiken und Beobachtungen für dieses Experiment .
WeakReference : Objekte, auf die nur schwach verwiesen wird, werden bei jedem GC-Zyklus (geringfügig oder vollständig) erfasst.
SoftReference : Wann Objekte erfasst werden, auf die nur sanft verwiesen wird, hängt ab von:
-XX: SoftRefLRUPolicyMSPerMB = N-Flag (Standardwert ist 1000, auch bekannt als 1 Sekunde)
Menge an freiem Speicher im Heap.
Beispiel:
Dann wird ein Objekt erfasst, auf das nur von SoftReference verwiesen wird, wenn der letzte Zugriff beim Zugriff länger als 10 Sekunden ist.