重看LeakCanary

news/2024/11/28 7:24:58/

LeakCanary是我很久之前看的东西了,我当时侯对它的印象就是它可以用来检测内存泄漏,具体原理就是将弱引用对象延迟个5s然后看是否被回收,如果没有被回收,那么就说明发生了内存泄漏,其他的也没有仔细地看

现在就详细地梳理一遍这个流程:

1.LeakCanary的使用方法

很简单,我们只需要在build.gradle.kts里面加上

debugImplementation ("com.squareup.leakcanary:leakcanary-android:2.12")

注意,这个leakcanary是2.6的版本,以前,我们需要手动在Application中调用LeakCanary.install(this);进行初始化工作

但是现在2.4的版本之后,就不需要手动调用了,当我们加上上面的那个之后点击sync运行,当我们点击我们AndroidStudio的Run 'app',安装好app之后,你会发现你的手机上会多一个这个app

bc10e0a2b0ac4a3b965bdab91d0a65bb.jpg

 

这个app就会来汇报存在哪些内存泄漏

好,现在有2个问题

1:为什么我们其他的导入用的是

implementation()

而LeakCanary用的是

debugImplementation

2:为什么要生成一个Leaks用来检测内存泄漏

我们分别来看看吧

 

1.1为什么导入用的是debugImplementation

在网上搜到的资料显示的是:

在Android项目中,通常会使用两种依赖配置来引入库:implementation和debugImplementation。其中,implementation配置表示该库是项目的一部分,会被打包到最终的发布版本中;而debugImplementation配置表示该库仅在调试模式下使用,不会被打包到发布版本中。

LeakCanary通常被用于调试和排查内存泄漏问题,因此建议将其导入为debugImplementation。这样,在发布版本中不会包含LeakCanary的代码,避免增加应用的体积和性能开销。

这个怎么理解呢?在AndroidStudio里面双击shift然后你搜索leakcanary然后你随便点进去看它的path你会发现,它的路径都不是在该项目上的,而是在你电脑的gradle路径下面

它的主要目的就是不想让LeakCanary的代码出现在Release版本的项目中

注意哦,这里说的是Release版本的项目,也就仅仅针对于Release版本,不包括Debug版本哦

1.2为什么要生成一个Leaks来检测内存泄漏

搜到的原因是这样的,因为内存泄漏的检查和分析过程涉及到大量复杂的堆转储操作,可能会阻塞主线程影响正常应用的运行,因此LeakCanary将耗时操作转移到单独进程中处理,然后通过Leaks应用以图形化可视的方式方便用户查看。

那这样还有一个疑问了,既然是大量复杂的运算,与其开一个新的进程,为什么我们不新开一个线程来解决呢?

我的理解是使用单独的进程而不是新开一个线程,它的好处就在于不必担心影响主应用的内存分配和其他系统资源,保证独立性方便进行检测

2.LeakCanary的原理

2.1LeakCanary的初始化

LeakCanary的初始化早期是需要我们自己手动在application的onCreate()里面进行初始化的,但是现在导入LeakCanary的包之后就不用我们手动进行初始化了,记住,这里说的是不用手动进行初始化了,不是不用进行初始化了,它会在MainProcessAppWatcherInstaller.kt这个类里面进行初始化,通过调用

AppWatcher.manualInstall()

然后才进行的初始化,那么为什么之前版本的LeakCanary是在Application的onCreate()初始化,而现在是在MainProcessAppWatcherInstaller.kt这个类呢?首先MainProcessAppWatcherInstaller.kt这个类继承自ContentProvider

(其实我感觉很无语的一件事就是MainProcessAppWatcherInstaller.kt他是在gradler的,但是ContentProvider这个类是在SDK里面的)

其中ContentProvider的onCreate()的生命周期是要早于Application的onCreate()方法而要晚于Application的attachBaseContext的生命周期

那么Application的attachBaseContext话,它是当application刚开始进行初始化的时候调用的,当application的初始化执行完毕之后才会调用application的onCreate()方法进行全局性的初始化,比如单例对象的创建。

