本章爲官方文檔,主要介紹 Android 如何管理應用進程和內存分配。android
首先了解爲何要有內存優化,官方的文檔介紹程序員
https://developer.android.com/topic/performance/memory-overview?hl=zh-cnweb
Android 運行時 (ART) 和 Dalvik 虛擬機使用分頁和內存映射來管理內存。這意味着應用修改的任何內存,不管修改的方式是分配新對象仍是輕觸內存映射的頁面,都會一直駐留在 RAM 中,而且沒法換出。要從應用中釋放內存,只能釋放應用保留的對象引用,使內存可供垃圾回收器回收。這種狀況有一個例外:對於任何未經修改的內存映射文件(如代碼),若是系統想要在其餘位置使用其內存,可將其從 RAM 中換出。緩存
https://developer.android.com/topic/performance/memory?hl=zh-cn安全
隨機存取存儲器 (RAM) 在任何軟件開發環境中都是一項寶貴資源,但在移動操做系統中,因爲物理內存一般都有限,所以 RAM 就更寶貴了。雖然 Android 運行時 (ART) 和 Dalvik 虛擬機都執行例行的垃圾回收任務,但這並不意味着您能夠忽略應用分配和釋放內存的位置和時間。您仍然須要避免引入內存泄漏問題(一般因在靜態成員變量中保留對象引用而引發),並在適當時間(如生命週期回調所定義)釋放全部 Reference 對象。微信
Android經過的如下幾個方面對內存進行管理:app
垃圾回收框架
垃圾回收編輯器
ART 或 Dalvik 虛擬機之類的受管內存環境會跟蹤每次內存分配。一旦肯定程序再也不使用某塊內存,它就會將該內存從新釋放到堆中,無需程序員進行任何干預。這種回收受管內存環境中的未使用內存的機制稱爲「垃圾回收」。垃圾回收有兩個目標:在程序中查找未來沒法訪問的數據對象,並回收這些對象使用的資源。ide
Android 的內存堆是分代的,這意味着它會根據分配對象的預期壽命和大小跟蹤不一樣的分配存儲分區。例如,最近分配的對象屬於「新生代」。當某個對象保持活動狀態達足夠長的時間時,可將其提高爲較老代,而後是永久代。
堆的每一代對相應對象可佔用的內存量都有其自身的專用上限。每當一代開始填滿時,系統便會執行垃圾回收事件以釋放內存。垃圾回收的持續時間取決於它回收的是哪一代對象以及每一代有多少個活動對象。
儘管垃圾回收速度很是快,但仍會影響應用的性能。一般狀況下,您沒法從代碼中控制什麼時候發生垃圾回收事件。系統有一套專門肯定什麼時候執行垃圾回收的標準。當條件知足時,系統會中止執行進程並開始垃圾回收。若是在動畫或音樂播放等密集型處理循環過程當中發生垃圾回收,則可能會增長處理時間,進而可能會致使應用中的代碼執行超出建議的 16ms 閾值,沒法實現高效、流暢的幀渲染。
此外,您的代碼流執行的各類工做可能迫使垃圾回收事件發生得更頻繁或致使其持續時間超過正常範圍。例如,若是您在 Alpha 混合動畫的每一幀期間,在 for 循環的最內層分配多個對象,則可能會使內存堆受到大量對象的影響。在這種狀況下,垃圾回收器會執行多個垃圾回收事件,並可能下降應用的性能。
共享內存
共享內存
爲了在 RAM 中容納所需的一切,Android 會嘗試跨進程共享 RAM 頁面。它能夠經過如下方式實現這一點:
每一個應用進程都從一個名爲 Zygote 的現有進程分叉。系統啓動並加載通用框架代碼和資源(如 Activity 主題背景)時,Zygote 進程隨之啓動。爲啓動新的應用進程,系統會分叉 Zygote 進程,而後在新進程中加載並運行應用代碼。這種方法使爲框架代碼和資源分配的大多數 RAM 頁面可在全部應用進程之間共享。大多數靜態數據會內存映射到一個進程中。這種方法使得數據不只能夠在進程之間共享,還能夠在須要時換出。靜態數據示例包括:Dalvik 代碼(經過將其放入預先連接的 .odex 文件中進行直接內存映射)、應用資源(經過將資源表格設計爲可內存映射的結構以及經過對齊 APK 的 zip 條目)和傳統項目元素(如 .so 文件中的原生代碼)。在不少地方,Android 使用明確分配的共享內存區域(經過 ashmem 或 gralloc)在進程間共享同一動態 RAM。例如,窗口 surface 使用在應用和屏幕合成器之間共享的內存,而光標緩衝區則使用在內容提供器和客戶端之間共享的內存。
分配與回收應用內存
分配與回收應用內存
Dalvik 堆侷限於每一個應用進程的單個虛擬內存範圍。這定義了邏輯堆大小,該大小能夠根據須要增加,但不能超過系統爲每一個應用定義的上限。
堆的邏輯大小與堆使用的物理內存量不一樣。在檢查應用堆時,Android 會計算按比例分攤的內存大小 (PSS) 值,該值同時考慮與其餘進程共享的髒頁和乾淨頁,但其數量與共享該 RAM 的應用數量成正比。此 (PSS) 總量是系統認爲的物理內存佔用量。有關 PSS 的詳情,請參閱調查 RAM 使用量指南。
Dalvik 堆不壓縮堆的邏輯大小,這意味着 Android 不會對堆進行碎片整理來縮減空間。只有當堆末尾存在未使用的空間時,Android 才能縮減邏輯堆大小。可是,系統仍然能夠減小堆使用的物理內存。垃圾回收以後,Dalvik 遍歷堆並查找未使用的頁面,而後使用 madvise 將這些頁面返回給內核。所以,大數據塊的配對分配和解除分配應該使全部(或幾乎全部)使用的物理內存被回收。可是,從較小分配量中回收內存的效率要低得多,由於用於較小分配量的頁面可能仍在與其餘還沒有釋放的數據塊共享。
限制應用內存
限制應用內存
爲了維持多任務環境的正常運行,Android 會爲每一個應用的堆大小設置硬性上限。不一樣設備的確切堆大小上限取決於設備的整體可用 RAM 大小。若是您的應用在達到堆容量上限後嘗試分配更多內存,則可能會收到 OutOfMemoryError。
在某些狀況下,例如,爲了肯定在緩存中保存多少數據比較安全,您可能須要查詢系統以肯定當前設備上確切可用的堆空間大小。您能夠經過調用 getMemoryClass() 向系統查詢此數值。此方法返回一個整數,表示應用堆的可用兆字節數。
切換應用
切換應用
當用戶在應用之間切換時,Android 會將非前臺應用保留在緩存中。非前臺應用就是指用戶看不到或未運行前臺服務(如音樂播放)的應用。例如,當用戶首次啓動某個應用時,系統會爲其建立一個進程;可是當用戶離開此應用時,該進程不會退出。系統會將該進程保留在緩存中。若是用戶稍後返回該應用,系統就會重複使用該進程,從而加快應用切換速度。
若是您的應用具備緩存的進程且保留了目前不須要的資源,那麼即便用戶未使用您的應用,它也會影響系統的總體性能。當系統資源(如內存)不足時,它將會終止緩存中的進程。系統還會考慮終止佔用最多內存的進程以釋放 RAM。
以上內容爲官方內容,可從官網查閱:
強調內存釋放的重要性而且建議從如下幾點優化應用內存使用:
監控可用內存和內存使用量
使用內存效率更高的代碼結構
移除會佔用大量內存的資源和庫
夯實基礎,關注前沿,娛樂生活
掌握更多前沿技術,獲取更多笑點
請關注--------喘口仙氣
本文分享自微信公衆號 - 喘口仙氣(gh_db8538619cdd)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。