LeakCanary原理从0到1

文章目录

    • 引用分类
      • 强引用
      • 软引用
      • 弱引用
      • 虚引用
    • LeakCanary
      • 理论依据
      • 源码解析
            • LeakCanary 2.0 的初始化放在了自带的ContentProvider中:

为了使文章尽量通俗易懂。在探究 LeakCanary之前,有必要补充些 Java引用的知识。

引用分类

强引用

强引用是使用最普遍的引用。一个对象具有强引用,则在GC发生时,该对象将不会回收。当Jvm虚拟机内存空间不足时,虚拟机会抛出OutOfMemoryError错误,不会回收具有强引用的对象来解决内存不足的问题。

软引用

当一个对象只有软引用,若虚拟机内存空间足够,垃圾回收器就不会回收该对象;
若内存空间不足,下次GC时这些只有软引用对象将被回收。若垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

在创建软引用实例时,可以传入一个引用队列(ReferenceQueue)将该软引用与引用队列关联,这样当软引用所引用的对象被垃圾回收器回收前,Jvm虚拟机会把这个软引用加入到与之关联的引用队列中。

弱引用

弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在GC发生时,若一个对象只有虚引用,不管虚拟机内存空间是否足够,都会回收它的内存。

在创建弱引用实例时,可以传入一个引用队列(ReferenceQueue)将该软引用与引用队列关联,这样当软引用所引用的对象被垃圾回收器回收前,Jvm虚拟机就会把这个软引用加入到与之关联的引用队列中。

虚引用

虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

在创建虚引用实例时,可以传入一个引用队列(ReferenceQueue)将该软引用与引用队列关联,这样当软引用所引用的对象被垃圾回收器回收前,Jvm虚拟机就会把这个软引用加入到与之关联的引用队列中。

软引用弱引用虚引用的构造方法均可以传入一个ReferenceQueue与之关联。在引用所指的对象被回收后,引用(reference)本身将会被加入到ReferenceQueue之中,此时引用所引用的对象reference.get()已被回收 (reference此时不为nullreference.get()此时为null)。

所以,在一个非强引用所引用的对象回收时,如果引用reference没有被加入到被关联的ReferenceQueue中,则表示还有引用所引用的对象还没有被回收。如果判断一个对象的非强引用本该出现在ReferenceQueue中,实际上却没有出现,则表示该对象发送内存泄漏。

LeakCanary

理论依据

  • 当一个ActivityonDestory方法被执行后,说明该Activity的生命周期已经走完,在下次GC发生时,该Activity对象应将被回收。
  • 通过上面对引用的学习,可以考虑在onDestory发生时为Activity创建一个弱引用,并关联一个RefrenceQuence,当Activity被正常回收,弱引用应该出现在该RefrenceQuence中,否则便可以判断该Activity存在内存泄漏。
  • 通过Application.registerActivityLifecycleCallbacks()方法可以注册Activity生命周期的监听,每当一个Activity调用onDestroy进行页面销毁时,去获取到这个Activity的弱引用并关联一个ReferenceQuence,通过检测ReferenceQuence中是否存在该弱引用判断这个Activity对象是否正常回收。
  • onDestory被调用后,初步观察到Activity未被GC正常回收时,手动触发一次GC,由于手动发起GC请求后并不会立即执行垃圾回收,所以需要在一定时延后再二次确认Activity是否已经回收,如果再次判断Activity对象未被回收,则表示Activity存在内存泄漏。

源码解析

  1. 在导入依赖后使用如下方法便可以使用LeakCanary进行Activity内存泄漏分析:
//:MyApp.java
public class MyApp extends Application {
    
   @Override
   public void onCreate() {
    
       super.onCreate();
       //判断是否在主进程中
       if (LeakCanary.isInAnalyzerProcess(this)) {
    
           // This process is dedicated to LeakCanary for heap analysis.
           // You should not init your app in this process.
           return;
       }
       //使用LeakCanary
       LeakCanary.install(this);
   }
}
LeakCanary 2.0 的初始化放在了自带的ContentProvider中:

ContentProvider的onCreate的调用时机介于Application的attachBaseContextonCreate之间,LeakCanary 2.0将LeakCanary的初始化放在了自带的ContentProvider的onCreate函数中,将multiprocess设为false可以保证ContentProvider只初始化一次,LeakCanary也只初始化一次

  1. 进入LeakCanary#install(Application application)
//:LeakCanary.java
public final class LeakCanary {
    

 /**
  * Creates a {@link RefWatcher} that works out of the box, and starts watching activity
  * references (on ICS+).
  */
 public static RefWatcher install(Application application) {
    
   return refWatcher(application)
   	   .listenerServiceClass(DisplayLeakService.class)//内存泄漏后用于显示的线上泄漏信息
       .excludedRefs(AndroidExcludedRefs.createAppDefaults().build())//白名单
       .buildAndInstall();
 }

 

你可能感兴趣的:(Android,JVM虚拟机,Android,LeakCanary,内存分析)