Il existe 4 types de références en Java : StrongReference, SoftReference, WeakReference et PhantomReference (la légendaire référence fantôme haha),
Ces quatre types de références sont étroitement liés à GC. Examinons leurs définitions et scénarios d'utilisation un par un :
1. Référence solide
StrongReference est l'implémentation de référence par défaut de Java. Elle survivra dans la JVM aussi longtemps que possible lorsqu'aucun objet ne pointe vers elle, elle sera recyclée après l'exécution du GC.
Code Java
Copiez le code comme suit :
@Test
public void strongReference() {
Référent d'objet = new Object();
/**
* Créer une StrongReference via une affectation
*/
Objet strongReference = référent ;
assertSame (référent, strongReference);
référent = nul ;
Système.gc();
/**
* StrongReference ne sera pas recyclé après GC
*/
assertNotNull(strongReference);
}
2. WeakRéférence et WeakHashMap
WeakReference, comme son nom l'indique, est une référence faible Lorsque l'objet référencé n'a plus de référence forte dans la JVM, la référence faible sera automatiquement recyclée après GC.
Copiez le code comme suit :
@Test
public void faibleRéférence() {
Référent d'objet = new Object();
WeakReference<Object> lowRerference = new WeakReference<Object>(référent);
assertSame(référent, faibleRerference.get());
référent = nul ;
Système.gc();
/**
* Une fois qu'il n'y a plus de référence forte pointant vers le référent, la référence faible sera automatiquement recyclée après GC
*/
assertNull(weakRerference.get());
}
WeakHashMap utilise WeakReference comme clé. Une fois qu'il n'y a pas de référence forte à la clé, WeakHashMap supprimera automatiquement l'entrée correspondante après GC.
Copiez le code comme suit :
@Test
public void lowHashMap() lance InterruptedException {
Map<Object, Object> lowHashMap = new WeakHashMap<Object, Object>();
Clé d'objet = new Object();
Valeur de l'objet = new Object();
faibleHashMap.put(clé, valeur);
assertTrue(weakHashMap.containsValue(value));
clé = nulle ;
Système.gc();
/**
* Attendez que les entrées non valides entrent dans ReferenceQueue afin qu'elles puissent être effacées lors du prochain appel de getTable
*/
Thread.sleep(1000);
/**
* Une fois qu'il n'y a plus de référence forte à la clé, WeakHashMap supprimera automatiquement l'entrée correspondante après GC
*/
assertFalse(weakHashMap.containsValue(value));
}
3.SoftRéférence
SoftReference a fondamentalement les mêmes caractéristiques que WeakReference. La plus grande différence est que SoftReference conservera la référence le plus longtemps possible jusqu'à ce que la JVM manque de mémoire avant de la recycler (garantie de la machine virtuelle). Cette fonctionnalité rend SoftReference très adapté aux applications de mise en cache.
Copiez le code comme suit :
@Test
public void softReference() {
Référent d'objet = new Object();
SoftReference<Object> softRerference = new SoftReference<Object>(référent);
assertNotNull(softRerference.get());
référent = nul ;
Système.gc();
/**
* les références logicielles ne seront recyclées qu'avant jvm OutOfMemory, elles sont donc très adaptées aux applications de mise en cache
*/
assertNotNull(softRerference.get());
}
4. Référence fantôme
En tant que protagoniste de cet article, Phantom Reference est très différent de WeakReference et SoftReference, car sa méthode get() renvoie toujours null, d'où son nom.
Code Java
Copiez le code comme suit :
@Test
public void phantomReferenceAlwaysNull() {
Référent d'objet = new Object();
PhantomReference<Object> phantomReference = new PhantomReference<Object>(référent, new ReferenceQueue<Object>());
/**
* La méthode get de référence fantôme renvoie toujours null
*/
assertNull(phantomReference.get());
}
Vous vous demandez peut-être à quoi sert une référence qui renvoie toujours null ? Veuillez faire attention au deuxième paramètre ReferenceQueue lors de la construction de PhantomReference (en fait, WeakReference & SoftReference peuvent également avoir ce paramètre).
La seule utilisation de PhantomReference est de suivre le moment où le référent est mis en file d'attente dans ReferenceQueue.
5. PertinenceQueue
Lorsqu'un WeakReference commence à renvoyer null, l'objet vers lequel il pointe est prêt à être recyclé. À ce stade, un travail de nettoyage approprié peut être effectué. Transmettez un ReferenceQueue au constructeur d'un Reference. Lorsque l'objet est recyclé, la machine virtuelle. sera automatiquement L'objet est inséré dans la ReferenceQueue. WeakHashMap utilise la ReferenceQueue pour effacer les entrées dont les clés n'ont plus de références fortes.
Code Java
Copiez le code comme suit :
@Test
public void referenceQueue() lance InterruptedException {
Référent d'objet = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
WeakReference<Object> lowReference = new WeakReference<Object>(référent, referenceQueue);
assertFalse(weakReference.isEnqueued());
Référence<? extends Object> interrogé = referenceQueue.poll();
assertNull(interrogé);
référent = nul ;
Système.gc();
assertTrue(weakReference.isEnqueued());
Référence <? extends Object> supprimé = referenceQueue.remove();
assertNotNull (supprimé);
}
6. PhantomReference vs WeakReference
PhantomReference a deux avantages. Premièrement, elle nous permet de savoir exactement quand l'objet est supprimé de la mémoire. Cette fonctionnalité peut être utilisée pour certains besoins particuliers (tels que Distributed GC, XWork et google-guice utilisent également PhantomReference pour effectuer un travail de nettoyage).
Deuxièmement, cela peut éviter certains problèmes fondamentaux causés par la finalisation. Comme mentionné ci-dessus, la seule fonction de PhantomReference est de suivre le moment où le référent est mis en file d'attente dans ReferenceQueue, mais WeakReference a également des fonctions correspondantes.
Il s'agit de la méthode finalize de Object.Cette méthode sera appelée avant l'exécution de gc.Si un objet surcharge la méthode finalize et crée délibérément une référence forte à lui-même dans la méthode, cela empêchera ce cycle de GC. recyclé. Cet objet peut provoquer n'importe quel GC. Le résultat final est qu'il y a beaucoup de déchets dans la JVM mais OutOfMemory. Ce problème peut être évité en utilisant PhantomReference, car PhantomReference est en cours de finalisation. Il est recyclé après l'exécution de la méthode, ce qui signifie qu'il est impossible d'obtenir la référence d'origine pour le moment, donc le problème ci-dessus ne se produira pas. Bien sûr, il s'agit d'un exemple très extrême et ne se produit généralement pas.
7. Comparaison
Références douces, faibles et fantômes | ||||
---|---|---|---|---|
Taper | But | Utiliser | Quand GCed | Classe de mise en œuvre |
Référence solide | Une référence ordinaire. Maintient les objets en vie tant qu'ils sont référencés. | référence normale. | Tout objet non pointé peut être récupéré. | défaut |
Référence logicielle | Maintient les objets en vie à condition qu'il y ait suffisamment de mémoire. | pour garder les objets en vie même après que les clients ont supprimé leurs références (caches sensibles à la mémoire), au cas où les clients recommenceraient à les demander par clé. | Après une première passe gc, la JVM décide qu'elle a encore besoin de récupérer plus d'espace. | java.lang.ref.SoftReference |
Faible référence | Maintient les objets en vie uniquement lorsqu'ils sont utilisés (accessibles) par les clients. | Conteneurs qui suppriment automatiquement les objets qui ne sont plus utilisés. | Après que gc ait déterminé que l'objet n'est que faiblement accessible | java.lang.ref.WeakReference java.util.WeakHashMap |
Référence fantôme | Vous permet de nettoyer après la finalisation mais avant que l'espace ne soit récupéré (remplace ou augmente l'utilisation de finalize()) | Traitement de nettoyage spécial | Après finalisation. | java.lang.ref.PhantomReference |
8. Résumé
Les applications générales n'impliqueront pas de programmation de référence, mais comprendre ces connaissances sera utile pour comprendre le principe de fonctionnement du GC et du réglage des performances. Elle peut également être utilisée lors de la mise en œuvre de certaines fonctionnalités de base telles que la mise en cache.