Strong / Soft / Weak / Phantom Reference
java.lang.ref
库中的SoftReference
、WeakReference
和PhantomReference
提供了更灵活的垃圾回收方式,他们继承自抽象类Reference
,按照引用的强度依次递减。
Contents
1. Strong Reference
平时使用最多的就是强引用(Strong Reference),如:
Random rand = new Random(47);
当对象可以通过强引用可及时,该对象就不会被垃圾回收。有时候强引用会显得“过强”,比如实现一个图像缓存,缓存中保存了对图像的引用,当图像不再使用时,如果缓存中还保存了对该图像的强引用,图像就不会被垃圾回收,需要手动断开缓存中的引用。
2. WeakReference
弱引用(WeakReference)不会强制对象留存在内存中,当对象只能通过弱引用可及时,对象就可以被垃圾回收。可以通过下面的方式建立弱引用:
WeakReference<VeryBig> w = new WeakReference<VeryBig>(new VeryBig("Weak"));
然后就可以通过w.get()
获取引用。如果w.get()
返回了null
,就说明对象被垃圾回收了。
Weak Reference常用于实现规范映射(Canonicalized Mapping),每一个值只有一个实例,当程序需要某个值时,就会查询并返回该值得实例,不会创建新的实例,从而节省了存储空间。Java内置了WeakHashMap
,其中的键使用了弱引用,当键成为垃圾时,整个条目就会被删除。
3. SoftReference
软引用(SoftReference)和弱引用类似,但更倾向于保留对象。只能被弱引用可及的对象会在下一次垃圾回收中被丢弃;只能被软引用可及的对象一般会多保留一段时间,通常是在急需内存时才被回收。软引用适合用于缓存,由垃圾回收机制决定对象是否可及,以及在何时被回收。
4. PhantomReference
虚引用(PhantomReference)对对象的引用更加弱,PhantomReference
的get()
始终返回null
,无法通过虚引用来获取对象。虚引用只能和ReferenceQueue
一起使用。
5. ReferenceQueue
垃圾回收器可以在对象的可及性发生特定的改变时,把对象的引用加入到ReferenceQueue。ReferenceQueue可以记录被回收对象的引用。
如果在WeakReference
的构造器中指定一个ReferenceQueue
,那么当该WeakReference
指向的对象变为垃圾时,该对象就会被自动加入到所指定的ReferenceQueue
中,之后就可以通过这个ReferenceQueue
来为死引用(Dead Reference)进行清理工作。
也可以为PhantomReference
的构造器中指定一个ReferenceQueue
,这里与上面使用WeakReference
的区别在于入队的时机。WeakReference
会在对象只能被弱引用可及时立即入队,这发生在finalize()
和垃圾回收之前,这时如果再为对象建立一个强引用,就可以防止对象被回收(这是很不规范的做法)。而PhantomReference
只会在对象被从内存上移除后入队,PhantomReference
的get()
始终返回null
,也就防止了把对象从垃圾回收中“挽救”回来的行为。
PhantomReference
可以用于判断对象被从内存上移除的时刻,如在操作体积巨大的类的时候,可以在一个类被实际从内存上移除后,再加载新的类,避免内存不足的情况。PhantomReference
还阻止了在finalize()
为即将被回收的对象建立强引用、从而妨碍对象被回收的行为。
6. 用例
下面是一个来自Thinking in Java中Containers in Depth一章的例子。
import java.lang.ref.*; import java.util.*; class VeryBig { private static final int SIZE = 10000; private long[] la = new long[SIZE]; private String ident; public VeryBig(String id) { ident = id; } public String toString() { return ident; } protected void finalize() { System.out.println("Finalizing " + ident); } } public class References { private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>(); public static void checkQueue() { Reference<? extends VeryBig> inq = rq.poll(); if(inq != null) System.out.println("In queue: " + inq.get()); } public static void main(String[] args) { int size = 10; // Or, choose size via the command line: if(args.length > 0) size = new Integer(args[0]); LinkedList<SoftReference<VeryBig>> sa = new LinkedList<SoftReference<VeryBig>>(); for(int i = 0; i < size; i++) { sa.add(new SoftReference<VeryBig>(new VeryBig("Soft " + i), rq)); System.out.println("Just created: " + sa.getLast()); checkQueue(); } LinkedList<WeakReference<VeryBig>> wa = new LinkedList<WeakReference<VeryBig>>(); for(int i = 0; i < size; i++) { wa.add(new WeakReference<VeryBig>(new VeryBig("Weak " + i), rq)); System.out.println("Just created: " + wa.getLast()); checkQueue(); } SoftReference<VeryBig> s = new SoftReference<VeryBig>(new VeryBig("Soft")); WeakReference<VeryBig> w = new WeakReference<VeryBig>(new VeryBig("Weak")); System.gc(); LinkedList<PhantomReference<VeryBig>> pa = new LinkedList<PhantomReference<VeryBig>>(); for(int i = 0; i < size; i++) { pa.add(new PhantomReference<VeryBig>(new VeryBig("Phantom " + i), rq)); System.out.println("Just created: " + pa.getLast()); checkQueue(); } } } /* Output from OS X 10.11 + JDK 8 Just created: java.lang.ref.SoftReference@60e53b93 Just created: java.lang.ref.SoftReference@5e2de80c Just created: java.lang.ref.SoftReference@1d44bcfa Just created: java.lang.ref.SoftReference@266474c2 Just created: java.lang.ref.SoftReference@6f94fa3e Just created: java.lang.ref.SoftReference@5e481248 Just created: java.lang.ref.SoftReference@66d3c617 Just created: java.lang.ref.SoftReference@63947c6b Just created: java.lang.ref.SoftReference@2b193f2d Just created: java.lang.ref.SoftReference@355da254 Just created: java.lang.ref.WeakReference@4dc63996 Just created: java.lang.ref.WeakReference@d716361 Just created: java.lang.ref.WeakReference@6ff3c5b5 Just created: java.lang.ref.WeakReference@3764951d Just created: java.lang.ref.WeakReference@4b1210ee Just created: java.lang.ref.WeakReference@4d7e1886 Just created: java.lang.ref.WeakReference@3cd1a2f1 Just created: java.lang.ref.WeakReference@2f0e140b Just created: java.lang.ref.WeakReference@7440e464 Just created: java.lang.ref.WeakReference@49476842 Just created: java.lang.ref.PhantomReference@78308db1 Finalizing Weak Finalizing Weak 9 Finalizing Weak 8 Finalizing Weak 7 Finalizing Weak 6 Finalizing Weak 5 Finalizing Weak 4 Finalizing Weak 3 Finalizing Weak 2 Finalizing Weak 1 Finalizing Weak 0 In queue: null Just created: java.lang.ref.PhantomReference@27c170f0 In queue: null Just created: java.lang.ref.PhantomReference@5451c3a8 In queue: null Just created: java.lang.ref.PhantomReference@2626b418 In queue: null Just created: java.lang.ref.PhantomReference@5a07e868 In queue: null Just created: java.lang.ref.PhantomReference@76ed5528 In queue: null Just created: java.lang.ref.PhantomReference@2c7b84de In queue: null Just created: java.lang.ref.PhantomReference@3fee733d In queue: null Just created: java.lang.ref.PhantomReference@5acf9800 In queue: null Just created: java.lang.ref.PhantomReference@4617c264 In queue: null */
博客不错,嘎嘎!