Java: Unterschied zwischen starker / weicher / schwacher / Phantomreferenz


178

Ich habe diesen Artikel über das Thema gelesen , verstehe ihn aber nicht wirklich. Bitte geben Sie mir einige Ratschläge zusammen mit Beispielen bei der Beschreibung der Konzepte.



4
Ich habe dieses Dokument gelesen, es hilft mir nicht, mir vorzustellen, welchen Unterschied es macht. (Vielleicht, weil es ein schwer gelesenes Dokument ist)

14
Wenn Sie diesen Artikel lesen und immer noch nicht verstehen, haben Sie spezielle Fragen dazu? Es ist schwer zu antworten auf "Bitte erkläre mir Foo", "hier ist was es bedeutet", "Ich verstehe es nicht" ohne Angaben darüber, welche Teile du nicht bekommst.
Yshavit


@ LouisWasserman Der Top-Link ist nicht mehr gültig.
Mehraj Malik

Antworten:


142

Java bietet zwei verschiedene Arten / Klassen von Referenzobjekten : starke und schwache . Schwache Referenzobjekte können weiter in weich und Phantom unterteilt werden .

  • Stark
  • Schwach
    • Sanft
    • Phantom

Gehen wir Punkt für Punkt.

Starkes Referenzobjekt

StringBuilder builder = new StringBuilder();

Dies ist der Standardtyp / die Standardklasse des Referenzobjekts, sofern nicht anders angegeben: Es builderhandelt sich um ein starkes Referenzobjekt. Diese Art von Referenz macht das referenzierte Objekt nicht für GC geeignet. Das heißt, wenn ein Objekt von einer Kette starker Referenzobjekte referenziert wird , kann kein Müll gesammelt werden.

Schwaches Referenzobjekt

WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);

Schwache Referenzobjekte sind nicht der Standardtyp / die Standardklasse des Referenzobjekts und sollten zur Verwendung explizit wie im obigen Beispiel angegeben werden. Diese Art von Referenz macht das Referenzobjekt für GC geeignet. Das heißt, wenn die einzige Referenz, die für das StringBuilderObjekt im Speicher erreichbar ist, tatsächlich die schwache Referenz ist, kann der GC das StringBuilderObjekt mit Müll sammeln . Wenn ein Objekt im Speicher nur über schwache Referenzobjekte erreichbar ist, ist es automatisch für die GC geeignet.

Schwachstellen

Es können zwei verschiedene Schwächungsstufen angegeben werden: weich und phantomisch .

Ein weiches Referenzobjekt ist im Grunde ein schwaches Referenzobjekt, das etwas mehr im Speicher verbleibt: Normalerweise widersteht es dem GC-Zyklus, bis kein Speicher mehr verfügbar ist und das Risiko besteht OutOfMemoryError(in diesem Fall kann es entfernt werden).

Andererseits ist ein Phantomreferenzobjekt nur nützlich, um genau zu wissen, wann ein Objekt effektiv aus dem Speicher entfernt wurde: Normalerweise werden sie verwendet, um das seltsame Wiederbelebungs- / Auferstehungsverhalten von finalize () zu korrigieren , da sie das Objekt selbst nicht zurückgeben, sondern helfen nur dabei , ihre Gedächtnispräsenz im Auge zu behalten .

Schwache Referenzobjekte sind ideal zum Implementieren von Cache-Modulen. Tatsächlich kann eine Art automatische Räumung implementiert werden, indem der GC Speicherbereiche bereinigen kann, wenn Objekte / Werte durch eine starke Referenzkette nicht mehr erreichbar sind. Ein Beispiel ist die WeakHashMap , bei der schwache Schlüssel beibehalten werden.


76

Schwache Referenz:

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.

Soft Reference:

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.

Phantomreferenz:

Eine Phantomreferenz unterscheidet sich erheblich von SoftReference oder WeakReference. Der Griff um das Objekt ist so schwach, dass Sie das Objekt nicht einmal abrufen können - die Methode get () gibt immer null zurück. Die einzige Verwendung für eine solche Referenz besteht darin, zu verfolgen, wann sie in eine ReferenceQueue eingereiht wird, da Sie an diesem Punkt wissen, dass das Objekt, auf das sie zeigt, tot ist.

Dieser Text wurde extrahiert aus: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references


