app性能优化包括很多方面,其中重要的部分就是内存分析,主要是分析是否存在内存泄露,下面就是通过几种工具进行分析:

1、Lint

android studio自带分析工具,可以进行检测,常见的内存泄露可以检测出来

Android如何检测内存泄露 android内存泄漏检测工具_内存泄露

2、LeakCanary

内存泄露检测工具,只要app集成了LeakCanary,当app启动时候,出现内存泄露就会在通知栏发送通知,开发者就可以点进去查看具体的内存泄露详细信息,包括具体问题在哪一行

Android如何检测内存泄露 android内存泄漏检测工具_Android如何检测内存泄露_02


集成就比较简单了,只需要两部,一是在app的build.gradle中导入包

//leakCanary内存泄露检测
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
    releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'

二是在application中进行初始化

/**
     * LeakCanary初始化 只有在debug状态下才进行检测
     * @return
     */
    public void initLeakCanary(Application application) {
        if (BuildConfig.DEBUG) {
            LeakCanary.install(application);
        }
    }

3、Memory Profile

Android studio自带的分析工具,可以查看当前app的内存使用情况,包括Java或者kotlin代码的占用内存,native code占用内存,grphics图像占用内存,栈内存,以及不可定义类型占用的内存,可以实时监测内存使用情况,如果出现内存 增大或者抖动现象,可以查看占用内存的对象,使用非常方便。

Android如何检测内存泄露 android内存泄漏检测工具_android_03

4、MAT

MemoryAnalyzerTool,可以在http://www.eclipse.org/mat/downloads.php官网下载即可,下载好之后即可解压使用,点击MemoryAnalyzer.exe就可以打开界面了。

Android如何检测内存泄露 android内存泄漏检测工具_内存分析_04


界面如下:

Android如何检测内存泄露 android内存泄漏检测工具_内存泄露_05


因为我开发用的是Android Studio工具,所以可以使用profile中的Memory导出hprof文件。

先点击dump java heap,导出堆栈信息。

Android如何检测内存泄露 android内存泄漏检测工具_内存分析_06


然后点击保存堆栈信息,保存到一个hprof文件。

Android如何检测内存泄露 android内存泄漏检测工具_内存分析_07


Android如何检测内存泄露 android内存泄漏检测工具_android_08


但是这个文件不能在MAT中直接打开,需要使用sdk工具进行转换一下,使用hprof-conv工具,前提是要配置sdk的环境变量。

Android如何检测内存泄露 android内存泄漏检测工具_android_09


转换之后的文件即可使用MAT打开。

打开之后的界面如下所示:

Android如何检测内存泄露 android内存泄漏检测工具_内存泄露_10


我们主要看的是内存泄露的情况,也就是在Histogram的内容。点击之后

Android如何检测内存泄露 android内存泄漏检测工具_Android如何检测内存泄露_11


然后我们就可以查找自己的类,是否存在内存泄露的情况。点击类右击选择List objects—》with incoming references,查找内部相互应用堆栈信息。

Android如何检测内存泄露 android内存泄漏检测工具_内存泄露_12


说明:incoming reference:是指引用我的对象列表,handler对象,Activity就是在incoming reference中。

outgoing reference:我引用的对象,比如Activity中创建的handler对象,就是在outgoing中。

结果如下:

Android如何检测内存泄露 android内存泄漏检测工具_内存分析_13


然后右击类,点击Path To GC Root —》exclude all phantom/weak/woft etc.references ,去除弱引用之类的信息,这部分不构成内存泄露。

Android如何检测内存泄露 android内存泄漏检测工具_性能优化_14


就能查找到泄露的信息,具体的引用参数名称和类名。

Android如何检测内存泄露 android内存泄漏检测工具_android_15


到这里我们就可以根据存在的内存泄露进行修改了。

如果存在内存泄露情况,并且LeakCanary也没有报异常,那么我们就使用Memory Profile进行监测,反复多次操作,看前后的内存使用是否存在差距,如果存在那就是存在内存泄露了,然后就根据页面分析代码。

我们也可以使用MAT对比前后两次的堆栈信息。将两次的堆栈信息,通过下面的命令,添加到对比表页面中,进行比对。

Android如何检测内存泄露 android内存泄漏检测工具_内存分析_16


点击右边的!号,就可以生成对比的结果。

Android如何检测内存泄露 android内存泄漏检测工具_性能优化_17


对比结果如下:然后进行筛选查找我们自己的类即可。

Android如何检测内存泄露 android内存泄漏检测工具_Android如何检测内存泄露_18

以上基本都能发现内存泄露问题。

说明:以上内存泄露都是通过单例传入activity对象导致的
代码如下:

/**
 * 模拟内存泄露
 */
class LeakUtil private constructor(context: Context){
    private var mContext:Context?=context
    companion object{
        private var instance :LeakUtil?=null
            fun getInstance(context: Context): LeakUtil {
                if (instance == null) {
                    synchronized(LeakUtil::class) {
                        if (instance == null) {
                            instance = LeakUtil(context)
                        }
                    }
                }
                return instance!!
            }
    }
}

Activity中调用

LeakUtil.Companion.getInstance(this);