擷取記憶體快照資料,查看應用程式中有哪些物件在擷取時正在使用記憶體,並找出記憶體流失情形,或導致延遲、沒有回應,甚至應用程式異常終止的記憶體配置行為。尤其是在長時間使用者工作階段之後,記憶體快照資料可顯示您認為不應位於記憶體中、但仍位於記憶體中的物件,藉此找出記憶體流失情形。
本頁說明 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) 使用原生記憶體。Shallow Size:該物件類型使用的 Java 記憶體總量 (以位元組為單位)。
Retained Size:該類別的所有執行個體所保留的記憶體總大小 (以位元組為單位)。
使用堆積選單篩選特定堆積:
- 應用程式堆積 (預設):應用程式配置記憶體的主要堆積。
- 映像檔堆積:系統開機映像檔,包含開機期間預先載入的類別。此處的配置絕不會移動或消失。
- Zygote 堆積:Android 系統中寫入時複製的堆積,應用程式的程序是從這個堆積分支而來。
使用「配置」下拉式選單,選擇配置的安排方式:
- Arrange by class (default):根據類別名稱將所有配置分組。
- Arrange by package:根據套件名稱將所有配置分組。
使用課程下拉式選單,依課程群組篩選:
- 所有類別 (預設):顯示所有類別,包括程式庫和依附元件中的類別。
- 顯示活動/片段記憶體流失:顯示導致記憶體流失的類別。
- 顯示專案類別:只顯示專案定義的類別。
按一下類別名稱即可開啟「Instance」窗格。所列的每種執行個體都包含下列項目:
- Depth:從任何 GC 根目錄到所選執行個體的最短躍點。
- Native Size:原生記憶體中該執行個體的大小。只有 Android 7.0 以上版本才會顯示這個資料欄。
- Shallow Size:Java 記憶體中該執行個體的大小。
- Retained Size:該執行個體支配的記憶體大小 (請參閱「支配樹狀圖」)。
按一下執行個體,即可顯示「執行個體詳細資料」,包括「欄位」和「參照」。常見的欄位和參照型別是結構化型別
、陣列
和 Java 中的原始資料型別
。在欄位或參照上按一下滑鼠右鍵,即可前往原始碼中的相關例項或行。
- 欄位:顯示這個執行個體中的所有欄位。
- 參照:顯示「Instance」分頁中醒目顯示的物件的所有參照。
找出記憶體流失問題
如要快速篩選出可能與記憶體流失相關聯的類別,請開啟類別下拉式選單,然後選取「顯示活動/片段流失」。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 樹狀結構和相關聯的狀態樹狀結構)。 - 在不同的活動狀態下,在您的應用程式與其他應用程式之間切換。舉例來說,你可以前往主畫面,然後返回應用程式。
匯出及匯入記憶體快照資料記錄
您現在可以從分析器的「過去的記錄」分頁中匯出及匯入記憶體快照資料檔案。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