Android內存優化6 瞭解Android是如何管理App內存

1, Dalvik & ART

Android在4.4以前一直使用的Dalvik虛擬機做爲App的運行VM的, 4.4中引入了ART做爲開發者備選, 5.0起正式將ART做爲默認VM了.html

咱們首先來簡單瞭解下兩者:android

1.1 Dalvik

若是隻是想簡單瞭解, 我的以爲百度百科上這個Dalvik的介紹基本就知足要求了.shell

若是你們想深刻, 能夠看下老羅的Android之旅Dalvik的相關博文, 從代碼層面上分析了Dalvik的啓動, 運行機制等. 值得一看.緩存

須要說明的是, Dalvik採用的是JIT技術, 在應用程序啓動時, JIT經過進行連續的性能分析來優化程序代碼的執行, 在程序運行的過程當中, Dalvik在不斷的進行將字節碼編譯成機器碼的工做.bash

1.2 ART

ART 取自 Android RunTime. Android用其取代Dalvik, 主要目的就是爲了提高運行性能. 因此, ART相比Dalvik有幾個關鍵的提高:網絡

引入AOT(ahead-of-time)預編譯技術

在安裝apk的過程當中, ART會使用dex2oat程序全部的字節碼預編譯成了機器碼. 應用程序運行過程當中無需進行實時的編譯工做, 只須要進行直接調用. 故而提升了應用程序的運行效率.併發

GC效率

  • 由原來的兩次GC暫停減小爲一次.
  • 以較少的GC時間回收最近分配的, 短命的對象.
  • 提高GC工程學, 使併發GC更及時.
  • 壓縮GC, 以減小後臺內存使用和內存碎片.

開發和調試

  • 支持內存/方法執行的採樣分析.
  • 支持更多的調試技.
  • 在Crash report中提供更多信息.

2, Android的內存管理方式

ART和Dalvik都是使用pagingmemory-mapping(mmapping)來管理內存的. 這就意味着, 任何被分配的內存都會持續存在, 惟一的釋放這塊內存的方式就是釋放對象引用(讓對象GC Root不可達), 故而讓GC程序來回收內存.app

2.1 App的內存分配和回收

對於每一個App進程來講, Heap內存被限制在一個虛擬的內存區間內. 且定義了邏輯上的使用的Heap Size, 這個Heap Size在系統限制的最大值以內是隨着應用的使用狀況而變化的.函數

Heap內存的邏輯大小和實際物理內存的大小是不相同的. 後面咱們在使用Memory Monitor等內存分析工具分析內存時, 會看到一個叫作Proportional Set Size (PSS)的值, 這個值纔是系統認爲的你的App所佔用的物理內存大小.工具

這個PSS值也就是實際物理內存大小, 統計包括了你的應用進程所佔用的內存大小, 和共享內存中佔用的內存大小(比例分配方式計算).

Android VM不會壓縮Heap內存的邏輯大小, 故而沒法經過碎片整理的方式來釋放Heap空間, 而只能經過回收Heap尾部的空內存塊來壓縮邏輯內存大小.

這時, 咱們的GC就出場了, GC以後, VM會遍歷Heap找到不被使用的pages, 經過madvise函數將其返回給內核, 從而釋放這塊被邏輯Heap使用的物理內存.

2.2 App內存限制

Android是一個多任務系統, 爲了保證多任務的運行, Android給每一個App可以使用的Heap大小設定了一個限定值.

這個值是系統設置的prop值, 系統編譯時內置的, 保存在system/build.prop中. 通常國內的手機廠商都會作修改, 根據手機配置不一樣而不一樣, 能夠經過以下命令查看:

$ adb shell shell@hwH60:/ $ cat /system/build.prop 

以手頭的Huawei 榮耀6爲例, heap size相關的prop以下:

dalvik.vm.heapstartsize=8m
dalvik.vm.heapgrowthlimit=192m
dalvik.vm.heapsize=512m
dalvik.vm.heaptargetutilization=0.75
dalvik.vm.heapminfree=2m
dalvik.vm.heapmaxfree=8m

其中:

dalvik.vm.heapstartsize

-- App啓動後, 系統分配給它的Heap初始大小. 隨着App使用可增長.

dalvik.vm.heapgrowthlimit

-- 默認狀況下, App可以使用的Heap的最大值, 超過這個值就會產生OOM.

dalvik.vm.heapsize

-- 若是App的manifest文件中配置了largeHeap屬性, 以下.則App可以使用的Heap的最大值爲此項設定值.

<application android:largeHeap="true"> ... </application> 

dalvik.vm.heaptargetutilization

