Android 內存管理詳解

2021-02-24 程式設計師Android

和你一起終身學習,這裡是程式設計師Android

經典好文推薦,通過閱讀本文,您將收穫以下知識點:

一、Android 垃圾回收機制(GC)
二、共享內存
三、內存的申請與回收
四、內存限制
五、不同App切換時的內存管理

Android Runtime(ART)和Dalvik虛擬機使用 分頁 和 內存映射 來管理內存。這意味著應用程式修改的任何內存(無論是通過分配新對象通過映射頁面)都將保留在RAM中,並且不能被分頁。
應用程式釋放內存的唯一方法是釋放應用程式持有的對象引用,即使垃圾收集器回收(GC)回收內存 。
比如:如果系統想要在其他地方使用該內存,則可以將任何未經修改的映射到mmap中文件(例如代碼)分頁出RAM。

本頁面介紹了Android如何管理應用程式進程和內存分配。有關如何在應用程式中更高效地管理內存的更多信息,請參閱管理您的應用程式的內存。

一、Android 垃圾回收機制(GC)

ART 或 Dalvik虛擬機的託管內存環境會跟蹤每個內存分配情況。一旦它確定一段內存不再被程序使用,它將它釋放回堆(Heap)中,並且不需要程式設計師的任何幹預。回收託管內存環境中未使用內存的機制稱為垃圾回收(GC)。

1.垃圾回收機制的目的

垃圾回收機制的目的:
1.在程序中查找將來不再使用的數據對象(Object)
2.回收這些對象所佔用的內存資源。

Android 內存是一個典型的堆內存(Heap),這意味著系統會根據被分配的對象的預期壽命和大小有不同的分配桶。
例如,最近分配的對象屬於年輕一代。當一個對象保持足夠的活動時間時,它可以被提升到一個老一代,然後是一個永久的時代。

每個堆的生成都有自己佔用內存的上限。任何時候一旦內存即將被填滿,系統就會執行一個垃圾回收事件去試圖釋放內存。垃圾收集的持續時間取決於它正在回收的那個對象以及回收多少個正在活躍的對象。

儘管垃圾器回收的速度相當快,但它仍然可能會影響應用程式的性能。並且你一般不會控制垃圾器回收你代碼事件的時間。
系統垃圾回收機制具有一定運行中的標準,這個標準主要用於確定何時執行垃圾收集。當條件滿足時,系統停止執行進程並開始垃圾收集。

如果垃圾回收發生在密集的處理循環(如動畫)或音樂播放期間,可能會增加處理時間。這種增長可能會推動您的應用程式執行代碼超過推薦的16ms閾值,以實現高效流暢的幀渲染。

此外,您的代碼流可能會執行各種強制垃圾收集事件的工作,或使其持續時間超過正常。例如,如果在alpha混合動畫的每個幀期間在for循環的最內部分配了多個對象,則可能會佔用大量的內存堆,並使用大量對象。在這種情況下,垃圾收集器將執行多個垃圾收集事件,並可能降低應用程式的性能。

有關垃圾收集的更多一般信息,請參閱垃圾收集。

二、共享內存

為了適應不同的RAM需求,Android 嘗試在不同進程之間共享內存,共享內存的方法如下:

1. APP共享Framework框架代碼以及資源

每個APP的進程都是從Zygote進程中分離出來的。
Zygote 進程:
Zygote進程是在系統啟動並加載Framwork框架代碼和資源(如Activity Theme)時開始。要啟動一個新的應用程式進程,系統會從Zygote進程fork分離出來,然後在新進程中加載並運行應用程式的代碼。這種方法允許大部分分配給Framework框架代碼和資源的RAM頁面與所有應用程式進程之間共享。

2. 大多數靜態數據可以跨進程共享

大多數靜態數據被映射到一個進程。這種技術允許數據在進程之間共享,並允許在需要時將其分頁。示例靜態數據包括:Dalvik代碼(通過將其放置在用於直接映射的預連結.odex文件中),應用程式資源(通過將資源表設計為可以被映射的結構以及通過對齊APK的zip條目) 以及.so文件中的本地代碼等傳統項目元素。

3. Android使用顯式分配的共享內存區域(使用ashmem或gralloc)共享同一個動態RAM。

例如,窗口表面使用應用程式和屏幕合成器之間的共享內存,遊標緩衝區使用內容提供者和客戶端之間的共享內存。

由於共享內存的廣泛使用,確定您的應用使用多少內存需要謹慎。在調查您的RAM使用情況中討論了正確確定應用程式內存使用情況的技巧。如需獲取更多內容,請看RAM使用情況分析詳解。

三、APP內存的申請與回收

Dalvik 虛擬機會限制每個應用程式進程的虛擬內存範圍。它定義了邏輯堆的大小,並且可以根據需要增長,但只能達到系統為每個應用程式定義的限制。

