Android 3.0+ 内存泄漏检测

1、简介

Android虚拟机的垃圾回收采用的是根搜索算法。GC会从根节点(GC Roots)开始对heap进行遍历。到最后,部分没有直接或者间接引用到GC Roots的就是需要回收的垃圾,会被GC回收掉。而内存泄漏出现的原因就是存在了无效的引用,导致本来需要被GC的对象没有被回收掉,这就造成了内存泄露。

说白了就是有对象没有被回收。

2、简单实例

1)写一个会导致内存泄漏小程序

主要文件
Android 3.0+ 内存泄漏检测
MainActivity.java 实现界面跳转
TwoActivity.java 创建一个延时处理的 handler 程序
当我们跳转到 TwoActivity 界面,紧接着返回主界面, TwoActivity 对象会得不到释放,
因为 handler 会对twoActivity 产生引用。

Android 3.0+ 内存泄漏检测

MainActivity.java

package recognizerdemo.speech.baidu.com.myapplication;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button =  (Button) findViewById(R.id.but_id);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.but_id:
                Intent intent = new Intent(this,TwoActivity.class);
                startActivity(intent);
                break;
                default:
                    break;
        }
    }
}

TwoActivity.java

package recognizerdemo.speech.baidu.com.myapplication;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;

public class TwoActivity  extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_two);

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {

            }
        },1000000);
    }
    }


3、Android Profile 进行内存监控

Android 3.0+ 内存泄漏检测

Android 3.0+ 内存泄漏检测

我们点击了两次 我们可以看到再输出的报告里
Android 3.0+ 内存泄漏检测
TwoActivity 有两个实例

四个参数 的含义:
Heap Dump 右边四列的意思分别如下:
Alloc Count:Java堆中的实例个数
Native Size:native层分配的内存大小。
Shallow Size:Java堆中分配实际大小
Retained Size:这个类的所有实例保留的内存总大小(并非实际大小)

我们单击它,发现右侧出现了Instance View,然后单击Instance View的对象。
在Instance View中,会显示在ActivityOne中的各种对象,而它下方的Reference则是显示诸多对这个存货的ActivityOne对象的引用。大部分都是系统层面的引用,只有一个格外显眼,就是通过“this”对ActivityOne的引用,点进去我们可以发现是MessageQueue持有了这个引用,可以定位到是Handler的内存泄漏了。

Android 3.0+ 内存泄漏检测

4、正常情况下测试内存

1)我们修改TwoActivity.java 代码,不做任何事情

public class TwoActivity  extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_two);

/*        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {

            }
        },1000000);*/
    }
    }

2)重新检测一下内存
Android 3.0+ 内存泄漏检测

我们可以发现再内存监控中 根本没有找到 TwoActivity 对象的存在,已经被完全回收。

所以当我们使用内存监控,发现哪个对象数据异常的时候,就可以定位到了泄露的原因。

文献参考:
基于Android Studio的内存泄漏检测与解决全攻略
https://blog.****.net/jinhui157/article/details/73863314

(Android Studio 3.0)Android Profiler内存泄漏检查
https://blog.****.net/Double2hao/article/details/78784758

Android性能优化之Android Device Monitor使用
https://blog.****.net/my_rabbit/article/details/79831911

内存泄露:分析及工具使用
https://blog.****.net/zeqiao/article/details/77334522