JDK 中除了默認的 Strong Reference 之外,還有三個其他的 Reference:
WeakReference
SoftReference
PhantomReference
他們都是為了更高效地利用 Heap。
如果一個變量的 Reference 只剩下WeakReference,那么 GC 會毫不留情地把這個變量回收掉。也就是說,WeakReference沒有能力能夠讓這個變量可以在內存中再飛一會。
Android開發者應該都了解WeakReference的用法,一個比較典型的應用場景是Handler,為了避免 Memory Leak,我們會定義一個內部靜態類,然后以WeakReference的形式引用Activity,這樣一來,隊列中的Message(可能會排隊很長時間)就不會干擾到 GC 回收Activity。
從SoftReference 的官方定義來看,只有當內存告急(即將 OOM)時,才會對只剩下 Soft Reference 的變量進行回收,因此 SoftReference 比較適合用來做 Cache:
Soft references are most often used to implement memory-sensitive caches.
但是SoftReference 的 Android 版本對此持不同意見:
In practice, soft references are inefficient for caching.
因為 SoftReference 無法提供足夠的信息可以讓 runtime 很輕松地決定 clear 它還是 keep 它。舉個例子,如果有 10 個 SoftReference 變量,并且他們所引用的變量都沒有了 Strong Reference,那么 runtime 就懵逼了,因為它不知道該 clear 哪幾個或者 keep 哪幾個。更要命的是,runtime 不知道應該是 clear 掉 SoftReference 還是增大 Heap。
所以android放棄了SoftReference,推薦使用android.util.LruCache做 Cache 管理,至少LruCache可以根據變量的使用頻次來決定是否應該 clear 掉它,這樣就比單純使用SoftReference多了一個決策條件 - 使用頻次。