LeakCanary代码走读

191 阅读15分钟

LeakCanary

应用稳定性和性能是非常重要的,LeakCanary作为这方面的工具,技术原理深厚,值得一探。 LeakCanary检测缩小内存泄漏错点,主要工作原理过程

  1. 检测保留的对象。
  2. 倾倒堆。
  3. 分析堆。
  4. 对泄漏进行分类。

初级核心思路,迭代演化重构,以至于庞杂

1、概览

整个工程模块结构设计:
    leakcanary-repo529))
        leakcanary11leakcanary-android(没有源码,主要集成依赖)
            leakcanary-android-core
            leakcanary-android-instrumentation
            leakcanary-android-process
            leakcanary-android-release
            leakcanary-android-startup
            leakcanary-android-utils
            leakcanary-app[apk]
            leakcanary-app-aidl
            leakcanary-app-service
            leakcanary-deobfuscation-gradle-plugin[jar]
        object-watcher6object-watcher[jar]
            object-watcher-android
            object-watcher-android-androidx
            object-watcher-android-core
            object-watcher-android-startup
            object-watcher-android-support-fragments
        plumber3plumber-android
            plumber-android-core
            plumber-android-startup
        samples1leakcanary-android-sample[apk]
        shark6+2shark[jar]
            shark-android[jar]
            shark-cli[jar]
            shark-graph[jar]
            shark-hprof[jar]
            shark-hprof-test[jar]
            shark-log[jar]
            shark-test[jar]

2、模块依赖关系

