Explication détaillée des quatre types de référence de Java (référence forte, référence logicielle, référence faible, référence virtuelle liée)

Après JDK1.2, Java a élargi le concept de références et a divisé les références en quatre types : référence forte, référence douce, référence faible et référence fantôme. Les quatre citations sont d'intensité décroissante. (Pour plus de détails, voir : Quatre types de référence en Java)

1. Référence forte (StrongReference)
La référence forte est la référence la plus couramment utilisée. Si un objet a une référence forte, le garbage collector ne le récupérera jamais. Lorsque l'espace mémoire est insuffisant, la machine virtuelle Java préfère générer une erreur OutOfMemoryError et provoquer la fin anormale du programme, plutôt que de recycler arbitrairement des objets avec des références fortes pour résoudre le problème de mémoire insuffisante. ps : Une référence forte signifie en fait ce que nous entendons habituellement par A a = new A().
2. Référence logicielle (SoftReference)
Si un objet n'a qu'une référence logicielle, l'espace mémoire est suffisant et le ramasse-miettes ne le récupérera pas ; si l'espace mémoire est insuffisant, la mémoire de ces objets sera récupérée. Tant que le garbage collector ne le récupère pas, l'objet peut être utilisé par le programme. Les références logicielles peuvent être utilisées pour implémenter une mise en cache sensible à la mémoire (un exemple est donné ci-dessous).
Les références logicielles peuvent être utilisées conjointement avec une file d'attente de références (ReferenceQueue). Si l'objet référencé par la référence logicielle est recyclé par le ramasse-miettes, la machine virtuelle Java ajoutera la référence logicielle à la file d'attente de références qui lui est associée.
3. Référence faible
La différence entre une référence faible et une référence souple est que les objets avec uniquement des références faibles ont un cycle de vie plus court. Au cours du processus d'analyse par le thread du ramasse-miettes de la zone mémoire sous sa juridiction, une fois qu'un objet avec uniquement des références faibles est trouvé, sa mémoire sera récupérée, que l'espace mémoire actuel soit suffisant ou non. Cependant, comme le garbage collector est un thread de très faible priorité, il ne trouvera pas nécessairement rapidement les objets avec uniquement des références faibles.
Les références faibles peuvent être utilisées conjointement avec une file d'attente de référence (ReferenceQueue). Si l'objet référencé par la référence faible est récupéré, la machine virtuelle Java ajoutera la référence faible à la file d'attente de référence associée.
4.PhantomRéférence
"Référence virtuelle", comme son nom l'indique, n'a que le nom. Contrairement à d'autres types de références, les références virtuelles ne déterminent pas le cycle de vie de l'objet. Si un objet ne contient que des références fantômes, il peut alors être récupéré par le ramasse-miettes à tout moment comme s'il n'avait aucune référence.
Les références virtuelles sont principalement utilisées pour suivre l'activité des objets recyclés par le garbage collector. Une différence entre les références virtuelles, les références logicielles et les références faibles est que les références virtuelles doivent être utilisées conjointement avec une file d'attente de références (ReferenceQueue). Lorsque le garbage collector se prépare à recycler un objet, s'il constate qu'il possède encore une référence virtuelle, il ajoutera la référence virtuelle à la file d'attente de références qui lui est associée avant de recycler la mémoire de l'objet.

Chaque type de référence est expliqué en détail ci-dessous.

1. Référence forte (StrongReference)

Caractéristiques des citations fortes :

  • 1. Des références fortes peuvent accéder directement à l’objet cible ;
  • 2. L'objet pointé par le verrou de référence puissant ne sera à aucun moment recyclé par le système. La JVM préfère lever une exception MOO plutôt que de récupérer l'objet pointé par une référence forte ;
  • 3. Des applications puissantes peuvent provoquer des fuites de mémoire ;

Exemples d'utilisation :

String str= new String("bonjour");

La variable str pointe vers l'espace de tas où se trouve l'instance StringBuffer, et l'objet peut être exploité via str.

2.SoftRéférence

Les références souples sont le type de référence le plus fort en dehors des références fortes. Il est utilisé pour décrire certains objets utiles mais pas nécessaires. Pour les objets associés à des références logicielles, ces objets seront inclus dans la portée de recyclage pour le deuxième recyclage avant qu'une exception de dépassement de mémoire ne se produise dans le système. S'il n'y a pas assez de mémoire pour ce recyclage, une exception de dépassement de mémoire sera levée.

