2016年7月26日 星期二

使用軟引用(SoftReference)導致物件莫名被回收的例子

在研究在android 中使用pdfbox, 查看原始碼的時候, 發現一個怪現象,
有一個的map的物件, 是用來cache字型的的地方, 但很奇怪它裡面的
字型資料, 總是只能保存大約三種, 第四種字型讀進來時, 就會清除
其中一種, 導致cahce的字型幾乎沒沒什麼作用, 因為每次取用字型時,
都不能從cache讀取, 而是要從檔案讀取, 後來看了原始碼才發現, 其
中PDFont這個物件被定義成SoftReference了.


參考軟引用與其他幾個引用的說明:
(來源:http://www.cnblogs.com/skywang12345/p/3154474.html)

強引用(StrongReference)
    強引用是使用最普遍的引用。如果一個對象具有強引用,那垃圾回收器絕不會回收它。當內存空間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內存不足的問題。


軟引用(SoftReference)
    如果一個對像只具有軟引用,則內存空間足夠,垃圾回收器就不會回收它;如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存。

弱引用(WeakReference)

    弱引用與軟引用的區別在於:只具有弱引用的對象擁有更短暫的生命週期。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。不過,由於垃圾回收器是一個優先級很低的線程,因此不一定會很快發現那些只具有弱引用的對象。

虛引用(PhantomReference)

    “虛引用”顧名思義,就是形同虛設,與其他幾種引用都不同,虛引用並不會決定對象的生命週期。如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。



再看看pdfbox的原始碼


說明使用軟引用的原因: 當有記憶體壓力(不足)時, 才回收
/**
 * A resource cached based on SoftReference, retains resources until memory pressure causes them
 * to be garbage collected.
 */

public class DefaultResourceCache implements ResourceCache
{

//PDFont這個物件被定義成SoftReference了
    private final Map> fonts =
            new HashMap>();

但其所謂記憶體不足時, 才回收SoftReference的物件, 但我實際觀察ram的
變化情形, 例如每個app可使用96M的ram, 但當使用到50M左右,
SoftReference的物件就被回收了, 所以所謂的ram不足, 應不是指整個可用
的ram不足, 也許是一開始給的heap size 不足, 就導致回收發生了, 但據我
粗淺無知的理解, 當heap size不足時, app 會請求更大的 heapsize, 直到超
過app 的最大限制96M才會發出, out of memory.

所以使用SoftReference在我的app, 反而是個造成效率低下的原因了, 取消
SoftReference改成

    private final Map fonts =
            new HashMap();


一切cache的動作就正常了.


  © Blogger templates Psi by Ourblogtemplates.com 2008

Back to TOP