如何進行記憶體洩漏的分析
使用Android Studio Monitors
AndroidMonitors是Android Studio自帶的功能,我們可以通過裡面的Memory子產品來進行記憶體洩漏的分析,平時開發我們也可以通過該子產品來觀察記憶體的抖動情況。

這裡我們首先知道,标注1是進行GC的操作,标注2是進行Dump操作,也就是可以生成我們瞬時的堆記憶體快照,我們主要也是通過分析堆記憶體的快照來進行記憶體洩漏分析。
一般我們先進行幾次gc操作,待記憶體平穩後,執行dump操作。會生成一個phrof的記憶體快照
此時我們可以看到幾個面闆:
- ClassName:堆記憶體中存在的類
- Instaance:類存在的執行個體
- ReferenceTree:持有該類的引用
幾個屬性的含義:
- Depth:引用的層級
- Shallow Size:對象的大小(Byte)
- Dominating Size:釋放該對象能節省的堆記憶體(Byte)
将快照轉換為Mat能夠導入的格式
在as的captures中可以右鍵選擇export to standard .hprof 将快照轉換為mat能夠帶入的檔案格式
使用MAT
MAT是一款功能更強大的記憶體洩漏分析工具,在實際的記憶體分析中,我們可以結合Monitors進行記憶體洩漏分析。
下載下傳位址http://www.eclipse.org/mat/
導入快照後,我們可以通過Histogram檢視記憶體快照
在Histogram中,我們可以通過篩選過濾出我們項目中的包和類,這個操作實際中很有用。
選中具體的對象後,右鍵list objects--with incoming references可以檢視對改對象持有的應用
我們可以看到,這個時候引用還是非常的,我們需要過濾一些無用的軟引用之類的。通過右鍵-megre shortest path to GC roots-exclude all phantom/sofe/weak etc.refrences進行過濾,這個時候基本就能查出我們自己寫的代碼的引用
另外Mat還支援2個快照進行比對,這個功能也是非常有用的。
我們可以在Navigation History中選擇 Histogram,然後右鍵選擇Add to compare basket加入比較選項,将2個快照的Histogram加入後在compare basket欄中點選紅色感歎号就可以執行快照的比對。
使用leakcanary
Square開源了一個記憶體洩露自動探測神器——LeakCanary,它是一個Android和Java的記憶體洩露檢測庫,可以大幅度減少了開發中遇到的OOM問題。
github https://github.com/square/leakcanary
通過官方的文檔介紹,我們可以輕松在項目內建
加入依賴:
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
}
Application 配置:
public class ExampleApplication extends Application {
......
//在自己的Application中添加如下代碼
public static RefWatcher getRefWatcher(Context context) {
ExampleApplication application = (ExampleApplication) context
.getApplicationContext();
return application.refWatcher;
}
//在自己的Application中添加如下代碼
private RefWatcher refWatcher;
@Override
public void onCreate() {
super.onCreate();
......
//在自己的Application中添加如下代碼
refWatcher = LeakCanary.install(this);
......
}
.....
}
使用 RefWatcher 監控那些本該被回收的對象:
public abstract class BaseFragment extends Fragment {
@Override public void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());
refWatcher.watch(this);
}
}
最後如果有記憶體洩漏,會接收到相應的推送。
這樣我們就能在編碼的階段,盡量的避免出現記憶體洩漏的情況。
如何對自己的項目進行記憶體洩漏分析
上面說了這麼多,怎麼來對我們自己的項目進行記憶體洩漏的分析呢?
一般我們都是在不知道項目中那裡有存在記憶體洩漏的情況下,怎麼來查找出那個地方出現了記憶體洩漏?
這裡我們主要檢查Activity及Fragment的記憶體洩漏情況。
使用Memory Usage檢視Activity及Fragment的記憶體洩漏情況,首先先運作自己項目到MainActivity,觀察 Menory Usage。
待gc記憶體穩定後,我們可以執行一些操作,如進入其他的Activity執行其他操作,然後 檢測記憶體的抖動情況及gc穩定後,記憶體與初始記憶體的對比。
這裡我使用開啟不保留活動來模拟MainActivity的異常退出及恢複。繼續看Menory Usage。
這個時候,我隻有在MainActivity出現過, 理論上應當隻有一個MainActivity的執行個體,這個地方就是一個值得懷疑的記憶體洩漏的點。這個時候我們就可以通過Mioniter和Mat進行記憶體分析
這個時候我們可以看到引用的的可懷疑對象,接着我們就進入源碼分析。
果然這裡有一個單例持有了MainActivity的使用。
分析記憶體洩漏是一個體力活,我們大概在項目中主要要記住。
- 使用leakcanary 在編碼階段進行檢測
- 結合記憶體抖動及Memory Usage 檢查Activity及Fragment的的洩漏情況
- 使用Monitor及Mat進行引用持有分析找出懷疑的對象
- 分析源代碼,找到元兇
轉自:http://www.jianshu.com/p/2c9fc4e871a4