android記憶體管理機制與優化

jackzhous_發表於2020-12-11

android記憶體管理機制與優化心得

簡介

android使用Dvalik/ART虛擬機器來對應用管理,其使用專門的垃圾回收機制來管理堆上的記憶體,程式設計師無需自己去釋放分配的記憶體;雖然減輕了我們許多的工作量,但是當我們開發的時候分配記憶體不合理,也很容易造成記憶體管理不當,如記憶體抖動、記憶體洩漏和記憶體碎片,所以我們也要弄明白虛擬機器是如何管理記憶體,然後我們在去針對性的優化

記憶體管理機制

android記憶體採用的是paging頁和mapping對映來對記憶體進行管理,page主要是把記憶體化成一頁頁的管理,而mapping主要是對映一些庫和共享變數到我們的app程式;
然後,虛擬機器使用分代垃圾回收的方法,年輕代和年老代,年輕代採用複製演算法垃圾回收,這是為了解決記憶體碎片的問題,但是也不能完全解決記憶體碎片的問題,因為記憶體管理的最小單位就是以頁來管理的,如果一頁4K,哪怕只佔用了1K,也無法對這頁記憶體進行回收;記憶體出現問題後,一般會引出以下幾個問題:

記憶體抖動

所謂記憶體抖動,直觀的感受就是記憶體動態波形圖,連續上下的波峰波谷,其背後就是因為頻繁的建立物件分配堆上的記憶體,使堆上記憶體達到了一定的閾值,觸發垃圾回收去回收記憶體,釋放後又大量分配記憶體,垃圾回收在釋放,不停的重複這一過程;

記憶體洩漏

android的記憶體洩漏一個原則就是生命週期長的物件持有生命週期短的物件,導致短週期物件無法及時得到回收,這個解決的辦法:一是不使用的引用後,我們要及時將引用賦值為null,對於一些特殊場景,如跨執行緒的操作,可以使用弱引用持有物件,弱引用不影響GC對垃圾的回收;

記憶體碎片

頁單位來管理記憶體,假如每頁4K,使用for迴圈不停2K+1K的物件,分配第一頁時,先佔用2K,然後再佔用1K,第二次迴圈分配,需要2K記憶體,但是發現第一頁已經只剩下1K了,這個時候只能到下一個記憶體頁,分配2K和1K,這樣迴圈下來,每頁都還剩下1K的空閒記憶體,加入每頁中的2K是臨時變數,而1K則是長久的物件,一次GC下來,2K釋放了還有許多的頁記憶體佔用1K,這個記憶體頁無法得到釋放,也無法被分配,這就產生了許多諮詢無法使用;

如何解決?

使用複用池,有物件池和Bitmap複用池,實質原理提請申請好一些物件,佔用記憶體,申請時我們去物件池索取,不使用時規還給物件池,這樣我們多次使用的記憶體都是同一塊記憶體,就不會造成記憶體碎片和記憶體抖動了

物件池

Pools.SynchronizedPool<Object> t = new Pools.SynchronizedPool<>(10);
Object obj = t.acquire();
t.release(obj);

android中的message就是用的這個東西

最後,我們app其實佔用記憶體大的更多的都是圖片,圖片我們也可以是使用複用池,不過要自己實現,可以參考GlideBitmapPool,採用了LruBitmapPool演算法,最近使用原則;其底層是HashMap+LinkedGroupMap.Entry的雙連結串列結構,快速訪問;

相關文章