堆的邏輯大小與堆使用的物理內存量不同。在檢查應用程式的堆時,Android 會計算一個名為「比例集合大小** Proportion Set Size 」(PSS)** 的值,該值與其他進程共享的髒頁面(Page)和乾淨頁面(Page),並且數量與多少應用程式共享該RAM成正比。(PSS)總數是系統認為是您的物理內存的足跡。有關PSS的更多信息,請參閱RAM使用情況指南。

Dalvik堆不壓縮堆的邏輯大小,這意味著 Android不會整理堆以關閉空間。當堆的末尾有未使用的空間時,Android只能縮小邏輯堆的大小。然而,系統仍然可以減少堆使用的物理內存。在垃圾收集之後,Dalvik遍歷堆並找到未使用的頁面,然後使用madvise將這些頁面返回給內核。
因此,成對的大塊分配和釋放應該會導致所有(或幾乎全部)所使用的物理內存的回收。但是,從小分配中回收內存的效率可能會低得多,因為用於小分配的頁面仍可能與尚未釋放的其他內容共享。

四、APP內存限制

為了維護一個主要的多功能環境,Android 對每個應用程式的堆大小設定了一個硬限制。確切的堆大小限制根據設備有多少RAM可用而有所不同。如果您的應用程式已達到堆容量並嘗試分配更多內存,則可能會收到OutOfMemoryError。

在某些情況下,您可能需要查詢系統以確定在當前設備上有多少堆空間可用 。
例如,確定有多少數據可以安全地保留在緩存中。你可以通過調用getMemoryClass()來查詢這個數字。此方法返回一個整數,指示可用於應用程式堆的兆字節數。

五、不同App切換時的內存管理

當用戶在應用程式之間進行切換時,Android會保留不在前臺的應用程式(即對用戶不可見,或者在最近最少使用(LRU)緩存中運行諸如音樂播放之類的前臺服務)。例如,當用戶第一次啟動應用程式時,會為其創建一個進程; 但是當用戶離開應用程式時,該過程不會退出。系統保持進程緩存。如果用戶稍後返回到應用程式,系統將重新使用該進程,從而使應用程式切換更快。

如果您的應用程式具有緩存的進程,並且保留了當前不需要的內存,那麼您的應用程式(即使用戶不使用它)也會影響系統的整體性能。由於系統內存不足,它會以最近使用最少的進程開始,終止LRU緩存中的進程。系統也考慮到保存最多內存的進程,並可以終止它們以釋放RAM。

注意:當系統開始在LRU緩存中查殺進程時,它主要是自下而上的。系統也考慮哪些進程消耗更多的內存,從而為系統提供更多的內存增益。在整個LRU列表中消耗的內存越少,留在列表中的機會就越好,並能夠快速恢復。

友情推薦:

Android 開發乾貨集錦

至此,本篇已結束。轉載網絡的文章,小編覺得很優秀,歡迎點擊閱讀原文,支持原創作者,如有侵權,懇請聯繫小編刪除,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!

點個在看,方便您使用時快速查找!

