简介
在JAVA中我们平时使用的引用方式叫做强引用。其实在JAVA.Lang.ref包下还定义了SoftReference、WeakReference和PhantomReference三种引用。这几种引用依次减弱这个“弱”指的是,当GC来的时候,它更容易被回收。
可达性定义
为了正确的理解和使用这三种引用,理解他们的可达性非常重要。
强可达:从根节点,至少有一个强引用路径可达。并且没有其他三种引用。
软可达:强引用不可达。从根节点,至少有一个软引用路径可达,并且没有弱和虚引用。
弱可达:强引用、软引用皆不可达。从根节点,至少有一个弱引用路径可达,并且没有虚引用。
虚可达:强、软、弱引用皆不可达。有虚引用且被finalized。
软引用
当感觉内存可能有压力的时候可以使用软引用。但是并不鼓励使用软引用来做缓存,因为RunTime并没有足够的信息来判断哪个引用该clear哪个该keep。更致命的是,它也不知道如何在clear软引用和增大Heap之间做出选择。clear次数太频繁增加CPU负担,clear的太晚又浪费内存。所以建议使用android.util.LruCache替代软引用。
GC在清除软引用时是 as late as possible的,也就是在OOM之前才试图清除它。如果SoftReference关联了一个ReferenceQueue,当GC清除掉这个软引用时会捎带着吧它enqueue到这个queue里。
弱引用
在实现一个自动回收的Map时,弱引用非常有用。
另外弱引用被GC回收的策略是as soon as,也就是一旦它是弱可达,当GC来时,它就会被清除。它也可以通过构造函数来关联ReferenceQueue。
虚引用
ReferenceQueue的用处
当软可及对象被回收之后,虽然这个SoftReference对象的get()方法返回null,但这个SoftReference对象已经不再具有存在的价值,需要一个适当的清除机制,避免大量SoftReference对象带来的内存泄漏。所以当对象的get()方法返回null的时候,也就是VM将这个软引用回收了,回收之后VM就会把它放入Queue中,然后我们可以通过调用Queue的poll方法把这个软引用取出来做进一步处理。