-- 當前理想的堆內存利用率. GC後, Dalvik的Heap內存會進行相應的調整, 調整到當前存活的對象的大小和 / Heap大小 接近這個選項的值, 即這裏的0.75. 注意, 這只是一個參考值.

dalvik.vm.heapminfree

-- 單次Heap內存調整的最小值.

dalvik.vm.heapmaxfree

-- 單次Heap內存調整的最大值.

也能夠直接使用getprop查看單項prop:

$ adb shell getprop dalvik.vm.heapsize 512m 

2.3 切換App時的內存管理機制

Android的進程級別

Android 系統會盡量長時間地保持應用進程, 但爲了新建進程或運行更重要的進程, 最終須要清除舊進程來回收內存. 爲了肯定保留或終止哪些進程, 系統會根據進程中正在運行的組件以及這些組件的狀態, 將每一個進程設定了一個重要級別. 必要時, 系統會首先消除重要性最低的進程, 而後是重要性略低的進程, 依此類推, 以回收系統資源.

依據重要程度從大到小依次分爲5級:

前臺進程

用戶當前操做所必需的進程. 若是一個進程知足如下任一條件, 即視爲前臺進程:

  • 託管用戶正在交互的 Activity(已調用 Activity 的 onResume() 方法)
  • 託管某個 Service,後者綁定到用戶正在交互的 Activity
  • 託管正在「前臺」運行的 Service(服務已調用 startForeground())
  • 託管正執行一個生命週期回調的 * Service(onCreate()、onStart() 或 onDestroy())
  • 託管正執行其 onReceive() 方法的 BroadcastReceiver

只有在內在不足以支持它們同時繼續運行這一萬不得已的狀況下,系統纔會終止它們。 此時,設備每每已達到內存分頁狀態,所以須要終止一些前臺進程來確保用戶界面正常響應。

可見進程

沒有任何前臺組件、但仍會影響用戶在屏幕上所見內容的進程。 若是一個進程知足如下任一條件,即視爲可見進程:

  • 託管不在前臺、但仍對用戶可見的 Activity(已調用其 onPause() 方法)。例如,若是前臺 Activity 啓動了一個對話框,容許在其後顯示上一 Activity,則有可能會發生這種狀況
  • 託管綁定到可見(或前臺)Activity 的 Service
    可見進程被視爲是極其重要的進程,除非爲了維持全部前臺進程同時運行而必須終止,不然系統不會終止這些進程。

服務進程

正在運行已使用 startService() 方法啓動的服務且不屬於上述兩個更高類別進程的進程。儘管服務進程與用戶所見內容沒有直接關聯,可是它們一般在執行一些用戶關心的操做(例如,在後臺播放音樂或從網絡下載數據)。所以,除非內存不足以維持全部前臺進程和可見進程同時運行,不然系統會讓服務進程保持運行狀態。

後臺進程

包含目前對用戶不可見的 Activity 的進程(已調用 Activity 的 onStop() 方法)。這些進程對用戶體驗沒有直接影響,系統可能隨時終止它們,以回收內存供前臺進程、可見進程或服務進程使用。 一般會有不少後臺進程在運行,所以它們會保存在 LRU (最近最少使用)列表中,以確保包含用戶最近查看的 Activity 的進程最後一個被終止。若是某個 Activity 正確實現了生命週期方法,並保存了其當前狀態,則終止其進程不會對用戶體驗產生明顯影響,由於當用戶導航回該 Activity 時,Activity 會恢復其全部可見狀態。

空進程

不含任何活動應用組件的進程。保留這種進程的的惟一目的是用做緩存,以縮短下次在其中運行組件所需的啓動時間。 爲使整體系統資源在進程緩存和底層內核緩存之間保持平衡,系統每每會終止這些進程。

切換App的內存管理

當用戶切換App時, 被切換到後臺的App所使用的內存並未所以刪除, 該App進程被緩存到一個LRU緩存中, 以便用戶切換回來時, 能更快的啓動App, 讓多任務更流暢.

可是, 當系統內存不夠用的時候, 就會根據LRU特性, 以及上面說到的進程級別(同時也會考慮該App進程佔用的內存大小)來決定殺死哪些進程, 來回收內存, 以便執行當前任務.

因此, 若是咱們爲了避免要讓系統kill掉咱們的App, 能夠從進程級別, 內存消耗量等幾個方面進行優化.

結語

本文加上GC那些事兒, 咱們講了兩篇的理論知識, 相信你們對Android的內存管理有了個大致的瞭解, 後面將介紹一些內存分析工具以及使用, 結合實際來講明怎麼分析內存問題.

做者:anly_jun 連接:https://www.jianshu.com/p/4ad716c72c12 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索