Quelle est la différence entre java.lang.ref.WeakReference
et java.lang.ref.SoftReference
?
java
reference
weak-references
soft-references
driekken
la source
la source
Réponses:
De Comprendre les références faibles , par Ethan Nicholas:
Et Peter Kessler a ajouté dans un commentaire:
la source
Les références faibles sont collectées avec impatience. Si GC trouve qu'un objet est faiblement accessible (accessible uniquement via des références faibles), il effacera immédiatement les références faibles à cet objet. En tant que tels, ils sont bons pour conserver une référence à un objet pour lequel votre programme conserve également (fortement référencé) des "informations associées", comme les informations de réflexion mises en cache sur une classe, ou un wrapper pour un objet, etc. Tout ce qui fait aucun sens à garder après que l'objet auquel il est associé soit GC-ed. Lorsque la référence faible est effacée, elle est mise en file d'attente dans une file d'attente de référence que votre code interroge quelque part, et elle supprime également les objets associés. Autrement dit, vous conservez des informations supplémentaires sur un objet, mais ces informations ne sont pas nécessaires une fois que l'objet auquel il fait référence disparaît. Réellement, dans certaines situations, vous pouvez même sous-classer WeakReference et conserver les informations supplémentaires associées sur l'objet dans les champs de la sous-classe WeakReference. Une autre utilisation typique de WeakReference est en conjonction avec Maps pour conserver les instances canoniques.
Les références logicielles, d'autre part, sont bonnes pour la mise en cache des ressources externes et recréables car le GC retarde généralement leur effacement. Il est cependant garanti que toutes les SoftReferences seront effacées avant que OutOfMemoryError ne soit levée, donc elles ne peuvent théoriquement pas provoquer un OOME [*].
Un exemple typique de cas d'utilisation consiste à conserver une forme analysée d'un contenu à partir d'un fichier. Vous implémenteriez un système dans lequel vous chargeriez un fichier, l'analyseriez et conserveriez une SoftReference à l'objet racine de la représentation analysée. La prochaine fois que vous aurez besoin du fichier, vous essaierez de le récupérer via SoftReference. Si vous pouvez le récupérer, vous vous êtes épargné une autre charge / analyse, et si le GC l'a effacé entre-temps, vous le rechargez. De cette façon, vous utilisez de la mémoire libre pour l'optimisation des performances, mais ne risquez pas un OOME.
Maintenant pour le [*]. Garder une SoftReference ne peut pas provoquer un OOME en soi. Si, d'autre part, vous utilisez par erreur SoftReference pour une tâche, une WeakReference est destinée à être utilisée (à savoir, vous conservez les informations associées à un objet en quelque sorte fortement référencées et les jetez lorsque l'objet Reference est effacé), vous pouvez exécuter OOME comme votre code qui interroge la ReferenceQueue et rejette les objets associés peut ne pas s'exécuter en temps opportun.
Ainsi, la décision dépend de l'utilisation - si vous mettez en cache des informations coûteuses à construire, mais néanmoins reconstructibles à partir d'autres données, utilisez des références logicielles - si vous conservez une référence à une instance canonique de certaines données, ou si vous souhaitez avoir une référence à un objet sans le "posséder" (l'empêchant ainsi d'être GC'd), utiliser une référence faible.
la source
WeakReference
est que dans les endroits où l'on devrait l'utiliser, le fait que l'on puisse rester valide pendant un certain temps après que la référence soit hors de portée peut être tolérable, mais n'est pas souhaitable.WeakReference
pour observer les exécutions du GC. Voir l'élaboration: stackoverflow.com/a/46291143/632951En Java ; ordre du plus fort au plus faible, il y a: fort, doux, faible et fantôme
Une référence forte est une référence normale qui protège l'objet référé de la collecte par GC. c.-à-d. ne jamais ramasser les ordures.
Une référence logicielle peut être collectée par le garbage collector, mais ne sera probablement pas collectée tant que sa mémoire n'est pas nécessaire. c.-à-d. les ordures ramassent avant
OutOfMemoryError
.Une référence faible est une référence qui ne protège pas un objet référencé de la collecte par GC. c.-à-d. que les ordures se collectent lorsqu'aucune référence forte ou douce.
Une référence fantôme est une référence à un objet référencée fantôme après sa finalisation, mais avant que sa mémoire allouée ne soit récupérée.
La source
Analogie: Supposons qu'une JVM est un royaume, Object est un roi du royaume et GC est un attaquant du royaume qui essaie de tuer le roi (objet).
la source
until memory is available
n'a pas de sens. Tu veux direis eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use
?Référence faible http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
Principe:
weak reference
est lié à la collecte des ordures. Normalement, un objet en ayant un ou plusieursreference
ne sera pas éligible pour la récupération de place.Le principe ci-dessus n'est pas applicable lorsqu'il l'est
weak reference
. Si un objet n'a qu'une référence faible avec d'autres objets, il est prêt pour la collecte des ordures.Regardons l'exemple ci-dessous: Nous avons un
Map
avec des objets où Key fait référence à un objet.Maintenant, pendant l'exécution du programme que nous avons fait
emp = null
. LaMap
tenue la clé n'a pas de sens ici comme il estnull
. Dans la situation ci-dessus, l'objet n'est pas récupéré.WeakHashMap
WeakHashMap
est celui où les entrées (key-to-value mappings
) seront supprimées lorsqu'il ne sera plus possible de les récupérer à partir duMap
.Permettez-moi de montrer l'exemple ci-dessus avec WeakHashMap
Sortie: a pris
20 calls to System.gc()
pour résultataMap size
: 0.WeakHashMap
n'a que des références faibles aux clés, pas des références fortes comme les autresMap
classes. Il y a des situations auxquelles vous devez faire attention lorsque la valeur ou la clé est fortement référencée bien que vous l'ayez utiliséeWeakHashMap
. Cela peut être évité en enveloppant l'objet dans une référence faible .Références souples.
Soft Reference
est légèrement plus fort que la référence faible. La référence logicielle permet le ramasse-miettes, mais demande au ramasse-miettes de l'effacer uniquement s'il n'y a pas d'autre option.Le ramasse-miettes ne collecte pas de manière agressive les objets facilement accessibles comme il le fait avec les objets peu accessibles - au lieu de cela, il ne collecte les objets facilement accessibles que s'il "a vraiment besoin" de la mémoire. Les références souples sont une façon de dire au garbage collector: "Tant que la mémoire n'est pas trop serrée, je voudrais garder cet objet autour. Mais si la mémoire devient vraiment serrée, allez-y et récupérez-la et je traiterai avec ça." Le garbage collector est nécessaire pour effacer toutes les références logicielles avant de pouvoir lancer
OutOfMemoryError
.la source
NullPointerException
dansaMap.get().put(...)
.WeakHashMap
exemple (puisque c'est le premier qui démontre un comportement faible). Regardez le document pour "WeakHashMap":"An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. "
L'intérêt de l'utilisation de WeakHashMap est que vous n'avez pas à déclarer / transmettre un WeakReference; le WeakHashMap le fait pour vous, en interne. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.htmlWeakHashMap
en action, avec un exemple d'application montrant comment les entrées sont supprimées uniquement après l' exécution de la récupération de place, voir ma réponse à la question, WeakHashMap est-il en constante croissance, ou efface-t-il les clés de récupération? .La seule vraie différence entre une référence douce et une référence faible est que
la source
SoftReference
est conçu pour les caches. Lorsqu'il est constaté qu'un a faitWeakReference
référence à un objet autrement inaccessible, il sera immédiatement effacé.SoftReference
peut être laissé tel quel. En règle générale, il existe un algorithme relatif à la quantité de mémoire libre et au dernier temps utilisé pour déterminer si elle doit être effacée. L'algorithme Sun actuel consiste à effacer la référence si elle n'a pas été utilisée en autant de secondes qu'il y a de mégaoctets de mémoire libre sur le tas Java (configurable, le serveur HotSpot vérifie le maximum de tas possible défini par-Xmx
).SoftReference
s sera effacé avantOutOfMemoryError
son lancement, sauf indication contraire.la source
java.lang
. Un tel abus de synonymes ne fait de bien à personne.Cet article peut être très utile pour comprendre les références fortes, douces, faibles et fantômes.
Pour vous donner un résumé,
Si vous n'avez que des références faibles à un objet (sans références fortes), alors l'objet sera récupéré par GC lors du tout prochain cycle GC.
Si vous n'avez que des références logicielles à un objet (sans références fortes), l'objet ne sera récupéré par GC que lorsque JVM manque de mémoire.
Vous pouvez donc dire que les références fortes ont un pouvoir ultime (ne peuvent jamais être collectées par GC)
Les références souples sont puissantes que les références faibles (car elles peuvent échapper au cycle GC jusqu'à ce que JVM manque de mémoire)
Les références faibles sont encore moins puissantes que les références douces (car elles ne peuvent échapper à aucun cycle GC et seront récupérées si l'objet n'a pas d'autre référence forte).
Restaurant Analogy
Maintenant, si vous êtes un client fort (analogue à une référence forte), alors même si un nouveau client vient au restaurant ou quoi qu'il arrive, vous ne quitterez jamais votre table (la zone de mémoire sur le tas). Le serveur n'a pas le droit de vous dire (ni même de vous demander) de quitter le restaurant.
Si vous êtes un client doux (analogue à une référence douce), alors si un nouveau client vient au restaurant, le serveur ne vous demandera pas de quitter la table à moins qu'il ne reste plus de table vide pour accueillir le nouveau client. (En d'autres termes, le serveur vous demandera de quitter la table uniquement si un nouveau client intervient et qu'il n'y a plus d'autre table pour ce nouveau client)
Si vous êtes un client faible (analogue à une référence faible), le serveur, à sa guise, peut (à tout moment) vous demander de quitter le restaurant: P
la source
La seule vraie différence
Selon le document , les WeakReferences lâches doivent être effacées par un GC en cours d'exécution.
Selon le document , les références logicielles lâches doivent être effacées avant que le MOO ne soit lancé.
C'est la seule vraie différence. Tout le reste ne fait pas partie du contrat. (Je suppose que les derniers documents sont contractuels.)
Les références logicielles sont utiles.Les caches sensibles à la mémoire utilisent des références logicielles, pas des références faibles.
La seule utilisation appropriée de WeakReference est d'observer le fonctionnement du GC. Pour ce faire, créez un nouveau WeakReference dont l'objet sort immédiatement de la portée, puis essayez d'en retirer null
weak_ref.get()
. Quand c'est le casnull
, vous apprenez qu'entre cette durée, le GC a fonctionné.Quant à une mauvaise utilisation de WeakReference, la liste est interminable:
un hack moche pour implémenter une référence souple de priorité 2 de sorte que vous n'ayez pas à en écrire une, mais cela ne fonctionne pas comme prévu car le cache serait effacé à chaque exécution du GC, même lorsqu'il y a de la mémoire disponible. Voir https://stackoverflow.com/a/3243242/632951 pour les phails. (D'ailleurs, que se passe-t-il si vous avez besoin de plus de 2 niveaux de priorité de cache? Vous auriez toujours besoin d'une vraie bibliothèque pour cela.)
un hack moche pour associer des données à un objet d'une classe existante, mais cela crée une fuite de mémoire (OutOfMemoryError) lorsque votre GC décide de faire une pause après la création de vos faibles références. En outre, c'est au-delà de la laideur: une meilleure approche consiste à utiliser des tuples.
un hack moche pour associer des données à un objet d'une classe existante, où la classe a le culot de se rendre non sous-classable, et est utilisé dans un code de fonction existant que vous devez appeler. Dans un tel cas, la solution appropriée consiste soit à éditer la classe et à la rendre sous-classable, soit à éditer la fonction et à lui faire prendre une interface à la place d'une classe, ou à utiliser une fonction alternative.
la source
equals()
n'est qu'une identité d'objet? Les références logicielles semblent être un gaspillage là-bas, car une fois qu'un objet clé n'est plus fortement accessible, personne ne cherchera plus jamais ce mappage.Les six types d'états d'accessibilité aux objets en Java:
Pour plus de détails: https://www.artima.com/insidejvm/ed2/gc16.html «réduire
la source
Il faut savoir qu'un objet faiblement référencé ne sera collecté que s'il a UNIQUEMENT des références faibles. S'il a autant qu'une référence forte, il n'est pas collecté quel que soit le nombre de références faibles qu'il possède.
la source
Pour donner un aspect d'utilisation de la mémoire en action, j'ai fait une expérience avec des références fortes, douces, faibles et fantômes sous forte charge avec des objets lourds en les conservant jusqu'à la fin du programme. Puis suivi de l'utilisation du tas et du comportement du GC . Ces mesures peuvent varier au cas par cas, mais donnent certainement une compréhension de haut niveau. Voici les résultats.
Comportement du tas et du GC sous une charge élevée
Vous pouvez obtenir des graphiques plus détaillés , des statistiques, des observations pour cette expérience ici .
la source
WeakReference : les objets qui ne sont que faiblement référencés sont collectés à chaque cycle GC (mineur ou complet).
SoftReference : lorsque des objets qui sont uniquement référencés en douceur sont collectés, cela dépend:
-XX: indicateur SoftRefLRUPolicyMSPerMB = N (la valeur par défaut est 1000, alias 1 seconde)
Quantité de mémoire libre dans le tas.
Exemple:
Ensuite, l'objet qui n'est référencé que par SoftReference sera collecté si la dernière fois lors de son accès est supérieure à 10 secondes.
la source