|
Android Runtime(ART)和Dalvik虛擬機使用 分頁 和 內(nèi)存映射 來管理內(nèi)存。 這意味著應用程序修改的任何內(nèi)存(無論是通過分配新對象通過映射頁面)都將保留在RAM中,并且不能被分頁。 應用程序釋放內(nèi)存的唯一方法是釋放應用程序持有的對象引用,即使垃圾收集器回收(GC)回收內(nèi)存 。 比如:如果系統(tǒng)想要在其他地方使用該內(nèi)存,則可以將任何未經(jīng)修改的映射到mmap中文件(例如代碼)分頁出RAM。
本頁面介紹了Android如何管理應用程序進程和內(nèi)存分配。 有關如何在應用程序中更高效地管理內(nèi)存的更多信息,請參閱管理您的應用程序的內(nèi)存。 本篇文章主要介紹 Android 開發(fā)中的部分知識點,通過閱讀本篇文章,您將收獲以下內(nèi)容: 1.Android 垃圾回收機制(GC) 2.共享內(nèi)存 3.內(nèi)存的申請與回收 4.內(nèi)存限制 5.不同App切換時的內(nèi)存管理
希望看到這里的您 有任何需要都可以私信我哦
1.Android 垃圾回收機制(GC)ART 或 Dalvik虛擬機的托管內(nèi)存環(huán)境會跟蹤每個內(nèi)存分配情況。 一旦它確定一段內(nèi)存不再被程序使用,它將它釋放回堆(Heap)中,并且不需要程序員的任何干預。 回收托管內(nèi)存環(huán)境中未使用內(nèi)存的機制稱為垃圾回收(GC)。 垃圾收集有兩個目的: 1.在程序中查找將來不再使用的數(shù)據(jù)對象(Object) 2.回收這些對象所占用的內(nèi)存資源。 Android 的內(nèi)存是一個典型的堆內(nèi)存(Heap),這意味著系統(tǒng)會根據(jù)被分配的對象的預期壽命和大小有不同的分配桶。 例如,最近分配的對象屬于年輕一代。 當一個對象保持足夠的活動時間時,它可以被提升到一個老一代,然后是一個永久的世代。 每個堆的生成都有自己占用內(nèi)存的上限。任何時候一旦內(nèi)存即將被填滿,系統(tǒng)就會執(zhí)行一個垃圾回收事件去試圖釋放內(nèi)存。垃圾收集的持續(xù)時間取決于它正在回收的那個對象以及回收多少個正在活躍的對象。 盡管垃圾器回收的速度相當快,但它仍然可能會影響應用程序的性能。并且你一般不會控制垃圾器回收你代碼事件的時間。 系統(tǒng)垃圾回收機制具有一定運行中的標準,這個標準主要用于確定何時執(zhí)行垃圾收集。當條件滿足時,系統(tǒng)停止執(zhí)行進程并開始垃圾收集。 如果垃圾回收發(fā)生在密集的處理循環(huán)(如動畫)或音樂播放期間,可能會增加處理時間。這種增長可能會推動您的應用程序執(zhí)行代碼超過推薦的16ms閾值,以實現(xiàn)高效流暢的幀渲染。 此外,您的代碼流可能會執(zhí)行各種強制垃圾收集事件的工作,或使其持續(xù)時間超過正常。例如,如果在alpha混合動畫的每個幀期間在for循環(huán)的最內(nèi)部分配了多個對象,則可能會占用大量的內(nèi)存堆,并使用大量對象。在這種情況下,垃圾收集器將執(zhí)行多個垃圾收集事件,并可能降低應用程序的性能。 有關垃圾收集的更多一般信息,請參閱垃圾收集。 2.共享內(nèi)存為了適應不同的RAM需求,Android 嘗試在不同進程之間共享內(nèi)存,共享內(nèi)存的方法如下: 每個APP的進程都是從Zygote進程中分離出來的。 Zygote 進程:
Zygote進程是在系統(tǒng)啟動并加載Framwork框架代碼和資源(如Activity Theme)時開始。 要啟動一個新的應用程序進程,系統(tǒng)會從Zygote進程fork分離出來,然后在新進程中加載并運行應用程序的代碼。 這種方法允許大部分分配給Framework框架代碼和資源的RAM頁面與所有應用程序進程之間共享。 大多數(shù)靜態(tài)數(shù)據(jù)可以跨進程共享
大多數(shù)靜態(tài)數(shù)據(jù)被映射到一個進程。這種技術允許數(shù)據(jù)在進程之間共享,并允許在需要時將其分頁。 示例靜態(tài)數(shù)據(jù)包括:Dalvik代碼(通過將其放置在用于直接映射的預鏈接.odex文件中),應用程序資源(通過將資源表設計為可以被映射的結構以及通過對齊APK的zip條目) 以及.so文件中的本地代碼等傳統(tǒng)項目元素。 Android使用顯式分配的共享內(nèi)存區(qū)域(使用ashmem或gralloc)共享同一個動態(tài)RAM。
例如,窗口表面使用應用程序和屏幕合成器之間的共享內(nèi)存,游標緩沖區(qū)使用內(nèi)容提供者和客戶端之間的共享內(nèi)存。 由于共享內(nèi)存的廣泛使用,確定您的應用使用多少內(nèi)存需要謹慎。 在調(diào)查您的RAM使用情況中討論了正確確定應用程序內(nèi)存使用情況的技巧。如需獲取更多內(nèi)容,請看RAM使用情況分析詳解。 3.APP內(nèi)存的申請與回收Dalvik 虛擬機會限制每個應用程序進程的虛擬內(nèi)存范圍。它定義了邏輯堆的大小,并且可以根據(jù)需要增長,但只能達到系統(tǒng)為每個應用程序定義的限制。
堆的邏輯大小與堆使用的物理內(nèi)存量不同。在檢查應用程序的堆時,Android 會計算一個名為“比例集合大小** Proportion Set Size ”(PSS)** 的值,該值與其他進程共享的臟頁面(Page)和干凈頁面(Page),并且數(shù)量與多少應用程序共享該RAM成正比。(PSS)總數(shù)是系統(tǒng)認為是您的物理內(nèi)存的足跡。有關PSS的更多信息,請參閱RAM使用情況指南。 Dalvik堆不壓縮堆的邏輯大小,這意味著 Android不會整理堆以關閉空間。當堆的末尾有未使用的空間時,Android只能縮小邏輯堆的大小。然而,系統(tǒng)仍然可以減少堆使用的物理內(nèi)存。在垃圾收集之后,Dalvik遍歷堆并找到未使用的頁面,然后使用madvise將這些頁面返回給內(nèi)核。 因此,成對的大塊分配和釋放應該會導致所有(或幾乎全部)所使用的物理內(nèi)存的回收。但是,從小分配中回收內(nèi)存的效率可能會低得多,因為用于小分配的頁面仍可能與尚未釋放的其他內(nèi)容共享。
4.APP內(nèi)存限制為了維護一個主要的多功能環(huán)境,Android 對每個應用程序的堆大小設定了一個硬限制。 確切的堆大小限制根據(jù)設備有多少RAM可用而有所不同。 如果您的應用程序已達到堆容量并嘗試分配更多內(nèi)存,則可能會收到OutOfMemoryError。 在某些情況下,您可能需要查詢系統(tǒng)以確定在當前設備上有多少堆空間可用 。 例如,確定有多少數(shù)據(jù)可以安全地保留在緩存中。 你可以通過調(diào)用getMemoryClass()來查詢這個數(shù)字。 此方法返回一個整數(shù),指示可用于應用程序堆的兆字節(jié)數(shù)。 5.不同App切換時的內(nèi)存管理當用戶在應用程序之間進行切換時,Android會保留不在前臺的應用程序(即對用戶不可見,或者在最近最少使用(LRU)緩存中運行諸如音樂播放之類的前臺服務)。 例如,當用戶第一次啟動應用程序時,會為其創(chuàng)建一個進程; 但是當用戶離開應用程序時,該過程不會退出。 系統(tǒng)保持進程緩存。 如果用戶稍后返回到應用程序,系統(tǒng)將重新使用該進程,從而使應用程序切換更快。 如果您的應用程序具有緩存的進程,并且保留了當前不需要的內(nèi)存,那么您的應用程序(即使用戶不使用它)也會影響系統(tǒng)的整體性能。 由于系統(tǒng)內(nèi)存不足,它會以最近使用最少的進程開始,終止LRU緩存中的進程。 系統(tǒng)也考慮到保存最多內(nèi)存的進程,并可以終止它們以釋放RAM。 注意:當系統(tǒng)開始在LRU緩存中查殺進程時,它主要是自下而上的。 系統(tǒng)也考慮哪些進程消耗更多的內(nèi)存,從而為系統(tǒng)提供更多的內(nèi)存增益。 在整個LRU列表中消耗的內(nèi)存越少,留在列表中的機會就越好,并能夠快速恢復。
|