Was ist der Unterschied zwischen SoftReference und WeakReference in Java?

811

Was ist der Unterschied zwischen java.lang.ref.WeakReferenceund java.lang.ref.SoftReference?

driekken
quelle
9
SoftReferences sind Arten von (nicht wirklich, aber zur Diskussion) WeakReferences, die normalerweise gesammelt werden, wenn JVM denkt, dass nicht genügend Speicher vorhanden ist.
Ajeet Ganga
5
@AjeetGanga, Lose schwache Refs werden immer gesammelt, wenn der GC läuft. Siehe stackoverflow.com/a/46291143/632951
Pacerier

Antworten:

927

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 eigentliche WidgetObjekt 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), dass weakWidget.get()plötzlich eine Rückkehr erfolgt null.

...

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.

SoftReferencessind nicht erforderlich anders zu verhalten , als WeakReferences, 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.

Michael Myers
quelle
7
Post nicht mehr verfügbar, finden Sie auf Wayback-Maschine: web.archive.org/web/20061130103858/http://weblogs.java.net/blog/…
riccardo.tasso
Dieses Mal ist das Archiv nicht mehr verfügbar
user1506104
209

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).

driekken
quelle
14
Besonders nützlich für die Erklärung, wann schwache Objekte verwendet werden würden.
Jack BeNimble
Ein wichtiger Punkt bei der ordnungsgemäßen Verwendung von a WeakReferenceist, 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.
Supercat
Ich habe Probleme zu verstehen, was WeakHashMap verwendet, wenn es immer einen schwachen Verweis auf sein Schlüsselwertobjekt erzeugt.
@supercat, Es gibt nur eine ordnungsgemäße Verwendung WeakReference, um GC-Läufe zu beobachten. Siehe Ausarbeitung: stackoverflow.com/a/46291143/632951
Pacerier
1
@ Pacerier: Der Autor dieses Beitrags ist einfach falsch. Er vernachlässigt einige andere Nutzungsszenarien wie das Abonnement von Ereignissen, sein zweiter Punkt ist unsinnig und sein dritter Punkt geht davon aus, dass ein Programmierer Dinge tun kann, die möglicherweise nicht möglich sind. Sein erster Punkt ist vernünftig, hängt aber direkt mit dem zusammen, was ich gesagt habe. Wenn Code beispielsweise häufig große unveränderliche Objekte erstellen und vergleichen muss , ist der Gebäudeteil häufig billiger, wenn Code neue Objekte erstellt, ohne zu berücksichtigen, ob sie bereits vorhanden sind, aber ein Vergleich zwischen einem Objekt und sich selbst (identische Referenzen) ...
Supercat
155

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.

Quelle

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.

  • Wenn King Strong ist , kann GC ihn nicht töten.
  • Wenn King Soft ist , greift GC ihn an, aber King regiert das Königreich mit Schutz, bis Ressourcen verfügbar sind.
  • Wenn König schwach ist , greift GC ihn an, regiert aber das Königreich ohne Schutz.
  • Wenn König Phantom ist , hat GC ihn bereits getötet, aber König ist über seine Seele verfügbar.
Premraj
quelle
7
Weiche Referenz ... until memory is availablemacht 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?
ToolmakerSteve
1
Ja, Garbage Collector sammelt die Referenz erst, wenn der Speicher verfügbar ist.
Premraj
2
Ich mag einfach erklärte Sachen, ohne zu viel bla bla bla +1 von mir!
Adelin
3
Hervorragende Zusammenfassung mit innovativem Beispiel
Ravindra Babu
+1, weiterführende Literatur: javarevisited.blogspot.in/2014/03/…
Roottraveller
77

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 referencenicht 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 Mapwith 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 MapHalten 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

WeakHashMapIn key-to-value mappingsdiesem 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 sizeder: 0.

WeakHashMaphat nur schwache Verweise auf die Schlüssel, keine starken Verweise wie andere MapKlassen. 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 Referenceist 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.

