(一)Android的內存管理機制

 

Google在Android的官網上有這樣一篇文章,初步介紹了Android是如何管理應用的進程與內存分配:http://developer.android.com/training/articles/memory.html。 Android系統的Dalvik虛擬機扮演了常規的內存垃圾自動回收的角色,Android系統沒有爲內存提供交換區,它使用 paging與 memory-mapping(mmapping)的機制來管理內存,下面簡要概述一些Android系統中重要的內存管理基礎概念。

1)共享內存

Android系統通過下面幾種方式來實現共享內存:

 

  • Android應用的進程都是從一個叫做Zygote的進程fork出來的。Zygote進程在系統啓動,並載入通用的framework的代碼與資源之後開始啓動。爲了啓動一個新的程序進程,系統會fork Zygote進程生成一個新的進程,然後在新的進程中加載並運行應用程序的代碼。這就使得大多數的RAM pages被用來分配給framework的代碼,同時促使RAM資源能夠在應用的所有進程之間進行共享。
  • 大多數static的數據被mmapped到一個進程中。這不僅僅讓同樣的數據能夠在進程間進行共享,而且使得它能夠在需要的時候被paged out。常見的static數據包括Dalvik Code、app resources、so文件等。
  • 大多數情況下,Android通過顯式的分配共享內存區域(例如ashmem或gralloc)來實現動態RAM區域能夠在不同進程之間進行共享的機制。比如,Window Surface在App與Screen Compositor之間使用共享的內存,Cursor Buffers在Content Provider與Clients之間共享內存。

 

2)分配與回收內存

 

  • 每一個進程的Dalvik Heap都反映了使用內存的佔用範圍。這就是通常邏輯意義上提到的Dalvik Heap Size,它可以隨着需要進行增長,但是增長行爲會有一個系統爲它設定上限。
  • 邏輯上講的Heap Size和實際物理意義上使用的內存大小是不對等的,Proportional Set Size(PSS)記錄了應用程序自身佔用以及與其他進程進行共享的內存。
  • Android系統並不會對Heap中空閒內存區域做碎片整理。系統僅僅會在新的內存分配之前判斷Heap的尾端剩餘空間是否足夠,如果空間不夠會觸發GC操作,從而騰出更多空閒的內存空間。在Android的高級系統版本里面針對Heap空間有一個Generational Heap Memory的模型,最近分配的對象會存放在Young Generation區域。當這個對象在該區域停留的時間達到一定程度,它會被移動到Old Generation,最後累積一定時間再移動到Permanent Generation區域。系統會根據內存中不同的內存數據類型分別執行不同的GC操作。例如,剛分配到Young Generation區域的對象通常更容易被銷燬回收,同時在Young Generation區域的GC操作速度會比Old Generation區域的GC操作速度更快(如圖1所示)。

 

 

圖1  根據不同內存數據類型執行不同GC操作

每一個Generation的內存區域都有固定的大小。隨着新的對象陸續被分配到此區域,當對象總的大小臨近這一級別內存區域的閥值時,會觸發GC操作,以便騰出空間來存放其他新的對象(如圖2所示)。

 

圖2  對象值臨近閥值觸發GC操作

通常情況下,GC發生的時候,所有的線程都是會被暫停的。執行GC所佔用的時間和它發生在哪一個Generation也有關係,Young Generation中的每次GC操作時間是最短的,Old Generation其次,Permanent Generation最長。執行時間的長短也和當前Generation中的對象數量有關,遍歷樹結構查找20000個對象比起遍歷50個對象自然是要慢很多的。

3)限制應用的內存

 

  • 爲了整個系統的內存控制需要,Android系統爲每一個應用程序都設置一個硬性的Dalvik Heap Size最大限制閾值,這個閾值在不同的設備上會因爲RAM大小不同而各有差異。如果你的應用佔用內存空間已經接近這個閾值,此時再嘗試分配內存的話,很容易引發OutOfMemoryError錯誤。
  • ActivityManager.getMemoryClass()可以用來查詢當前應用的Heap Size閾值,這個方法會返回一個整數,表明應用的Heap Size閾值是多少MB(Megabates)。

 

4)應用切換操作

 

  • Android系統並不會在用戶切換應用的時候執行交換內存操作。Android會把那些不包含Foreground組件的應用進程放到LRU Cache中。例如,當用戶開始啓動一個應用時,系統會爲它創建一個進程。但是當用戶離開此應用,進程不會立即被銷燬,而是被放到系統的Cache當中。如果用戶後來再切換回到這個應用,此進程就能夠被馬上完整地恢復,從而實現應用的快速切換。
  • 如果你的應用中有一個被緩存的進程,這個進程會佔用一定的內存空間,它會對系統的整體性能有影響。因此,當系統開始進入Low Memory的狀態時,它會由系統根據LRU的規則與應用的優先級,內存佔用情況以及其他因素的影響綜合評估之後決定是否被殺掉。
  • 對於那些非foreground的進程,Android系統是如何判斷Kill掉哪些進程的問題,請參考Processes and Threads
內容來源於 小紅提技術博客,http://www.xiaohongti.com/ 轉載請保留地址,尊重版權。
發佈了60 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章