“A small leak will sink a great ship.” - Benjamin Franklin
在android開發(fā)中,由于程序員的疏忽,對于android framework處理組件對象的聲明周期不夠了解,導(dǎo)致了一些內(nèi)存沒有釋放。
目前Android上處理處理內(nèi)存問題的方法均是基于強大的hprof文件的分析,包括android studio memory dump, leakcanary和eclipse mat(standalone)工具,本文主要針對通用的hporf分析,這也會適用于leakcanry無法檢測的情況.
下面將通過eclipse mat2,adb等工具的配合使用來找到示例工程中內(nèi)存泄漏所出現(xiàn)問題的地方
內(nèi)存對象實時監(jiān)測
- 安裝mat示例程序后,為了觀察內(nèi)存中各個對象的使用情況,運行一下命令:
while true; do adb shell dumpsys com.example.jefforeilly.mat ; sleep ;-
打開應(yīng)用后,內(nèi)存使用情況
剛使用時內(nèi)存使用情況 -
然后我們正常使用應(yīng)用(包含2次登錄登出,打開主頁面,打開fragment,關(guān)閉fragment)使用后
應(yīng)用使用后內(nèi)存使用情況
-
內(nèi)存泄漏分析
Android Studio Memory Dump
- 遇到這種內(nèi)存泄漏問題,我們可以先用android studio2的memoery dump功能查看reference tree,選擇打開dominator_tree](https://developer.android.com/studio/profile/am-memory.html))
C93EE648-089B-449C-9248-A4EAE8D8F2D8.png
其中activity是我們最關(guān)心的組件之一,應(yīng)為它們占用的內(nèi)存較大,也更容易發(fā)現(xiàn),按圖所示步驟,第圖中四步,我們發(fā)現(xiàn)viewpropertyanimatorcompat listener沒有被釋放,這個是我們自己產(chǎn)生的對象,顯然有問題。
Eclipse MAT分析
-
不過,大多數(shù)情況,我們創(chuàng)建的對象可能更多,他們的ref 深度也超出我們可以隨意查找的范圍,這就需要使用更加請更加專業(yè)的分析工具Eclipse Memory Analyzer了,
在剛才應(yīng)用的路徑Myapplication/captures下 首先轉(zhuǎn)換android hporf 格式hprof-conv com.example.jefforeilly.myapplication_2016.07.22_09.18.hprof converted.hprof -
轉(zhuǎn)換android vm的hprof格式之后,就可以使用eclipse mat做分析了,
-
首先搜索任意我們認(rèn)為應(yīng)該被回收的對象名稱,如這個例子中的MainActivity, 這里發(fā)現(xiàn)了5個入口, 為簡單處理,我們?nèi)x所有對象, 右鍵選擇
merge shorttest paths to gc roots(exclude weak references), 得到距離gc root 更近的節(jié)點.
EA5A3190-E96B-46C2-943C-F43B81EAD47A.png 依次展開這些節(jié)點, 發(fā)現(xiàn)了當(dāng)前線程函數(shù)棧中有animator,也是我們new出的對象,這個Thread就是MainThread, 沒有手動釋放的animator還在運行, 這就很明確告訴我們對它處理的相關(guān)代碼有問題了
-

上面尋找內(nèi)存泄漏的方法也同樣使用于內(nèi)存優(yōu)化的過程,如果所有對象和內(nèi)存能夠合理釋放,在dominator tree中找到dominator node,看它是否可以釋放,如果可以就release掉它,這樣由他支配的其他節(jié)點也會被回收,如此這樣內(nèi)存便可以持續(xù)優(yōu)化了。



