強引用
Java中的引用,類似于C++的指針祠汇。通過引用熄诡,可以對堆中的對象進行操作凰浮。在某個函數(shù)中苇本,當創(chuàng)建了一個對象菜拓,該對象被分配在堆中,通過這個對象的引用才能對這個對象進行操作俺夕。
假設以上代碼是在方法內(nèi)運行的劝贸,那么局部變量str將被分配在椃∮猓空間上疙剑,而對象StringBuffer實例,被分配在堆空間中嚼蚀。局部變量str指向StringBuffer實例所在的堆空間管挟,通過str可以操作該實例,那么str就是StringBuffer的引用导帝。
此時您单,運行一個賦值語句:
那么荞雏,str所指向的對象也將被str1所指向凤优,同時在局部棧空間上會分配空間存放str1變量俺驶。此時挖垛,該StringBuffer實例就有兩個引用秉颗。對引用的”==”操作用于表示兩個操作數(shù)所指向的堆空間地址是否相同蚕甥,不表示兩個操作數(shù)所指向的對象是否相等栋荸。
強引用特點:
強引用可以直接訪問目標對象晌块。
強引用所指向的對象在任何時候都不會被系統(tǒng)回收。JVM寧愿拋出OOM異常呼伸,也不會回收強引用所指向的對象钝尸。
強引用可能導致內(nèi)存泄露珍促。
軟引用
軟引用是除了強引用外,最強的引用類型娇斩⊙妫可以通過java.lang.ref.SoftReference使用軟引用芒帕。一個持有軟引用的對象,不會被JVM很快回收,JVM會根據(jù)當前堆的使用情況來判斷何時回收基矮。當堆的使用率臨近閾值時,才會回收軟引用的對象本砰。 看下我工作中使用到軟引用的場景钢悲,加載一個1080x1920分辨率的圖,約900多K, 對于我們來說还棱,這個圖已是非常大了。
1.首先通過BitmapFactory.decodeStream構(gòu)造一個大圖bitmap
2.然后把這個bitmap轉(zhuǎn)成Drawble類型办铡,構(gòu)成強引用琳要。
3.接著使用SoftReference構(gòu)造這個drawable對象的軟引用drawables.
4.最后通過軟引用的get()方法,取得drawable對象實例的強引用童叠,發(fā)現(xiàn)對象被未回收课幕。在GC在內(nèi)存充足的情況下撰豺,不會回收軟引用對象。
在實際中亩歹,一起請求很多相關圖片凡橱,從網(wǎng)絡,這時就會請求非常多的內(nèi)存空間顾稀,導致內(nèi)存吃緊坝撑,系統(tǒng)開始會GC巡李。這次GC后,drawables.get()不再返回Drawable對象殊橙,而是返回null,這時屏幕上背景圖不顯示叠纹,說明在系統(tǒng)內(nèi)存緊張的情況下誉察,軟引用被回收制肮。
使用軟引用以后,在OutOfMemory異常發(fā)生之前综液,這些緩存的圖片資源的內(nèi)存空間可以被釋放掉的儒飒,從而避免內(nèi)存達到上限桩了,避免Crash發(fā)生。
需要注意的是蕉扮,在垃圾回收器對這個Java對象回收前颗圣,SoftReference類所提供的get方法會返回Java對象的強引用在岂,一旦垃圾線程回收該Java對象之后,get方法將返回null易茬。所以在獲取軟引用對象的代碼中及老,一定要判斷是否為null,以免出現(xiàn)NullPointerException異常導致應用崩潰骄恶。
到底什么時候使用軟引用岸蜗,什么時候使用弱引用呢?
個人認為叠蝇,如果只是想避免OutOfMemory異常的發(fā)生,則可以使用軟引用。如果對于應用的性能更在意悔捶,想盡快回收一些占用內(nèi)存比較大的對象铃慷,則可以使用弱引用。
還有就是可以根據(jù)對象是否經(jīng)常使用來判斷蜕该。如果該對象可能會經(jīng)常使用的犁柜,就盡量用軟引用。如果該對象不被使用的可能性更大些堂淡,就可以用弱引用。
另外绢淀,和弱引用功能類似的是WeakHashMap萤悴。WeakHashMap對于一個給定的key,其映射的存在并不阻止垃圾回收器對該鍵的回收皆的,回收以后覆履,其條目從映射中有效地移除。WeakHashMap使用ReferenceQueue實現(xiàn)的這種機制费薄。
弱引用
弱引用是一種比軟引用較弱的引用類型硝全。在系統(tǒng)GC時,只要發(fā)現(xiàn)弱引用楞抡,不管系統(tǒng)堆空間是否足夠伟众,都會將對象進行回收。但是召廷,由于垃圾回收器的線程通常優(yōu)先級很低凳厢,因此,并一不定能很快的發(fā)現(xiàn)持有弱引用的對象柱恤。這種情況下数初,弱引用對象可以存在較長的一段時間。一旦一個弱引用對象被垃圾回收器回收梗顺,便會加入到一個注冊引用隊列中泡孩。 看一個工作中實例:播放器的播放Panel,是一個View寺谤,就是在視頻播放時仑鸥,可以show、hide, 也可以拖拽進度條之類变屁,還有上面的音量眼俊,亮度調(diào)節(jié)等。這樣一個view粟关,我們用弱引用疮胖,因為在視頻播放過程中,不論硬解還是軟解,都將占用大量內(nèi)存澎灸。保證視頻的渲染效果院塞。
在VideoControllerView.java 有如下一段代碼:
在GC之前,弱引用對象并未被垃圾回收器發(fā)現(xiàn)性昭,因此通過mView.get()方法可以取得對應的強引用拦止。但是只要進行垃圾回收,弱引用對象一旦被發(fā)現(xiàn)糜颠,便會立即被回收汹族,并加入注冊引用隊列中。此時其兴,再次通過mView.get()方法取得強引用就會失敗顶瞒。
注意:軟引用,弱引用都非常適合來保存那些可有可無的緩存數(shù)據(jù)忌警。如果這樣做搁拙,當系統(tǒng)內(nèi)存不足時,這些緩存數(shù)據(jù)會被回收法绵,不會導致內(nèi)存溢出箕速。而當內(nèi)存資源充足時,這些緩存數(shù)據(jù)又可以存在相當長的時間朋譬。
虛引用
虛引用是所有引用類型中最弱的一個盐茎。一個持有虛引用的對象,和沒有引用幾乎是一樣的徙赢,隨時都可能被垃圾回收器回收字柠。當試圖通過虛引用的get()方法取得強引用時,總是會失敗狡赐。并且窑业,虛引用必須和引用隊列一起使用,它的作用在于跟蹤垃圾回收過程枕屉。
當垃圾回收器準備回收一個對象時常柄,如果發(fā)現(xiàn)它還有虛引用,就會在垃圾回收后搀擂,銷毀這個對象西潘,獎這個虛引用加入引用隊列。
實際中幾乎沒用哨颂,暫不介紹喷市。
最后一張圖總結(jié)下:
原文地址:http://blog.csdn.net/hejjunlin/article/details/52637333