美文网首页开源库
Android 性能优化之内存分析工具----LeakCanar

Android 性能优化之内存分析工具----LeakCanar

作者: 初夏的雪 | 来源:发表于2021-01-07 14:39 被阅读0次

    前言

    LeakCanary(https://square.github.io/leakcanary)是Square公司研发的一个可视化的内存泄漏分析工具,源码github地址为https://github.com/square/leakcanary

    LeakCanary对Android框架内部的了解使它有一种独特的能力来缩小每次泄露的原因,帮助开发人员显著减少OutOfMemoryError崩溃。

    LeakCanary运作原理

    第一步:检查保留的对象

    LeakCanary可嫁接到Android的生命周期中,以便于自动检查activity 和Fragment等销毁时进行垃圾收集,这些被销毁的对象的若应用被传递给ObjectWatcher对象。支持自动检查的对象有:

    被销毁的Activity实例、被销毁的Fragment实例、被销毁的Fragment View实例,被清除的ViewModel实例

    如果这些被ObjectWatcher所持有的对象的弱应用在执行GC 5秒后,ObjectWather仍然持有对象的弱应用,那该对象就被视为内存泄漏。

    LeakCanary等待持有的这些泄漏对象数量达到一个阈值(5)的时候,就会将这些对象dump到转储堆中;而在未达到阈值的时候,会发出一个找到几个泄漏对象的通知。

    第二步:转储堆

    LeakCanary将这些保留对象转储到Android文件系统的.hprof文件中,这回导致程序冻结一小段时间,同时也会发出正在dump的通知“LeakCanary is dumping the memory to investigate leaks”。

    第三步:分析堆

    LeakCanary使用Shrk来解析上一步的.hproof文件,找到保留的对象。并从垃圾回收的泄漏跟踪中找到该保留对象的引用路径。

    LeakCanary会为每一个泄漏跟踪创建一个签名,将签名相同的泄漏组合在一起,然后将以通知的方式显示分析结果的摘要,并在Logcat中打印结果。

    点击通知,可以打开每一条泄漏的位置及其详细引用关系。

    第四步:泄漏分类

    将发现的泄漏分为两类: 应用程序泄漏和库泄漏,关于库的泄漏我们就可以飘过了,我们主要关心应用程序的泄漏就好了。

    LeakCanary使用

    第一步: 准备阶段:

    ​ 1)自定义LeakCanaryApplication

    class LeakCanaryApplication : Application() {
    
        //用于存放视图
        val viewMap = ArrayList<View>()
        
        override fun onCreate(){
            super.onCreate();
        }
      }
    

    ​ 2) MainActivity中添加一个TextView

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val textView = findViewById<TextView>(R.id.helloworld);
    
            //将布局加载出来的视图添加到application的视图容器中
            (application as LeakCanaryApplication).viewMap.add(textView)
        }
    }
    

    第二步:build.gradle中添加依赖 & (可选)自定义Application的onCreate()配置

        //leakCanary for debug
        debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.6'
    
        // NEW: LeakCanary for releases!
        releaseImplementation 'com.squareup.leakcanary:leakcanary-android-release:2.6'
        // Optional: detect retained objects. This helps but is not required.
        releaseImplementation 'com.squareup.leakcanary:leakcanary-object-watcher-android:2.6'
    

    由于笔者用的是最新的LeakCanary 2.6的版本,已经完全支持Kotlin ,而且2.6 添加依赖后不需要在application中初始化了。不过如果你觉得默认的不够白富美,可以自己在application中进行一些配置(当然不止下面的那些):

     override fun onCreate() {
            super.onCreate()
    
            //要自定义堆转储和分析,
    
            LeakCanary.config = LeakCanary.config.copy(retainedVisibleThreshold = 3)
    
            //要在运行时自定义对保留对象的检测
            AppWatcher.config=AppWatcher.config.copy(watchFragmentViews = false)
    
            //禁用堆转储和分析    AppWatcher.objectWatcher仍然会保持跟踪保留的对象,并LeakCanary将寻找这些对象当您更改LeakCanary.Config.dumpHeap回true。
            LeakCanary.config = LeakCanary.config.copy(dumpHeap = false)
    
            //隐藏泄漏显示活动启动器图标
            LeakCanary.showLeakDisplayActivityLauncherIcon(false)
        }
    

    好了就这么简单,你现在可以大摇大摆的运行你的app了。

    因为LeakCanary检查的是activity ,fragment在调用onDestory时发生GC后5秒仍然还保留的对象,所以我们点击设备的Back按键让页面关闭,看看日志:


    发现泄漏logcat日志.png

    这时候在我们的运行该app的设备上会收到一条通知:


    发现泄漏的通知.png

    点击上图中的通知,会自动开始dump,如下图


    发现泄漏的通知2.png

    dump会将签名相同的泄漏进行合并,我们继续点击该通知:如下


    发现泄漏的通知3.png

    打开通知后,就是LeakCanary抓取的泄漏的地方,继续点击进去


    发现泄漏的通知4.png

    下图就是LeakCanary 检查出来泄漏的地方(左侧红色线和下划线标注),是不是很清晰


    发现泄漏的通知5.png

    LeakCanary 可以帮我们找到内存泄漏的地方对象及其引用关系,接下来就需要我们自己去堵上这个泄漏了。笔者就不在废话了.

    Good Luck !!!!!!!

    相关文章

      网友评论

        本文标题:Android 性能优化之内存分析工具----LeakCanar

        本文链接:https://www.haomeiwen.com/subject/sfezoktx.html