Android 性能優(yōu)化-Java引用類型

Java引用類型分為強引用、軟引用、弱引用、虛引用,本文對四種引用類型進行分析


強引用

強引用:日常開發(fā)中最常見的引用類型,直接通過new來創(chuàng)建對象,如果放任不管對象將不會被回收當(dāng)對象不斷增加不做釋放就會造成OOM,所以需要手動去釋放內(nèi)存再等待GC的回收,也可以通過類似Activity有生命周期的類伴隨類銷毀回收一并回收掉。

//new出對象object
Object object = new Object();
//將object對象引用鏈斷開等待GC回收
object  = null ;

軟引用

軟引用(SoftReference):軟引用用來存放不是必須存在但是還有用的對象,一般來說軟引用對象不會被回收,只有在內(nèi)存不足時會選擇釋放掉軟引用內(nèi)存,來滿足程序正常運行。舉個例子來描述Activity頁面上呈現(xiàn)幾張圖片,可能會執(zhí)行其他耗內(nèi)存操作,比如從APP中切出去到其他耗內(nèi)存的動作時,圖片是沒有在頁面顯示的,所以圖片的內(nèi)存可以有也可以沒有(因為頁面也看不見嘛有沒有都一樣),但是當(dāng)從其他任務(wù)執(zhí)行結(jié)束回到APP中時,還需要圖片的正常顯示,這種情況的圖片就是不是必須存在但是還有用的對象。如果使用強引用的話,當(dāng)APP切換到后臺但是內(nèi)存不足時就會拋出OOM,但是使用軟引用存放對象的話,當(dāng)內(nèi)存不足時會優(yōu)先去回收軟引用的對象這樣就會有多余的內(nèi)存供給調(diào)用,這樣就會減少因內(nèi)存不足而引發(fā)的OOM。

弱引用

弱引用(WeakReference):弱引用不管內(nèi)存足夠或是不足夠都可以被回收的一種引用類型,第一次GC掃描到會進行標(biāo)記,第二次掃描直接進行回收。下面用代碼展示下弱引用:

//模擬弱引用效果,先創(chuàng)建一個對象一會將對象回收
Object weakObject = new Object() ;
//創(chuàng)建一個引用隊列
ReferenceQueue referenceQueue = new ReferenceQueue();
//創(chuàng)建弱引用
WeakReference<Object> weakReference = new WeakReference<>(weakObject,referenceQueue);
//打印弱引用中的對象  第一次打印
System.out.println("weakReference: "+ weakReference.get());
//打印引用隊列中對象  第二次打印
System.out.println("referenceQueue: "+referenceQueue.poll());
//將對象設(shè)置為null
weakObject = null ;
//手動GC回收一下
System.gc();
//因為這里方便調(diào)試看回收效果所以等待兩秒
Thread.sleep(2000);
//打印弱引用中的對象  第三次打印
System.out.println("weakReference: "+ weakReference.get());
//打印引用隊列中對象  第四次打印
System.out.println("referenceQueue: "+referenceQueue.poll());

這里模擬對象被回收過程,然后展示弱引用可以存儲對象信息并可以使用對象,當(dāng)GC觸發(fā)時對象被回收引用隊列內(nèi)保存回收引用信息。來看下打印結(jié)果:

弱引用代碼執(zhí)行結(jié)果.png

不難看出弱引用是可以存儲對象信息并使用的第一次打印是Object對象(java.lang.Object),而在沒觸發(fā)GC的時候引用隊列為null,但觸發(fā)GC回收之后,引用對象被回收所以第三次打印醫(yī)用對象信息為null,最后第四次打印因為對象被回收但是回收引用的信息會存儲在引用隊列中,所以第四次打印可以打印出回收引用信息(java.lang.ref.WeakReference)。

虛引用

虛引用(PhantomReference):虛引用一般被稱為幽靈、幻影引用,虛引用不對生存造成任何影響,僅用于跟蹤GC的回收通知,一般開發(fā)不適用虛引用,在特定的情況下可能使用就是需要記錄GC何時回收對象信息,那么虛引用就可能會排上用場。下面用代碼展示下虛引用:

//模擬虛引用效果,先創(chuàng)建一個對象一會將對象回收
Object phantomObject = new Object() ;
//創(chuàng)建一個引用隊列
ReferenceQueue referenceQueue = new ReferenceQueue();
//創(chuàng)建虛引用
PhantomReference<Object> phantomReference = new PhantomReference<>(phantomObject,referenceQueue);
//打印弱引用中的對象  第一次打印
System.out.println("phantomReference: "+ phantomReference.get());
//打印引用隊列中對象  第二次打印
System.out.println("referenceQueue: "+referenceQueue.poll());
//將對象設(shè)置為null
phantomObject = null ;
//手動GC回收一下
System.gc();
//因為這里方便調(diào)試看回收效果所以等待兩秒
Thread.sleep(2000);
//打印弱引用中的對象  第三次打印
System.out.println("phantomReference: "+ phantomReference.get());
//打印引用隊列中對象  第四次打印
System.out.println("referenceQueue: "+referenceQueue.poll());

這里模擬對象回收過程,然后展示虛引用可以存儲對象回收信息但是虛引用并不能引用對象僅僅能記錄對象回收信息,當(dāng)GC觸發(fā)時對象被回收引用隊列內(nèi)保存回收引用信息。來看下打印結(jié)果:


虛引用代碼執(zhí)行結(jié)果.png

如果這里對比弱引用來看的話,不難看出虛引用是弱引用的降級版,因為弱引用可以引用對象實例,然而虛引用不可以引用對象實例僅用于存儲對象被回收信息。


以上就是就是四種引用類型的簡要介紹,對比文章內(nèi)容不難看出實際上強、軟、弱、虛引用的能力是一次遞減。在實際開發(fā)中好好利用四種引用類型,會大大的減少開發(fā)過程中的內(nèi)存溢出異常。

下一篇 將了解內(nèi)存抖動是什么以及內(nèi)存抖動發(fā)生的原因及常見解決辦法

Android 性能優(yōu)化-內(nèi)存篇(4) - 簡書

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容