android stdio内存泄露分析工具使用

来源:互联网 发布:mac如何使用shadowsock 编辑:程序博客网 时间:2024/05/28 05:19

什么是内存泄漏

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

public class Singleton {    private static Singleton instance;    private Context mContext;    private Singleton(Context context){        this.mContext = context;    }    public static Singleton getInstance(Context context){        if (instance == null){            synchronized (Singleton.class){                if (instance == null){                    instance = new Singleton(context);                }            }        }        return instance;    }}

由于在调用Singleton的getInstance()时传入了Activity,当instance没有释放时,这个Activity会一直存在从而导致内存出现泄露。

正确的方式:将new Singleton(context)改为new Singleton(context.getApplicationContext()),这样便和传入的Activity没关系了。
在实际开发过程中,内存泄露并不是那么容易找到起因,因此就需要用到一些工具来辅助找到问题所在。

检测内存泄露的发生

在android stdio中运行程序,找到Android Monitor显示如下界面,并重点关注Memory这一项,用以观察不同时间App中内存的动态使用情况:
这里写图片描述

分析步骤

  1. 程序运行起来后,点击橙色小车车这里写图片描述 手动触发一次GC,点击dump java heap 这里写图片描述成功后会自动打开 hprof文件,文件以Snapshot+时间来命名,通过它可查看Java的Heap。Reference Tree代表指向该实例的引用,可以从这里面查看内存泄漏的原因,Shallow Size(浅堆大小)指的是该对象本身占用内存的大小,Retained Size(保留堆大小)代表该对象被释放后,垃圾回收器能回收的内存总和。
    这里写图片描述

2.接下来分析内存泄露可以有两种方式:
1)在上诉Android Studio自带的界面中分析便好。点击界面中的Analyzer Tasks,查看界面中的Analyzer Results 处是否有结果。看网上的这张图便一目了然。
这里写图片描述
在Reference Tree里面,直接就可以看到持有该Activity的单例对象,直接定位到该单例中的代码,发现代码中出现了
public static VideoTagHelper getInstance(Context context) {
if (tagHelper == null) {
tagHelper = new VideoTagHelper();
}
tagHelper.context = context;
return tagHelper;
}
在修复了内存泄漏问题后,网友举例的代码中内存使用下降了16.3%!!!
2)通过Android Studio自带的界面,查看内存泄露还不是很智能,可以借助第三方工具,比如MAT。Eclipse Memory Analyze 是Java 堆转储文件分析工具,可以帮助你发现内存漏洞和减少内存消耗。下载地址 http://eclipse.org/mat/downloads.php 。打开它。
这里写图片描述
注意:MAT并不会准确地告诉我们哪里发生了内存泄漏,而是会提供一大堆的数据和线索,我们需要自己去分析这些数据来去判断到底是不是真的发生了内存泄漏。
用MAT打开内存分析的文件: Android Studio生成的hprof文件在Android Studio的Captrues这个目录中可以找到,使用MAT直接打开它是行不通的,会出现下面错误
这里写图片描述
因为android的虚拟机导出的内存文件hprof文件格式与标准的 java hprof文件格式标准不一样,根本原因是两者的虚拟机不一致导致的。因此需要将它做个转换。找到android sdk的目录运行cmd,
这里写图片描述
打开命令行窗口后,运行指令hprof-conv 源文件 目标文件将文件进行转换才能在MAT中成功打开。
使用MAT分析
1)打开标准的hprof文件后,可以看到
这里写图片描述
点击Leak Suspects 链接可以生成报告
2)通过上面那张图,对内存状态有一个整体印象,接着找到有可能导致内存泄露的元凶,通常也就是消耗内存最多的对象,再进一步去查看这个内存消耗大户的具体情况,看看是否有什么异常的行为。
可以通过查看从 GC 根元素到内存消耗聚集点的最短路径。
这里写图片描述
点击detail来到每个problem,具体问题具体分析。直到找到问题。
这里写图片描述

原创粉丝点击