一、源码
LeakCanary内存分析模块,独立进程,包名:leakcanary,保持app进程独立。
在Application类执行LeakCanary.install(this)方法。
public static RefWatcher install(Application application) {
return refWatcher(application).listenerServiceClass(DisplayLeakService.class)
.excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
.buildAndInstall();
}
refWatcher()方法,生成AndroidRefWatcherBuilder建造者,buildAndInstall()方法,创建RefWatcher对象,Ref观察者监控引用对象。
DisplayLeakService服务,消息通知栏。
public RefWatcher buildAndInstall() {
RefWatcher refWatcher = build();
if (refWatcher != DISABLED) {
if (watchActivities) {
ActivityRefWatcher.install(context, refWatcher);
}
if (watchFragments) {
FragmentRefWatcher.Helper.install(context, refWatcher);
}
}
LeakCanaryInternals.installedRefWatcher = refWatcher;
return refWatcher;
}
ActivityRefWatcher观察Activity,FragmentRefWatcher观察Fragment,build()方法创建RefWatcher,返回赋值给静态对象LeakCanaryInternals。
ActivityRefWatcher类的install()方法。
public static void install(Context context, RefWatcher refWatcher) {
Application application = (Application) context.getApplicationContext();
ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);
application.registerActivityLifecycleCallbacks(activityRefWatcher.lifecycleCallbacks);
}
Application类registerActivityLifecycleCallbacks()方法,监听所有Activity生命周期回调,仅重写onActivityDestroyed方法,当关闭一个Activity(销毁)时,会触发此方法。
private final Application.ActivityLifecycleCallbacks lifecycleCallbacks =
new ActivityLifecycleCallbacksAdapter() {
@Override public void onActivityDestroyed(Activity activity) {
refWatcher.watch(activity);
}
};
Activity组件销毁时,RefWatcher类的watch()方法分析跟踪,观察该Activity组件对象是否会被gc回收。
二、监控原理
watch(Object)方法,观察Object对象是否被回收,(监控的Activity对象)。
public void watch(Object watchedReference, String referenceName) {
final long watchStartNanoTime = System.nanoTime();
String key = UUID.randomUUID().toString();
retainedKeys.add(key);
final KeyedWeakReference reference =
new KeyedWeakReference(watchedReference, key, referenceName, queue);
ensureGoneAsync(watchStartNanoTime, reference);
}
创建一个KeyedWeakReference弱引用(继承WeakReference),生成key,将代表弱引用的key加入retainedKeys列表。
public WeakReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
WeakReference构造方法,弱引用对象,关联ReferenceQueue队列,父类Reference内部ReferenceQueue,Reference类enqueue()方法,向队列插入本身。
public boolean enqueue() {
return queue != null && queue.enqueue(this);
}
Reference的ReferenceQueue
private void ensureGoneAsync(final long watchStartNanoTime, final KeyedWeakReference reference) {
watchExecutor.execute(new Retryable() {
@Override public Retryable.Result run() {
return ensureGone(reference, watchStartNanoTime);
}
});
}
ensureGoneAsync方法,WatchExecutor执行者触发ensureGone()方法。
Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) {
removeWeaklyReachableReferences();
if (gone(reference)) {
return DONE;
}
gcTrigger.runGc();
removeWeaklyReachableReferences();
if (!gone(reference)) {
...
File heapDumpFile = heapDumper.dumpHeap();
HeapDump heapDump = heapDumpBuilder.heapDumpFile(heapDumpFile).referenceKey(reference.key)
.referenceName(reference.name)
.watchDurationMs(watchDurationMs)
.gcDurationMs(gcDurationMs)
.heapDumpDurationMs(heapDumpDurationMs)
.build();
heapdumpListener.analyze(heapDump);
}
return DONE;
}
removeWeaklyReachableReferences()方法,从ReferenceQueue队列poll(),(回收的弱引用对象被加入ReferenceQueue队列),表示对象被gc,从列表retainedKeys删除对应key键值,gone()方法,判断retainedKeys是否包含key。
Reference和ReferenceQueue
当弱引用Reference关联对象被回收,虚拟机将该弱引用加入ReferenceQueue队列,只需判断在这个队列中是否包含弱引用即可。
Reference类的enquque()方法,向Reference内部队列ReferenceQueue添加。
gone()方法,ReferenceQueue队列弱引用是空时,对象未回收是可达的,手动gc操作。
@Override
public void runGc() {
Runtime.getRuntime().gc();
enqueueReferences();
System.runFinalization();
}
Runtimel类gc()操作,再一次执行removeWeaklyReachableReferences()方法和gone()方法,当retainedKeys不包含该若引用key时,说明对象被gc。
两次回收判断(包括一次gc后),如果都判定未回收,大概率是无法回收,说明这个对象存在内存泄漏。
三、泄漏处理
检测到泄漏时,dumpHeap生成一个文件。HeapDump的Listener的analyze方法,分析的是HeapDump对象,ServiceHeapDumpListener继承了Listener接口,启动一个HeapAnalyzerService服务,继承IntentService,在单独进程中分析。利用HeapAnalyzer,内部采用mat对内存进行分析并生成结果。
在分析时,分为findLeakingReference与findLeakTrace来查找泄漏的引用与轨迹,根据GCRoot开始按树形结构依次建议当前引用的轨迹信息。
开启内存泄漏查看页面DisplayLeakActivity。
四、总结
1,注册ActivityLifecycleCallbacks监听回调Activity销毁方法,RefWathcer类分析观察Activity对象。
2,虚拟机将回收的Reference弱引用加入其关联的ReferenceQueue队列,通过队列中的弱引用判定对象是否被回收,
3,每一个监控对象(watch方法)创建一个弱引用KeyedWeakReference。
4,弱引用Reference内部WeakReference队列,Reference的enqueue()方法,将自己加入队列。
任重而道远
网友评论