@Synchronized fun watch(
watchedReference: Any,
referenceName: String
) {
if (!isEnabled()) {
return
}
// 移除被回收的所有的弱应用对象
removeWeaklyReachableReferences()
val key = UUID.randomUUID()
.toString()
val watchUptimeMillis = clock.uptimeMillis()
// 对 Activity 创建 弱应用对象
val reference =
KeyedWeakReference(watchedReference, key, referenceName, watchUptimeMillis, queue)
if (referenceName != "") {
CanaryLog.d(
"Watching instance of %s named %s with key %s", reference.className,
referenceName, key
)
} else {
CanaryLog.d(
"Watching instance of %s with key %s", reference.className, key
)
}
watchedReferences[key] = reference
checkRetainedExecutor.execute {
// 延时5秒后,如果该对象还未被回收,则发生内存泄漏。
// 当泄漏的对象5个以上时,dump 出 hprof 文件,找到泄漏路径
moveToRetained(key)
}
}
private fun 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.
var ref: KeyedWeakReference?
do {
// 获取引用对象
ref = queue.poll() as KeyedWeakReference?
if (ref != null) {
// 如果存在,则表示已经被回收,从观察列表中移除
val removedRef = watchedReferences.remove(ref.key)
if (removedRef == null) {
retainedReferences.remove(ref.key)
}
}
} while (ref != null)
}
}
LeakCanary Principle
[TOC]
这篇文章介绍 LeakCanary 的原理,基于版本 2.0,kotlin。
基本使用
加入依赖即可,以使用 ContentProvider 进行自动初始化。LifeCycle 库类似, 可用于初始化sdk,三方库等。
基本原理
Reference
Reference 把内存分为 4 种状态,Active,Pending,Exqueued, Inactive。
Active 一般说来内存一开始被分配的状态都是 Active
Pending 快要放入队列(ReferenceQueue)的对象,也就是马上要回收的对象
Enqueued 对象已经进入队列,已经被回收的对象。方便我们查询某个对象是否被回收
Inactive 最终的状态,无法变成其他的状态。
ReferenceQueue
引用队列,在 Reference 被回收的时候,Reference 会被添加到 ReferenceQueue 中
如果检测一个对象是否被回收
需要采用 Reference + ReferenceQueue
在 Reference 类加载的时候,Java 虚拟机会创建一个最大优先级的后台线程,这个线程的工作就是不断检测 pending 是否为 null,如果不为 null,那么就将它放到 ReferenceQueue。因为 pending 不为 null,就说明引用所指向的对象已经被 GC。
Heap Dump
Heap Dump也叫堆存储文件,是一个Java进程在某个时间点上的内存快照。
原理说明
初始化
上述代码很容易理解,首先是对 Activity 的生命周期进行监听,在 destory 发生的时候进行监听,看是否被回收。
监听过程
核心代码如下:
回过去看原理,还是很熔体理解。
moveToRetained() 就是后续判断泄漏对象和分析 dump 文件的工作。这里不做过多介绍。
同理, fragment 的观察过程也类似。