Thalaivar
quelle
5
Sie können eine NullPointerExceptionin bekommen aMap.get().put(...).
Xehpuk
Ihr erstes HashMap-Beispiel sieht falsch aus. Wenn Sie "aMap.put (emp, val);" Sowohl 'emp' als auch 'val' sind starke Referenzen. Intern wird eine neue Variable erstellt, die 'emp' und 'val' enthält. Wenn Sie also "emp = null;" Sie machen nur die Variable "emp" ungültig, nicht jedoch die Variable intern in der Hash-Map (die noch das ursprüngliche Employee-Objekt enthält). Daher enthält die Hash-Map immer noch einen starken Verweis auf 'emp', unabhängig davon, was Sie mit der Variablen 'emp' außerhalb tun.
Tiago
@Tiago. Nein. Vermutlich beziehen Sie sich mit "erstem Beispiel" auf das WeakHashMapBeispiel (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
ToolmakerSteve
Hat 0 Aufrufe von System.gc () ausgeführt, um eine schwache HashMap-Größe von 0 zu erhalten. Ist die Ausgabe Ihres zweiten Programms?
Adelin
1
Ein weiteres Beispiel für eine WeakHashMapAktion 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? .
Basil Bourque
50

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.

Samir Mangroliya
quelle
@ ATorras, Samir. Ich habe diese Antwort hier erweitert: stackoverflow.com/a/46291143/632951
Pacerier
25

SoftReferenceist für Caches konzipiert. Wenn festgestellt wird, dass ein WeakReferenceObjekt auf ein ansonsten nicht erreichbares Objekt verweist, wird es sofort gelöscht. SoftReferencekann 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). SoftReferences wird gelöscht, bevor OutOfMemoryErrores geworfen wird, sofern nicht anders erreichbar.

Tom Hawtin - Tackline
quelle
9
Aber in Android wird es nicht für Caches empfohlen. Developer.android.com/reference/java/lang/ref/…
Yaroslav Mytkalyk
4
@DoctororDrive tbf die Frage war über Java, nicht Dalvik! :-P
fabspro
2
@YaroslavMytkalyk, Ehrlich gesagt, wenn Android das Verhalten einer Klasse neu schreiben möchte, sollte es seinen eigenen Namespace verwenden, nicht java.lang. Ein solcher Missbrauch von Synonymen nützt niemandem etwas.
Pacerier
9

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

  • Kellner - GC
  • Sie - Objekt im Haufen
  • Restaurantbereich / Raum - Haufenraum
  • Neuer Kunde - Neues Objekt, das einen Tisch im Restaurant haben möchte

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.

Verschwenderische Kothari
quelle
7

Der einzige wirkliche Unterschied

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.


Die einzig richtige Verwendung von WeakReference ist die Beobachtung des GC-Laufs. Dazu erstellen Sie eine neue WeakReference, deren Objekt sofort den Gültigkeitsbereich verlässt, und versuchen dann, null zu entfernen weak_ref.get(). Wenn dies der nullFall 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.

Pacerier
quelle
Was ist mit einem Cache, in dem der Schlüsseltyp 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.
HighCommander4
Ich stimme dir nicht zu. Verwenden Sie WeakReference, wenn Sie GC ohnehin nicht beeinflussen möchten (Sie möchten möglicherweise eine Objektreferenz speichern und später überprüfen, ob sie noch vorhanden ist, ohne dies zu bevorzugen). Verwenden Sie SoftReference, wenn Sie den GC beeinflussen möchten, um zu versuchen, das Objekt zu behalten (dh wenn Sie möchten, dass der GC es behält).
David Refaeli
Ein gutes Beispiel für die Verwendung von WeakReference ist AsyncTask von Android, um eine Instanz des Kontexts beizubehalten. Auf diese Weise hat die AsyncTask keinen starken Bezug dazu, wenn der Kontext stirbt (wenn Aktivität - Bildschirmrotation usw.), und kann daher durch Müll gesammelt werden. Überprüfen Sie youtu.be/…
David Refaeli
3

