從 JDK1.2 版本開始忠蝗,把對象的引用分為四種級別摄咆,從而使程序能更加靈活的控制對象的生命周期誓琼。這四種級別由高到低依次為:
- 強引用 StrongReference
- 軟引用 SoftReference
- 弱引用 WeakReference
- 虛引用 PhantomReference
Android 中采用了標注與清理(Mark and Sweep)回收算法:
從”GC Roots” 集合開始晌缘,將內(nèi)存整個遍歷一次长捧,保留所有可以被 GC Roots 直接或間接引用到的對象晦闰,而剩下的對象都當作垃圾對待并回收放祟。
在 Android 中,每一個應用程序對應有一個單獨的 Dalvik 虛擬機實例呻右,而每一個 Dalvik 虛擬機的大小是固定的(如 32M跪妥,可以通過ActivityManager.getMemoryClass()獲得)。這意味著我們可以使用的內(nèi)存不是無節(jié)制的声滥。所以即使有著 GC 幫助我們回收無用內(nèi)存眉撵,還是需要在開發(fā)過程中注意對內(nèi)存的引用。否則,就會導致內(nèi)存泄露执桌。
強引用 StrongReference
強引用是使用最普遍的引用鄙皇。如果一個對象具有強引用,那垃圾回收器絕不會回收它仰挣。當內(nèi)存空間不足伴逸,Java 虛擬機寧愿拋出 OutOfMemoryError 錯誤,使程序異常終止膘壶,也不會靠隨意回收具有強引用的對象來解決內(nèi)存不足的問題错蝴。如代碼 String s=”abc” 中變量 s 就是字符串對象”abc” 的一個強引用。只要你給強引用對象 s 賦空值 null, 該對象就可以被垃圾回收器回收颓芭。因為該對象此時不再含有其他強引用顷锰。
弱引用 WeakReference
弱引用通過類 WeakReference 來表示。弱引用并不能阻止垃圾回收亡问。如果使用一個強引用的話官紫,只要該引用存在,那么被引用的對象是不能被回收的州藕。弱引用則沒有這個問題束世。在垃圾回收器運行的時候,如果對一個對象的所有引用都是弱引用的話床玻,該對象會被回收毁涉。
軟引用 SoftReference
弱引用和軟引用的區(qū)別在于:如果一個對象只具有軟引用,若內(nèi)存空間足夠锈死,垃圾回收器就不會回收它贫堰;如果內(nèi)存空間不足了,才會回收這些對象的內(nèi)存待牵。
而只具有弱引用的對象擁有更短暫的生命周期其屏。在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對象缨该,不管當前內(nèi)存空間足夠與否漫玄,都會回收它的內(nèi)存。
所以從引用的強度來講: 強引用 > 軟引用 > 弱引用压彭。
虛引用 PhantomReference
一個只被虛引用持有的對象可能會在任何時候被 GC 回收。虛引用對對象的生存周期完全沒有影響渗常,也無法通過虛引用來獲取對象實例壮不,僅僅能在對象被回收時,得到一個系統(tǒng)通知(只能通過是否被加入到 ReferenceQueue 來判斷是否被 GC皱碘,這也是唯一判斷對象是否被 GC 的途徑)询一。
我們都知道,java 的 Object 類里面有個 finalize 方法,它的工作原理是這樣的:一旦垃圾回收器準備好釋放對象占用的內(nèi)存空間健蕊,將首先調用其 finalize 方法菱阵,并且在下一次垃圾回收動作發(fā)生時,才會真正回收對象占用的內(nèi)存缩功。但是晴及,問題在于,虛擬機不能保證 finalize 何時被調用嫡锌,因為 GC 的運行時間是不固定的虑稼。
使用虛引用就可以解決這個問題,虛引用主要用來跟蹤對象被垃圾回收的活動势木,主要用來實現(xiàn)比較精細的內(nèi)存使用控制蛛倦,這對于 Android 設備來說是很有意義的。比如啦桌,我們可以在確定一個 Bitmap 被回收后溯壶,再去申請另外一個 Bitmap 的內(nèi)存,通過這種方式可以使得程序所消耗的內(nèi)存維持在一個相對較低且穩(wěn)定的水平甫男。