擷取記憶體快照資料

擷取記憶體快照資料,查看應用程式中有哪些物件正在使用記憶體,並找出記憶體流失或導致應用程式延遲、凍結甚至異常終止的記憶體配置行為。在長時間使用者工作階段後擷取記憶體快照資料特別有用,因為這時記憶體中可能仍有物件,但這些物件不應再存在。

本頁說明 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 heap:Android 系統中寫入時複製的堆積,應用程式的程序是從這個堆積分支而來。

使用排序下拉式選單,選擇配置的排序方式:

  • Arrange by class (預設):根據類別名稱將所有配置分組。
  • Arrange by package:根據套件名稱將所有配置分組。

使用班級下拉式選單篩選班級群組:

  • 所有類別 (預設):顯示所有類別,包括來自程式庫和依附元件的類別。
  • 顯示活動/片段洩漏:顯示導致記憶體洩漏的類別。
  • 顯示專案類別:只顯示專案定義的類別。

按一下類別名稱,開啟「Instance」窗格。每個列出的例項都包含下列項目:

  • Depth:從任何 GC 根目錄到所選執行個體的最短躍點。
  • Native Size:原生記憶體中該執行個體的大小。只有 Android 7.0 以上版本才會顯示這個資料欄。
  • Shallow Size:Java 記憶體中該執行個體的大小。
  • Retained Size:該執行個體支配的記憶體大小 (請參閱「支配樹狀圖」)。

按一下要檢查的執行個體,即可顯示「Instance Details」(執行個體詳細資料),包括其「Fields」(欄位)和「References」(參照)。常見的欄位和參照類型是 Java 中的結構化類型 、陣列 和原始資料類型 。在欄位或參照上按一下滑鼠右鍵,即可前往原始碼中的相關例項或行。

  • 欄位:顯示這個例項中的所有欄位。
  • 參照:顯示「Instance」分頁中所醒目顯示物件的所有參照。

找出記憶體流失

如要快速篩選可能與記憶體流失相關的類別,請開啟類別下拉式選單,然後選取「Show activity/fragment leaks」。Android Studio 會顯示其認為代表應用程式中的 ActivityFragment 例項導致記憶體流失的類別。篩選器會顯示的資料類型包括:

  • 已遭刪除但仍受參照的 Activity 執行個體。
  • 不含有效 FragmentManager 但仍受參照的 Fragment 執行個體。

請注意,在下列情況下,篩選器可能會產生偽陽性結果:

  • Fragment 已建立但尚未使用。
  • Fragment 已快取,但不屬於 FragmentTransaction

如要手動查看記憶體外洩情形,請瀏覽類別和例項清單,找出「Retained Size」過大的物件。請注意下列任一原因所導致的記憶體流失情形:

  • 長時間參照 ActivityContextViewDrawable 以及可能會保留 ActivityContext 容器參照的其他物件。
  • 可保留 Activity 例項的非靜態內部類別 (例如 Runnable)。
  • 保留物件超過必要時間的快取。

發現潛在的記憶體外洩問題時,請使用「Instance Details」中的「Fields」和「References」分頁,跳至所需的執行個體或原始程式碼行。

觸發記憶體流失問題以進行測試

如要分析記憶體用量,請對應用程式程式碼施加壓力,並嘗試強制發生記憶體流失問題。如要在應用程式中引發記憶體流失,其中一個方法就是在檢查堆積前先讓應用程式運作一段時間。記憶體流失情形可能會逐漸蔓延至堆積中的配置頂部。不過,流失情形越少,就需要更長的應用程式執行時間,以便觀察流失情形。

您也可以透過下列任一方式觸發記憶體流失:

  • 在不同的活動狀態下,將裝置從直向轉為橫向再轉回直向,依此多次反覆執行。旋轉裝置經常會導致應用程式的 ActivityContextView 物件流失,這是因為系統會重新建立 Activity,而且如果應用程式在其他位置保留其中任一物件的參照,系統將無法執行垃圾收集。
  • 在不同的活動狀態下,在您的應用程式與其他應用程式之間切換。例如前往主畫面,然後返回應用程式。

匯出及匯入堆積快照錄製內容

您可以從分析器的「過去記錄」分頁匯出及匯入快照資料檔案。Android Studio 會將錄製內容儲存為 .hprof 檔案。

或者,如要使用其他 .hprof 檔案分析工具 (例如 jhat),您必須將 .hprof 檔案從 Android 格式轉換為 Java SE .hprof 檔案格式。如要轉換檔案格式,請使用 {android_sdk}/platform-tools/ 目錄中提供的 hprof-conv 工具。接著執行含有兩個引數 (原始 .hprof 檔案名稱和已轉換 .hprof 檔案寫入位置) 的 hprof-conv 指令,包括新的 .hprof 檔案名稱。例如:

hprof-conv heap-original.hprof heap-converted.hprof