LeakCanary 1.3版本源码分析

为什么是1.3版本呢,是因为之前看过的源码,有几点没说明白的,补充一下。如有错误,还请指出来。谢谢

基本使用

  1. 在build.gradle中:

     dependencies {
       debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
       releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
     }
    
  2. 在Application中:

     private RefWatcher refWatcher;
    
     @Override
     public void onCreate() {
         super.onCreate();
         //LeakCanary 检测内存泄漏
     	refWatcher = LeakCanary.install(this);
     }
    

    到这里,它就可以监控我们的Activity是否出现了内存泄漏问题了。

     public static RefWatcher getRefWatcher(Context context) {
         App application = (App) context.getApplicationContext();
         return application.refWatcher;
     }
    

    如果我们想监控某个对象是否能够造成内存泄漏就如下监控Fragment:

     @Override
     public void onDestroy() {
         super.onDestroy();
         RefWatcher refWatcher = App.initAppInstance().getRefWatcher();
         refWatcher.watch(this,getClass().getSimpleName());
     }
    

    监控Bitmap

     RefWatcher refWatcher = App.initAppInstance().getRefWatcher();
     refWatcher.watch(bitmap);
    

中文文档走你

检测Activity泄漏、watch()源码流程分析

  • 核心内容

    WeakReference弱引用,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否(这一点与SoftReference不同),都会回收它的内存。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

    WeakReference和ReferenceQueue联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

       @Test
       public void addition_isCorrect() throws Exception {
           ReferenceQueue<MyClass> queue = new ReferenceQueue<>();
           MyClass m = new MyClass();
           // 声明weakreference
           WeakReference w = new WeakReference(m,queue);
           // 断开强引用
           m = null;
           System.gc();
           // 睡眠3秒是因为,主动调用gc是不一定会立马执行
           Thread.sleep(3000);
           // 回收后会被加入到queue中,所以queue.poll()出来不为null,就说明被回收了
           while(queue.poll()!=null){
                 System.out.println("被回收了");
           }
      }
    
  • 大体流程如下:

    1. 监控最终都是调用了watch(object)
    2. 给object随机一个key存储到 set集合中
    3. 以objcet为参数初始化一个KeyedWeakReference引用object
    4. 开启线程进行监控、GC、写dumpheap操作
    5. 从软引用中poll出它内部的objcet,根据是否为空来清除set中的key
    6. 最后根据set中是否包含key,判断来进行是否调用GC
    7. 调用完GC之后在进行第5部操作,根据set中是否包含key来进行保存dumpheap操作
  • 源码解析工作流程:

  • RefWatcher初始化工作

    从LeakCanary.install(this)开始:

      RefWatcher refWatcher = LeakCanary.install(this);
    
      public static RefWatcher install(Application application) {
          return install(application, DisplayLeakService.class);
      }
    

    调用了:

      public static RefWatcher install(Application application, Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
    
      	//判断泄露分析进程和被分析的进程是否是同一个进程
    
          if(isInAnalyzerProcess(application)) {
              return RefWatcher.DISABLED;
          } else {
    
      		//不是,则进行RefWatcher的初始化工作
    
              enableDisplayLeakActivity(application);
              ServiceHeapDumpListener heapDumpListener = new ServiceHeapDumpListener(application, listenerServiceClass);
    
      		//初始化refWatcher
              RefWatcher refWatcher = androidWatcher(application, heapDumpListener);
    
      		//监控Activity
              ActivityRefWatcher.installOnIcsPlus(application, refWatcher);
              
      		return refWatcher;
          }
      }
    

    初始化refWatcher:

      public static RefWatcher androidWatcher(Application app, Listener heapDumpListener) {
          AndroidDebuggerControl debuggerControl = new AndroidDebuggerControl();
          AndroidHeapDumper heapDumper = new AndroidHeapDumper(app);
          heapDumper.cleanup();
      	
      	//到RefWatcher的构造方法
          return new RefWatcher(new AndroidWatchExecutor(), debuggerControl, GcTrigger.DEFAULT, heapDumper, heapDumpListener);
      }
    

    RefWatcher的构造方法

      public RefWatcher(Executor watchExecutor, DebuggerControl debuggerControl, GcTrigger gcTrigger,
        HeapDumper heapDumper, HeapDump.Listener heapdumpListener) {
          this.watchExecutor = checkNotNull(watchExecutor, "watchExecutor");
          this.debuggerControl = checkNotNull(debuggerControl, "debuggerControl");
      	
      	//手动调用GC的interface
          this.gcTrigger = checkNotNull(gcTrigger, "gcTrigger");
          
      	this.heapDumper = checkNotNull(heapDumper, "heapDumper");
          this.heapdumpListener = checkNotNull(heapdumpListener, "heapdumpListener");
      	
      	//存储监控引用的名称的set集合
          retainedKeys = new CopyOnWriteArraySet<>();
    
      	//存储监控对象的Queue
          queue = new ReferenceQueue<>();
        }
    

    至此 RefWatcher的初始化工作完成

  • 监控Activity

    由上述install中开始

      //监控Activity
      ActivityRefWatcher.installOnIcsPlus(application, refWatcher);
    

    调用过程:ActivityRefWatcher类

      public static void installOnIcsPlus(Application application, RefWatcher refWatcher) {
          if(VERSION.SDK_INT >= 14) {
              ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);
              activityRefWatcher.watchActivities();
          }
      }
    
      public void watchActivities() {
    
      	//停止监控
          this.stopWatchingActivities();
    
      	//给我们的application注册ActivityLifecycleCallback,生命周期监控
          this.application.registerActivityLifecycleCallbacks(this.lifecycleCallbacks);
      }
    

    生命周期监控回调:lifecycleCallbacks

      private final ActivityLifecycleCallbacks lifecycleCallbacks = new ActivityLifecycleCallbacks() {
          public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
          }
    
          public void onActivityStarted(Activity activity) {
          }
    
          public void onActivityResumed(Activity activity) {
          }
    
          public void onActivityPaused(Activity activity) {
          }
    
          public void onActivityStopped(Activity activity) {
          }
    
          public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
          }
    
          public void onActivityDestroyed(Activity activity) {
      		
      		//监控Activity的onDestory方法
              ActivityRefWatcher.this.onActivityDestroyed(activity);
    
          }
      };
    

    最终调用了refWatcher.watch()方法,来监控

      void onActivityDestroyed(Activity activity) {
          this.refWatcher.watch(activity);
      }
    

    到这里我们就知道了,LeakCanary初始化之后就对Activity的onDestory方法进行了监控,如果一直没有走onDestory(),说明出现了泄漏问题。然后具体的如何监控,提示的话是在watch()方法中实现的。

  • watch()

      public void watch(Object watchedReference) {
        watch(watchedReference, "");
      }
    
      public void watch(Object watchedReference, String referenceName) {
          checkNotNull(watchedReference, "watchedReference");
          checkNotNull(referenceName, "referenceName");
          if (debuggerControl.isDebuggerAttached()) {
            return;
          }
          final long watchStartNanoTime = System.nanoTime();
          String key = UUID.randomUUID().toString();
    
      	//给引用object随机一个key存到retainedKeys中
          retainedKeys.add(key);
    
      	//初始化一个自定义的弱引用,将监控的引用object 存到弱引用中 ,同时记录下内部 key 和 name
          final KeyedWeakReference reference =
              new KeyedWeakReference(watchedReference, key, referenceName, queue);
      
      	//异步执行 检查泄漏操作及GC操作
          watchExecutor.execute(new Runnable() {
            @Override public void run() {
              ensureGone(reference, watchStartNanoTime);
          }
        });
      }
    
    
      //检查是否泄漏、GC、保存heapdump信息的方法
      void ensureGone(KeyedWeakReference reference, long watchStartNanoTime) {
          long gcStartNanoTime = System.nanoTime();
      
          long watchDurationMs = NANOSECONDS.toMillis(gcStartNanoTime - watchStartNanoTime);
    
      	//清除retainedKeys中的key
          removeWeaklyReachableReferences();
      	//判断 reference的key是否还在set集合中,如果不在 就结束了。如果还在就执行gc操作
          if (gone(reference) || debuggerControl.isDebuggerAttached()) {
            return;
          }
          gcTrigger.runGc();
      	//执行完 GC 之后,再进行清除retainedKeys中的key操作
          removeWeaklyReachableReferences();
      	//判断 reference的key是否还在set集合中,如果还在就执行将heapDump记录下来
          if (!gone(reference)) {
            long startDumpHeap = System.nanoTime();
            long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);
      
            File heapDumpFile = heapDumper.dumpHeap();
      
            if (heapDumpFile == null) {
              // Could not dump the heap, abort.
              return;
            }
            long heapDumpDurationMs = NANOSECONDS.toMillis(System.nanoTime() - startDumpHeap);
            heapdumpListener.analyze(
                new HeapDump(heapDumpFile, reference.key, reference.name, watchDurationMs, gcDurationMs,
                    heapDumpDurationMs));
          }
        }
    
      //讲object从queue队列中取出来,如果不是空说明已经被GC回收了,就将存储到set集合中的key删除掉
      private void removeWeaklyReachableReferences() {
          // WeakReferences are enqueued as soon as the object to which they point to becomes weakly
          // reachable. This is before finalization or garbage collection has actually happened.
          KeyedWeakReference ref;
          while ((ref = (KeyedWeakReference) queue.poll()) != null) {
            retainedKeys.remove(ref.key);
          }
        }
    
      //判断 弱引用的key是否还在 set集合中
      private boolean gone(KeyedWeakReference reference) {
         return !retainedKeys.contains(reference.key);
      }
    

到这里整体流程就OK了,具体的那个将dumpheap保存下来没有写。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章