
本文在騰訊技術推文上 修改 釋出。
http://wetest.qq.com/lab/view/63.html?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.195040.TASKID&ADUIN=913337456&ADSESSION=1468996652&ADTAG=CLIENT.QQ.5431_.0&ADPUBNO=26510
自從Google在2013年釋出了Android Studio後,Android Studio憑借着自己良好的記憶體優化,酷炫的UI主題,強大的自動補全提示以及Gradle的編譯支援正逐漸取代Eclipse,成為主流的Android開發IDE。Android Studio在為我們提供了良好的編碼體驗的同時,也提供了許多對App性能分析的工具,讓開發者可以更友善分析App性能。Google在IO大會上一直告誡開發者不要無節制的使用手機記憶體,要注意一些不良的開發習慣會導緻App的記憶體洩漏。雖然如今網上檢測App記憶體洩漏的文章汗牛充棟,但是要使用DDMS和MAT,不僅使用步驟複雜繁瑣,而且要手動排查記憶體洩漏的位置,操作起來多有不便。其實Android Studio已經開始支援自動進行記憶體洩漏檢查了,本文就帶着大家一探其中的奧妙吧。
什麼是記憶體洩漏
這個也是個面試常客,通俗來說,定義了的變量沒使用,就是記憶體洩漏了。Android虛拟機的垃圾回收采用的是根搜尋算法,還一種是程式計數器算法。GC會從根節點(GC Roots)開始對heap進行周遊。到最後,部分沒有直接或者間接引用到GC Roots的就是需要回收的垃圾,會被GC回收掉。而記憶體洩漏出現的原因就是存在了無效的引用,導緻本來需要被GC的對象沒有被回收掉。
舉個例子
mLeak是存儲在靜态區的靜态變量,而Leak是内部類,其持有外部類Activity的引用。這樣就導緻Activity需要被銷毀時,由于被mLeak所持有,是以系統不會對其進行GC,這樣就造成了記憶體洩漏。
再舉一個最常犯的例子
如果我們在在調用Singleton的getInstance()方法時傳入了Activity。那麼當instance沒有釋放時,這個Activity會一直存在。是以造成記憶體洩露。
解決方法可以将new Singleton(context)改為new Singleton(context.getApplicationContext())即可,這樣便和傳入的Activity沒關系了。
記憶體洩漏的檢測
打開Android Studio,編譯代碼,在模拟器或者真機上運作App,然後點選
,在Android Monitor下點選Monitor對應的Tab,進入如下界面
在Memory一欄中,可以觀察不同時間App記憶體的動态使用情況,點選
可以手動觸發GC,點選
可以進入HPROF Viewer界面,檢視Java的Heap,如下圖
Reference Tree代表指向該執行個體的引用,可以從這裡面檢視記憶體洩漏的原因,Shallow Size指的是該對象本身占用記憶體的大小,Retained Size代表該對象被釋放後,垃圾回收器能回收的記憶體總和。
下面我們以掌上道聚城用戶端為例,來一探記憶體洩漏檢測的方法。
打開Android Studio,編譯代碼,運作掌上道聚城,然後開始盡情的耍我們的App啦,然後就從Memory Monitor裡面觀察App的記憶體使用曲線,突然發現,納尼!!!怎麼記憶體使用越來越大了,這就很有可能是發生記憶體洩漏了,然後點選
手動進行GC,再點選
觀看JavaHeap,點選Analyzer Task,Android Monitor就可以為我們自動分析洩漏的Activity啦,分析出來如下圖所示
在Reference Tree裡面,我們直接就可以看到持有該Activity的單例對象,直接定位到該單例中的代碼,發現代碼中出現了
和剛剛舉得例子裡出現的錯誤一模一樣,我們修複了檢查出的記憶體洩漏的問題,并将修複前和修複後的代碼在相同的模拟器上運作并進行相同的操作,檢視他們使用記憶體的情況,如下圖所示
有記憶體洩漏的情況,占用記憶體約為43M
修複了記憶體洩漏問題,占用記憶體為36M在修複了記憶體洩漏問題後,記憶體使用下降了16.3%!!!
最後補充一個我遇到的例子
優化代碼後,明顯解決了上述問題
最後,在掌握了Android Monitor的使用方法後,相信能在android開發的路上助各位一臂之力。
、