关于android:LeakCanary-分析

48次阅读

共计 6546 个字符,预计需要花费 17 分钟才能阅读完成。

LeakCanary 是 Square 公司推出个一个内存泄露检测工具,

[地址:[https://square.github.io/leak…]()](https://square.github.io/leak…

应用

简略应用,

在我的项目 Model 的 build.gradle 文件中 dependencies{}中退出

debugImplementation 'com.squareup.leakcanary:leakcanary-android:version'

而后在你的 App 中的 onCreate()办法中增加

LeakCanary.install(this);

这样 LeakCanary 就能够监控零碎的 Activity 的内存泄露了,默认应用只能检测到 Activity 的内存泄露。

如果你想检测其余对象的内存泄露,能够自定义监控对象。

    refWatcher = LeakCanary.install(this);

LeakCanary.install(this) 办法返回一个 RefWatcher 对象,调用该队的的 watch()办法就行了。

该办法的签名如下

// 传入你想检测的对象
public void watch(Object watchedReference) {watch(watchedReference, "");
}

原理

LeakCanary 中对内存透露检测的外围原理就是基于 WeakReference 和 ReferenceQueue 实现的。

1.  当一个 Activity 须要被回收时,就将其包装到一个 WeakReference 中,并且在 WeakReference 的结构器中传入自定义的 ReferenceQueue。2.  而后给包装后的 WeakReference 做一个标记 Key,并且在一个强援用 Set 中增加相应的 Key 记录

3.  最初被动触发 GC,遍历自定义 ReferenceQueue 中所有的记录,并依据获取的 Reference 对象将 Set 中的记录也删除

通过下面 3 步之后,还保留在 Set 中的就是:该当被 GC 回收,然而理论还保留在内存中的对象,也就是产生透露了的对象

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;}
 enableDisplayLeakActivity(application);
 HeapDump.Listener heapDumpListener =
 new ServiceHeapDumpListener(application, listenerServiceClass);
 RefWatcher refWatcher = androidWatcher(application, heapDumpListener);
 //  LeakCanary 中监听 Activity 生命周期是由 ActivityRefWatch 来负责的,次要是通过注册 Android 零碎提供的 ActivityLifecycleCallbacks,来监听 Activity 的生命周期办法的调用,ActivityRefWatcher.installOnIcsPlus(application, refWatcher);// 默认只检测 Activity 的内存泄露
 return refWatcher;// 返回 refWatcher 对象,}

RefWatcher 对象的构造方法如下。

     private final Executor watchExecutor; // 线程池
     private final DebuggerControl debuggerControl;
     private final GcTrigger gcTrigger;//GC 触发器
     private final HeapDumper heapDumper;
     private final Set<String> retainedKeys; // 检测对象的 Key 汇合
     private final ReferenceQueue<Object> queue;// 若援用队列
     private final HeapDump.Listener heapdumpListener;

    public RefWatcher(Executor watchExecutor, DebuggerControl debuggerControl, GcTrigger gcTrigger,HeapDumper heapDumper, HeapDump.Listener heapdumpListener) {this.watchExecutor = checkNotNull(watchExecutor, "watchExecutor");
     this.debuggerControl = checkNotNull(debuggerControl, "debuggerControl");
     this.gcTrigger = checkNotNull(gcTrigger, "gcTrigger");
     this.heapDumper = checkNotNull(heapDumper, "heapDumper");
     this.heapdumpListener = checkNotNull(heapdumpListener, "heapdumpListener");
     retainedKeys = new CopyOnWriteArraySet<>();
     queue = new ReferenceQueue<>();}

咱们看下 ActivityRefWatcher 这个类的外部实现,该类只反对 ICE_CREAM_SANDWICH 以上的版本。@TargetApi(ICE_CREAM_SANDWICH) public final class ActivityRefWatcher {
​
​
 private final Application application;
 private final RefWatcher refWatcher;

 public static void installOnIcsPlus(Application application, RefWatcher refWatcher) {
 低于 ICE_CREAM_SANDWICH 版本的本人在 BaseActivity 的 onDestroy 办法中解决
 if (SDK_INT < ICE_CREAM_SANDWICH) {// If you need to support Android < ICS, override onDestroy() in your base activity.
 return;
 }
 ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);
 activityRefWatcher.watchActivities();}
​
 /**
 * Constructs an {@link ActivityRefWatcher} that will make sure the activities are not leaking
 * after they have been destroyed.
 */
 public ActivityRefWatcher(Application application, final RefWatcher refWatcher) {this.application = checkNotNull(application, "application");
 this.refWatcher = checkNotNull(refWatcher, "refWatcher");
 }
​
​
 public void watchActivities() {
 // Make sure you don't get installed twice.
 stopWatchingActivities();
//   application 注册 ActivityLifecycleCallbacks 接口
 application.registerActivityLifecycleCallbacks(lifecycleCallbacks);
 }
​
 public void stopWatchingActivities() {application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks);
 }

 private final Application.ActivityLifecycleCallbacks 接口 lifecycleCallbacks =
 new Application.ActivityLifecycleCallbacks() {@Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { }
​
 @Override public void onActivityStarted(Activity activity) { }
​
 @Override public void onActivityResumed(Activity activity) { }
​
 @Override public void onActivityPaused(Activity activity) { }
​
 @Override public void onActivityStopped(Activity activity) { }
​
 @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { }
​
 // 在 Activity 销毁时开启检测
 @Override public void onActivityDestroyed(Activity activity) {ActivityRefWatcher.this.onActivityDestroyed(activity);
 }
 };

 // 检测
 void onActivityDestroyed(Activity activity) {refWatcher.watch(activity);
 }

}

