Android Dalvik虛擬機內存分配問題
原文地址:http://blog.csdn.net/goodlixueyong/article/details/40716779 作者:viclee108
之前遇到一個Android上圖片加載不出來的問題,在三星的note3上極容易出現,而在nexus 4上則很難出現。後來通過DDMS觀察發現,是某一個模塊一直內存泄漏使得內存接近上限,導致一些大圖(需要的內存比較大)申請內存失敗,一直加載不出來。爲什麼會出現這種狀況呢?
通過getprop拿到兩個手機上dalvik虛擬機的參數,三星的note3上的dalvik.vm.heapgrowthlimit爲64M,而nexus4上的dalvik.vm.heapgrowthlimit爲192M,後者是前者的三倍。也就是說note3上存在內存泄漏的時候,虛擬機的內存很容易就達到64M的上限,而在nexus4上要達到192M還是很難的,這也就解釋了前面的現象。
說到這裏,我們來看看虛擬機的幾個重要參數的意義。
dalvik.vm.heapstartsize
查看方法:getprop|grep dalvik.vm.heapstartsize
堆分配的初始大小,調整這個值會影響到應用的流暢性和整體ram消耗。這個值越小,系統ram消耗越慢,但是由於初始值較小,一些較大的應用需要擴張這個堆,從而引發gc和堆調整的策略,會應用反應更慢。相反,這個值越大系統ram消耗越快,但是程序更流暢。
dalvik.vm.heapgrowthlimit
查看方法:getprop|grep dalvik.vm.heapgrowthlimit
極限堆大小,dvm heap是可增長的,但是正常情況下dvm heap的大小是不會超過dalvik.vm.heapgrowthlimit的值。如果受控的應用dvm heap size超過該值,則將引發oom。
dalvik.vm.heapsize
查看方法:getprop|grep dalvik.vm.heapsize
使用大堆時,極限堆大小。一旦dalvik heap size超過這個值,直接引發oom。在android開發中,如果要使用大堆,需要在manifest中指定android:largeHeap爲true。這樣dvm heap最大可達dalvik.vm.heapsize。
[dalvik.vm.heaptargetutilization]: [0.75] 可以設定內存利用率的百分比,當實際的利用率偏離這個百分比的時候,虛擬機會在GC的時候調整堆內存大小,讓實際佔用率向個百分比靠攏。
上面的幾個參數是與虛擬機的內存分配相關的,虛擬機的內存分配過程是下面這樣的:
1 首先判斷一下需要申請的size是不是過大,如果申請的size超過了堆的最大限制,則轉入步驟6
2 嘗試分配,如果成功則返回,失敗則轉入步驟3
3 判斷是否gc正在進行垃圾回收,如果正在進行則等待回收完成之後,嘗試分配。如果成功則返回,失敗則轉入步驟4
4 自己啓動gc進行垃圾回收,這裏gcForMalloc的參數是false。所以不會回收軟引用,回收完成後嘗試分配,如果成功則返回,失敗則轉入步驟5
5 調用dvmHeapSourceAllocAndGrow嘗試分配,這個函數會擴張堆。所以heap startup的時候可以給一個比較小的初始堆,實在不夠用再調用它進行擴張
6 進入回收軟引用階段,這裏gcForMalloc的參數是ture,所以需要回收軟引用。然後調用dvmHeapSourceAllocAndGrow嘗試分配,如果失敗則拋出OOM。