废话不多说直接说流程
- 通过adb dump 内存快照
adb shell am dumpheap {进程名} {存储路径}
例如:
adb shell am dumpheap nova.priv.terminal.player.PlayService /sdcard/1.hprof
- 导出到电脑上
adb pull /sdcard/1.hprof C:\Users\...\1.hprof
- 导出以后我们会得到
1.hprof
文件,但是这个不是mat
工具用到的标准文件。我们需要使用sdk自带的hprof-conv.exe
(platform-tools文件夹下) 工具进行转换,转换以后我们就得到了1_mat.hprof
文件
转换mat标准文件
命令:hprof-conv -z src dst
例如:hprof-conv -z 1.hprof 1_mat.hprof
下来我们就需要使用mat进行分析了,打开以后如下图,我们呢点击
histogram
mat下载地址:http://www.eclipse.org/mat/downloads.php
-
进入Histogram 页面有我们在红框位置输入我们想要找的类,然后右键选择
merge shortest paths to Gc roots
然后在选择exclude all phantom/weak/soft etc.references
选项
-
就得到了如下的引用图,从图中我们分析出 loginActivity是被inputMethodManager所引用(这其实是android系统的一个bug),所以我们主要将两者之间的联系给断开就行,解决方法如下
使用反射的方式将引用的view置为null
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
try {
//获得 所有属性 getField->public 以及父类
Field mCurRootViewField = InputMethodManager.class.getDeclaredField("mCurRootView");
//设置允许访问权限
mCurRootViewField.setAccessible(true);
// 对象
Object mCurRootView = mCurRootViewField.get(im);
if (null != mCurRootView){
Context context = ((View) mCurRootView).getContext();
if (context == this){
//破怪gc 引用链
mCurRootViewField.set(im,null);
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}