1. 程式人生 > >Android Studio 快速定位記憶體洩露的方法

Android Studio 快速定位記憶體洩露的方法

前言

記憶體洩露是指一些生命週期結束的物件,由於一些原因還存在記憶體中,並且不能被GC回收,導致記憶體不斷的增長,最終導致程式卡頓甚至記憶體溢位(俗稱的OOM)。

本文根據Google的官方文件,結合筆者的實際使用情況,介紹瞭如何使用 Android Studio(簡稱AS)自帶的工具對記憶體進行監控、分析,特此記錄。

工具介紹

Memory Monitor 是AS中自帶的一種記憶體監視器,提供了記憶體監控和記憶體分析功能,能夠讓開發者非常方便的檢查App的RAM的使用情況。

這裡寫圖片描述
上圖中,區域D是記憶體的監控介面,其中各個按鈕從左至右的功能如下:

  • Enable:開啟/暫停記憶體監控
  • Initiate GC:點選後執行一次GC操作。
  • Dump Java Heap:Java記憶體堆映象。點選生成一個hprof檔案顯示當前的Java記憶體堆情況
  • Start Application Tracking:跟蹤記憶體使用情況。點選第一次開始跟蹤,點選第二次結束跟蹤並生成alloc檔案。(在本文中不做介紹)
  • Memory monitor help:跳轉到官方幫助文件

引數說明

Memory Monitor引數

引數名 含義
Free 當前程序,剩餘的可用記憶體
Allocated 當前程序,已經使用的記憶體

兩者相加,就是此時App分配給當前程序的可用記憶體總量,這一總量會隨著記憶體使用的情況發生變化,當總量超過App允許的最大記憶體使用量時,就會出現OOM。

hprof檔案引數

hprof 檔案是某個時間點的記憶體分析檔案,記錄了當前時間點的記憶體分配、使用情況,從這個檔案中,我們可以檢查出大多數的記憶體洩露場景,並快速的定位到造成記憶體洩露的原因。下面是這個檔案的一些引數的含義的介紹:

引數名 含義
Class Name 儲存在記憶體中的物件名稱
Total Count 在記憶體中存在的物件的個數
Heap Count 在堆記憶體中存在的物件的個數
Sizeof 每個物件佔用的記憶體大小
Shallow Size 當前物件自身佔用的記憶體大小
Retained Size 當前物件保留的記憶體大小
Instance 當前物件在記憶體中的例項
Reference Tree 當前例項的引用列表
Depth GC Root 到當前例項的最小權重
Dominating Size 當前例項可支配的大小

關於這些引數解釋,還有下面幾點需要注意:

  1. Total Count 和 Heap Count 不同的原因是因為Java的記憶體分為堆記憶體和棧記憶體,其中 Heap Count 是指在堆記憶體中的儲存個數。堆記憶體是由Java的記憶體回收機制管理的,應用對於記憶體的分析和優化也是基於堆記憶體的,所以我們需要關注的也是 Heap Count 的值。

  2. Retained Size 意思是保留的記憶體大小,也是指的當前物件如果被GC後堆上能釋放的大小,和 Shallow Size 相比,它的大小包括了當前物件引用的一些物件的大小,這兩種大小的具體解釋可以看看這篇文章:Shallow heap & Retained heap

  3. 深度這個引數表示的是從 GC Root 到選定例項的最短的跳轉(這裡的跳轉可理解成從一個類找到另一個類),在分析 Reference Tree 時可以根據這個值展開對應的項(比如說這個值是5,你就在 Reference Tree 中找4,然後找3,一直到0,既可以找到被 GC Root 持有的例項)

使用詳解

使用 hprof 檔案進行分析

在介紹引數時我提到過,可以通過分析 hprof 檔案來快速的定位程式碼中簡單的記憶體洩露,所謂的簡單的記憶體洩露,就是由於 Activity 造成的記憶體洩露。

Activity 造成的記憶體洩露是 Android 開發中最常見,也是最容易產生的記憶體洩露,文章開頭提到的案例中,有很多都是會造成 Activity 洩露例子,而 AS 為我們提供了一個工具,能夠自動的幫我們找到 hprof 檔案中 Activity 的洩露。

這裡寫圖片描述

如上圖所示,我們點選“Analyzer Tasks”,選中“Detect Leaked Activities”,然後點選“Perform Analysis”,便可以在 Analysis Results 下生成一個“Leaked Activities”的可展開項,展開後我們就可以看到是哪個 Activity 造成的記憶體洩露。點選 Leaked Activities 下的子項後,我們可以在 Reference Tree 下面可能會看到如下內容:

這裡寫圖片描述

這種情況我們可以看到,所洩露的 Activity 被用不同的顏色展示出來了,我們依次展開其子項就可以找到造成記憶體洩露的地方,而依據就是 Depth 這個值,當 Depth 為0時,就是造成記憶體洩露的罪魁禍首了。

Depth 這個值我們上面有過介紹,是 GC Root 到當前例項的最小跳轉次數(可以抽象的理解成 GC Root 到達例項的最小權重),當 Depth 為0時表示對應的例項被 GC Root 直接持有,反映在記憶體洩露的前提下,就是造成記憶體洩露的根源。

轉換檔案到MAT分析

上面我們提到過,AS 提供的工具能幫我們快速的定位到與 Activity 相關的記憶體洩露,有時我們需要更加詳細的分析應用的記憶體情況,還是需要使用到 MAT 的工具。

MAT 需要的也是 hprof 檔案,但是不能直接 AS 生成的 hprof 檔案,所以我們需要將hprof檔案轉換為MAT可識別的檔案,AS 也為我們提供了這個方法。

這裡寫圖片描述

我們可以在 AS 的側邊欄上看到有一個“Captures”的頁卡,開啟後,可以看到所有我們生成的 hprof 檔案,選擇一個檔案後,右鍵選擇“Export to standard .hprof”,然後選擇輸出位置和檔名就可以了。

注意:有些人的 AS 側邊欄上沒有這個頁卡,可以在”View - Tool Windows - Captures”中開啟

優點分析

  • 優點:
    • Google的親兒子,不用擔心維護問題。
    • 嵌入在 AS 中,使用方便。
    • 可以自動分析 Activity 相關的記憶體洩露
    • 定位迅速,使用簡單

  • 缺點:
    • 功能單一,通過列表展示資料不直觀

所以,筆者認為,AS 提供的工具,適合我們在開發過程中監視、分析我們的記憶體使用情況,當檢測到記憶體使用出現異常時,可以先嚐試解決 AS 定位到的問題,如果記憶體的使用情況得不到改善,再考慮使用 MAT 工具來進行記憶體分析。

參考文獻