leakcanary1.5代码流程

LeakCanary 使用

在Application的onCreate中,如下操作

1
2
3
4
5
6
7
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);
}

2.LeakCanary.install(this);

1
2
3
4
5
public static RefWatcher install(Application application) {
return refWatcher(application).listenerServiceClass(DisplayLeakService.class)
.excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
.buildAndInstall();
}
refWatcher(application)

返回一个AndroidRefWatcherBuilder对象 AndroidRefWatcherBuilder extends RefWatcherBuilder

1
2
3
4
/** 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));
}
  • DisplayLeakService extends AbstractAnalysisResultService extends IntentService 用于展示leak之后的dump信息
  • 创建ServiceHeapDumpListener对象 作为heapDumpListener

2..excludedRefs(AndroidExcludedRefs.createAppDefaults().build())

ExcludedRefs排除的引用?
AndroidExcludedRefs.createAppDefaults().build() 创建一个ExcludedRefs对象给RefWatcherBuilder

1
2
3
4
5
6
7
8
9
/**
* 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;
}
  • 创建RefWatcher对象
  • enableDisplayLeakActivity(context)
  • ActivityRefWatcher.install((Application) context, refWatcher)

enableDisplayLeakActivity(context)

1
2
3
public static void enableDisplayLeakActivity(Context context) {
setEnabled(context, DisplayLeakActivity.class, true);
}

DisplayLeakActivity用于展示dump的Activity

1
2
3
4
5
6
7
8
9
public static void setEnabled(Context context, final Class<?> componentClass,
final boolean enabled) {
final Context appContext = context.getApplicationContext();
executeOnFileIoThread(new Runnable() {
@Override public void run() {
setEnabledBlocking(appContext, componentClass, enabled);
}
});
}

executeOnFileIoThread

1
2
3
public static void executeOnFileIoThread(Runnable runnable) {
fileIoExecutor.execute(runnable);
}

private static final Executor fileIoExecutor = newSingleThreadExecutor(“File-IO”);
是一个单线程线程池在执行setEnabledBlocking(),冻结应用

1
2
3
4
5
6
7
8
public static void setEnabledBlocking(Context appContext, Class<?> componentClass,
boolean enabled) {
ComponentName component = new ComponentName(appContext, componentClass);
PackageManager packageManager = appContext.getPackageManager();
int newState = enabled ? COMPONENT_ENABLED_STATE_ENABLED : COMPONENT_ENABLED_STATE_DISABLED;
// Blocks on IPC.
packageManager.setComponentEnabledSetting(component, newState, DONT_KILL_APP);
}

Android 应用冻结流程分析

ActivityRefWatcher.install((Application) context, refWatcher)

1
2
3
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);
}

application.registerActivityLifecycleCallbacks(lifecycleCallbacks);

lifecycleCallbacks为ActivityRefWatcher中的成员变量,值得注意的是

ActivityRefWatcher.java

1
2
3
@Override public void onActivityDestroyed(Activity activity) {
ActivityRefWatcher.this.onActivityDestroyed(activity);
}

继续跟代码

1
2
3
void onActivityDestroyed(Activity activity) {
refWatcher.watch(activity);
}

RefWatcher.java

1
2
3
public void watch(Object watchedReference) {
watch(watchedReference, "");
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void watch(Object watchedReference, String referenceName) {
if (this == DISABLED) {
return;
}
checkNotNull(watchedReference, "watchedReference");
checkNotNull(referenceName, "referenceName");
final long watchStartNanoTime = System.nanoTime();
String key = UUID.randomUUID().toString();
retainedKeys.add(key);
final KeyedWeakReference reference =
new KeyedWeakReference(watchedReference, key, referenceName, queue);//1

ensureGoneAsync(watchStartNanoTime, reference);//2
}
final KeyedWeakReference reference =new KeyedWeakReference(watchedReference, key, referenceName, queue)

KeyedWeakReference继承弱引用,构造器传入watchedReference、referenceName,key。watchedReference是监视destory的Activity对象,referenceName = “”,key为随机生成

System.nanoTime()返回的是纳秒,nanoTime而返回的可能是任意时间,甚至可能是负数

ensureGoneAsync(watchStartNanoTime, reference)
1
2
3
4
5
6
7
private void ensureGoneAsync(final long watchStartNanoTime, final KeyedWeakReference reference) {
watchExecutor.execute(new Retryable() {
@Override public Retryable.Result run() {
return ensureGone(reference, watchStartNanoTime);
}
});
}
watchExecutor

watchExecutor由RefWatcher构造函数传入

RefWatcherBuilder.java

#build()

1
2
3
4
5
6
7
8
9
10
public final RefWatcher build() {

WatchExecutor watchExecutor = this.watchExecutor;
if (watchExecutor == null) {
watchExecutor = defaultWatchExecutor();
}

return new RefWatcher(watchExecutor, debuggerControl, gcTrigger, heapDumper, heapDumpListener,
excludedRefs);
}

#watchExecutor()

1
2
3
4
5
/** @see WatchExecutor */
public final T watchExecutor(WatchExecutor watchExecutor) {
this.watchExecutor = watchExecutor;
return self();
}

AndroidRefWatcherBuilder.java

1
2
3
public AndroidRefWatcherBuilder watchDelay(long delay, TimeUnit unit) {
return watchExecutor(new AndroidWatchExecutor(unit.toMillis(delay)));
}
1
2
3
@Override protected WatchExecutor defaultWatchExecutor() {
return new AndroidWatchExecutor(DEFAULT_WATCH_DELAY_MILLIS);
}

watchExecutor对象是一个AndroidWatchExecutor,DEFAULT_WATCH_DELAY_MILLIS = 5s

AndroidWatchExecutor.java

1
2
3
4
5
6
7
@Override public void execute(Retryable retryable) {
if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
waitForIdle(retryable, 0);
} else {
postWaitForIdle(retryable, 0);
}
}

如果在主线程

ensureGone(reference, watchStartNanoTime)

  • 两次 removeWeaklyReachableReferences()
  • gcTrigger.runGc()
  • heapdumpListener.analyze()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@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();
}

ServiceHeapDumpListener.java

1
2
3
4
@Override public void analyze(HeapDump heapDump) {
checkNotNull(heapDump, "heapDump");
HeapAnalyzerService.runAnalysis(context, heapDump, listenerServiceClass);
}

RefWatcher其实就是一个引用观察者对象,是用于监测当前实例对象的引用状态的