內存異常的情況:
我們看到一直在上漲~
內存正常的情況:
內存有漲有跌,這樣才說明內存能夠被回收。
Mat 工具的使用:
使用mat 打開hprof文件,查看你認爲可能泄露的類的引用。
如果是java層導致的泄露,會有下面類似的截圖:
你們能看到調用鏈,我這裏泄露是因爲用當前的context 註冊了廣播,沒有取消註冊導致的。
如果是native 的佔用,可能你打開之後,看不到引用鏈,後面只寫了native
表示你被natvie 的堆棧 或者變量佔用了,這時候,就要分析代碼了。看這個沒啥用了。你看看當前的activity 是不是傳遞給了c 層。
比如,我下面就是一個native 的佔用導致activity 泄漏:
有問題的:
mCore.setChapterGraphKeywordCallback(new JNIChapterGraphKeywordCallbackImp(this));
修改之後:
/**
* 這裏使用靜態內部類 加弱引用
* 解決 內存泄漏問題
* 不要直接把BookBrowserFragment 或者 Activity 傳遞給C 層
* 容易導致內存泄漏
*
* */
static class JNIChapterGraphKeywordCallbackImp implements JNIChapterGraphKeywordCallback{
private WeakReference<BookBrowserFragment> mWeakReference;
public JNIChapterGraphKeywordCallbackImp(BookBrowserFragment bookBrowserFragment) {
mWeakReference = new WeakReference<>(bookBrowserFragment);
}
@Override
public List<String> loadChapterGraphKeyword(int i) {
BookBrowserFragment bookBrowserFragment = mWeakReference.get();
if (bookBrowserFragment != null) {
return bookBrowserFragment.loadChapterGraphKeyword(i);
}else{
return null;
}
}
}
其實AS 也提供了查看內存的實例的方法,
下面是解決內存泄漏之前 和 之後的對比圖:
總結:
- mat 的使用
- this 查看 當前fragment 和 activity 被哪裏引用了
- leakCarary 的功能mat 都有,而且還有native 引用
- 內存裏面的實例太多,就是被泄露了,回收不了。
- c層不要直接引用fragment
- leakCarary 可以解決基本上java層的泄漏