内存泄漏分析检测

检测工具

  • AndroidStudio3.0以上
  • Memory analyzer或者eclipse MAT插件

1.准备工作:

首先我们模拟内存泄漏,如下代码:
ToastUtils.java

public class ToastUtils {
    private static final ToastUtils ourInstance = new ToastUtils();
    private static Context mContext;

    public static ToastUtils getInstance(Context context) {
        mContext =context;
        return ourInstance;
    }

    private ToastUtils() {
    }

    public void showToast(String msg){
        Toast.makeText(mContext,msg,Toast.LENGTH_SHORT).show();
    }

}

Main2Activity

public class Main2Activity extends AppCompatActivity {

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        ToastUtils.getInstance(this).showToast("hahahhaha");

        handler.sendEmptyMessageDelayed(1,6000);
    }
}

2.开始检测

2.1以Android Profiler运行应用程序,点击如下按钮

Android Profiler

2.2选择MEMORY,点击如下按钮

MEMORY

2.3开始进行测试,随便点点我们的应用然后点击下图1按钮请求gc,再点击2获取一份内存快照,如下:

内存泄漏分析检测_第1张图片
获取内存快照

2.4分析生成的文件,生成的文件如下图:

内存泄漏分析检测_第2张图片
内存快照
  • Alloc Cout 对象数
  • Shallow Size 对象占用内存大小
  • Retained Set 对象引用组占用的内存

注:如果Alloc Cout 数量不是1的话,可能就发生了内存泄漏

2.4点击保存到本地,文件名为1.hprof

保存到本地

2.5使用hprof-conv命令转成标准的mat文件

命令如下:

hprof-conv -z /Users/cool/me/1.hprof /Users/cool/me/1_mat.hprof

如果找不到hprof-conv命令,请配置一下环境变量,hprof-con为/SDK/platform-tools/下的工具
将1_mat.hprof拖到 Memory analyzer中,或者已安装mat插件的eclipse中
如下:


内存泄漏分析检测_第3张图片
mat

点击红框中的按钮,再根据泄漏的类名Main2Activity来筛选,


内存泄漏分析检测_第4张图片
image.png

回车,得到下面结果

内存泄漏分析检测_第5张图片
image.png

选中要排查的类,排除软弱虚引用


内存泄漏分析检测_第6张图片
image.png

将得到结果全部展开,如下:

内存泄漏分析检测_第7张图片
image.png

分析此图,我们看到有3个泄漏点,因为内存泄漏是自己模拟的,所以我们很快就能定位到问题,这里假装是真实开发的项目,我们一个一个分析:

  • 第一个泄漏点:沿着Main2Activity一直往上追溯,会发现GCRoot为 com.cool.skinresource.ToastUtils,这里的代码写的有问题,打开后发现单例中静态引用Activity实例导致gc无法回收
  • 第二个泄漏点:仔细看就知道handler机制导致的内存泄漏,非静态内部类持有外部类Activity的引用导致的
    *第三个泄漏点:Toast的内部类mNextView,mView持有了Activity的引用,这里是因为静态的Context才导致的,如果需要解决此泄漏,需要通过反射将mNextView,mView置为null,将引用链打破即刻

将问题解决后再重复此步骤检测,直至没有内存泄漏

你可能感兴趣的:(内存泄漏分析检测)