前提概要

内存泄漏是常见又重要的问题,针对这个问题谷歌在Android Studio 3.0中推出了Android Profiler。笔者此篇文章主要记录一下Android Profiler在内存泄漏方面的使用。

Android Profiler

Android Profiler在Android Studio左下角,需要在Android Studio 3.0及其以上才会有。如果是Android Studio 3.0并且也未有这个按钮,读者也不用着急,运行一下自己的项目就会出现。当点击MEMORY那一行的时候就能进入内存检查的界面。

接下来笔者通过分析内存泄漏的实例的方式来介绍Android Profiler的使用。

实例

主要是三个Activity:MainActivity,ActivityOne,ActivityTwo。
MainActivity:主Activity,用于开启内存泄漏的两个Activity。
ActivityOne:通过handler方式泄漏。
ActivityTwo:通过静态引用方式泄漏。

代码如下:
MainActivity:

public class MainActivity extends AppCompatActivity {    public static Activity activity;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();    }    private void initView() {        Button btnOne=findViewById(R.id.btn_one);        btnOne.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Intent intent=new Intent(MainActivity.this,ActivityOne.class);                startActivity(intent);            }        });        Button btnTwo=findViewById(R.id.btn_two);        btnTwo.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Intent intent=new Intent(MainActivity.this,ActivityTwo.class);                startActivity(intent);            }        });    }}

ActivityOne:

public class ActivityOne extends Activity {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        new Handler().postDelayed(new Runnable() {            @Override            public void run() {            }        },1000000);    }}

ActivityTwo:

public class ActivityTwo extends Activity {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        MainActivity.activity=this;    }}

内存泄漏分析

操作

首先我们打开MainActivity,分别开启ActivityOne和ActivityTwo并退出,回到MainActivity。接着打开Android Profiler。

检查内存泄漏对象

首先要点击左上方的“Dump Java heap”按钮。(如果是检查内存泄漏,笔者建议在点击之前先点击垃圾回收按钮,以防可回收的存货对象的混淆)

然后就会显示此刻的JAVA堆中对象以及引用情况,我们可以在Heap Dump的右上角选择对象的排列方式,笔者比较推荐按报名排序,因为一般我们检查的都是自己所写的类的泄漏,而非系统层的。

如图,我们很快就发现ActivityOne和ActivityTwo泄漏了。
笔者打开了ActivityOne和ActivityTwo之后,回到MainActivity界面并按下垃圾回收按钮。不泄露的情况应该是只有MainActivity被分配了内存,而ActivityOne和ActivityTwo均存活,说明内存没有被释放,即内存泄漏了。

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

在内存泄漏检查的过程中,笔者也出现过理论上对象应该被回收,却仍保留的情况。一般情况下,如果Shallow Size和Retained Size都非常小并且相等,都可以认为是已经被回收的对象。因为系统已经不认为它会被用到,并且没有给它保留分配的内存。

解决内存泄漏(方法一)

继续我们在Heap Dump界面的操作,以检查ActivityOne为例,我们单击它,发现右侧出现了Instance View,然后单击Instance View的对象。

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

解决内存泄漏(方法二)

第一种内存泄漏的检查方法由于有过多的系统引用的混淆,相信并不让人觉得容易上手。这时候相信读者会想尝试第三个录制按钮了。
Record memory allocations:
这个按钮的作用是记录一段时间内的内存分配的内容,点击红色的小圆表示开始录制,点击小正方形是结束录制。(录制时间不建议超过10s,计算内存会很慢)

操作

首先重新运行APP,停留在MainActivity界面,然后点击红色小圆按钮开始录制,接着分别打开ActivityOne和ActivityTwo然后退出,回到MainActivity界面,最后点击小正方形结束录制。

解决内存泄漏

然后我们仍然是按照包名排列,找到内存泄漏的对象。

然后我们选择ActivityOne,再单击Instance View 中的这个对象。我们可以发现,完全能再代码中追踪到这个引用创建的地方。

我们双击Call Stack中的第一行,发现可以直接跳转到代码内存泄漏的地方。

两者优劣

解决内存泄漏方法一:
1、可以用于检查内存泄漏,并不仅仅是查看引用情况。
2、不需要定位引用的创建时间,因为查看的是java堆该时的状态。
3、不可以定位到相关代码。
4、系统引用也会显示,容易混淆。

解决内存泄漏方法二:
1、可以直接定位到相关代码。
2、不会有过多的系统引用混淆。
3、需要定位对象创建的时间,在内存记录的时间内进行操作才会显示。

总结

Android Profiler只是解决内存泄漏的一个工具,在一些情况下无法定位到相关代码。比如以下情况:

A a=A();……c=a;

在这种情况下,如果A类泄漏,那么代码只能定位到 “A a=A();”,而下面的间接引用却无法由Android Profiler体现出来,这就需要读者通过阅读源码来自行解决了。

总之也算是孰能生巧,新工具固然能提高我们的效率,但是还是无法替代手动检查的工作。

更多相关文章

  1. android 的内存、内部存储和外部存储的理解/cache/system。
  2. Android(安卓)系统信息获取(CPU,RAM,ROM,Battery,SD-card,版本等)
  3. Android高效加载大图、多图解决方案,有效避免程序OOM
  4. android:largeHeap属性
  5. android studio 通过svn导入eclipse项目
  6. Android开发注意点小记
  7. Android(安卓)JNI编程内存问题定位方法
  8. Android编译时主要瓶颈分析
  9. android 进程内存查看

随机推荐

  1. Android(安卓)为模拟器安装其他软件
  2. Android重力感应实现方式简介
  3. Android音频流程一(JNI部分)
  4. ANDROID问题总结
  5. Android中常用的框架(从GitHub开源库中代
  6. 关于Android(安卓)studio 使用fastjson报
  7. Android技术归档
  8. ScrollView常用属性汇总
  9. Android下进行单元测试
  10. Android:shape的使用详解(2)