leakcanary-repo(529))
    leakcanary(11)
        leakcanary-android(门面aar,没有代码,仅集成核心依赖)
            api projects.leakcanary.leakcanaryAndroidCore
            api projects.objectWatcher.objectWatcherAndroid
            implementation projects.plumber.plumberAndroid
            implementation libs.kotlin.stdlib
        leakcanary-android-core(核心ui)
            api projects.shark.sharkAndroid
            api projects.objectWatcher.objectWatcherAndroidCore
            api projects.objectWatcher.objectWatcherAndroidAndroidx
            api projects.objectWatcher.objectWatcherAndroidSupportFragments
            implementation libs.kotlin.stdlib
            compileOnly libs.androidX.work.runtime
            compileOnly libs.androidX.work.multiprocess
        leakcanary-android-instrumentation(测试)
            api projects.leakcanary.leakcanaryAndroidCore
        leakcanary-android-process(独立进程分析)
            api projects.shark.sharkLog
            api projects.objectWatcher.objectWatcherAndroidCore
            implementation libs.kotlin.stdlib
            implementation libs.androidX.work.multiprocess
        leakcanary-android-release(后台锁屏任务分析拦截器)
            api projects.shark.sharkAndroid
            api projects.leakcanary.leakcanaryAndroidUtils
            implementation libs.kotlin.stdlib
            implementation libs.okio2
        leakcanary-android-startup(门面aar,没有代码,androidx.startup.Initializer方式初始化)
            api projects.leakcanary.leakcanaryAndroidCore
            implementation projects.objectWatcher.objectWatcherAndroidStartup
            implementation projects.plumber.plumberAndroidStartup
        leakcanary-android-utils(几个工具类)
            api projects.shark.sharkLog
            implementation libs.kotlin.stdlib
        leakcanary-app(应用)
            implementation projects.leakcanary.leakcanaryAppAidl
            implementation projects.leakcanary.leakcanaryAndroid
        leakcanary-app-aidl(跨进程传输分析数据接口)
            implementation libs.kotlin.stdlib
            implementation projects.shark.shark
        leakcanary-app-service(带存储权限访问的跨进程传输分析数据的客户端)
            implementation projects.leakcanary.leakcanaryAppAidl
            implementation projects.shark.shark
        leakcanary-deobfuscation-gradle-plugin(插件)
            implementation libs.kotlin.stdlib
            implementation libs.gradlePlugin.kotlin
            implementation libs.gradlePlugin.android
            compileOnly gradleApi()
    object-watcher(6object-watcher(给对象附加观察属性--引用情况)
            implementation libs.kotlin.stdlib
            api projects.shark.sharkLog
        object-watcher-android(借助cp自动加载,安装对象观察核心)
            api projects.objectWatcher.objectWatcherAndroidCore
        object-watcher-android-androidx(object-watcher-android-core之androidx兼容)
            api projects.objectWatcher.objectWatcherAndroidCore
            implementation libs.kotlin.stdlib
            compileOnly libs.androidX.fragment
        object-watcher-android-core(提供默认的4类对象的观察)
            api projects.objectWatcher.objectWatcher
            api projects.leakcanary.leakcanaryAndroidUtils
            implementation libs.curtains
            implementation libs.kotlin.stdlib
        object-watcher-android-startup(androidx.startup.Initializer,安装对象观察核心)
            api projects.objectWatcher.objectWatcherAndroidCore
            implementation libs.androidX.startup
        object-watcher-android-support-fragments(object-watcher-android-core之support兼容,已删除整个模块)
            api projects.objectWatcher.objectWatcherAndroidCore
            implementation libs.kotlin.stdlib
            compileOnly libs.androidSupport
    plumber(3)
        plumber-android(借助cp,安装框架库泄漏修复)
            api projects.plumber.plumberAndroidCore
            implementation libs.kotlin.stdlib
        plumber-android-core(枚举已知漏洞修复方案)
            api projects.shark.sharkLog
            api projects.leakcanary.leakcanaryAndroidUtils
            implementation libs.kotlin.stdlib
            implementation libs.curtains
            compileOnly libs.androidX.fragment
        plumber-android-startup(androidx.startup.Initializer方式初始化,安装框架库泄漏修复)
            api projects.plumber.plumberAndroidCore
            implementation libs.kotlin.stdlib
            implementation libs.androidX.startup
    samples(1)
        leakcanary-android-sample
            debugImplementation projects.leakcanary.leakcanaryAndroid
            debugImplementation projects.leakcanary.leakcanaryAppService
            debugImplementation projects.leakcanary.leakcanaryAndroidStartup
            debugImplementation projects.leakcanary.leakcanaryAndroidProcess
            releaseImplementation projects.leakcanary.leakcanaryAndroidRelease
            releaseImplementation projects.objectWatcher.objectWatcherAndroid
            implementation libs.kotlin.stdlib
    shark(6+2)
        shark(生成对分析报告)
            api projects.shark.sharkGraph
            implementation libs.kotlin.stdlib
            implementation libs.okio2
        shark-android(生成安卓量身定制的对分析报告)
            api projects.shark.shark
            implementation libs.kotlin.stdlib
        shark-cli(shark命令行界面使你可以直接从pc分析安卓设备上应用程序产生的堆)
            api projects.shark.sharkAndroid
            implementation libs.clikt
            implementation libs.neo4j
            implementation libs.jline
            implementation libs.kotlin.stdlib
        shark-graph(导航堆对象图)
            api projects.shark.sharkHprof
            implementation libs.kotlin.stdlib
            implementation libs.okio2
        shark-hprof(hprof文件中的记录读写)
            api projects.shark.sharkLog
            implementation libs.kotlin.stdlib
            compileOnly libs.okio1
        shark-hprof-test(写辅助类)
            implementation libs.kotlin.stdlib
            implementation libs.junit
            implementation libs.okio2
            implementation projects.shark.sharkHprof
        shark-log(日志接口)
            implementation libs.kotlin.stdlib
        shark-test(测试堆转储)
            implementation libs.kotlin.stdlib
            implementation libs.assertjCore
            implementation libs.junit

可以看到项目有多条依赖线,主要的app依赖,startup依赖,测试依赖,等。串一下对整个工程不留太多遗漏。

3、模块业务实现

leakcanary-repo(529))
    leakcanary(11)
        leakcanary-android(门面aar,没有代码,仅集成核心依赖)
            不提供代码的目的需要思考一下
        leakcanary-android-core(核心ui)
            LeakCanaryFileProvider对于hprof文件存储位置权限读写兼容
            LeakActivity主界面,tab以及Screen泛化切换,可以接受外部Uri方式的hprof文件,发dump事件触发泄漏分析或通知展示等。
            HeapDumpsScreen中间HeapDumps页面,
            HeapAnalysisTable堆分析泄漏记录表
            AndroidDebugHeapAnalyzer分析hprof文件得到泄漏记录,插入HeapAnalysisTable表。分析得到泄漏记录使用shark族库,具体看。
            HeapDumpScreen多类型列表,顶部html可点击标签,中间泄漏数量,下部泄漏列表,直接HeapAnalysisTable查询泄漏记录展示列表
            LeakScreen\&DisplayLeakAdapter展示具体泄漏位置,将泄漏信息展示成html文本拼接
            NotificationReceiver接受堆转储广播,获取堆转储文件
            HeapDumpTrigger采集堆转储文件,展示泄漏通知,发送获取堆转储文件状态事件
            AndroidDebugHeapDumper采用Debug.dumpHprofData获取堆转储文件
            RemoteWorkManagerHeapAnalyzer\&RemoteHeapAnalyzerWorker
                通过LeakCanary.Config.eventListeners接受堆转储完成事件结合leakcanary-android-process的RemoteLeakCanaryWorkerService达到独立进程分析堆转储
    leakcanary-android-instrumentation(测试)
        
    leakcanary-android-process(独立进程初始化及分析)
        
    leakcanary-android-release(后台锁屏任务分析拦截器)
        
    leakcanary-android-startup(门面aar,没有代码,androidx.startup.Initializer方式初始化)
        
    leakcanary-android-utils(几个工具类)
        
    leakcanary-app(应用)
        
    leakcanary-app-aidl(跨进程传输分析数据接口)
       
    leakcanary-app-service(带存储权限访问的跨进程传输分析数据的客户端)
        
    leakcanary-deobfuscation-gradle-plugin(插件)
       
