Quelle est la différence?
De Comprendre les faibles références , par Ethan Nicholas:
Références faibles
Un référence faible, tout simplement, est un référence qui n'est pas assez forte pour forcer un objet à rester en mémoire . Les faibles références vous permettent de tirer profit de la capacité du ramasse-miettes à déterminer l'accessibilité pour vous, de sorte que vous ne pas le faire vous-même. Vous créez une référence faible comme celle-ci:
WeakReference weakWidget = new WeakReference(widget);
et alors ailleurs dans le code, vous pouvez utiliser
weakWidget.get()
pour obtenir le .__ réel.Widget
object. Bien sûr le faible la référence n'est pas assez forte pour empêcher la collecte des ordures, de sorte que vous pouvez trouve (s'il n'y a pas de fortes références au widget) queweakWidget.get()
démarre soudainement retournantnull
....
Références douces
Un référence souple est exactement comme un référence faible, sauf que c'est moins désireux de jeter l'objet à auquel il se réfère. Un objet qui est faiblement accessible (les références les plus fortes à celle-ci sont
WeakReferences
) sera jeté à la prochaine poubelle cycle de collecte, mais un objet qui est généralement accessible rester pendant un moment.
SoftReferences
ne sont pas requis à se comporter différemment queWeakReferences
, mais en pratique doucement les objets accessibles sont généralement conservé tant que la mémoire est dedans offre abondante. Cela les rend un excellente base pour une cache, telle comme le cache d'image décrit ci-dessus, puisque vous pouvez laisser la poubelle collectionneur s'inquiéter à la fois comment accessibles les objets sont (un objet fortement accessible sera jamais être supprimé du cache) et à quel point il est nécessaire. la mémoire qu'ils consomment.
Et Peter Kessler a ajouté dans un commentaire:
Sun JRE traite les SoftReferences différemment des WeakReferences. Nous essayons de conserver les objets référencés par SoftReference s'il n'y a pas de pression sur la mémoire disponible. Un détail: les règles pour les JRE "-client" et "-server" sont différentes: le JRE -client essaie de garder votre empreinte réduite en préférant supprimer les SoftReferences plutôt que d’étendre le tas, alors que le performances élevées en préférant agrandir le tas (si possible) plutôt que de supprimer les SoftReferences. Une taille unique ne convient pas à tous.
Les références faibles sont recueillies 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 utiles pour Conserver une référence à un objet pour lequel votre programme conserve également (Fortement référencé) "informations associées" quelque part, comme en cache Des informations de réflexion sur une classe ou un wrapper pour un objet, etc. .. Tout ce qui n'a aucun sens de conserver après l'objet auquel il est associé est associé à 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érences Que votre code interroge quelque part et les objets associés à Sont également ignorés. En d'autres termes, vous conservez des informations supplémentaires sur un objet , Mais ces informations ne sont plus nécessaires une fois que l'objet auquel il fait référence disparaît. En fait, dans certaines situations, vous pouvez même créer une sous-classe WeakReference et conserver les informations supplémentaires associées à l’objet dans les champs de la sous-classe WeakReference. Une autre utilisation typique de WeakReference est associée à Maps pour conserver des instances canoniques.
Les SoftReferences, d’autre part, sont utiles pour la mise en cache de ressources externes pouvant être reconstituées Le GC retardant généralement leur effacement. Il est cependant garanti que toutes les SoftReferences seront effacées avant que OutOfMemoryError ne soit renvoyé. Par conséquent, ils Ne peuvent théoriquement pas causer un OOME [*].
Un exemple typique de cas d'utilisation consiste à conserver une forme analysée d'un contenu à partir d'un fichier Vous mettriez en place un système dans lequel vous chargeriez un fichier, l'analyseriez et garderiez Un SoftReference dans l'objet racine de la représentation analysée. La prochaine foisvous avez besoin du fichier, vous essayerez de le récupérer via SoftReference. Si vous pouvez le récupérer, vous vous êtes épargné un autre chargement/analyse, et si le GC. L'a effacé dans l'intervalle, vous le rechargez. De cette façon, vous utilisez de la mémoire libre Pour optimiser les performances, mais ne courez pas le risque de tomber sur OOME.
Maintenant pour le [*]. Garder un SoftReference ne peut pas causer un OOME en soi. Si D’autre part, vous utilisez par erreur SoftReference pour une tâche, un WeakReference est utiliséà utiliser (c’est-à-dire que vous conservez en quelque sorte les informations associées à un objet Fortement référencées, et les ignorez lorsque l'objet de référence est effacé), vous pouvez vous heurter à OOME car votre code qui interroge ReferenceQueue et ignore les objets associés risque de ne pas s'exécuter dans les délais impartisfashion.
Ainsi, la décision dépend de l'utilisation - si vous mettez en cache des informations coûteuses à construire, mais que Néanmoins reconstructibles à partir d'autres données, utilisez des références logicielles - si vous conservez une référence à un nom canonique. exemple de certaines données, ou.vous voulez avoir une référence à un objet sans le "posséder" (donc l'empêcher de l'être), utilisez une référence faible.
En 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érencé de la collecte par GC. c'est-à-dire que les ordures ne sont jamais ramassées.
Une référence Soft est éligible à la collecte par le ramasse-miettes, mais ne sera probablement pas collectée tant que sa mémoire ne sera pas nécessaire. c'est-à-dire que les ordures sont collectées avant OutOfMemoryError
.
Une référence Weak est une référence qui ne protège pas un objet référencé de la collection par GC. c'est-à-dire que les ordures sont collectées lorsqu'aucune référence forte ou douce n'est fournie.
Une référence Phantom est une référence à un objet qui est référencé de manière fantomatique après sa finalisation, mais avant que sa mémoire allouée n'ait été récupérée.
Analogie: Supposons qu'une JVM est un royaume, Object est un roi du royaume et GC est un attaquant du royaume qui tente de tuer le roi (objet).
Référence faiblehttp://docs.Oracle.com/javase/1.5.0/docs/api/Java/lang/ref/WeakReference.html
Principe:weak reference
est lié à la récupération de place. Normalement, un objet ayant une ou plusieurs variables reference
ne sera pas éligible pour la récupération de place.
Le principe ci-dessus n'est pas applicable quand il s'agit de weak reference
. Si un objet n'a qu'une référence faible avec d'autres objets, il est alors prêt pour la récupération de place.
Regardons l'exemple ci-dessous: Nous avons une Map
avec des objets où Key est la référence d'un objet.
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());
}
}
Maintenant, pendant l'exécution du programme, nous avons créé emp = null
. La Map
détenant la clé n'a pas de sens ici car elle est null
. Dans la situation ci-dessus, l'objet n'est pas récupéré.
WeakHashMap
WeakHashMap
est un endroit où les entrées (key-to-value mappings
) seront supprimées lorsqu'il ne sera plus possible de les récupérer à partir de Map
.
Me laisser montrer l'exemple ci-dessus même avec WeakHashMap
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());
}
}
Sortie: Il a fallu 20 calls to System.gc()
pour générer aMap size
sur: 0.
WeakHashMap
n'a que des références faibles aux clés, pas des références fortes comme les autres classes Map
. Certaines situations doivent être prises en compte lorsque la valeur ou la clé est fortement référencée bien que vous ayez utilisé WeakHashMap
. Cela peut être évité en encapsulant l'objet dans un WeakReference.
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");
}
}
Références molles.
Soft Reference
est légèrement plus fort que la référence faible. La référence souple permet la récupération de place, mais demande au récupérateur de place de l'effacer seulement 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 pour les objets faiblement accessibles. Il ne collecte les objets accessibles que s'il a réellement besoin de la mémoire. Les références symboliques sont un moyen de dire au ramasse-miettes: "Tant que la mémoire n'est pas trop étroite, j'aimerais conserver cet objet. Mais si la mémoire devient trop petite, allez-y, récupérez-la et je traiterai avec ça." Le ramasse-miettes est nécessaire pour effacer toutes les références logicielles avant de pouvoir lancer OutOfMemoryError
.
La seule vraie différence entre une référence souple et une référence faible est que
le ramasse-miettes utilise des algorithmes pour décider si récupérer un objet facilement accessible, mais récupère toujours un objet faible objet accessible.
SoftReference
est conçu pour les caches. Lorsqu'il est constaté qu'une WeakReference
fait référence à un objet 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 disponible 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 pendant autant de secondes qu'il reste des mégaoctets de mémoire libre sur le segment de mémoire Java (configurable, le serveur HotSpot configurable vérifie le segment de mémoire maximal possible défini par -Xmx
). SoftReference
s sera effacé avant que OutOfMemoryError
ne soit lancé, à moins que vous ne puissiez l'atteindre.
Par le doc , desserrez WeakReferences must par un GC en cours d'exécution.
Pour le doc , les SoftReferences en vrac doivent être effacés 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 SoftReferences sont utiles. Les caches sensibles à la mémoire utilisent SoftReferences, pas WeakReferences .
weak_ref.get()
. Quand c'est null
, vous apprenez qu'entre cette durée, le GC s'est exécuté.En ce qui concerne incorrect utilisation de WeakReference, la liste est sans fin:
un bidouillage médiocre pour implémenter une priorité de priorité 2 telle que vous n'avez pas à en écrire un, encore _ cela ne fonctionne pas comme prévu car le cache serait effacé à la toutes exécution du GC , même quand il y a de la mémoire disponible. Voir https://stackoverflow.com/a/3243242/632951 pour les phails. (En outre, si vous avez besoin de plus de 2 niveaux de priorité de cache? Vous aurez toujours besoin d'une vraie bibliothèque pour cela.)
un bidouillage moche pour associer des données à un objet d'une classe existante, encore il crée une fuite de mémoire (OutOfMemoryError) lorsque votre GC décide de faire une pause après la création de vos références faibles. En outre, cela va au-delà de laide: une meilleure approche consiste à utiliser des n-uplets.
un bidouillage moche pour associer des données à un objet d'une classe existante, où la classe a le courage de se rendre non-sous-classable, et est utilisée dans un code de fonction existant que vous devez appeler. Dans ce cas, la solution appropriée consiste à éditer la classe et à la rendre sous-classable, ou à éditer la fonction et à lui faire prendre une interface au lieu d'une classe, ou d'utiliser une fonction alternative.
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 avez uniquement faibles références à un objet (sans références fortes), l'objet sera récupéré par GC au cours du prochain cycle de GC.
Si vous ne disposez que de soft references à un objet (sans références fortes), l'objet ne sera récupéré par GC que lorsque la JVM sera à court de mémoire.
Donc, vous pouvez dire que, les références fortes ont pouvoir ultime (ne peut jamais être collecté par GC)
Les références logicielles sont puissantes que les références faibles (car elles peuvent échapper au cycle GC jusqu'à ce que la JVM manque de mémoire)
Les références faibles sont même moins puissantes que les références souples (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).
Analogie au restaurant
Maintenant, si vous êtes un {client fort} _ (analogue à une référence forte), alors même si un nouveau client arrive dans le restaurant ou quoi que ce soit, vous ne quitterez jamais votre table (la zone de mémoire sur le tas). Le serveur n'a pas le droit de vous dire (ou même de vous demander) de quitter le restaurant.
Si vous êtes un {client léger} _ (comme une référence virtuelle), si un nouveau client arrive dans le restaurant, le serveur ne vous demandera pas de quitter la table à moins qu'il ne reste plus de table vide pour accueillir le client. nouveau client. (En d'autres termes, le serveur vous demandera de quitter la table uniquement si un nouveau client intervient et s'il ne reste aucune autre table pour ce nouveau client)
Si vous êtes un {client faible} _ (analogue à une référence faible), le serveur peut, à sa guise, peut (à tout moment) vous demander de quitter le restaurant: P
Les six types d'états d'accessibilité d'objets en Java -
Pour plus de détails: https://www.artima.com/insidejvm/ed2/gc16.html «collapse
Pour donner un aspect d'utilisation de la mémoire en action, j'ai fait une expérience avec des références Fort, Doux, Faible et Fantôme sous une charge lourde avec des objets lourds en les conservant jusqu'à la fin du programme. Puis surveillait l'utilisation du segment de mémoire et le comportement de la GC . Ces métriques peuvent varier au cas par cas mais donnent certainement une compréhension de haut niveau. Vous trouverez ci-dessous les résultats.
Comportement de tas et de GC sous forte charge
Vous pouvez obtenir plus de détails graphiques, statistiques, observations pour cette expérience ici .
Sachez qu’un objet faiblement référencé ne sera collecté que s’il contient UNIQUEMENT des références faibles. S'il y a une seule référence forte, il ne sera pas collecté, peu importe le nombre de références faibles qu'il possède.
WeakReference : les objets qui ne sont que très faiblement référencés sont collectés à chaque cycle GC (mineur ou complet).
SoftReference : la collecte d'objets qui ne sont que faiblement référencés dépend de:
-XX: indicateur SoftRefLRUPolicyMSPerMB = N (la valeur par défaut est 1000, soit 1 seconde)
Quantité de mémoire libre dans le tas.
Exemple:
Ensuite, un objet référencé uniquement par SoftReference sera collecté si le dernier accès a été supérieur à 10 secondes.