最初调用 refWatcher 对象的 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();
 // 随机生成 Key
 String key = UUID.randomUUID().toString();
 // 将 Key 放入 retainedKeys 汇合中,retainedKeys 是一个 CopyOnWriteArraySet 对象。retainedKeys.add(key);
 // 将检测对象,key,referenceName,queue 构建一个 KeyedWeakReference 对象
 final KeyedWeakReference reference =
 new KeyedWeakReference(watchedReference, key, referenceName, queue);
​
 // 向线程池 watchExecutor 提交一个工作。在该工作里启动检测。watchExecutor.execute(new Runnable() {@Override public void run() {ensureGone(reference, watchStartNanoTime);
 }
 });
 }


 void ensureGone(KeyedWeakReference reference, long watchStartNanoTime) {long gcStartNanoTime = System.nanoTime();
​
 long watchDurationMs = NANOSECONDS.toMillis(gcStartNanoTime - watchStartNanoTime);
 // 移出援用队列里的对象
 removeWeaklyReachableReferences();
 if (gone(reference) || debuggerControl.isDebuggerAttached()) {return;}
 // 启动垃圾回收
 gcTrigger.runGc();
 // 移出援用队列里的对象
 removeWeaklyReachableReferences();
 // 如果 retainedKeys 里边仍然蕴含改若援用对象的 key. 阐明该弱对象援用的对象泄露了。if (!gone(reference)) {long startDumpHeap = System.nanoTime();
 long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);
 // 生成 Dump 文件
 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));
 }
 }

 // 移出如援用对象
 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;
 // 遍历队列,如果队列里的元素等于以后的对象,阐明以后对象被回收了,就从 retainedKeys 里移出弱援用对象对一个的 key.
 while ((ref = (KeyedWeakReference) queue.poll()) != null) {retainedKeys.remove(ref.key);
 }
 }

 // 判断以后的 reference 对象对象的 Key 是否蕴含在 retainedKeys,如果在就阐明 reference 没有被垃圾回收
 private boolean gone(KeyedWeakReference reference) {return !retainedKeys.contains(reference.key);
 }

正文完
 0