2023-03-02 17:32:00
「Leakcanary 」是我们经常用于检测内存泄漏的工具,简单的使用方式,内存泄漏的可视化,是我们开发中必备的工具之一。 分析源码之前他目前人在北京,3年工作经验,正在寻找新的机会,如果你刚好有资源,可以联系我,微信/留言都可以,感谢。
Leakcanary 大神的 github ,最好的老师。
一、使用1、配置1dependencies {
2debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
3releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
4// Optional, if you use support library fragments:
5debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.3'
6}
2、简单使用1publicclassExampleApplicationextendsApplication{
2
3@OverridepublicvoidonCreate(){
4super.onCreate();
5if(LeakCanary.isInAnalyzerProcess( this)) {
6// This process is dedicated to LeakCanary for heap analysis.
7// You should not init your app in this process.
8return;
9}
10LeakCanary.install( this);
11// Normal app init code...
12}
13}
超级简单的配置和使用方式。最后就会得出以下的事例说明。
二、准备工作1、Reference
Reference 把内存分为 4 种状态,Active 、 Pending 、 Enqueued 、 Inactive。
引用队列,在 Reference 被回收的时候,Reference 会被添加到 ReferenceQueue 中
3、如果检测一个对象是否被回收
需要采用 Reference + ReferenceQueue
2ReferenceQueue queue = newReferenceQueue();
3
4// 创建弱引用,此时状态为Active,并且Reference.pending为空,
5// 当前Reference.queue = 上面创建的queue,并且next=null
6// reference 创建并关联 queue
7WeakReference reference = newWeakReference( newObject(), queue);
8
9// 当GC执行后,由于是弱引用,所以回收该object对象,并且置于pending上,此时reference的状态为PENDING
10System.gc();
11
12// ReferenceHandler从 pending 中取下该元素,并且将该元素放入到queue中,
13//此时Reference状态为ENQUEUED,Reference.queue = ReferenceENQUEUED
14
15// 当从queue里面取出该元素,则变为INACTIVE,Reference.queue = Reference.NULL
16Reference reference1 = queue.remove();
在 Reference 类加载的时候,Java 虚拟机会会创建一个最大优先级的后台线程,这个线程的工作就是不断检测 pending 是否为 null,如果不为 null,那么就将它放到 ReferenceQueue。因为 pending 不为 null,就说明引用所指向的对象已经被 GC,变成了不也达。
4、ActivityLifecycleCallbacks
用于监听所有 Activity 生命周期的回调方法。
1privatefinalApplication.ActivityLifecycleCallbacks lifecycleCallbacks =
2newApplication.ActivityLifecycleCallbacks() {
3@OverridepublicvoidonActivityCreated(Activity activity, Bundle savedInstanceState){
4}
5
6@OverridepublicvoidonActivityStarted(Activity activity){
7}
8
9@OverridepublicvoidonActivityResumed(Activity activity){
10}
11
12@OverridepublicvoidonActivityPaused(Activity activity){
13}
14
15@OverridepublicvoidonActivityStopped(Activity activity){
16}
17
18@OverridepublicvoidonActivitySaveInstanceState(Activity activity, Bundle outState){
19}
20
21@OverridepublicvoidonActivityDestroyed(Activity activity){
22ActivityRefWatcher. this.onActivityDestroyed(activity);
23}
24};
5、Heap Dump
Heap Dump也叫堆转储文件,是一个Java进程在某个时间点上的内存快照。
三、原理说明
1、监听 Activity 的生命周期。
2、在 onDestory 的时候,创建对应的 Actitity 的 Refrence 和 相应的 RefrenceQueue,启动后台进程去检测。
3、一段时间后,从 RefrenceQueue 中读取,如果有这个 Actitity 的 Refrence,那么说明这个 Activity 的 Refrence 已经被回收,但是如果 RefrenceQueue 没有这个 Actitity 的 Refrence 那就说明出现了内存泄漏。
4、dump 出 hprof 文件,找到泄漏路径。
分析源码
程序的唯一入口 LeakCanary.install(this);
1、install
DisplayLeakService 这个类负责发起 Notification 以及将结果记录下来写在文件里面。以后每次启动LeakAnalyzerActivity就从这个文件里读取历史结果,并展示给我们。
1publicstaticRefWatcher install(Application application){
2returninstall(application, DisplayLeakService.class);
3}
1publicstaticRefWatcher install(Application application,
2Class extends AbstractAnalysisResultService> listenerServiceClass){
百万 源码3//如果在主线程 那么返回一个无用的 RefWatcher 详解 1.1
4if(isInAnalyzerProcess(application)) {
5returnRefWatcher.DISABLED;
6}
7//把 DisplayLeakActivity 设置为可用 用于显示 DisplayLeakActivity 就是我们看到的那个分析界面