Strong / Soft / Weak / Phantom Reference

  java.lang.ref库中的SoftReferenceWeakReferencePhantomReference提供了更灵活的垃圾回收方式,他们继承自抽象类Reference,按照引用的强度依次递减。

1. Strong Reference

  平时使用最多的就是强引用(Strong Reference),如:

  当对象可以通过强引用可及时,该对象就不会被垃圾回收。有时候强引用会显得“过强”,比如实现一个图像缓存,缓存中保存了对图像的引用,当图像不再使用时,如果缓存中还保存了对该图像的强引用,图像就不会被垃圾回收,需要手动断开缓存中的引用。

2. WeakReference

  弱引用(WeakReference)不会强制对象留存在内存中,当对象只能通过弱引用可及时,对象就可以被垃圾回收。可以通过下面的方式建立弱引用:

然后就可以通过w.get()获取引用。如果w.get()返回了null,就说明对象被垃圾回收了。

  Weak Reference常用于实现规范映射(Canonicalized Mapping),每一个值只有一个实例,当程序需要某个值时,就会查询并返回该值得实例,不会创建新的实例,从而节省了存储空间。Java内置了WeakHashMap,其中的键使用了弱引用,当键成为垃圾时,整个条目就会被删除。

3. SoftReference

  软引用(SoftReference)和弱引用类似,但更倾向于保留对象。只能被弱引用可及的对象会在下一次垃圾回收中被丢弃;只能被软引用可及的对象一般会多保留一段时间,通常是在急需内存时才被回收。软引用适合用于缓存,由垃圾回收机制决定对象是否可及,以及在何时被回收。

4. PhantomReference

  虚引用(PhantomReference)对对象的引用更加弱,PhantomReferenceget()始终返回null,无法通过虚引用来获取对象。虚引用只能和ReferenceQueue一起使用。

5. ReferenceQueue

  垃圾回收器可以在对象的可及性发生特定的改变时,把对象的引用加入到ReferenceQueue。ReferenceQueue可以记录被回收对象的引用。

  如果在WeakReference的构造器中指定一个ReferenceQueue,那么当该WeakReference指向的对象变为垃圾时,该对象就会被自动加入到所指定的ReferenceQueue中,之后就可以通过这个ReferenceQueue来为死引用(Dead Reference)进行清理工作。

  也可以为PhantomReference的构造器中指定一个ReferenceQueue,这里与上面使用WeakReference的区别在于入队的时机。WeakReference会在对象只能被弱引用可及时立即入队,这发生在finalize()和垃圾回收之前,这时如果再为对象建立一个强引用,就可以防止对象被回收(这是很不规范的做法)。而PhantomReference只会在对象被从内存上移除后入队,PhantomReferenceget()始终返回null,也就防止了把对象从垃圾回收中“挽救”回来的行为。

  PhantomReference可以用于判断对象被从内存上移除的时刻,如在操作体积巨大的类的时候,可以在一个类被实际从内存上移除后,再加载新的类,避免内存不足的情况。PhantomReference还阻止了在finalize()为即将被回收的对象建立强引用、从而妨碍对象被回收的行为。

6. 用例

  下面是一个来自Thinking in Java中Containers in Depth一章的例子。

1 Comment

  1. QQ651018067

    博客不错,嘎嘎!

Comments are closed.