Android內存情況

 衆所周知,在寫 android 程序的時候,很容易出現 OOM ,而出現的時機大多數是由 Bitmap decode 引發的:

1

ERROR/AndroidRuntime(16350): java.lang.OutOfMemoryError: bitmap size exceeds VM budget

      我們知道,android程序內存一般限制在16M,當然也有24M的,而android程序內存被分爲2部分:native和dalvik:

dalvik就是我們平常說的java堆,我們創建的對象是在這裏面分配的,而bitmap是直接在native上分配的,對於內存的限制是native+dalvik不能超過最大限制。

注:

一旦內存分配給Java後,以後這塊內存縱然開釋後,也只能給Java的施用,這個估計跟java虛擬機裏把內存分成好幾塊進行緩存的原因有關,反正C就別想用到這塊的內存了,所以要是Java突然佔用了一個大塊內存,縱然很快開釋了: 

C能施用的內存 = 16M - Java某一瞬間佔用的最大內存。 

Bitmap的生成是通過malloc進行內存分配的,佔用的是C的內存,這個也就說明了,上面所說的的4MBitmap無法生成的原因,因爲在13MJava用過後,剩下C能用的只有3M了。

      用以下命令可以查看程序的內存使用情況:

adb shell dumpsysmeminfopackagename orpid程序的包名或者進程id


    其中size是需要的內存,而allocated是分配了的內存,對應的2列分別是native和dalvik,當總數也就是total這一列超過單個程序內存的最大限制時,OOM就很有可能會出現了。

       多數時候,發生OOM 都是在做一些跟圖片相關的操作,以下提出一些建議儘量可以減少這種情況的發生:

1

.decode bitmap 的時候,儘量配置下Options,例如:inSameSize

2

.Bitmap使用完以後,調用 bitmap.recycle()來釋放內存

 

3

.如果應用是基於圖片的應用,儘量採用LazyLoad和DymanicRecycle

4.decode bitmap 的時候,將decode代碼 try catch 出來,catch oom error,避免程序crash,可以在catch裏面做一些釋放內存操作


關於Android的Native內存和Dalvik內存

1.   Dalvik內存

每一個Android應用在底層都會對應一個獨立的Dalvik虛擬機實例,其代碼在虛擬機的解釋下得以執行。

很多人認爲Dalvik虛擬機是一個Java虛擬機,因爲Android的編程語言恰恰就是Java語言。但是這種說法並不準確,因爲 Dalvik虛擬機並不是按照Java虛擬機的規範來實現的,兩者並不兼容;

同時還要兩個明顯的不同:

  1.Java虛擬機運行的是Java字節碼,而Dalvik虛擬機運行的則是其專有的文件格式DEX(Dalvik Executable)。

2.在Java SE程序中的Java類會被編譯成一個或者多個字節碼文件(.class)然後打包到JAR文件,而後Java虛擬機會從相應的CLASS文件和JAR文件中獲取相應的字節碼;Android應用雖然也是使用Java語言進行編程,但是在編譯成CLASS文件後,還會通過一個工具(dx)將應用所有的 CLASS文件轉換成一個DEX文件,而後Dalvik虛擬機會從其中讀取指令和數據。

Dalvik虛擬機的簡介:

Dalvik虛擬機主要是完成對象生命週期的管理,堆棧的管理,線程管理,安全和異常的管理,以及垃圾回收等等重要功能。

Dalvik虛擬機的主要特徵Dalvik虛擬機非常適合在移動終端上使用,相對於在桌面系統和服務器系統運行的虛擬機而言,它不需要很快的CPU速度和大量的內存空間。

Dalvik虛擬機有如下幾個主要特徵:

1.專有的DEX文件格式

DEXDalvik虛擬機專用的文件格式,而問什麼棄用已有的字節碼文件(CLASS文件)而採用新的格式呢?一個應用中會定義很多類,編譯完成後即會有很多相應的CLASS文件,CLASS文件間會有不少冗餘的信息;而DEX文件格式會把所有的 CLASS文件內容整合到一個文件中。這樣,除了減少整體的文件尺寸,I/O操作,也提高了類的查找速度。

2.增加了新的操作碼的支

3.文件結構儘量簡潔,使用等長的指令,藉以提高解析速度

4.儘量擴大隻讀結構的大小,藉以提高跨進程的數據共享

2.   Native內存

如何修改Android應用程序的默認最大內存值

Android應用程序的默認最大內存值爲16M,有些應用程序可能會出現內存溢出,譬如ERROR/AndroidRuntime(264):java.lang.OutOfMemoryError: bitmap size exceeds VM budget

除了要檢查修正代碼之外,還可以考慮修改Android應用程序的默認最大內存值。

修改應用程序的默認最大內存有2種方法:

1、修改代碼,適用於自己編譯燒機:

當應用程序分配內存時,會調用到dalvik/vm/alloc/HeapSource.c中的dvmTrackExternalAllocation()方法,繼而調用到externalAllocPossible()方法,該方法要求當前堆已使用的大小(由currentHeapSize和hs->externalBytesAllocated構成)加上我們需要再次分配的內存大小不能超過堆的最大內存值,如果超過就會報錯。 

有兩個地方決定了一個堆的最大內存: 

1)dalvik/vm/Init.c中的 

gDvm.heapSizeMax = 16 * 1024 * 1024;    // Spec says 75%physical mem 

2)frameworks/base/core/jni/AndroidRuntime.cpp中的 

property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4,"16m"); 

因此解決辦法就是將以上2點中默認的16M改大一點,譬如32M。

2、修改配置文件,適用於燒機後的版本。

修改或添加/system/build.prop中的配置項:

dalvik.vm.heapstartsize=20m

dalvik.vm.heapgrowthlimit=200m

dalvik.vm.heapsize=320m


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