擷取記憶體快照資料,查看在擷取時,應用程式中有哪些物件正在占用記憶體,並找出記憶體流失或記憶體配置行為,這些行為會導致延遲、凍結,甚至應用程式異常終止。尤其是在長時間使用者工作階段之後,記憶體快照資料可顯示您認為不應位於記憶體中、但仍位於記憶體中的物件,藉此找出記憶體流失情形。
本頁說明 Android Studio 提供的工具,可用於收集及分析記憶體快照資料。或者,您也可以在指令列中使用 dumpsys 檢查應用程式記憶體,並查看 Logcat 中的垃圾收集 (GC) 事件。
為什麼要分析應用程式記憶體
Android 提供受管理記憶體環境;當 Android 判定應用程式不再使用部分物件時,垃圾收集器就會將未使用的記憶體釋放回堆積中。我們正持續改善 Android 尋找未使用記憶體的運作機制,不過在所有 Android 版本中,系統有時會暫停執行您的程式碼。在多數情況下,這類暫停情形不易察覺。不過,如果應用程式配置記憶體的速度勝過於系統收集記憶體的速度,即使收集器釋出足以滿足配置需求的記憶體,應用程式仍可能會發生延遲情形。這類延遲可能會導致應用程式略過影格,並讓顯示畫面變慢。
即使應用程式執行速度沒有變慢,但如果發生記憶體流失情形,應用程式在背景中運作時仍會保留該記憶體。這個行為會強制執行不必要的垃圾收集事件,因而降低其餘的系統記憶體效能。系統最後會強制終止應用程式程序來回收記憶體。之後,當使用者返回應用程式時,應用程式程序就必須完全重新啟動。
如要進一步瞭解可減少應用程式記憶體用量的程式設計做法,請參閱「[管理應用程式的記憶體]記憶體」。
記憶體快照資料總覽
如要擷取記憶體快照資料,請選取「Analyze Memory Usage (Heap Dump)」工作 (使用「Profiler: run 'app' as debuggable (complete data)」)。擷取記憶體快照資料時,Java 記憶體用量可能會暫時增加。這是正常現象,因為記憶體快照資料會在與應用程式相同的程序中發生,因此需要一些記憶體來收集資料。擷取記憶體快照資料後,您會看到以下內容:
類別清單會顯示下列資訊:
- Allocations:堆積中的配置數量。
Native Size:該物件類型使用的原生記憶體總量 (以位元組為單位)。這裡會顯示 Java 中已配置的部分物件,因為 Android 會針對某些架構類別 (例如
Bitmap) 使用原生記憶體。淺層大小:該物件類型使用的 Java 記憶體總量 (以位元組為單位)。
保留大小:該類別的所有執行個體所保留的記憶體總大小 (以位元組為單位)。
使用堆積選單篩選特定堆積:
- 應用程式堆積 (預設):主要堆積,應用程式會在這個堆積上配置記憶體。
- 映像檔堆積:系統開機映像檔,包含開機期間已預先載入的類別。此處的配置絕不會移動或消失。
- Zygote heap:Android 系統中寫入時複製的堆積,應用程式的程序是從這個堆積分支而來。
使用排列下拉式選單,選擇配置的安排方式:
- Arrange by class (default):根據類別名稱將所有配置分組。
- Arrange by package:根據套件名稱將所有配置分組。
使用類別下拉式選單,篩選出特定類別群組:
- All classes (default):顯示所有類別,包括程式庫和依附元件中的類別。
- 顯示活動/片段流失:顯示導致記憶體流失的類別。
- 「Show project classes」:只顯示專案定義的類別。
按一下類別名稱,開啟「Instance」窗格。所列的每種執行個體都包含下列項目:
- Depth:從任何 GC 根目錄到所選執行個體的最短躍點。
- Native Size:原生記憶體中該執行個體的大小。只有 Android 7.0 以上版本才會顯示這個資料欄。
- Shallow Size:Java 記憶體中該執行個體的大小。
- 保留大小:該執行個體支配的記憶體大小 (請參閱「支配樹狀圖」)。
按一下執行個體,即可顯示「Instance Details」,包括「Fields」和「References」。常見的欄位和參照類型包括 Java 中的結構化類型
、陣列
和原始資料類型
。在欄位或參照上按一下滑鼠右鍵,即可前往原始碼中的相關例項或行。
- 欄位:顯示這個執行個體中的所有欄位。
- References:顯示「Instance」分頁中醒目顯示物件的所有參照。
偵測重複的點陣圖
從 Android Studio Narwhal 4 開始,您也可以在記憶體快照資料檢視畫面中偵測多餘的點陣圖。
以下是獵殺方法:
- 在 Android Studio 中開啟「Profiler」分頁
- 按一下「記憶體快照資料」 (或「記憶體用量」),然後按一下「Record」,擷取應用程式目前記憶體狀態的快照。
- 掃描分析結果,找出黃色警告三角形 ⚠️,Android Studio 會使用這個符號標記多次儲存的重複點陣圖。
- 或者,您也可以前往分析器標頭,選擇「Filter by:」,然後選取「Duplicate Bitmaps」設定。
- 按一下任何標記的項目,即可開啟「Bitmap Preview」窗格,查看哪張圖片重複出現。
- 請根據這項視覺確認結果,找出程式碼中多餘的載入邏輯,並實作更完善的快取策略。
找出記憶體流失
如要快速篩選可能與記憶體流失相關的類別,請開啟類別下拉式選單,然後選取「Show activity/fragment leaks」。Android Studio 會顯示可能導致應用程式中 Activity 和 Fragment 執行個體記憶體流失的類別。
如要手動尋找記憶體流失,請瀏覽類別和執行個體清單,找出保留大小較大的物件。請注意下列任一原因所導致的記憶體流失情形:
Activity或Context的長期參照,可能會洩漏託管的 Compose 組合圖 (例如ComposeView及其子可組合項)。- 洩漏 Jetpack Compose 狀態物件 (
MutableState)、狀態容器或擷取Context的 lambda。 - 忘記在
DisposableEffect的onDispose區塊中清除事件監聽器或觀察器。 - 可保留
Activity執行個體的非靜態內部類別 (例如Runnable)。 - 保留物件超過必要時間的快取。
發現潛在的記憶體流失問題時,請使用「Instance Details」中的「Fields」和「References」分頁,跳至相關的執行個體或原始碼行。
觸發記憶體流失以進行測試
如要分析記憶體用量,請對應用程式程式碼施加壓力,並嘗試強制發生記憶體流失問題。如要在應用程式中引發記憶體流失,其中一個方法就是在檢查堆積前先讓應用程式運作一段時間。記憶體流失情形可能會逐漸蔓延至堆積中的配置頂部。不過,流失情形越少,就需要更長的應用程式執行時間,以便觀察流失情形。
您也可以透過下列任一方式觸發記憶體流失:
- 在不同的活動狀態下,將裝置從直向轉為橫向再轉回直向,依此多次反覆執行。如果應用程式在非同步作業或狀態容器中保留
Activity或Context的參照,旋轉裝置通常會導致應用程式流失Activity(以及其託管的 Compose UI 樹狀結構和相關聯的狀態樹狀結構)。 - 在不同的活動狀態下,在您的應用程式與其他應用程式之間切換。例如,前往主畫面,然後返回應用程式。
匯出及匯入記憶體快照資料記錄
您可以在分析器的「Past Recordings」分頁中匯出及匯入記憶體快照資料檔案。Android Studio 會將錄製內容儲存為 .hprof 檔案。
或者,如要使用其他 .hprof 檔案分析工具 (例如 jhat),您必須將 .hprof 檔案從 Android 格式轉換為 Java SE .hprof 檔案格式。如要轉換檔案格式,請使用 {android_sdk}/platform-tools/ 目錄中提供的 hprof-conv 工具。接著執行含有兩個引數 (原始 .hprof 檔案名稱和已轉換 .hprof 檔案寫入位置,包括新的 .hprof 檔案名稱) 的 hprof-conv 指令,例如:
hprof-conv heap-original.hprof heap-converted.hprof