Android記憶體最佳化1 瞭解Android是如何管理App記憶體

來源:互聯網
上載者:User

標籤:對話方塊   遍曆   程式碼   csdn   工程   記憶體不足   sys   手機廠商   記憶體最佳化   

1, Dalvik & ART

Android在4.4之前一直使用的Dalvik虛擬機器作為App的運行VM的, 4.4中引入了ART作為開發人員備選, 5.0起正式將ART作為預設VM了.

我們首先來簡單瞭解下二者:

1.1 Dalvik

如果只是想簡單瞭解, 個人覺得百度百科上這個Dalvik的介紹基本就滿足要求了.

如果大家想深入, 可以看下老羅的Android之旅中Dalvik的相關博文, 從代碼層面上分析了Dalvik的啟動, 運行機制等. 值得一看.

需要說明的是, Dalvik採用的是JIT技術, 在應用程式啟動時, JIT通過進行連續的效能分析來最佳化程式碼的執行, 在程式啟動並執行過程中, Dalvik在不斷的進行將位元組碼編譯成機器碼的工作.

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都是使用paging和memory-mapping(mmapping)來管理記憶體的. 這就意味著, 任何被分配的記憶體都會持續存在, 唯一的釋放這塊記憶體的方式就是釋放對象引用(讓對象GC Root不可達), 故而讓GC程式來回收記憶體.

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[email protected]:/ $ cat /system/build.prop

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

dalvik.vm.heapstartsize=8mdalvik.vm.heapgrowthlimit=192mdalvik.vm.heapsize=512mdalvik.vm.heaptargetutilization=0.75dalvik.vm.heapminfree=2mdalvik.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.heapsize512m
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
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

Android記憶體最佳化1 瞭解Android是如何管理App記憶體

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.