Les références logicielles peuvent être utilisées via java.lang.ref.SoftReference. Un objet contenant une référence logicielle ne sera pas recyclé rapidement par la JVM. La JVM déterminera quand le collecter en fonction de l'utilisation actuelle du tas. Lorsque l'utilisation du tas approche du seuil, les objets de référence logiciels seront recyclés. Par conséquent, les références logicielles peuvent être utilisées pour implémenter des caches sensibles à la mémoire.

La particularité de SoftReference est qu'une de ses instances enregistre une référence logicielle à un objet Java. L'existence de la référence logicielle n'empêche pas le thread de garbage collection de recycler l'objet Java. Autrement dit, une fois que SoftReference enregistre une référence logicielle à un objet Java, avant que le thread de récupération ne recycle l'objet Java, la méthode get() fournie par la classe SoftReference renvoie une référence forte à l'objet Java. Une fois que le thread poubelle a collecté l'objet Java, la méthode get() renverra null.

Exemples d'utilisation :

Object obj = new Object();
SoftReference sf = new SoftReference<>(obj);
obj = null;
System.gc();

3. Référence faible (WeakReference)

Une référence faible est un type de référence plus faible qu’une référence souple. Pendant le GC du système, tant qu'une référence faible est trouvée, l'objet sera recyclé, que l'espace du tas du système soit suffisant ou non. En Java, vous pouvez utiliser l'instance java.lang.ref.WeakReference pour enregistrer une référence faible à un objet Java.

Exemple d'utilisation 1 :

Object obj = new Object ();
WeakReference sf = new WeakReference(obj);
obj = null;

Exemple d'utilisation 2 :

Dans le code source du JDK, ThreadLoaclMap.Entry (pour plus de détails, voir : Causes des fuites de mémoire causées par ThreadLoacl )

Insérer la description de l'image ici

Les références logicielles et les références faibles sont très appropriées pour sauvegarder les données de cache inutiles. Si vous faites cela, lorsque la mémoire système est insuffisante, ces données de cache seront recyclées sans provoquer de débordement de mémoire. Lorsque les ressources mémoire sont suffisantes, ces données mises en cache peuvent exister pendant une longue période, accélérant ainsi le système.

4.PhantomRéférence

Les références virtuelles sont les plus faibles de tous les types. Un objet contenant une référence virtuelle équivaut presque à n'avoir aucune référence et peut être recyclé par le ramasse-miettes à tout moment. Lorsque vous essayez d'obtenir une référence forte via la méthode get() d'une référence virtuelle, cela échoue toujours. De plus, les références virtuelles doivent être utilisées avec la file d'attente de références, qui est utilisée pour suivre le processus de garbage collection.

Lorsque le garbage collector se prépare à recycler un objet, s'il constate qu'il a encore une référence virtuelle, il détruira l'objet après le garbage collection et ajoutera la référence virtuelle à la file d'attente de référence. Le programme peut savoir si l'objet référencé sera récupéré en déterminant si une référence virtuelle a été ajoutée à la file d'attente de références. Si le programme découvre qu'une référence virtuelle a été ajoutée à la file d'attente de références, il peut prendre les mesures nécessaires avant que la mémoire de l'objet référencé ne soit récupérée.

Exemples d'utilisation :

Object obj = new Object ();
ReferenceQueue referenceQueue = new ReferenceQueue<>();
PhantomReference pr = new PhantomReference<>(obj,referenceQueue);
obj = null;

À propos de l'extension de la classe WeakHashMap

La classe WeakHashMap se trouve dans le package java.util. Elle implémente l'interface Map et est une implémentation de HashMap. Elle utilise des références faibles comme solution de stockage pour les données internes. WeakHashMap est une application typique de références faibles et peut être utilisée comme une simple solution de table de cache.

Les deux morceaux de code suivants utilisent respectivement WeakHashMap et HashMap pour enregistrer une grande quantité de données :

public void test(){
    
    
    Map weakHashMap= new WeakHashMap();
    for (int i =0;i<10000;i++){
    
    
    	weakHashMap.put("key"+i,new byte[i]);
	}
}

Remarque : Si les clés de WeakHashMap contiennent des références fortes dans le système, alors WeakHashMap dégénérera en un HashMap ordinaire car toutes les entrées ne peuvent pas être automatiquement nettoyées.

Source originale : https://zhuanlan.zhihu.com/p/57452267

おすすめ

転載: blog.csdn.net/weixin_43828467/article/details/115397718