Die sechs Arten von Objekterreichbarkeitszuständen in Java:

  1. Stark erreichbare Objekte - GC sammelt diese Art von Objekt nicht (stellt den von ihm belegten Speicher wieder her ). Diese sind über einen Wurzelknoten oder ein anderes stark erreichbares Objekt erreichbar (dh über lokale Variablen, Klassenvariablen, Instanzvariablen usw.).
  2. Weich erreichbare Objekte - GC kann je nach Speicherkonflikt versuchen , diese Art von Objekten zu sammeln. Diese sind von der Wurzel über ein oder mehrere weiche Referenzobjekte erreichbar
  3. Schwach erreichbare Objekte - GC muss diese Art von Objekten sammeln. Diese sind von der Wurzel über ein oder mehrere schwache Referenzobjekte erreichbar
  4. Wiederbelebbare Objekte - GC sammelt diese Objekte bereits. Aber sie können durch die Ausführung eines Finalisierers in einen der Zustände zurückkehren - Stark / Weich / Schwach
  5. Phantomarisch erreichbares Objekt - GC ist bereits dabei, diese Objekte zu sammeln, und hat festgestellt, dass es von keinem Finalizer wiederbelebt werden kann (wenn es selbst eine finalize () -Methode deklariert, wurde sein Finalizer ausgeführt) . Diese sind von der Wurzel über ein oder mehrere Phantomreferenzobjekte erreichbar
  6. Nicht erreichbares Objekt - Ein Objekt ist weder stark, leise, schwach noch phantomreich erreichbar und kann nicht wiederbelebt werden. Diese Objekte sind zur Rückgewinnung bereit

Für weitere Informationen: https://www.artima.com/insidejvm/ed2/gc16.html «Zusammenbruch

V. Vidyasagar
quelle
4
Keine gute Beschreibung von Phantomreferenzen. Außerdem haben Sie die 4 Typen in einer bestimmten Reihenfolge aufgelistet. "Phantom" ist der schwächste Typ, nicht der stärkste Typ. Die traditionelle Reihenfolge, um diese aufzulisten, ist "stark, weich, schwach, Phantom". Und ich habe keine Ahnung, woher Sie die Vorstellung haben, dass Phantomobjekte für Caching-Mechanismen verwendet werden. AFAIK, sie sind ein vorübergehender Zustand, der nur vom GC gesehen wird, nicht etwas, mit dem ein gewöhnlicher Programmierer arbeiten würde.
ToolmakerSteve
@ToolmakerSteve und alle - Entschuldigung für einige Dinge 1. die falsche Erklärung der Phantomreferenzen in der vorherigen Version meiner Antwort und 2. Verzögerung bei der Korrektur der Fehler. Jetzt wurde die Antwort durch Korrigieren der Fehler verbessert
V.Vidyasagar
1

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.

Fai Lau
quelle
Dies ist gesunder Menschenverstand ... das gleiche gilt für Softref und Phantomref.
Pacerier
1

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

  • Starke / harte Referenz - Im weiteren Verlauf des Programms konnte JVM kein beibehaltenes stark referenziertes Objekt erfassen. Endete schließlich in "java.lang.OutOfMemoryError: Java Heap Space"
  • Soft Reference - Im weiteren Verlauf des Programms nahm die Heap-Nutzung weiter zu, aber die GC der alten Generation trat auf, als sie sich dem maximalen Heap näherte. GC wurde etwas später nach dem Start des Programms gestartet.
  • Schwache Referenz - Als das Programm gestartet wurde, wurden die Objekte fast sofort fertiggestellt und gesammelt. Meist wurden Gegenstände in der Müllabfuhr der jungen Generation gesammelt.
  • Phantomreferenz - Ähnlich wie bei einer schwachen Referenz wurden auch Objekte mit Phantomreferenz finalisiert und der Müll sofort gesammelt. Es gab keine GC der alten Generation und alle Objekte wurden in der Müllabfuhr der jungen Generation selbst gesammelt.

Hier erhalten Sie detailliertere Grafiken, Statistiken und Beobachtungen für dieses Experiment .

Ravi K.
quelle
0

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:

  1. -XX: SoftRefLRUPolicyMSPerMB = N-Flag (Standardwert ist 1000, auch bekannt als 1 Sekunde)

  2. Menge an freiem Speicher im Heap.

    Beispiel:

    • Heap hat 10 MB freien Speicherplatz (nach vollständiger GC);
    • -XX: SoftRefLRUPolicyMSPerMB = 1000

    Dann wird ein Objekt erfasst, auf das nur von SoftReference verwiesen wird, wenn der letzte Zugriff beim Zugriff länger als 10 Sekunden ist.

Artem Petrov
quelle