Java中的弱引用

第一次接触到弱引用WeakReference是在ThreadLocal中, 于是就把相关知识梳理了下



引用简介

引用跟垃圾回收相关, 关于引用的类位于java.long.ref包中, 他们的继承关系图如下(蓝色表示抽象类):

引用相关的类

按照他们阻止被回收的能力强弱可以分为: 强引用 > 软引用(SoftReference) > 弱引用(WeakReference) > 虚引用(PhantomReference)

强引用

就是我们平时使用的对象的引用, 比如:Object o = new Object(), 那个o就是一个强引用.
如果一个对象通过强引用链可到达, 它是不会被回收的, 不可达时才有可能被回收.

弱引用

先说下弱引用(WeakReference), 它阻止被回收的能力不太强, 由JVM决定何时回收. 可以这样创建一个弱引用对象: WeakReference<Object> weakObject = new WeakReference<Object>(o);, 通过weakObject.get()就可以得到引用的对象了.
因为弱引用不能阻止回收, 所以如果没有其他强引用指向这个对象时, 当使用get方法时说不准就返回null了.
如果一个对象是弱引用可到达, 那么这个对象会JVM的下一个回收周期销毁.
有一个WeakHashMapHashMap几乎一样, 唯一的区别就是它的键(key)使用WeakReference引用, 当它里面的某个key被标记为垃圾时, 对应的这个Entry就被自动移除了

软引用

软引用(SoftReference)比弱引用稍微强一些, 当内存不足时(即将OutOfMemory)垃圾回收器才会回收这些软引用可到达的对象.

虚引用

虚引用(PhantomReference)指向的对象十分脆弱,我们不能用get方法来得到其指向的对象(get总返回null).
它的唯一作用就是当其指向的对象被回收之后,自己被加入到引用队列,用作记录该引用指向的对象已被销毁。

引用队列

各种引用的父类Reference中有个字段queue, 它就是引用队列ReferenceQueue.
一旦弱引用对象开始返回null, 该引用指向的对象就被标记成了垃圾.
当构造时传入一个ReferenceQueue对象, 则当引用只想的对象被标记为垃圾时, 这个引用对象会自动地加入到引用队列里面.
我们可以处理传入的引用队列来主动清理一些已经不用的引用.
软引用和弱引用被放入引用队列时, 并不能保证此时引用对象已经被销毁了(对象可以在finalize方法里再生), 虚引用放入引用队列时, 可保证引用对象已经被销毁了.