相關焦點

  • 最全的Android內存優化技巧
    本文主要介紹性能優化的一些手段,但是為了便於理解以及融會貫通,建議先了解Android內存管理機制,本文將從四個角度來介紹內存優化技巧減小對象的內存佔用儘量減少新分配出來的對象佔用內存的大小,使用更加輕量的對象1.
  • Android性能優化:帶你全面實現內存優化
    定義優化處理 應用程式的內存使用、空間佔用2. 作用避免因不正確使用內存 & 缺乏管理,從而出現 內存洩露(ML)、內存溢出(OOM)、內存空間佔用過大 等問題,最終導致應用程式崩潰(Crash)3.
  • android內存優化總結
    使用腳本每隔1s輸出對應包的PSS值PSS的定義是:Proportional Set Size 實際使用的物理內存(比例分配共享庫佔用的內存);共享內存則是:framework的代碼與資源在ram中佔有的內存。
  • Apache Spark 統一內存管理模型詳解
    轉載自 過往記憶(https://www.iteblog.com/) 本文連結:  【Apache Spark 統一內存管理模型詳解】(https://www.iteblog.com/archives/2342.html)本文將對 Spark 的內存管理模型進行分析,下面的分析全部是基於 Apache Spark 2.2.1
  • 如何自學Android, 教大家玩爆Android
    內存存儲將數據存儲在內存中,讀取速度最快但是不能永久性存儲。文件存儲通過Java的IO流將數據以文件的形式存儲在磁碟上。這幾個內容可以參考下面幾篇博文: Android HttpClient Android_HttpURLConnection_Get和Post請求 基於android的Socket通信 android WebView總結關於HttpClient,HttpURLConnection部分也可以參考郭霖的《第一行代碼》中的相關部分。
  • Android避免內存溢出(Out of Memory)方法總結
    當內存空間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內存不足的問題。軟引用:如果一個對象只具有軟引用,但內存空間足夠時,垃圾回收器就不會回收它;直到虛擬機報告內存不夠時才會回收, 只要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存。
  • Oracle自動內存管理SGA、PGA詳解
    MMON 使用內存指導。將內存移到 MMAN 最迫切需要的地方。如果使用 SPFILE:在關閉時保存組件大小 、保存的值用於引導程序組件大小 、無需再確定最佳值自動共享內存管理功能使用由以下兩個後臺進程實施的 SGA 內存中介:可管理性監視器 (MMON) 和內存管理器 (MMAN)。MMON 定期將統計信息和內存指導數據捕獲到內存中。
  • Android性能優化--內存優化
    上述三者之間的是一個遞進關係,內存抖動<內存洩露<內存溢出。對於一般應用主要是處理內存抖動和內存洩露兩點,處理好這兩點就會大大降低內存溢出的可能性。3.內存管理3.1 Java內存管理JVM的內存回收對於大多數開發者來說接觸的並不是很多。
  • Android開發必備的「80」個開源庫
    Android Developerhttps://developer.android.google.cn/Android Training 中文版http://hukai.me/android-training-course-in-chinese/index.htmlMaterial Design 中文版http
  • Linux內存、Swap、Cache、Buffer詳解(三)
    咱接著Linux內存、Swap、Cache、Buffer詳解(二)聊,前面提到Linux 內核會在內存將要耗盡時觸發內存自動回收工作。
  • Android性能優化:手把手帶你全面實現內存優化
    定義優化處理 應用程式的內存使用、空間佔用2. 作用避免因不正確使用內存 & 缺乏管理,從而出現 內存洩露(ML)、內存溢出(OOM)、內存空間佔用過大 等問題,最終導致應用程式崩潰(Crash)3. 儲備知識:Android 內存管理機制3.1 簡介
  • Android 內存洩漏探討
    了解了 Java 的內存分配之後,我們再來看看 Java 是怎麼管理內存的。Java是如何管理內存Java的內存管理就是對象的分配和釋放問題。在 Java 中,程式設計師需要通過關鍵字 new 為每個對象申請內存空間 (基本類型除外),所有的對象都在堆 (Heap)中分配空間。另外,對象的釋放是由 GC 決定和執行的。
  • 圖文詳解 Android Binder跨進程通信的原理
    而 Binder的作用則是:連接 兩個進程,實現了mmap()系統調用,主要負責 創建數據接收的緩存空間 & 管理數據接收緩存b. 註:傳統的跨進程通信需拷貝數據2次,但 Binder機制只需1次,主要是使用到了內存映射,具體下面會詳細說明2.5 內存映射3.
  • android布局詳解專題及常見問題 - CSDN
    Android 布局詳解1.重用布局當一個布局文件被多處使用時,最好<include>標籤來重用布局。  <include android:id=」@+id/cell3 layout=」@layout/workspace_screen」 /></LinearLayout>  上面的代碼中的<include>標籤還使用了一個android:id屬性,實際上,該屬性指定的是workspace_screen.xml布局文件中的根節點的android
  • Android 性能優化之內存洩漏,使用MAT&LeakCanary解決問題
    ,內存這個小妮子比較調皮,每個月總有那麼幾次洩漏或者溢出(OOM),這篇文章所講的是內存溢出,這裡要注意,內存溢出和內存洩漏是兩個概念,這點大家要清楚,當然,內存洩漏過多會導致內存洩漏,至於什麼是內存洩漏呢,大家都知道我們的內存回收機制是GC,所以用一句話來概括:GC回收機制所無法回收的垃圾對象。
  • 詳解 Android 是如何啟動的
    分區功能boot系統引導分區,包含著android 內核,系統沒有這個無法啟動。這一部分的鏡像在 boot unlocked 時,也能夠被擦除,但在這個過程中,不能被打斷,關機等等,否者會導致系統無法啟動。
  • Android Study之跳轉自啟動管理頁
    同時也為大家通過幾種不同方式去實現跳轉,大家可以仔細查看代碼~package cn.hle.skipselfstartmanager.util;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.net.Uri
  • Android Systrace 基礎知識(7) - Vsync 解讀
    [3]Systrace 基礎知識 - SystemServer 解讀[4]Systrace 基礎知識 - SurfaceFlinger 解讀[5]Systrace 基礎知識 - Input 解讀[6]Systrace 基礎知識 - Vsync 解讀[7]Systrace 基礎知識 - Vsync-App :基於 Choreographer 的渲染機制詳解[8]Systrace 基礎知識 - MainThread
  • Android開發5年,技術增長乏力,你差點什麼?
    其實,多線程使用最多的場景就是網絡請求中,而網絡往往就被我們以retrofit或者okhttp替代了,但是它底層卻大量在運用多線程;JVM就更不用說了,雖然我們普通的開發涉及不到JVM,然而App性能與它有著千絲萬縷的聯繫,每個App都會有自己的art虛擬機,甚至每一個進程都是有自己獨立的虛擬機,內存的回收是由虛擬機來管理的,GC回收算法怎樣,adj內存管理,這一切都基於虛擬機,那麼
  • Android架構學習資料
    ~Google官方出品Google官方出品:android-architecture其他的一些文章、Demo、App:文章淺談Andorid開發中的MVP模式  MVP IN ANDROID, PART 1MVP IN ANDROID, PART 2MVP IN ANDROID, PART 3