现在LeakCanary是在MainProcessAppWatcherInstaller.kt中注册就是为了监测application初始化的过程中是否会存在内存泄露问题,可以提供更全面,准确得到内存泄露监测效果

2.2LeakCanary的原理

LeakCanary的原理其实很简单,我们以Activity举例,Android为我们提供了一个Activity的生命周期监测的一个接口 ActivityLifeCycleCallBack接口,当Activity的生命周期处于onDestroyed()的时候,它就会生成一个Activity的弱引用对象并且为这个对象生成一个键,以键值对的方式存进Map中,这个Map中就是用来存储还有哪些对象没有被回收掉,我们通过Handler让这个弱引用对象延迟5s操作,如果它被回收掉,那么它就会被放进一个弱引用队列里面,并且将它从Map中移出调,如果没有被回收调的话 ,那么就会进行手动GC,如果仍然没有被回收掉,那么就说明发生了内存泄露。最终生成一个hprof文件,最开始我们不是说的那个Leaks app嘛,它读取hprof文件里面的数据,分析导致内存泄露的引用链,将分析的结果展示给用户

 


http://www.ppmy.cn/news/1360343.html

相关文章

Oracle EBS R12.1 FA 批量计划外折旧

在资产工作台上可以进行单个资产的计划外折旧,如果进行批量计划外折旧的话就需要进行开发客户化form或者webadi 进行数据上载后调用FA 标准API了 以下是标准API的demo示例 DECLAREl_trans_rec FA_API_TYPES.trans_rec_type; l_asset_hdr_rec FA_API_TYPES.asset_hdr…

【数据结构初阶 6】二叉树:堆的基本操作 + 堆排序的实现

文章目录 🌈 Ⅰ 二叉树的顺序结构🌈 Ⅱ 堆的概念与性质🌈 Ⅲ 堆的基本操作01. 堆的定义02. 初始化堆03. 堆的销毁04. 堆的插入05. 向上调整堆06. 堆的创建07. 获取堆顶数据08. 堆的删除09. 向下调整堆10. 判断堆空 🌈 Ⅳ 堆的基本…

Stable Diffusion 绘画入门教程(webui)-ControlNet(IP2P)

上篇文章介绍了深度Depth,这篇文章介绍下IP2P(InstructP2P), 通俗理解就是图生图,给原有图加一些效果,比如下图,左边为原图,右边为增加了效果的图: 文章目录 一、选大模型二、写提示词三、基础参…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的动物识别系统(Python+PySide6界面+训练代码)

摘要:本博客文章深入解析了基于深度学习的动物识别系统的完整代码,并展示了采用领先的YOLOv8算法的实现代码。该系统与YOLOv7、YOLOv6、YOLOv5等早期版本的性能进行了比较,可以从静态图像到实时视频流的各种媒介中识别动物的高效性和准确性。…

LeetCode 热题 100 | 二叉树(终)

目录 1 二叉树小结 1.1 模式一 1.2 模式二 2 236. 二叉树的最近公共祖先 3 124. 二叉树中的最大路径和 菜鸟做题(返校版),语言是 C 1 二叉树小结 菜鸟碎碎念 通过对二叉树的练习,我对 “递归” 有了一些肤浅的理解。…

c#常用的数据结构

Array数组 内存上连续存储, 数组是引用类型而不是值类型。 优点: 按照索引查询元素速度很快。 按照索引遍历数组很方便。 缺点: 声明数组时大小必须确定,且大小不能改变。 添加和删除元素的速度很慢,因为需要移…

[更新]ARCGIS之土地耕地占补平衡、进出平衡系统报备坐标txt格式批量导出工具(定制开发版)

序言 之前开发的耕地占补平衡报备格式,现在之前的基础上集成了耕地进出平衡报备格式导出。 之前版本软件详见:软件介绍 一、软件简介 本软件是基于arcgis二次开发的工具(插件),需要授权后才能使用; 本软件…

论文选题分享及思路(一)《基于C51单片机的自动化测量产线的设计》

论文选题分享及思路 题目 《基于C51单片机的自动化测量产线的设计》 核心:使用C51单片机按键控制传送带运动,并增加激光测量高度宽度功能及称重功能。 框架:摘要,题目背景,创新点,设计原理,程…