最近項目中的內存愈來愈大,因而瞭解關於Android內存分析相關的知識,用以解決實際問題。如今有不少好的內存分析工具好比:LeakCanary、DDMS、mat。java
1、首先簡單介紹下LeakCanary:android
在build.gradle文件中添加bash
在應用的application onCreate方法中添加LeakCanary.install(this),以下app
應用運行起來後,LeakCanary會自動去分析當前的內存狀態,若是檢測到泄漏會發送到通知欄,點擊通知欄就能夠跳轉到具體的泄漏分析頁面。eclipse
2、下面重點介紹下DDMS結合mat分析內存泄漏問題。工具
使用mat分析首先要經過eclipse或是Android studio生成hprof文件,而後使用命令cd到Android sdk的目錄下:gradle
cd /usr/local/android/sdk/tools //改爲本身的sdk目錄 hprof-conv com.scics.huaxi.hprof ff.hprof //轉換格式命令
這樣就生成可供mat分析的hprof文件。http://www.eclipse.org/mat/ 此處可下載mat,能夠下載獨立版亦能夠下載eclipse插件版,本人下的是獨立版本。將咱們獲得的hprof文件導入mat中得以下結果:ui
深色區域的3.6MB、9.3MB、9.6MB標示有內存泄漏的this
mat的菜單從左到右Overview、Histogram、Dominator_tree、QQL等插件
一、咱們先來看Histogram視圖
這裏簡單介紹下
狀態欄的意思class Name很簡單,Objects標示該對象出現的次數,Shallow Heap標示對象自己所佔的內存空間,Retained Heap標示對象自己及其直接飲用或間接引用一塊兒所佔的內存空間。通常來講若Shallow Heap和Retained Heap的差距很大就須要仔細分析該對象是否是產生了泄漏,由於它若釋放了那麼與它直接或間接關聯的對象不少都有可能(只能說可能會釋放,也許還會有其餘地方產生了此對象的引用)釋放。
能夠看到
shallow heap和Retained head差距很大,而且對於Android來講通常TextView、LinearLayout的對象用過以後就會釋放,這裏還存在這麼多。應該是某些activity沒有被銷燬致使的。故下面對TextView來分析:
Path To GC Roots -> exclude all phantim/weak/soft etc. references:查看這個對象的GC Root,不包含虛、弱引用、軟引用,剩下的就是強引用。從GC上說,除了強引用外,其餘的引用在JVM須要的狀況下是均可以 被GC掉的,若是一個對象始終沒法被GC,就是由於強引用的存在,從而致使在GC的過程當中一直得不到回收,所以就內存溢出了。能夠獲得以下:
展開第一個查看查看代碼獲得AudioManager是單例類它的mInstance對象持有AudioRecordButton的引用,AudioRecordButton的對象又持有AskDetail的引用,故而致使activity AskDetail沒有釋放致使內存泄漏。 此處修改在OnDestory中註銷AudioRecordButton的監聽器。ps:在Android代碼中這種相似監聽器的觀察者模式用的很是多,最好在destory的時候都要反注入,防止對象保有activity的引用致使activity不能釋放。
mAudioRecordBtn.setAudioFinishRecorderListener(null); mAudioRecordBtn = null;
二、QQL查詢
若你懷疑某個類有內存泄漏,則能夠直接經過QQL語句查詢該類在內存中的狀況如上。
三、Dominator_tree視圖
將內存中對象按從大到小的順序排列和Histogram視圖同樣分析大的對象,能夠經過查看對下的List Objects--->with incoming reference/with outgoing reference或者merge shortest path to gc root來查看內存泄漏的根本緣由。
經過對內存的分析,已讓我知道程序更容易出現內存泄漏的地方。此爲必經之路。
本篇完