if (LeakCanary.isInAnalyzerProcess(this)) { // This process is dedicated to LeakCanary for heap analysis. // You should not init your app in this process. return; } LeakCanary.install(this); // Normal app init code...
1.LeakCanary.isInAnalyzerProcess(this)
判断当前进程是否和HeapAnalyzerService在同一进程
1 2 3 4 5 6
* Whether the current process is the process running the {@link HeapAnalyzerService}, which is * a different process than the normal app process. */ public static boolean isInAnalyzerProcess(Context context) { return isInServiceProcess(context, HeapAnalyzerService.class); }
/** Builder to create a customized {@link RefWatcher} with appropriate Android defaults. */ public static AndroidRefWatcherBuilder refWatcher(Context context) { return new AndroidRefWatcherBuilder(context); }
以下均在AndroidRefWatcherBuilder.java中
.listenerServiceClass(DisplayLeakService.class)
1 2 3 4 5 6 7 8
/** * Sets a custom {@link AbstractAnalysisResultService} to listen to analysis results. This * overrides any call to {@link #heapDumpListener(HeapDump.Listener)}. */ public AndroidRefWatcherBuilder listenerServiceClass( Class<? extends AbstractAnalysisResultService> listenerServiceClass) { return heapDumpListener(new ServiceHeapDumpListener(context, listenerServiceClass)); }
/** * This returns the references in the leak path that can be ignored for app developers. This * doesn't mean there is no memory leak, to the contrary. However, some leaks are caused by bugs * in AOSP or manufacturer forks of AOSP. In such cases, there is very little we can do as app * developers except by resorting to serious hacks, so we remove the noise caused by those leaks. */ public static ExcludedRefs.Builder createAppDefaults() { return createBuilder(EnumSet.allOf(AndroidExcludedRefs.class)); }
3 .buildAndInstall();
1 2 3 4 5 6 7 8 9 10 11
/** * Creates a {@link RefWatcher} instance and starts watching activity references (on ICS+). */ public RefWatcher buildAndInstall() { RefWatcher refWatcher = build(); if (refWatcher != DISABLED) { LeakCanary.enableDisplayLeakActivity(context); ActivityRefWatcher.install((Application) context, refWatcher); } return refWatcher; }
public static void install(Application application, RefWatcher refWatcher) { new ActivityRefWatcher(application, refWatcher).watchActivities(); }
ActivityRefWatcher#watchActivities()
ActivityRefWatcher.java
1 2 3 4 5
public void watchActivities() { // Make sure you don't get installed twice. stopWatchingActivities(); //避免重复install application.registerActivityLifecycleCallbacks(lifecycleCallbacks); }
@SuppressWarnings("ReferenceEquality") // Explicitly checking for named null. Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) { long gcStartNanoTime = System.nanoTime(); long watchDurationMs = NANOSECONDS.toMillis(gcStartNanoTime - watchStartNanoTime);
removeWeaklyReachableReferences();
if (debuggerControl.isDebuggerAttached()) { // The debugger can create false leaks. return RETRY; } if (gone(reference)) { return DONE; } gcTrigger.runGc(); removeWeaklyReachableReferences(); if (!gone(reference)) { long startDumpHeap = System.nanoTime(); long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);
File heapDumpFile = heapDumper.dumpHeap(); if (heapDumpFile == RETRY_LATER) { // Could not dump the heap. return RETRY; } long heapDumpDurationMs = NANOSECONDS.toMillis(System.nanoTime() - startDumpHeap); heapdumpListener.analyze( new HeapDump(heapDumpFile, reference.key, reference.name, excludedRefs, watchDurationMs, gcDurationMs, heapDumpDurationMs)); } return DONE; }
removeWeaklyReachableReferences()
1 2 3 4 5 6 7 8 9
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); } }
gcTrigger.runGc()
1 2 3 4 5 6 7 8
public void runGc() {
// System.gc() does not garbage collect every time. Runtime.gc() is // more likely to perfom a gc. Runtime.getRuntime().gc(); enqueueReferences(); System.runFinalization(); }