Android OOM分析

由之前Android sdk文檔譯文可知,Android設備爲了保證多個APP的運行,保證足夠RAM的空間,對每個APP的運行時Java堆大小做出了限制,當你的APP申請的JAVA堆空間,超過了設備的Java堆大小
時,系統就會拋出OOM異常,停止當前APP運行。

一、設備的堆大小限制

首先每個設備的堆大小限制是不一樣的,你可以通過adb命令getprop dalvik.vm.heapgrowthlimit獲取當前設備的堆大小限制,同時,如果你的手機已經root的話,可以通過命令setprop dalvik.vm.heapgrowthlimit 32m(32M數值你可以根據需要設定)來設置當前設備的堆大小限制,這樣你就可以使你的APP模擬在不同物理內存的運行。
大家可能在網上之前看過很多文章寫Android設備堆大小限制16M,那估計是很早的文章了,現在大部分設備的堆大小限制都在100M以上,以我的手機華爲P9爲例堆大小已經達到了384M,所以想觸發OOM異常也不是這麼簡單的事了,但是也應當儘量減少堆內存,小心被系統KILL。

二、常見引發OOM的禍源

(1) 內存泄漏

長期持有理應釋放對象的引用,會導致堆內存不斷累積,從而引發OOM異常,Android大部分內存異常主要由於靜態持有外部對象的引用,導致外部對象無法及時釋放,以及Android組件或集合對象沒有被及時關閉。

(2) 大對象的處理的不當

Android 大的Java對象主要體現在Bitmap對象,因此一定要處理好Bitmap對象,尤其是大量的Bitmap對象的產生。在Android2.3.3(API 10)版本及以下,Bitmap的像素數據都存儲在native堆中,只有Bitmap對象本身會存儲在Java堆中,而native堆不受設備堆大小的限制,因此影響不大;
但是Android 3.0(API 11)及以上版本,像素數據也會存儲在Java堆中,這樣如果Bitmap對象頻繁申請或者Bitmap對象過大就會導致OOM異常產生。
對於Android2.3.3及以下版本,通過調用recycle()方法就可以來回收native堆內存,但是對於Android 3.0(API 11)及以上版本,由於對象及數據都在Java堆中,所以不能立即回收內存,Android SDK給出的建議就是複用,避免存在大量的Bitmap對象,具體參看官網
其實對於Android開發而言,爲了保證高效的內存使用,我們儘可能多的做到複用,避免頻繁的申請和是否內存。

三、內存分析Demo

本Demo可以通過不斷申請和釋放堆內存來查看堆內存的變化,這裏堆內存區分了Java堆和Native堆。在這個demo裏,你也可以看到Native堆大小不受設備的堆大小的限制,可以達到幾個G甚至更大,然而
對於Java堆的申請,當內存總和超過堆大小限制時就會觸發OOM異常。另外,當對於Native堆的釋放,會立即生效,而Java堆並不會立即釋放,即使調用了System.gc(),有時也可能不會釋放,得以印證。
代碼的github地址:https://github.com/qiaoyanfei/AppMemoryResearch

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章