性能優化——內存泄漏(2)工具分析篇

內存泄漏系列文章:
性能優化——內存泄漏(1)入門篇
性能優化——內存泄漏(2)工具分析篇
性能優化——內存泄漏(3)代碼分析篇java

1、簡述

在上一篇《性能優化——內存泄漏(1)入門篇》中,介紹了內存泄漏的基本概念,並舉了一個Demo,結合簡單的代碼分析,猜想出Demo中存在內存泄漏,並用Android Studio自帶的Memory Monitor證實了咱們的猜想,但開發中,業務邏輯可能比較複雜,對象引用繁多,難道都要這樣去作代碼分析嗎?確定不行,程序員的精力有限,且「很懶」(追求效率),咱們須要工具來幫助咱們進行分析。下面就來看看都有什麼神器吧。程序員

2、工具分析

一、System Information

System Information是Android Studio自帶的分析工具,能夠經過它來判斷APP總體是否存在內存泄漏。性能優化

一個不存在內存泄漏的APP,在其退出並執行過GC後,APP中全部的View和Activity都會被銷燬,因此,咱們能夠根據退出後內存中View和Activity的數量來判斷這個APP是否存在內存泄漏。操做以下:eclipse

以上一篇中的Demo爲例:
運行APP-->打開一個Activity-->屏幕旋轉-->點返回鍵(兩次)直到到桌面-->執行GC-->System Information-->Memory Usage工具

經過上述操做,會生成一個txt文本,其中就記錄着View和Activity的數量。以下圖所示,它們的值都爲0(主要看Activities),說明本APP不存在內存泄漏。相反的,只要值不爲0,那麼APP是存在內存泄漏的。post

這種方式只能判斷整個APP是否存在內存泄漏,但沒法知道哪裏有內存泄漏,也沒法得知是哪些對象引用形成的內存泄漏。性能

二、Analyzer Tasks

Analyzer Tasks 是Android Studio自帶的分析工具,能夠幫助咱們快速定位內存泄漏,並且使用上 very easy~優化

打開一個內存快照(.hprof文件),Android Studio的右側會出現Analyzer Tasks。3d

打開Analyzer Tasks後,能夠發現有2個選項和一個按鈕,說明以下圖所示,咱們須要的就是第一個"Detect Leaked Activities"。orm

執行任務後,下方的Analysis Results中會獲得泄漏的Activity,並且直接定位到了MemoryLeakActivity[0],要上篇中獲得的結果同樣。

三、MemoryAnalyzer(MAT)

這工具,真心以爲有點複雜,但功能比Android Studio自帶的Analyzer Tasks要強大的多。

MemoryAnalyzer是基於eclipse開發的,是一個單獨的軟件,它也是對.hprof文件進行分析,但必須是標準的.hprof文件,能夠從Android Studio中導出。

運行MAT,經過File-->Open Dump分別打開剛剛導出的test1.hprof和test2.hprof,選擇Leak Suspects Report-->Finish。

分析的方式有兩種,一種是單文件分析,一種是多文件分析,咱們先進行單文件分析。

1)單文件分析

切換到test2.hprof,打開Histogram。

點擊Histogram後,會出來一個Histogram標籤,會列出APP中全部類的實例個數,感受跟Android Studio的.hprof查看器差很少,MAT中的Objects至關於AS中查看器的Total Count。

經過包名篩選,找出了咱們本身寫的代碼,Android Studio的話能夠經過切換視圖來定位。能夠發現MemoryLeakActivity的實例有2個,說明它可能存在泄漏,再聯繫以前在獲取快照以前執行過GC,而這個Activity尚未銷燬,說明這個Activity應該是泄漏了。好,到這裏單文件分析就結束了。

2)多文件分析

分別將test1.hprof和test2.hprof的histogram添加到Compare Basket,詳細操做以下圖所示。

在Compare Basket中會有剛剛添加的兩個.hprof,點擊紅色感嘆號進行對比。

出來的Compared Tables列表跟Histogram很像,不過Objects和Shallow Heap標籤都是成雙成對。

同樣,咱們只關心咱們本身的代碼,因此經過Regex進行篩選。經過數據分析,能夠知道,在旋轉屏幕先後,MemoryLeakActivity的實例由1增長到了2,又由於test2.hprof是在執行了GC後獲取的,因此能夠斷定MemoryLeakActivity在旋轉屏幕後,內存泄漏了。

3)引用跟蹤

經過單文件分析或多文件分析,咱們知道MemoryLeakActivity發生了內存泄漏(被別的實例引用致使沒法被GC回收),因此回到test2.hporf的Histogram,篩選出MemoryLeakActivity,右擊List objects-->with incoming references。

出來的結果有2大塊,即對內存中的2個MemoryLeakActivity實例分別被引用的結果進行了分類,能夠看到每一個MemoryLeakActivity都被好多個對象引用了。

結合上篇中提到的java中幾個特殊類,咱們知道SoftReference、WeakReference和PhantomReference在GC通常不會形成內存泄漏,因此這些咱們能夠無論,也說是說,咱們能夠對它們進行排除。

對兩個Activity分別排除軟、弱、虛引用後,獲得的結果分別以下:

簡單分析下就知道了,第一個MemoryLeakActivity實例是泄漏的,引用它的對象就是CommonUtil。

3、總結

一、工具方面

我的仍是比較推薦使用Android Studio集成的System Information和Analyzer Tasks,主要是使用上方便快捷,還很簡單,若是你是高手,而且須要有更強大的功能來幫助你檢查APP中的內存泄漏的話,建議使用MAT,在網上多找些比較詳細的文章看看,本文對MAT的介紹只是冰山一角。

二、操做方面

工具僅僅只是幫助咱們快速定位APP中的內存泄漏,並不能直接告訴咱們哪裏有內存泄漏,實際開發中,須要咱們去猜想,去思考,要有清晰的思惟,千方百計的構思內存泄漏的斷定依據。這須要咱們本身去摸索,積累必定的經驗。最後,在獲取內存快照(Dump Java Heap)以前,建議多點幾回Initiate GC,等內存穩定成一條線時再獲取內存快照。

相關文章
相關標籤/搜索