read the fucking source code
前言
本文不包含分析LeakCanary
所使用的haha
库的代码.
本文基于:leakcanary-android:2.7
简单的使用仅是一句话,连初始化代码都不需要你写.
dependencies {
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
}
LeakCanary初始化分析
上图便是leakCanary
工程目录,而初始化代码位于leakcanary-android-process
.
其清单文件如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.squareup.leakcanary.objectwatcher" >
<uses-sdk android:minSdkVersion="14" />
<application>
<!--很巧妙的利用利用provider进行初始化-->
<provider
android:name="leakcanary.internal.AppWatcherInstaller$MainProcess"
android:authorities="${applicationId}.leakcanary-installer"
android:enabled="@bool/leak_canary_watcher_auto_install"
android:exported="false" />
</application>
</manifest>
这里补充一个知识点 AMS初始一个app的时候先调用Provider.onCreate
在调用Application.onCreate
.
又让我从LeakCanary
学来的奇淫技巧.
如果你想知道为什么可参考:
Application.onCreate 、ContentProvider.onCreate 、 Activity.onCreate 的调用顺序研究
//AppWatcherInstaller.kt
internal sealed class AppWatcherInstaller : ContentProvider() {
//内部类巧妙的运用,可以瞬间构造两个不同的provider,可以拿来切换或者测试等
internal class MainProcess : AppWatcherInstaller()
internal class LeakCanaryProcess : AppWatcherInstaller()
override fun onCreate(): Boolean {
val application = context!!.applicationContext as Application
AppWatcher.manualInstall(application)
return true
}
//ObjectWatcher.kt
class ObjectWatcher constructor(
private val clock: Clock,
//注意下这个参数,Executor很明显就是jdk类,用于封装线程调度
private val checkRetainedExecutor: Executor,
private val isEnabled: () -> Boolean = { true }
)
//AppWatcher.kt
object AppWatcher {
//ObjectWatcher对象具体后面将.我们首先观察一个属性checkRetainedExecutor
val objectWatcher = ObjectWatcher(
clock = { SystemClock.uptimeMillis() },
checkRetainedExecutor = {
//internal val mainHandler by lazy { Handler(Looper.getMainLooper()) }
//这里拿的android主线的handler
//为什么这里拿主线程是有一定原因的后文再讲
mainHandler.postDelayed(it, retainedDelayMillis)
},
isEnabled = { true }
)
fun manualInstall(
application: Application,
retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
watchersToInstall: List<InstallableWatcher> = appDefaultWatchers(application)
) {
//...略
//注册一些监听这里先不深究,讲到时在做分析
LeakCanaryDelegate.loadLeakCanary(application)
//我们在看下这个集合
watchersToInstall.forEach {
it.install()
}
}
fun appDefaultWatchers(
application: Application,
reachabilityWatcher: ReachabilityWatcher = objectWatcher
): List<InstallableWatcher> {
//每个集合对象表示可以监控内存泄露的类
return listOf(
//监控Activity
ActivityWatcher(application, reachabilityWatcher),
//fragment和viewmodel
FragmentAndViewModelWatcher(application, reachabilityWatcher),
//监控view
RootViewWatcher(reachabilityWatcher),
//监控service
ServiceWatcher(reachabilityWatcher)
)
}
}
上面将四个集合对象调用install
便完成了初始化.
ActivityWatcher
ActivityWatcher
用于监控Activity
相关的泄露.在了解之前先要补充一个小知识点.
ReferenceQueue妙用
ReferenceQueue
被相关引用我们可知道那些对象被回收.
public class JavaMain {
static String smg = new String("nihao");
public static void main(String[] args) throws InterruptedException {
ReferenceQueue<String> queue = new ReferenceQueue<>();
//WeakReference对象被回收时,会将reference放入queue中
Reference<String> reference = new WeakReference<>(smg, queue);
Reference<? extends String> poll = queue.poll();
//输出null,因为对象被smg引用
System.out.println(poll);
smg = null;
//执行Gc,在android请用Runtime.getRuntime().gc();具体原因后文讲解
System.gc();
TimeUnit.SECONDS.sleep(1);
//输出java.lang.ref.WeakReference@15db9742
poll = queue.poll();
System.out.println(poll);
}
}
上面是一个小例子,请务必理解.另外如果WeakReference持有的是常量池的引用,是不会被回收的.如下:
public class JavaMain {
//注意原来是new String("nihao")
//smg指向常量池nihao
static String smg = "nihao";
public static void main(String[] args) throws InterruptedException {
ReferenceQueue<String> queue = new ReferenceQueue<>();
Reference<String> reference = new WeakReference<>(smg, queue);
Reference<? extends String> poll = queue.poll();
//输出null
System.out.println(poll);
smg = null;
//执行Gc,在android请用Runtime.getRuntime().gc();具体原因后文讲解
System.gc();
TimeUnit.SECONDS.sleep(1);
poll = queue.poll();
//输出null.常量池对象不轻易回收
System.out.println(poll);
}
}
ActivityWatcher
的核心思想是在Activity
的Destroy
时,将Activity
放入一个WeakReference
中,而WeakReference
会传入一个ReferenceQueue
,在等候一定时间后判断ReferenceQueue
是否有了新元素.
ActivityWatcher
//ActivityWatcher.kt
class ActivityWatcher(
private val application: Application,
private val reachabilityWatcher: ReachabilityWatcher
) : InstallableWatcher {
private val lifecycleCallbacks =
object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
override fun onActivityDestroyed(activity: Activity) {
//利用Application对象注册Activity的destory回调.
//reachabilityWatcher指向AppWatcher.objectWatcher
reachabilityWatcher.expectWeaklyReachable(
activity, "${activity::class.java.name} received Activity#onDestroy() callback"
)
}
}
//初始化代码会调用
override fun install() {
application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
}
override fun uninstall() {
application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
}
}
class ObjectWatcher constructor(
private val clock: Clock,
private val checkRetainedExecutor: Executor,//指向main线程哦
private val isEnabled: () -> Boolean = { true }){
//放入要检测泄露的对象,和queue配合检测泄露,如果queue.pool返回对象时需要删除watchedObjects引用
private val watchedObjects = mutableMapOf<String, KeyedWeakReference>()
//queue存储要检测的休闲,和watchedObjects合作检测泄露
private val queue = ReferenceQueue<Any>()
@Synchronized override fun expectWeaklyReachable(
watchedObject: Any,
description: String
) {
if (!isEnabled()) {
return
}
//循环queue.pool函数直到返回null,期间同时清理能返回数据的watchedObjects对象
removeWeaklyReachableObjects()
val key = UUID.randomUUID()
.toString()
val watchUptimeMillis = clock.uptimeMillis()
//将当前Activity放入引用对象中,注意这里传入了queue
val reference =
KeyedWeakReference(watchedObject, key, description, watchUptimeMillis, queue)
//放入一个数组中
watchedObjects[key] = reference
//checkRetainedExecutor是主线程哦.execute会将任务丢到队列中,那么会延迟执行,
//为什么checkRetainedExecutor要是主线程?因为Activity调用destroy不会马上回收,
//android会在destroy返回后会做一些清理在回收
checkRetainedExecutor.execute {
//往下分析
moveToRetained(key)
}
}
private fun removeWeaklyReachableObjects() {
//比较简单,queue.pool返回了对象,那么证明对象被回收,watchedObjects也就没必要保存监控对象
var ref: KeyedWeakReference?
do {
ref = queue.poll() as KeyedWeakReference?
if (ref != null) {
watchedObjects.remove(ref.key)
}
} while (ref != null)
}
}
上文会将一个事件丢入main线程然后等候下次调度moveToRetained
,这时基本Activity已经被回收
private fun moveToRetained(key: String) {
//移除被回收对象
removeWeaklyReachableObjects()
val retainedRef = watchedObjects[key]
//如果removeWeaklyReachableObjects没有移除retainedRef 那么证明还没有回收
if (retainedRef != null) {
retainedRef.retainedUptimeMillis = clock.uptimeMillis()
//onObjectRetainedListeners在LeakCanaryDelegate.loadLeakCanary(application)被设置
onObjectRetainedListeners.forEach { it.onObjectRetained() }
}
}
//InternalLeakCanary.kt
//这里继承两个接口:
// (Application) -> Unit
// OnObjectRetainedListener
internal object InternalLeakCanary : (Application) -> Unit, OnObjectRetainedListener {
//运行到这
override fun onObjectRetained() = scheduleRetainedObjectCheck()
fun scheduleRetainedObjectCheck() {
//视为true即可
if (this::heapDumpTrigger.isInitialized) {
//heapDumpTrigger为HeapDumpTrigger,再次严禁的确认对象是否没有被释放
heapDumpTrigger.scheduleRetainedObjectCheck()
}
}
}
//HeapDumpTrigger.kt
fun scheduleRetainedObjectCheck(
delayMillis: Long = 0L
) {
val checkCurrentlyScheduledAt = checkScheduledAt
if (checkCurrentlyScheduledAt > 0) {
return
}
checkScheduledAt = SystemClock.uptimeMillis() + delayMillis
//backgroundHandler是一个子线程
backgroundHandler.postDelayed({
checkScheduledAt = 0
checkRetainedObjects()
}, delayMillis)
}
private fun checkRetainedObjects() {
//再次严禁的确认是否泄漏,
//获取存活数量
var retainedReferenceCount = objectWatcher.retainedObjectCount
if (retainedReferenceCount > 0) {
//触发gc后在获取一次存活数量
gcTrigger.runGc()
retainedReferenceCount = objectWatcher.retainedObjectCount
}
//...略
}
object Default : GcTrigger {
override fun runGc() {
// Code taken from AOSP FinalizationTest:
// https://android.googlesource.com/platform/libcore/+/master/support/src/test/java/libcore/
// java/lang/ref/FinalizationTester.java
// System.gc() does not garbage collect every time. Runtime.gc() is
// more likely to perform a gc.
//这里英文注释解释的很好,System.gc() 并不会每次都会执行gc,Runtime.gc()更加可能执行
Runtime.getRuntime()
.gc()
enqueueReferences()
System.runFinalization()
}
private fun enqueueReferences() {
// Hack. We don't have a programmatic way to wait for the reference queue daemon to move
// references to the appropriate queues.
try {
Thread.sleep(100)
} catch (e: InterruptedException) {
throw AssertionError()
}
}
}
在确认泄漏后我们不在分析,我们看看其他泄漏是怎么检测的
FragmentAndViewModelWatcher
class FragmentAndViewModelWatcher(
private val application: Application,
private val reachabilityWatcher: ReachabilityWatcher
) : InstallableWatcher {
private val fragmentDestroyWatchers: List<(Activity) -> Unit> = run {
val fragmentDestroyWatchers = mutableListOf<(Activity) -> Unit>()
//略这里 AndroidXFragmentDestroyWatcher放入fragmentDestroyWatchers
fragmentDestroyWatchers
}
private val lifecycleCallbacks =
object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
override fun onActivityCreated(
activity: Activity,
savedInstanceState: Bundle?
) {
//注意这里调用oncreate的时候放入一个观察
//fragmentDestroyWatchers存放AndroidXFragmentDestroyWatcher
for (watcher in fragmentDestroyWatchers) {
//调用AndroidXFragmentDestroyWatcher.invoke.
//
watcher(activity)
}
}
}
override fun install() {
application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
}
override fun uninstall() {
application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
}
}
//AndroidXFragmentDestroyWatcher.kt
internal class AndroidXFragmentDestroyWatcher(
private val reachabilityWatcher: ReachabilityWatcher
) : (Activity) -> Unit {
override fun invoke(activity: Activity) {
if (activity is FragmentActivity) {
val supportFragmentManager = activity.supportFragmentManager
//registerFragmentLifecycleCallbacks可以监听到每个fragment的添加和实例
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true)
//viewModel相关,先暂时放着
ViewModelClearedWatcher.install(activity, reachabilityWatcher)
}
}
private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentCreated(
fm: FragmentManager,
fragment: Fragment,
savedInstanceState: Bundle?
) {
//viewmodel相关,先跳过
ViewModelClearedWatcher.install(fragment, reachabilityWatcher)
}
override fun onFragmentViewDestroyed(
fm: FragmentManager,
fragment: Fragment
) {
val view = fragment.view
if (view != null) {
//检测view是否被持有,原理同Activity,这里不在重复讲解
reachabilityWatcher.expectWeaklyReachable(
view, "${fragment::class.java.name} received Fragment#onDestroyView() callback " +
"(references to its views should be cleared to prevent leaks)"
)
}
}
override fun onFragmentDestroyed(
fm: FragmentManager,
fragment: Fragment
) {
//检测fragment是否被持有,原理同Activity.这里不在重复讲解
reachabilityWatcher.expectWeaklyReachable(
fragment, "${fragment::class.java.name} received Fragment#onDestroy() callback"
)
}
}
}
ViewModelClearedWatcher
上一小节我们看到在fragment的create函数调用 ViewModelClearedWatcher.install(fragment, reachabilityWatcher)
进行监控viewmodel
的泄露.
请务必了解viewmodel基础知识:
internal class ViewModelClearedWatcher(
storeOwner: ViewModelStoreOwner,
private val reachabilityWatcher: ReachabilityWatcher
) : ViewModel() {
private val viewModelMap: Map<String, ViewModel>?
init {
//ViewModelStore内部有一个mMap对象,mMap存放所有的viewmodel
val mMapField = ViewModelStore::class.java.getDeclaredField("mMap")
mMapField.isAccessible = true
//获取fragment的ViewModelStoreOwner实例,通过实例获得这个mMap对象
//从而得到所有的viewmodel
mMapField[storeOwner.viewModelStore] as Map<String, ViewModel>
} catch (ignored: Exception) {
null
}
}
override fun onCleared() {
//开始回收viewmodel
//遍历所有的viewmodel然后检查是否泄漏
viewModelMap?.values?.forEach { viewModel ->
reachabilityWatcher.expectWeaklyReachable(
viewModel, "${viewModel::class.java.name} received ViewModel#onCleared() callback"
)
}
}
companion object {
fun install(
storeOwner: ViewModelStoreOwner,
reachabilityWatcher: ReachabilityWatcher
) {
//这里注意传入的factory,不过传入什么都是创建ViewModelClearedWatcher对象
val provider = ViewModelProvider(storeOwner, object : Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T =
ViewModelClearedWatcher(storeOwner, reachabilityWatcher) as T
})
//ViewModelClearedWatcher是一个间谍viewmodel,主要是为了监听oncleared回调
provider.get(ViewModelClearedWatcher::class.java)
}
}
}
ServiceWatcher
监控Service
的Destroy
代码可能略复杂.设计反射,和service
启动流程.需要知道一些插件化知识.
下文可能需要基础的handler
知识,可参阅博主:
handler相关知识
知识储备
我们四大组件的创建和销毁都会从AMS
通过Binder
(跨进程IPC方式)传到我们App
的ActivityThread.mh
处理.
而mh是我们的是一个Handler
,于是乎我们可以反射拿到mh
,然后给Handler
设置一个mCallback
对象即可拦截所有的AMS
消息.mCallback
返回false
会继续交给handler
处理.
public final class ActivityThread {
final H mH = new H();
private class H extends Handler {
}
}
我们设置mCallback
后
我们最后看下LeakCanary
相关代码
private val activityThreadClass by lazy { Class.forName("android.app.ActivityThread") }
//ActivityThread有一静态个属性currentActivityThread,保存自己的实例
private val activityThreadInstance by lazy {
activityThreadClass.getDeclaredMethod("currentActivityThread").invoke(null)!!
}
private fun swapActivityThreadHandlerCallback(swap: (Handler.Callback?) -> Handler.Callback?) {
//activityThreadClass为Class.forName("android.app.ActivityThread")
val mHField =
activityThreadClass.getDeclaredField("mH").apply { isAccessible = true }
//获取属性,这里mHField[xxxx]是kotlin语法不比困惑
val mH = mHField[activityThreadInstance] as Handler
//找到Handler.mCallback
val mCallbackField =
Handler::class.java.getDeclaredField("mCallback").apply { isAccessible = true }
//获取mCallback实例
val mCallback = mCallbackField[mH] as Handler.Callback?
//替换成自己的Handler.Callback,内部会转发到原始mCallback
mCallbackField[mH] = swap(mCallback)
}
service
还有一个相关的函数ActivityManagerProxy.serviceDoneExecuting
,
当service创建完成(回调oncreate之后)后,回调用ActivityManagerProxy.serviceDoneExecuting
.当service被销毁后(AMS下发消息,且回调onDestroy后)回调ActivityManagerProxy.serviceDoneExecuting
所以我们有两个hook
点可以用来检测被销毁.
//因为都是简单操作,读者可自行类别上文swapActivityThreadHandlerCallback
private fun swapActivityManager(swap: (Class<*>, Any) -> Any) {
val singletonClass = Class.forName("android.util.Singleton")
val mInstanceField =
singletonClass.getDeclaredField("mInstance").apply { isAccessible = true }
val singletonGetMethod = singletonClass.getDeclaredMethod("get")
val (className, fieldName) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
"android.app.ActivityManager" to "IActivityManagerSingleton"
} else {
"android.app.ActivityManagerNative" to "gDefault"
}
val activityManagerClass = Class.forName(className)
val activityManagerSingletonField =
activityManagerClass.getDeclaredField(fieldName).apply { isAccessible = true }
val activityManagerSingletonInstance = activityManagerSingletonField[activityManagerClass]
// Calling get() instead of reading from the field directly to ensure the singleton is
// created.
val activityManagerInstance = singletonGetMethod.invoke(activityManagerSingletonInstance)
val iActivityManagerInterface = Class.forName("android.app.IActivityManager")
mInstanceField[activityManagerSingletonInstance] =
swap(iActivityManagerInterface, activityManagerInstance!!)
}
另外最后补充一个小点ActivityThread
的mServices
保存了所有app的service
//ActivityThread.java
class ActivityThread{
final ArrayMap<IBinder, Service> mServices
= new ArrayMap<IBinder, Service>();
}
我们结合以下在看ServiceWatcher
就很简单.
//ServiceWatcher.java
//存放要观察的service
private val servicesToBeDestroyed = WeakHashMap<IBinder, WeakReference<Service>>()
private val activityThreadClass by lazy { Class.forName("android.app.ActivityThread") }
private val activityThreadInstance by lazy {
activityThreadClass.getDeclaredMethod("currentActivityThread").invoke(null)!!
}
//存放所有app的service
private val activityThreadServices by lazy {
val mServicesField =
activityThreadClass.getDeclaredField("mServices").apply { isAccessible = true }
@Suppress("UNCHECKED_CAST")
mServicesField[activityThreadInstance] as Map<IBinder, Service>
}
override fun install() {
checkMainThread()
try {
swapActivityThreadHandlerCallback { mCallback ->
uninstallActivityThreadHandlerCallback = {
swapActivityThreadHandlerCallback {
mCallback
}
}
Handler.Callback { msg ->
//回调stopservice函数
if (msg.what == STOP_SERVICE) {
val key = msg.obj as IBinder
//activityThreadServices一定不为空
//所以调用onServicePreDestroy,内部会将service放入servicesToBeDestroyed
//后面会回调serviceDoneExecuting函数
activityThreadServices[key]?.let {
onServicePreDestroy(key, it)
}
}
mCallback?.handleMessage(msg) ?: false
}
}
//servicesToBeDestroyed相关hook
swapActivityManager { activityManagerInterface, activityManagerInstance ->
uninstallActivityManager = {
swapActivityManager { _, _ ->
activityManagerInstance
}
}
Proxy.newProxyInstance(
activityManagerInterface.classLoader, arrayOf(activityManagerInterface)
) { _, method, args ->
if (METHOD_SERVICE_DONE_EXECUTING == method.name) {
val token = args!![0] as IBinder
//servicesToBeDestroyed会在创建的时候回调,也会在销毁的时候回调
//servicesToBeDestroyed所在上面销毁的时候加入元素.
//所以servicesToBeDestroyed包含要检测的service直接调用onServiceDestroyed确认是否泄漏
if (servicesToBeDestroyed.containsKey(token)) {
onServiceDestroyed(token)
}
}
try {
if (args == null) {
method.invoke(activityManagerInstance)
} else {
method.invoke(activityManagerInstance, *args)
}
} catch (invocationException: InvocationTargetException) {
throw invocationException.targetException
}
}
}
} catch (ignored: Throwable) {
SharkLog.d(ignored) { "Could not watch destroyed services" }
}
}