AS 也能檢測 Activity 內存泄露 | 吊打 OOM
序
OOM(Out of Memory)是 Android 開發(fā)繞不過去的坎,一定會遇到。但是很多時候,報錯的地方都并不是發(fā)生問題的原因,只是壓死駱駝的***一根稻草。
解決 OOM ,涉及到的東西太多了,從原理、分析工具、解決辦法很多個方向,所以準備做一個專門解決 OOM 需要用到的知識,集合成一個系列來發(fā)布。
就叫它《吊打 OOM》吧,準備慢慢寫好好寫,希望完結之后,不懼 OOM。
一、前言
OOM(Out of Memory) 大部分原因來自內存泄露,如果有內存泄露導致系統(tǒng) GC 無法將無用資源回收,就可能導致下次申請內存空間的時候,出現 OOM 的錯誤。
其實 Android Studio(以下簡稱 AS)已經自帶了一些內存泄露的檢查。但是它的功能有限,暫時只能對 Activity 發(fā)生的內存泄露進行檢查。
下面來了解如何使用 AS 分析 Activity 的內存泄露。
二、Android Monitor
一般用來做內存泄露的檢測,會推薦使用 LeakCannary ,它是 Square 提供的一個檢測內存泄露的開源庫,集成也非常的簡單。
有興趣的可以去 Github 上看它的文檔集成使用。
https://github.com/square/leakcanary
不過大多數情況下,我們可能不會去使用 LeakCanary ,畢竟它還是需要集成在項目中。而如果只是為了檢測一下是否有 Activity 的內存泄露情況,其實 AS 中已經提供了檢測的工具。
AS 本身也為我們提供了非常方便的 Android Monitor 工具,來幫我們監(jiān)聽當前 Debug 情況下,App 運行的情況,其中就包括 Memory 的監(jiān)控。
Memory 窗口可以完全監(jiān)聽當前正在 Debug 的 App 的內存使用情況。如果在正常操作的時候,看到此處的內存一直在飆高,卻沒有降低的跡象,你的 App 就可能存在內存泄露的問題。
先來簡單介紹一下 Memory 面板,如圖中標記的區(qū)域。
1、當前監(jiān)控的終端設備和進程。
2、被檢測的設備的內存分配情況。
Allocated:已經被使用的空間。
Free : 當前剩余的空間。
3、Memroy 分析的工具欄,包含一些內存分析相關的操作。
分析內存的工具欄,從左到右依次的作用是:
- Enable:終止檢測。
- Initiate GC :手動觸發(fā) GC。
- Jump java heap:獲取 hprof 分析文件。
- Start Allocation Tracking: 開始分配追蹤。
- Memory monitor help:查看幫助文檔。
特別提一下,內存分配情況只是標識當前的內存使用情況,如果還需要繼續(xù)使用內存,是可以繼續(xù)申請的,直到超過了 Dalvik Heap 分配的***內存數,就會觸發(fā) OOM。
今天介紹的方法,主要會使用到『獲取 hprof 分析文件的方法』,去獲取一個 hprof 文件進行分析,AS 使用這種方式生成的 hprof 文件,并非標準的 hprof 文件,是專門為 AS 分析使用的,所以如果想要交給 MAT 進行分析,還需要使用 hprof-conv 命令進行轉換一下。這不是本文的重點,本文介紹的方式只需要使用 AS 進行分析即可。
點擊『Jump java heap』按鈕之后,會自動生成當前設備當前進行的內存使用報告,我們就在此基礎上進行分析。
生成的時間完全視情況而定,可能受當前使用的內存大小和當前使用的設備配置決定。最終會生成一個 .hprof 的文件,文件的命名摻雜了包名和日期時間,能幫我們很好的區(qū)分它們。
生成的 .hprof 文件,會自動將其保存在項目的 captures 目錄下,同時也可以使用Captures 窗口查看。
在 hprof 的文件分析窗口中,右邊會有一個 Analyzer Tasks 子窗口,它就是本文的主角,用來分析 Activity 內存泄露的。
默認情況如上圖,點擊右上角的『Perform Analysis』按鈕,即可開始分析。
它主要是用來檢測泄露的 Activity 和 重復的 Strings 字符串。重復的 String 檢測,基本上處于無用的狀態(tài),沒什么實際用處,新建一個 App ,運行起來,它就是會有很多重復的 String ,占用的空間也不大,基本上也無需我們太過關心。
點擊『Perform Analysis』按鈕,開始嘗試檢測。
這里主要是使用 Detect Leaked Activitys 的功能,但是我們這是一個空項目,所以也沒有什么關于 Activity 內存泄露的問題。
三、Detect Leaked Activitys
既然沒有內存泄露的情況,那我們就手動的造一個 Activity 的內存泄露的情況。
我們知道,對于 Activity 而言,如果有內部類,可能會引發(fā)內存泄露,下面就是這樣一個會引發(fā)內存泄露的的例子。
上面創(chuàng)建了一個內部類,并且在 Activity 中,使用一個 static 的 變量去持有它,它不會在 Activity onFinish() 的時候被回收掉,而是一直處于內存中,就會引發(fā)內存泄露。
現在,我們打開 ChildActivity 然后關閉它,點擊 『Jump Java Heap』按鈕生成內存的 hprof 文件。
再繼續(xù)使用『Perform Analysis』進行 Activitys 的泄露檢測。
可以看到,這里已經能檢測出來 ChildActivity 存在內存泄露的問題了。
再進行點擊可以查看到更信息的情況,來看個完整的效果。
在 Referebce Tree 中,就可以清晰的看到,是 MemoryLeak 對象,造成的內存泄露。
檢測到 Activity 的內存泄露問題,我們只需要修復它就可以了。一些常規(guī)的編碼習慣(Activity 中的內部類,推薦 static 化),確實是可以避免掉這些問題。
【本文為51CTO專欄作者“張旸”的原創(chuàng)稿件,轉載請通過微信公眾號聯系作者獲取授權】