Android的內存管理機制


由於你的分享、點贊、在看
我足足的精氣神兒!

Android使用虛擬內存和分頁,不支持交換程序員

垃圾收集

不管是ART仍是Dalvik虛擬機,都和衆多Java虛擬機同樣,屬於一種託管內存環境(程序員不須要顯示的管理內存的分配與回收,交由系統自動管理)。託管內存環境會跟蹤每一個內存分配, 一旦肯定程序再也不使用一塊內存,它就會將其釋放回堆中,而無需程序員的任何干預。回收託管內存環境中未使用內存的機制稱爲垃圾回收。web

垃圾收集有兩個目標:緩存

  • 在程序中查找未來沒法訪問的數據對象;安全

  • 回收這些對象使用的資源。微信

Android的垃圾收集器不帶壓縮整理功能(Compact),即不會對Heap作碎片整理。app

Android的內存堆是分代式(Generational)的,意味着它會將全部分配的對象進行分代,而後分代跟蹤這些對象。例如,最近分配的對象屬於年輕代(Young Generation)。當一個對象長時間保持活動狀態時,它能夠被提高爲年老代(Older Generation),以後還能進一步提高爲永久代(Permanent Generation)。編輯器

每一代的對象可佔用的內存總量都有其專用上限。每當一代開始填滿時,系統就會執行垃圾收集事件以試圖釋放內存。垃圾收集的持續時間取決於它在收集哪一代的對象以及每一代中有多少活動對象。ide

雖然垃圾收集速度很是快,但它仍然會影響應用程序的性能。一般狀況下你不須要控制代碼中什麼時候執行垃圾收集事件。系統有一組用於肯定什麼時候執行垃圾收集的標準。知足條件後,系統將中止執行當前進程並開始垃圾回收。若是在像動畫或音樂播放這樣的密集處理循環中發生垃圾收集,則會增長處理時間。這種增長可能會致使你的應用程序中的代碼執行超過建議的16ms閾值。性能

爲實現高效,流暢的幀渲染,Android建議繪製一幀的時間不要超過16ms。flex

此外,你的代碼可能會執行各類工做,這些工做會致使垃圾收集事件更頻繁地發生,或使其持續時間超過正常範圍。例如,若是在Alpha混合動畫的每一個幀期間在for循環的最內部分配多個對象,則大量的對象就會污染內存堆。此時,垃圾收集器會執行多個垃圾收集事件,並可能下降應用程序的性能。

共享內存

Android能夠跨進程共享RAM頁面(Pages)。它能夠經過如下方式實現:

  • 每一個應用程序進程都是從名爲Zygote的現有進程分叉(fork)出來的。Zygote進程在系統引導並加載framework代碼和資源(例如Activity Themes)時啓動。要啓動新的應用程序進程,系統會fork Zygote進程,而後在新進程中加載並運行應用程序的代碼。這種方法容許在全部應用程序進程中共享大多數的爲framework代碼和資源分配的RAM頁面。

  • 大多數靜態數據都被映射到一個進程中。該技術容許在進程之間共享數據,而且還容許在須要時將其Page out。這些靜態數據包括:Dalvik代碼(經過將其置於預連接的.odex文件中進行直接的memory-mapping),app資源(經過將資源表設計爲能夠mmap的結構並經過對齊APK的zip條目) 和傳統的項目元素,如.so文件中的本地代碼。

  • 在許多地方,Android使用顯式分配的共享內存區域(使用ashmem或gralloc)在進程間共享相同的動態RAM。例如,Window surface在應用程序和屏幕合成器之間使用共享內存,而遊標緩衝區在Content Provider和客戶端之間使用共享內存。

分配和回收應用的內存

Android爲每一個進程分配內存的時候,採用了彈性分配方式,也就是剛開始並不會一下分配不少內存給每一個進程,而是給每個進程分配一個「夠用」的虛擬內存範圍。這個範圍是根據每個設備實際的物理內存大小來決定的,而且能夠隨着應用後續需求而增長,但最多也只能達到系統爲每一個應用定義的上限。

堆的邏輯大小與其使用的物理內存總量並不徹底相同。在檢查應用程序的堆時,Android會計算一個名爲「比例集大小」(PSS)的值,該值會考慮與其餘進程共享的髒頁面和乾淨頁面,但其總量與共享該RAM的應用程序數量成正比。此PSS總量就是系統認爲是你的物理內存佔用量。

Android會在內存中儘可能長時間的保持應用進程,即便有些進程再也不使用了。這樣,當用戶下次啓動應用的時候,只須要恢復當前進程就能夠了,不須要從新建立進程,進而減小應用的啓動時間。只有當Android系統發現內存不足,而其餘爲用戶提供更緊急服務的進程又須要內存時,Android就會決定關閉某些進程以回收內存。關於這部份內容,稍後再細說。

限制應用的內存

爲了維護高效的多任務環境,Android爲每一個應用程序設置了堆大小的硬性限制。該限制因設備而異,取決於設備整體可用的RAM。若是應用程序已達到該限制並嘗試分配更多內存,則會收到 OutOfMemoryError 。

在某些狀況下,你可能但願查詢系統以準確肯定當前設備上可用的堆空間大小,例如,肯定能夠安全地保留在緩存中的數據量。你能夠經過調用 getMemoryClass() 來查詢系統中的這個數字。此方法返回一個整數,指示應用程序堆可用的兆字節數。

切換應用

當用戶在應用程序之間切換時,Android會將非前臺應用程序(即用戶不可見或並無運行諸如音樂播放等前臺服務的進程)緩存到一個最近最少使用緩存(LRU Cache)中。例如,當用戶首次啓動應用程序時,會爲其建立一個進程; 可是當用戶離開應用程序時,該進程不會退出。系統會緩存該進程。若是用戶稍後返回應用程序,系統將從新使用該進程,從而使應用程序切換更快。

若是你的應用程序具備緩存進程而且它保留了當前不須要的內存,那麼即便用戶未使用它,你的應用程序也會影響系統的總體性能。當系統內存不足時,就會從最近最少使用的進程開始,終止LRU Cache中的進程。另外,系統還會綜合考慮保留了最多內存的進程,並可能終止它們以釋放RAM。

當系統開始終止LRU Cache中的進程時,它主要是自下而上的。系統還會考慮哪些進程佔用更多內存,由於在它被殺時會爲系統提供更多內存增益。所以在整個LRU列表中消耗的內存越少,保留在列表中而且可以快速恢復的機會就越大。




夯實基礎,關注前沿,娛樂生活

掌握更多前沿技術,獲取更多笑點 

請關注--------喘口仙氣



本文分享自微信公衆號 - 喘口仙氣(gh_db8538619cdd)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索