object-watcher(6object-watcher(给对象附加观察属性--引用情况)
        1. Clock:这个类的主要作用是提供一个可配置的时钟服务,用于 Android 应用测试中加速和模拟时间间隔和时间戳。  
        2. GcTrigger:这个类提供了与 System.gc() 相关的便捷工具方法,用于在可能的情况下快速启动垃圾回收并尽早清理未使用的内存空间。  
        3. KeyedWeakReference:这个类提供了一个对对象进行弱引用的封装,可以根据键值来存储和管理这些未使用的对象,以便于内存管理。  
        4. ObjectWatcher:这个类用于监控 Java 对象的引用计数并生成日志信息,以便检测应用程序中可能存在的内存泄漏或过度使用。  
        5. OnObjectRetainedListener:这个接口是 ObjectWatcher 的回调接口,用于处理内存对象的保留和释放事件,以便于进行相应的处理和分析。  
        6. ReachabilityWatcher:这个类可以用于监控和处理对象的可达性变化,以及相应的对象引用计数和生命周期变化。
    object-watcher-android-core(提供默认的4类对象的观察)
        - AndroidOFragmentDestroyWatcher:用于在Android O及以上版本中检测Fragment的内存泄漏问题。
        - Applications.kt:是否可以调试
        - LeakCanaryDelegate:用于处理内存泄漏检测的代理类。
        - ActivityWatcher:用于检测Activity的内存泄漏问题。
        - AppWatcher:用于监测整个应用程序中的内存泄漏问题。
        - FragmentAndViewModelWatcher:用于检测Fragment和ViewModel中的内存泄漏问题。
        - InstallableWatcher:用于检测可安装组件的内存泄漏问题,例如BroadcastReceiver和Service。
        - RootViewWatcher:用于检测根视图(RootView)中的内存泄漏问题。
        - ServiceWatcher:用于检测Service的内存泄漏问题。
    object-watcher-android-startup(androidx.startup.Initializer,安装对象观察核心)
       
    object-watcher-android-support-fragments(object-watcher-android-core之support兼容,已删除整个模块)
        
plumber(3)
    plumber-android(借助cp,安装框架库泄漏修复)
        
    plumber-android-core(枚举已知漏洞修复方案)
        
    plumber-android-startup(androidx.startup.Initializer方式初始化,安装框架库泄漏修复)
       
samples(1)
    leakcanary-android-sample
       
shark(6+2)
    shark(生成对分析报告)
        HeapAnalyzer核心类,分析堆转储文件得到HeapAnalysis,供AndroidDebugHeapAnalyzer|InstrumentationHeapAnalyzer| RealHeapAnalysisJob|AnalyzeCommand|InteractiveCommand调用,ui,测试框架,命令行,子进程
        HeapAnalysis分析结果:HeapAnalysis|HeapAnalysisFailure|HeapAnalysisSuccess|Leak|LibraryLeak|ApplicationLeak
        ActualMatchingReferenceReaderFactory用于创建匹配引用阅读器,其作用是实现匹配引用阅读器的创建和配置
        AndroidNativeSizeMapper用于映射Android原生(native)对象的工具
        AppSingletonInspector一种用于检测Android应用程序中单例(Singleton)对象的工具
        FilteringLeakingObjectFinder用于查找内存泄漏对象并排除一些不需要的对象。
        ReferencePathNode是指在Java虚拟机堆内存分析中,表示对象引用路径的节点
        GcRootProvider接口
        GcRootReference垃圾回收根引用
        HeapAnalysisException异常
        KeyedWeakReferenceFinder查找 Java 应用程序中的弱引用泄漏对象
        LeakingObjectFinder用于查找 Java 应用程序中的内存泄漏对象FilteringLeakingObjectFinder|KeyedWeakReferenceFinder|ArraySetFakeLeakingObjectFinder
        LeakNodeStatus
        LeaksAndUnreachableObjects
        LeakTrace描述 Java 应用程序中的内存泄漏问题。
        LeakTraceObject包含了描述内存泄漏对象的各种信息,例如对象的类型、对象的大小、对象的引用关系等。它还可以描述内存泄漏的原因和场景。
        LeakTracer通过分析 HeapDump 文件(堆转储文件),找到可能出现内存泄漏的对象。在检测过程中,LeakTracer 会遍历 HeapDump 文件中的所有对象,并根据对象之间的引用关系判断哪些对象可能出现了内存泄漏。如果出现了内存泄漏,LeakTracer 将记录下出现内存泄漏的对象,并提供相关的信息,例如对象的类型、对象的大小、对象的引用关系等。
        LeakTraceReference表示内存泄漏问题中的引用关系
        MatchingGcRootProvider可以根据特定的条件查找堆中特定类型的对象,并将这些对象与它们的GC Roots匹配。
        MetadataExtractor,用于提取Java堆转储文件(HeapDump)中的元数据信息。在Java应用程序中,元数据信息包括对象的类型、大小、地址等。AndroidMetadataExtractor
        ObjectDominators支配树(Dominator Tree)是指根据对象支配者(Dominators)而建立起来的一棵树形结构。在Java应用程序中,支配树表示了对象之间的支配关系,使得我们能够更加清楚地了解对象之间的引用关系,从而分析和解决内存泄漏等问题。
        ObjectInspector
        ObjectInspectors枚举了jdk几种类的描述:弱引用、类加载器、类、匿名类、线程
        ObjectReporter对象是否泄漏的报告,含原因
        OnAnalysisProgressListener堆转储文件内存泄漏分析步骤进度回调,HeapAnalyzer
        RealLeakTracerFactory,RealLeakTracerFactory 可以帮助我们创建 LeakTracer 对象,并提供检测内存泄漏的功能。
        Reference引用
        ReferenceLocationType枚举引用类型
        ReferenceMatcherJava中的垃圾收集机制(Garbage Collection,GC),并提供了一种方便的方式,帮助开发者根据不同的引用策略,对对象进行垃圾回收。
        ReferencePattern引用匹配,垃圾回收的模式匹配方法。ReferencePattern|JavaLocalPattern|StaticFieldPattern|InstanceFieldPattern|NativeGlobalVariablePattern
        ReferenceReader接口,用于实现垃圾回收器中的引用读取器。定义了一个read()方法,用于遍历堆对象中的所有引用。具体来说,read()方法可以读取堆对象中包含的所有弱引用、软引用、虚引用、普通引用等引用信息,并将其作为Reference对象返回。通过遍历每个堆对象中的所有引用,程序员可以进行引用匹配并进行相应的垃圾回收操作。
        AndroidReferenceReaderFactory的作用是创建并配置一个 Android 引用阅读器。通过使用不同的配置选项,可以创建不同类型的 Android 引用阅读器,以满足特定的需求。
        ChainingInstanceReferenceReader是一种链式实例引用读取器
        AndroidReferenceReaders枚举用于读取Android应用程序运行时对象引用关系的工具集合
        ApacheHarmonyInstanceRefReaders提供了创建 Apache Harmony 实例引用阅读器的方法
        FieldInstanceReferenceReader主要用于内存泄漏检测期间分析对象引用关系,将实例化对象与其字段引用关系连接起来
        FieldIdReader是一种用于读取Java类字段信息的工具。它可以帮助开发人员确定一个类的所有字段和它们的相关信息,例如字段的名称、类型、修饰符等。
        ObjectArrayReferenceReader用于读取Java堆转储文件(HeapDump)中的对象数组引用
        ClassReferenceReader提供了创建 Java 类引用阅读器的方
        JavaLocalReferenceReader读取当前 Java 方法的本地引用器,将当前方法中临时创建的对象与其引用关系连接起来
        ThreadObjects可以让开发人员访问和修改线程局部存储中的变量。
        JavaFrames是指在Java虚拟机堆栈分析中,表示Java方法调用链的框架。它是在Java虚拟机中执行程序时,维护程序状态和方法调用链的关键数据结构。在Java虚拟机堆栈中,每个线程都有自己的JavaFrames堆栈,其可以记录该线程执行的每个方法的信息,包括方法名、参数值、局部变量等。每一次方法调用,Java虚拟机会在栈上创建一个新的JavaFrame对象,保存该方法的信息,并将其推送到栈顶。当方法运行完成后,JavaFrame会出栈,返回调用方法,在方法执行过程中对JavaFrame的操作,可以通过Java虚拟机堆栈分析工具进行展示和分析。
        OpenJdkInstanceRefReaders枚举jdk几种常见集合列表的引用分析
        DelegatingObjectReferenceReader通过委托方式实现 ObjectReference 的解析和读取,具有较高的灵活性和扩展性。4类节点的读取
        ShortestPathFinder用于搜索最短路径的算法实现
        PathFindingResults寻路算法的结果,引用路径及支配节点树
        PrioritizingShortestPathFinder实现了 Dijkstra 算法,是一种广泛使用的最短路径查找算法。该算法通过维护一个节点集合以及每个节点到起点的最短距离,从而逐步遍历所有节点并计算出最短路径。
        Dominators一种用于计算支配器的算法
        DominatorTree是一个重要的数据结构,可以用于程序分析和优化,例如在循环展开、指针分析和内联函数等方面的应用。
        VirtualizingMatchingReferenceReaderFactoryr是一种特殊的引用读取器,它可以仅遍历与给定模板匹配的对象工厂
        InternalSharedExpanderHelpers|InternalSharkCollectionsHelper可以帮助开发人员在Shark框架中进行集合操作,例如在集合中添加或删除元素,查找集合中的元素,按排序规则对集合进行排序等。
    shark-android(生成安卓量身定制的对分析报告)
        AndroidBuildMirror系统sdk版本信息
        AndroidExtensions系统表示hash码
        AndroidMetadataExtractor元数据
        AndroidObjectInspectors枚举方式AOSP和库特有的重要的对象泄漏分析
        AndroidReferenceMatchers枚举已知的框架泄漏点匹配条件(类名,字段名,版本,描述)
        AndroidResourceIdNames资源id与name,用于分析资源泄漏
        AndroidServices进程中service的id
    shark-cli(shark命令行界面使你可以直接从pc分析安卓设备上应用程序产生的堆)

    shark-graph(导航堆对象图)
        HeapGraph堆对象图(多棵树)5中节点的数量及列表,提供id、name方式查询节点
        HeapObject|HeapClass|HeapInstance|HeapObjectArray|HeapPrimitiveArray堆对象图节点5种类型
        HeapField对象属性,可能是HeapObject的几种类型
        HeapValue值,基本类型以及对象类型
        ClassFieldsReader从IndexedClass读取FieldRecord
        FieldValuesReader从FieldRecord读取基本类型的值
        HprofHeapGraph堆快照的对象引用关系图的实现
        HprofInMemoryIndex堆对象图数据节点索引
    shark-hprof(hprof文件中的记录读写)
        ByteArraySourceProvider字节数组随机读取
        ConstantMemoryMetricsDualSourceProvider低内存随机读取
        DualSourceProvider随机读取流
        FileSourceProvider文件随机读取
        GcRoot垃圾回收根对象,分类比较多
        HprofDeobfuscator是一个用于解密 HPROF 文件的工具,能够消除应用程序代码混淆对内存调试造成的影响
        HprofHeader堆转储文件的元数据或者头
        HprofPrimitiveArrayStripper是一个用于去除 HPROF 文件中基本数据类型数组信息的工具。
        HprofRecord 文件中记录数据的基本单位,代表了 Heap(堆)中的一个 Java 对象或者其他数据结构,如线程栈、本地变量等。扩展种类比较多。
        HprofRecordReader读取堆转储文件中各种HprofRecord记录
        HprofRecordTag枚举HprofRecord的各种类型
        HprofVersion是 HPROF 文件的版本号,在 HPROF 文件的开头标识了 HPROF 文件的版本信息
        HprofWriter是一个用于生成 HPROF 文件的工具
        OnHprofRecordListener读取解析记录回调
        OnHprofRecordTagListener堆去解析记录类型回调
        PrimitiveType基础数据类型
        ProguardMapping记录了混淆前和混淆后的类、方法、字段之间的映射关系。
        ProguardMappingReader可以方便地读取 Proguard Mapping 文件,并将其中的映射关系提取出来,方便进行代码调试和分析。
        RandomAccessHprofReader
        RandomAccessSource是一种可以随机访问数据源的抽象,它可以通过指定偏移量和长度的方式读取数据源中的特定部分。
        RandomAccessSourceProvider是一个用于提供随机访问的数据源的工具。它可以方便地读取、操作和处理大型二进制数据,如图片和视频等文件。
        StreamingHprofReader与 RandomAccessHprofReader 不同的是,StreamingHprofReader 是一种基于流的 HPROF 文件解析器,它可以对 HPROF 文件进行逐字节解析,不需要全部读入内存。
        StreamingRecordReaderAdapter是一种可以将流式数据转换为记录形式的工具
        StreamingSourceProvider读取流接口
        ThrowingCancelableFileSourceProvider是一个实现 RandomAccessSourceProvider 接口,用于提供随机访问文件数据源的工具。与 CancelableFileSourceProvider 不同的是,ThrowingCancelableFileSourceProvider 在读取文件时,当遇到读取错误时会抛出异常。
        ValueHolder是一种数据容器,用于存储在某个上下文中的值。基本类型以及对象引用
    shark-hprof-test(写辅助类)
    
    shark-log(日志接口)
    
    shark-test(测试堆转储)
    

、、、

参考文档

(42条消息) 构造Dominator Tree以及Dominator Frontier_dominatortree_电影旅行敲代码的博客-CSDN博客

(42条消息) Leakcanary - hprof分析库shark 源码分析_shark源码分析_stone_cold_cool的博客-CSDN博客

(42条消息) 支配节点树及其构建算法 Dominator-tree and its Construction Algorithms_节点的支配节点_loongknown的博客-CSDN博客

LeakCanary (square.github.io)

LeakCanary 你真的了解么?看看这些高级用法 - 掘金 (juejin.cn)

(42条消息) android中hprof文件分析_android hprof_HankingHu的博客-CSDN博客

使用shark库解析Hprof文件(一) - 掘金 (juejin.cn)

HPROF Agent (openjdk.org)

Android 性能监控框架 Matrix(3)Hprof 文件分析 - 掘金 (juejin.cn)

使用shark库解析Hprof文件(一) - 掘金 (juejin.cn)