第一次接触到弱引用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的下一个回收周期销毁.
有一个WeakHashMap
和HashMap
几乎一样, 唯一的区别就是它的键(key)使用WeakReference
引用, 当它里面的某个key被标记为垃圾时, 对应的这个Entry
就被自动移除了
软引用(SoftReference
)比弱引用稍微强一些, 当内存不足时(即将OutOfMemory
)垃圾回收器才会回收这些软引用可到达的对象.
虚引用(PhantomReference)指向的对象十分脆弱,我们不能用get方法来得到其指向的对象(get总返回null
).
它的唯一作用就是当其指向的对象被回收之后,自己被加入到引用队列,用作记录该引用指向的对象已被销毁。
各种引用的父类Reference
中有个字段queue
, 它就是引用队列ReferenceQueue
.
一旦弱引用对象开始返回null
, 该引用指向的对象就被标记成了垃圾.
当构造时传入一个ReferenceQueue
对象, 则当引用只想的对象被标记为垃圾时, 这个引用对象会自动地加入到引用队列里面.
我们可以处理传入的引用队列来主动清理一些已经不用的引用.
软引用和弱引用被放入引用队列时, 并不能保证此时引用对象已经被销毁了(对象可以在finalize
方法里再生), 虚引用放入引用队列时, 可保证引用对象已经被销毁了.