重看LeakCanary

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.mzph.cn/news/698795.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务篇之分布式事务

一、Seata架构 Seata事务管理中有三个重要的角色: TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。 TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、…

docker学习总结

docker 1.初识Docker1.1.什么是Docker1.1.1.应用部署的环境问题1.1.2.Docker解决依赖兼容问题1.1.3.Docker解决操作系统环境差异1.1.4.小结 1.2.Docker和虚拟机的区别1.3.Docker架构1.3.1.镜像和容器1.3.2.DockerHub1.3.3.Docker架构1.3.4.小结 1.4.安装Docker 2.Docker的基本操…

Kubernetes Prometheus 系列|Prometheus介绍和使用|Prometheus+Grafana集成

目录 第1章Prometheus 入门1.1 Prometheus 的特点1.1.1 易于管理1.1.2 监控服务的内部运行状态1.1.3 强大的数据模型1.1.4 强大的查询语言 PromQL1.1.5 高效1.1.6 可扩展1.1.7 易于集成1.1.8 可视化1.1.9 开放性 1.2 Prometheus 的架构1.2.1 Prometheus 生态圈组件1.2.2 架构理…

Go 数据库编程精粹:database/sql 实用技巧解析

Go 数据库编程精粹:database/sql 实用技巧解析 简介database/sql 库的基础知识核心概念连接池驱动事务 环境配置 建立数据库连接连接到数据库示例:连接 MySQL 数据库连接池管理 执行查询和处理结果基本查询执行多行查询执行单行查询 结果处理处理多行结果…

基于Java SSM框架实现问卷调查系统项目【项目源码】

基于java的SSM框架实现问卷调查系统演示 B/S结构 BROWSER/SERVER程序架构方式是使用电脑中安装的各种浏览器来进行访问和使用的,相比C/S的程序结构不需要进行程序的安装就可以直接使用。BROWSER/SERVER架构的运行方式是在远程的服务器上进行安装一个,然…

普中51单片机学习(DS1302)

DS1302时钟 DS1302实时时钟具有能计算2100年之前的秒、分、时、日、日期、星期、月、年的能力,还有闰年调整的能力。内部含有31个字节静态RAM,可提供用户访问。采用串行数据传送方式,使得管脚数量最少,简单SPI 3线接口。工作电压…

4.8 Verilog过程连续赋值

关键词:解除分配,强制,释放 过程连续赋值是过程赋值的一种。赋值语句能够替换其他所有wire 或 reg 的赋值,改写wire 或 reg 类型变量的当前值。 与过程赋值不同的是,过程连续赋值表达式能被连续的驱动到wire 或 reg …

C++——基础语法(2):函数重载

4. 函数重载 函数重载就是同一个函数名可以重复被定义,即允许定义相同函数名的函数。但是相同名字的函数怎么在使用的时候进行区分呢?所以同一个函数名的函数之间肯定是要存在不同点的,除了函数名外,还有返回类型和参数两部分可以…

本地配置多个git账户及ll设置

本地配置多个git账户 清除全局配置将命令行,切换到ssh目录生成GitLab和Gitee的公钥、私钥去对应的代码仓库添加 SSH Keys添加私钥ll设置 管理密钥验证仓库配置关于gitgitee.com: Permission denied (publickey) 清除全局配置 此步骤可以不做,经测试不影…

总结一下最近几个主界面

目前展示了用Avalonia做几个主要流行的主界面,演示了一下组件的使用。用不同的实现方式实现一些方法。 1、独立大屏展示,类似一个实时监控,这是一种目前很方便的大屏效果。 主要涉及的内内容: (1)窗标题实…

【视频编码\VVC】环路滤波基础知识

本文为新一代通用视频编码H.266\VVC原理、标准与实现的简化笔记。 定义:在视频编码过程中进行滤波,滤波后的图像用于后续编码。 目的:1、提升编码图像的质量。2、为后续编码图像提供高质量参考,获得更好的预测效果。 VVC中主要…

使用LinkedList实现堆栈及Set集合特点、遍历方式、常见实现类

目录 一、使用LinkedList实现堆栈 堆栈 LinkedList实现堆栈 二、集合框架 三、Set集合 1.特点 2.遍历方式 3.常见实现类 HashSet LinkedHashSet TreeSet 一、使用LinkedList实现堆栈 堆栈 堆栈(stack)是一种常见的数据结构,一端…

后端程序员入门react笔记(五)ajax请求

常见的ajax Ajax 最原始的方式,基于原生的jsXmlHttpRequest 多个请求之间如果有先后关系,会存在很多层回调的问题,也是基于原生jsJquery Ajax 基于原生XHR封装,依赖Jquery框架,由jquery 框架去封装原生的XML(Xml)封装…

【高德地图】Android高德地图控件交互详细介绍

📖第5章 与地图控件交互 ✅控件交互🧊缩放按钮🧊指南针🧊定位按钮🧊地图Logo ✅手势交互🧊缩放手势🧊滑动手势🧊旋转手势🧊倾斜手势🧊指定屏幕中心点的手势操…

CSP-J 2023 T1 小苹果

文章目录 题目题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 题目传送门题解思路总代码 提交结果尾声 题目 题目描述 小 Y 的桌子上放着 n n n 个苹果从左到右排成一列,编号为从 1 1 1 到 n n n。 小苞是小 Y 的好朋友,每天她都会从…

EXCEL 在列不同单元格之间插入N个空行

1、第一步数据,要求在每个数字之间之间插入3个空格 2、拿数据个数*(要插入空格数1) 19*4 3、填充 4、复制数据到D列 5、下拉数据,选择复制填充这样1-19就会重复4次 6、全选数据D列排序,这样即完成了插入空格 以…

密评技术要求实施详解:每一步都关键

密评简介 密评定义:全称商用密码应用安全性评估, 是对采用商用密码技术、产品和服务集成建设的网络和信息系统密码应用的合规性、正确性、有效性进行评估的活动。 评测依据:GB/T 39786-2021《信息安全技术 信息系统密码应用基本要求》。 密评对象&…

新能源汽车PACK电池包的气密性测试需要用到哪些快速密封连接器

PACK电池包是新能源汽车的重要部件之一,在全部组装完成后需要对其壳体进行气密性测试,以确保壳体的密封性能,避免有雨水、灰尘等外界侵扰拒之门外,从而保证电池的使用寿命不受损害。 新能源汽车PACK电池包 在做气密性测试时需要用…

Jmeter基础(3) 发起一次请求

目录 Jmeter 一次请求添加线程组添加HTTP请求添加监听器 Jmeter 一次请求 用Jmeter进行一次请求的过程,需要几个步骤呢? 1、添加线程组2、添加HTTP请求3、添加监听器,查看结果树 现在就打开jmeter看下如何创建一个请求吧 添加线程组 用来…

CUDA自学笔记001 CUDA编程模型、CUDA线程模型及其管理、CUDA内存模型及其管理

CUDA编程模型 我们使用CUDA_C语言进行CUDA编程, 1,CUDA编程模型提供了线程抽象接口用于控制GPU中的线程 2,CUDA编程模型提供了内存访问控制,我们可以实现主机和GPU设备内存的控制,我们可以实现CPU和GPU之间内存的数据传…