1
Während alles in dieser Antwort korrekt aussieht, sieht es für mich auch so aus, als ob auf der verlinkten Webseite ein Fehler vorliegt. Das Javadoc für das Paket java.lang.ref und das für PhantomReference legen nahe, dass ein Objekt erst dann mit Müll gesammelt wird, wenn es nicht mehr "Phantom erreichbar" ist. Dies bedeutet, dass (im Gegensatz zu SoftReference) eine PhantomReference vor dem Objekt, auf das sie sich bezieht, aus der Warteschlange entfernt werden muss Müll gesammelt werden ... und seine Warteschlange bedeutet nicht, dass der zugehörige Speicher freigegeben wurde.
Theodore Murdock

2
Ich würde viel lieber in einer Welt leben, in der dieser Blog-Beitrag korrekt ist.
Theodore Murdock

1
@ TheodoreMurdock Das Javadoc ist korrekt. Eine Phantomreferenz behindert die Speicherbereinigung überhaupt nicht. Sobald ein Objekt in die Warteschlange gestellt wurde, kann es nicht einmal von einem Finalizer gespeichert werden, da die Finalizer bereits ausgeführt wurden. Es ist tot, aber noch nicht weg.
Leliel

@Leliel Eigentlich ein Phantom Referenz tut in der Tat Sammlung impede Mülls , nachdem es die Warteschlange gestellt wird ... ich dies vor kurzem realisiert , wenn ein Fehler früh , um eine Bereinigungsthread zu verlassen verursacht. Das Vorhandensein von Phantomreferenzen war ausreichend, um sicherzustellen, dass jedes Phantomreferenzobjekt in meinem Heap-Dump beibehalten wurde und nicht für die Erfassung verfügbar ist ... wenn Sie die Warteschlange nicht verarbeiten oder die Phantomreferenz bei der Verarbeitung der Warteschlange nicht für gc qualifizieren können ( Wenn Sie die Phantomreferenz nicht löschen (), enthält Ihr Speicherverlust sowohl die Phantomreferenz als auch das referenzierte Objekt.
Theodore Murdock

25

Der einfache Unterschied zwischen SoftReferenceund WeakReferencewird von Android Developer bereitgestellt .

Der Unterschied zwischen a SoftReferenceund a WeakReferenceist der Zeitpunkt, zu dem die Entscheidung getroffen wird, die Referenz zu löschen und in die Warteschlange zu stellen:

  • A SoftReferencesollte so spät wie möglich gelöscht und in die Warteschlange gestellt werden, dh wenn die Gefahr besteht, dass der VM der Speicher ausgeht.

  • A WeakReferencekann gelöscht und in die Warteschlange gestellt werden, sobald bekannt ist, dass es schwach referenziert ist.


16

Die drei Begriffe, die Sie verwendet haben, hängen hauptsächlich mit der Berechtigung von Object zusammen, Müll zu sammeln.

Schwache Referenz :: Diese Referenz ist nicht stark genug, um das Objekt zu zwingen, im Speicher zu bleiben. Es ist die Laune des Garbage Collectors , dieses Objekt für die Garbage Collection zu sammeln. Sie können diesen GC nicht zwingen, ihn nicht zu sammeln .

Soft Reference :: Es ist mehr oder weniger dasselbe wie die schwache Referenz. Man kann aber sagen, dass es das Objekt etwas stärker hält als die schwache Referenz aus der Garbage Collection.

Wenn die Garbage Collectors die schwache Referenz im ersten Lebenszyklus selbst erfassen, erfassen sie die Soft Reference im nächsten Zyklus der Garbage Collection.

Starke Referenz :: Es ist genau entgegengesetzt zu den beiden oben genannten Arten von Referenzen. Sie sind weniger geneigt, Müll zu sammeln (meistens werden sie nie gesammelt.)

Weitere Informationen finden Sie unter folgendem Link:

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html


3
Ich denke, das ist falsch - "Wenn die Garbage Collectors die schwache Referenz im ersten Lebenszyklus selbst erfassen, wird sie die weiche Referenz im nächsten Zyklus der Garbage Collection erfassen." Es ist nicht unbedingt so, wie können Sie so sicher sein, dass sie in aufeinanderfolgenden GC-Läufen auftreten? Mit GC können Objekte mit weichen Referenzen auch im 2. und 3. Lauf leben. Es gibt keine Dokumentation dafür. Wenn dies der Fall ist, erwähnen Sie bitte den angegebenen Link.
Saurabh Patil

2
Auch Ihre Antwort ist ein wenig vage. Sehen Sie sich diesen Satz an: „Es ist mehr oder weniger dasselbe wie die schwache Referenz. Aber man kann sagen, dass es das Objekt etwas stärker hält als die schwache Referenz aus der Garbage Collection. ' - Er fragt eindeutig nach dem Unterschied und nicht nach Ähnlichkeiten. Alle diese Wörter bringen mehr Verwirrung als Klarheit in das Thema.
Saurabh Patil

@ SaurabhPatil - Verpasste Ihren Kommentar. Hier gehen die Antworten. 1. "er fragt eindeutig nach dem Unterschied und nicht nach Ähnlichkeiten" - Siehe Beschreibung der Frage (nicht "nur" den Titel) "Bitte geben Sie mir einen Rat und bitte geben Sie mir ein Beispiel zur Beschreibung". 2. "Aber man kann sagen, dass es das Objekt ein bisschen mehr hält ..." Ich denke, SOF bietet die Möglichkeit, abzustimmen und auch neue Antworten zu geben.
Sabya

14

Dieser Artikel kann sehr hilfreich sein, um starke, weiche, schwache und Phantomreferenzen zu verstehen.


Um Ihnen eine Zusammenfassung zu geben,

Wenn Sie einen starken Verweis auf ein Objekt haben, kann das Objekt niemals von GC (Garbage Collector) gesammelt / zurückgefordert werden.

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.

Wir schaffen Phantom Referenzen auf ein Objekt zu verfolgen , wenn das Objekt in die Warteschlange gestellt wird ReferenceQueue. Sobald Sie wissen, dass Sie eine feinkörnige Finalisierung durchführen können. (Dies würde Sie davor bewahren, das Objekt versehentlich wiederzubeleben, da die Phantomreferenz Ihnen den Referranten nicht gibt.) Ich würde vorschlagen, dass Sie diesen Artikel lesen , um detaillierte Informationen darüber zu erhalten.


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 keinem GC-Zyklus entkommen 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 zu weicher 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.


10

4 Referenzgrade - Strong, Weak, Soft, Phantom

Stark - ist eine Art Referenz, die das referenzierte Objekt für die GC nicht geeignet macht. Builder-Klassen. zB - StringBuilder

Schwach - ist eine Referenz, die für GC in Frage kommt.

Soft - ist eine Art Referenz, deren Objekt für die GC in Frage kommt, bis Speicher verfügbar ist. Am besten für den Bildcache. Es wird sie halten, bis der Speicher verfügbar ist.

Phantom - ist eine Art Referenz, deren Objekt direkt für die GC in Frage kommt. Wird nur verwendet, um zu wissen, wann ein Objekt aus dem Speicher entfernt wird.

Verwendet:

  1. Hier können Sie feststellen, wann ein Objekt genau aus dem Speicher entfernt wurde.

  2. Wenn die finalize()Methode überladen ist, wird die GC für GC-berechtigte Objekte der beiden Klassen möglicherweise nicht rechtzeitig ausgeführt. Die Phantomreferenz macht sie also zuvor für GC geeignet. finalize()Deshalb können Sie OutOfMemoryErrors auch dann erhalten, wenn der größte Teil des Heaps Müll ist.

Schwache Referenzen sind ideal, um die Cache-Module zu implementieren.


10

Starke Referenzen

Dies sind Ihre regulären Objektreferenzen, die wir täglich codieren:

Employee emp = new Employee();

Die Variable "emp" enthält einen starken Verweis auf ein Employee-Objekt, und Objekte, die über eine Kette starker Verweise erreichbar sind, können nicht mit Speicherbereinigung belegt werden. Normalerweise ist dies das, was Sie wollen, aber nicht immer. Nehmen wir nun an, wir holen viele Mitarbeiter aus der Datenbank in einer Sammlung oder Karte ab und müssen sie regelmäßig verarbeiten. Um die Leistung zu erhalten, behalten wir sie im Cache.

Soweit dies gut ist, benötigen wir jetzt unterschiedliche Daten und diese Employee-Objekte, auf die nur im Cache verwiesen wird. Was verursacht einen Speicherverlust, weil diese Objekte nicht verwendet werden, aber immer noch nicht für die Speicherbereinigung geeignet sind und wir diese Objekte nicht aus dem Cache entfernen können, weil wir keinen Verweis auf sie haben? Hier müssen wir entweder den gesamten Cache manuell leeren, was mühsam ist, oder wir könnten andere Arten von Referenzen verwenden, z. B. schwache Referenzen.

Schwache Referenzen

Eine schwache Referenz fixiert ein Objekt nicht im Speicher und wird im nächsten GC-Zyklus einer GC unterzogen, wenn nicht auf andere Referenzen verwiesen wird. Wir können die von Java bereitgestellte WeakReference-Klasse verwenden, um die oben genannten Caches zu erstellen, in denen keine Objekte gespeichert werden, auf die nicht von einem anderen Ort verwiesen wird.

WeakReference<Cache> cache = new WeakReference<Cache>(data);

Um auf Daten zuzugreifen, müssen Sie cache.get () aufrufen. Dieser Aufruf zum Abrufen kann null zurückgeben, wenn die schwache Referenz Garbage Collected war: Sie müssen den zurückgegebenen Wert überprüfen, um NPEs zu vermeiden. Java bietet Sammlungen, die schwache Referenzen verwenden, z. B. speichert die WeakHashMap-Klasse Schlüssel (keine Werte) als schwache Referenzen. Wenn der Schlüssel GC'd ist, wird der Wert automatisch auch von der Karte entfernt.

Da schwache Referenzen auch Objekte sind, müssen wir sie bereinigen (sie sind nicht mehr nützlich, wenn das Objekt, auf das sie verweisen, GC-fähig war). Wenn Sie eine ReferenceQueue für eine schwache Referenz an den Konstruktor übergeben, hängt der Garbage Collector diese schwache Referenz an die ReferenceQueue an, bevor sie finalisiert oder GC-geprüft wird. Sie können diese Warteschlange regelmäßig verarbeiten und mit toten Referenzen umgehen.

Weiche Referenzen

Eine SoftReference ähnelt einer WeakReference, es ist jedoch weniger wahrscheinlich, dass Müll gesammelt wird. Weiche Referenzen werden nach Ermessen des Garbage Collectors als Reaktion auf den Speicherbedarf gelöscht. Die virtuelle Maschine garantiert, dass alle weichen Verweise auf leicht erreichbare Objekte gelöscht wurden, bevor jemals ein OutOfMemoryError ausgelöst wurde.

Phantomreferenzen

Phantomreferenzen sind die schwächsten aller Referenztypen. Wenn Sie get on aufrufen, wird immer null zurückgegeben. Ein Objekt wird nach seiner Fertigstellung phantomisch referenziert, aber bevor sein zugewiesener Speicher zurückgefordert wurde. Im Gegensatz zu schwachen Referenzen, die vor ihrer Fertigstellung in die Warteschlange gestellt werden oder GC-Phantomreferenzen werden selten verwendet.

Wie sind sie also nützlich? Wenn Sie eine Phantomreferenz erstellen, müssen Sie immer eine ReferenceQueue übergeben. Dies zeigt an, dass Sie eine Phantomreferenz verwenden können, um zu sehen, wann Ihr Objekt GC-fähig ist.

Hey, wenn schwache Referenzen in die Warteschlange gestellt werden, wenn sie als finalisiert, aber noch nicht GC-geprüft gelten, können wir eine neue starke Referenz auf das Objekt im Finalizer-Block erstellen und verhindern, dass das Objekt GC-geprüft wird. Ja, Sie können, aber Sie sollten das wahrscheinlich nicht tun. Um dies zu überprüfen, wird der GC-Zyklus für jedes Objekt mindestens zweimal durchgeführt, es sei denn, dieses Objekt ist nur über eine Phantomreferenz erreichbar. Aus diesem Grund kann Ihnen der Heap ausgehen, selbst wenn Ihr Speicher viel Müll enthält. Phantomreferenzen können dies verhindern.

Sie können mehr über meinen Artikel Arten von Referenzen in Java lesen (Stark, Weich, Schwach, Phantom) .


Sie haben geschrieben, dass schwache Aktualisierungen im nächsten Zyklus GC'ed werden, wenn sie nicht von anderen Aktualisierungen abgefragt werden ... aber sollten Sie nicht dasselbe mit starken Aktualisierungen tun? Wenn auf Stron Refrence in keiner Weise zugegriffen wird, wird es gelöscht ... wenn ja, wo ist dann wieder der Unterschied ...? #confused
filemonczyk

1
Wenn ein Objekt von s1 (stark) und s2 (stark) referenziert wird, ist das Objekt erst dann für die Speicherbereinigung geeignet, wenn sowohl s1 als auch s2 dereferenziert sind, wenn das Objekt jedoch von s1 (schwach) und s2 (referenziert) wird stark) dann ist das Objekt im nächsten GC-Zyklus für die Speicherbereinigung berechtigt, wenn es nur von s2 dereferenziert wird, da s1 eine schwache Referenz ist und wenn das Objekt keine andere Referenz als die schwache hat, ist es für GC
Naresh Joshi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.