Cet article présente principalement des informations pertinentes sur l'explication détaillée de l'utilisation de la référence en Java. Les amis qui en ont besoin peuvent se référer à
Explication détaillée de la référence Java
dans jdk. 1.2 et ses versions ultérieures, les quatre concepts de référence forte , de référence douce, de référence faible et de référence virtuelle ont été introduits. Il existe de nombreuses explications sur ces quatre concepts sur Internet, mais la plupart d'entre elles sont conceptuelles et générales. Aujourd'hui, je les ai analysées sur la base du code. Examinons d'abord la définition et l'explication générale (les types de référence sont dans le package Java.lang.ref).
1. Référence forte (StrongReference)
La référence forte ne sera pas recyclée par GC et il n'y a pas de type correspondant réel dans java.lang.ref. Par exemple :
Object obj = new Object();
La référence obj ici est une référence forte et ne sera pas recyclée par GC.
2. Référence Soft
La référence Soft ne sera recyclée par GC que lorsque la JVM signalera une mémoire insuffisante, sinon elle ne sera pas recyclée précisément à cause de cela. Les références logicielles de fonctionnalités sont largement utilisées dans la mise en cache et le pooling. Utilisation de la référence douce :
Object obj = new Object(); SoftReference<Object> softRef = new SoftReference(obj); // 使用 softRef.get() 获取软引用所引用的对象 Object objg = softRef.get();
3. Référence faible (WeakReference)
Lorsque GC découvre un objet de référence faible, l'objet référencé par WeakReference sera libéré. L’usage des références faibles est similaire aux références douces, mais la stratégie de recyclage est différente.
4. Référence fantôme (PhantomReference)
Une fois que le GC découvre l'objet de référence virtuel, il insérera l'objet PhantomReference dans la file d'attente ReferenceQueue . À l'heure actuelle, l'objet pointé par PhantomReference n'a pas été recyclé par le GC, mais ne sera pas recyclé tant que ReferenceQueue n'aura pas été réellement traité par vous. Utilisation de références virtuelles :
Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue); // 调用phanRef.get()不管在什么情况下会一直返回null Object objg = phanRef.get(); // 如果obj被置为null,当GC发现了虚引用,GC会将phanRef插入进我们之前创建时传入的refQueue队列 // 注意,此时phanRef所引用的obj对象,并没有被GC回收,在我们显式地调用refQueue.poll返回phanRef之后 // 当GC第二次发现虚引用,而此时JVM将phanRef插入到refQueue会插入失败,此时GC才会对obj进行回收 Reference<? extends Object> phanRefP = refQueue.poll();
Après avoir lu la définition simple, nous avons combiné le code pour le tester. Inutile de dire que les références fortes sont également décrites dans les références logicielles. Il est clair que la clé est la « référence faible » et la « référence virtuelle ».
Référence faible :
public static void main(String[] args) throws InterruptedException { Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); WeakReference<Object> weakRef = new WeakReference<Object>(obj, refQueue); System.out.println(weakRef.get()); System.out.println(refQueue.poll()); obj = null; System.gc(); System.out.println(weakRef.get()); System.out.println(refQueue.poll()); }
Puisque System.gc() indique à la JVM que c'est le bon moment pour exécute GC , mais l'exécution spécifique est décidée par la JVM, donc lorsque la JVM décide d'exécuter GC, le résultat est (en fait, ce code exécutera généralement GC) :
java.lang.Object@de6ced null null java.lang.ref.WeakReference@1fb8ee3
D'après les résultats de l'exécution, nous savons qu'en appelant faibleRef.get() nous obtenons l'objet obj. Puisque GC n'est pas exécuté, refQueue.poll() renvoie null Lorsque nous définissons obj = null ; référence pointant vers le tas. L'objet obj. Ici, la JVM a effectué un GC. Nous avons constaté que null a été renvoyé via faibleRef.get(), et refQueue.poll() a renvoyé l'objet WeakReference. obj après l'avoir recyclé dans la file d'attente refQueue.
Référence factice :
public static void main(String[] args) throws InterruptedException { Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue); System.out.println(phanRef.get()); System.out.println(refQueue.poll()); obj = null; System.gc(); System.out.println(phanRef.get()); System.out.println(refQueue.poll()); }
De même, lorsque la JVM exécute GC, le résultat est :
null null null java.lang.ref.PhantomReference@1fb8ee3
D'après les résultats de l'exécution, nous savons que ce que nous avons dit précédemment est correct. phanRef.get() retournera null quelles que soient les circonstances. Lorsque la JVM exécute GC, elle trouve. que le virtuel Après la référence, la JVM ne recycle pas l'objet PhantomReference, mais insère l'objet PhantomReference dans la file d'attente de référence virtuelle correspondante refQueue. Lors de l'appel de refQueue.poll() pour renvoyer l'objet PhantomReference, la méthode d'interrogation mettra d'abord en file d'attente la file d'attente de maintien de PhantomReference. (ReferenceQueue< ? super T>) est défini sur NULL, l'objet NULL hérite de de ReferenceQueue et la méthode enqueue(Reference paramReference) est remplacée par return false, et à ce moment obj est à nouveau Lorsqu'il est découvert par le GC, la JVM insère PhantomReference dans la file d'attente NULL et renvoie false si l'insertion échoue. À ce moment, le GC recyclera obj. En fait, grâce à ce code, on ne peut pas dire si obj est recyclé, mais il y a une phrase dans le javadoc commentaire de PhantomReference qui dit :
Une fois la poubelle Le collecteur décide qu'un objet obj est fantôme-reachable, il est mis en file d'attente dans la file d'attente correspondante, mais son référent n'est pas effacéc'est-à-dire la file d'attente de référence de la référence fantôme. doit être explicitement traité par un code d'application.
Traduction (cette phrase est très simple, je pense que beaucoup de gens devraient la comprendre) :
Une fois que le GC décide qu'un "obj" est virtuel accessible, il (faisant référence à PhantomReference) sera mis en file d'attente dans la file d'attente correspondante, mais sa référence n'a pas été effacée. Autrement dit, la file d’attente des références virtuelles doit être explicitement gérée par un code d’application.
L'utilisation de références faibles et de références virtuelles
软引用很明显可以用来制作caching和pooling,而弱引用与虚引用呢?其实用处也很大,首先我们来看看弱引用,举个例子:
class Registry { private Set registeredObjects = new HashSet(); public void register(Object object) { registeredObjects.add( object ); } }
所有我添加进 registeredObjects 中的object永远不会被GC回收,因为这里有个强引用保存在registeredObjects里,另一方面如果我把代码改为如下:
class Registry { private Set registeredObjects = new HashSet(); public void register(Object object) { registeredObjects.add( new WeakReference(object) ); } }
现在如果GC想要回收registeredObjects中的object,便能够实现了,同样在使用HashMap如果想实现如上的效果,一种更好的实现是使用WeakHashMap。
而虚引用呢?我们先来看看javadoc的部分说明:
Phantom references are useful for implementing cleanup operations that are necessary before an object gets garbage-collected. They are sometimes more flexible than the finalize() method.
翻译一下:
虚引用在实现一个对象被回收之前必须做清理操作是很有用的。有时候,他们比finalize()方法更灵活。
很明显的,虚引用可以用来做对象被回收之前的清理工作。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!