leakcanary捕获内存泄漏的时机


leakcannary可以自动监控的内存泄漏有哪些?

  • destroyed Activity对象
  • destroyed Fragment对象
  • destroyed fragment中的View对象
  • cleared ViewModel对象 (Activity和Fragment中都可能有)

监控Activity内存泄漏

internal class ActivityDestroyWatcher private constructor(
  private val objectWatcher: ObjectWatcher,
  private val configProvider: () -> Config
) {

  private val lifecycleCallbacks =
    object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
      override fun onActivityDestroyed(activity: Activity) {
        if (configProvider().watchActivities) {
          objectWatcher.watch(
              activity, "${activity::class.java.name} received Activity#onDestroy() callback"
          )
        }
      }
    }

  companion object {
    fun install(
      application: Application,
      objectWatcher: ObjectWatcher,
      configProvider: () -> Config
    ) {
      val activityDestroyWatcher =
        ActivityDestroyWatcher(objectWatcher, configProvider)
      application.registerActivityLifecycleCallbacks(activityDestroyWatcher.lifecycleCallbacks)
    }
  }
}

不出所料,会注册一个Application.ActivityLifecycleCallbacks,用于监控Activity的生命周期.然后在Activity onDestory()的时候,使用ObjectWatcher来监控Activity对象.

ObjectWatcher后面再详细看,这里不多说.

监控Fragment/Fragment中View的内存泄漏

internal object FragmentDestroyWatcher {

  private const val ANDROIDX_FRAGMENT_CLASS_NAME = "androidx.fragment.app.Fragment"
  private const val ANDROIDX_FRAGMENT_DESTROY_WATCHER_CLASS_NAME =
    "leakcanary.internal.AndroidXFragmentDestroyWatcher"

  // 防止Jetfier自动将support库转成Androidx
  private val ANDROID_SUPPORT_FRAGMENT_CLASS_NAME =
    StringBuilder("android.").append("support.v4.app.Fragment")
        .toString()
  private const val ANDROID_SUPPORT_FRAGMENT_DESTROY_WATCHER_CLASS_NAME =
    "leakcanary.internal.AndroidSupportFragmentDestroyWatcher"

  fun install(
    application: Application,objectWatcher: ObjectWatcher,configProvider: () -> AppWatcher.Config) {
    val fragmentDestroyWatchers = mutableListOf<(Activity) -> Unit>()

    // app包下的Fragment监控,只有Android O 及以上版本才生效
    if (SDK_INT >= O) {
      fragmentDestroyWatchers.add(
          AndroidOFragmentDestroyWatcher(objectWatcher, configProvider)
      )
    }

    // androidx包下的Fragment监控
    getWatcherIfAvailable(
        ANDROIDX_FRAGMENT_CLASS_NAME,
        ANDROIDX_FRAGMENT_DESTROY_WATCHER_CLASS_NAME,
        objectWatcher,
        configProvider
    )?.let {
      fragmentDestroyWatchers.add(it)
    }

    // android support包下面的Fragment监控
    getWatcherIfAvailable(
        ANDROID_SUPPORT_FRAGMENT_CLASS_NAME,
        ANDROID_SUPPORT_FRAGMENT_DESTROY_WATCHER_CLASS_NAME,
        objectWatcher,
        configProvider
    )?.let {
      fragmentDestroyWatchers.add(it)
    }

    if (fragmentDestroyWatchers.size == 0) {
      return
    }

    //在Activity onCreate()的时候注册FragmntLifecycleCallback
    application.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
      override fun onActivityCreated(
        activity: Activity,
        savedInstanceState: Bundle?
      ) {
        for (watcher in fragmentDestroyWatchers) {
          watcher(activity)
        }
      }
    })
  }

  // 判断类是否存在,利用反射进行实例化
  private fun getWatcherIfAvailable(
    fragmentClassName: String,
    watcherClassName: String,
    objectWatcher: ObjectWatcher,
    configProvider: () -> AppWatcher.Config
  ): ((Activity) -> Unit)? {

    return if (classAvailable(fragmentClassName) &&
        classAvailable(watcherClassName)
    ) {
      val watcherConstructor = Class.forName(watcherClassName)
          .getDeclaredConstructor(ObjectWatcher::class.java, Function0::class.java)
      @Suppress("UNCHECKED_CAST")
      watcherConstructor.newInstance(objectWatcher, configProvider) as (Activity) -> Unit
    } else {
      null
    }
  }

  private fun classAvailable(className: String): Boolean {
    return try {
      Class.forName(className)
      true
    } catch (e: Throwable) {
      false
    }
  }
}

Android中的Fragment/FragmentManager目前有3种:

  • android.app.Fragment

    Android O及以上可以使用FragmentManager.FragmentLifecycleCallbacks监听Fragment的生命周期

  • androidx.fragment.app.Fragment

  • android.support.v4.app.Fragment (已废弃,在Android Studio中都没法编译成功)

这里就是先注册一个Application.ActivityLifecycleCallbacks,在每个Activity onCreate()的时候注册FragmentManager.FragmentLifecycleCallbacks来监听Fragment的生命周期.

现在我们一般使用的都是Androidx中的Fragment,因此这里拿AndroidX中的Fragment来分析内存泄漏监控逻辑:

internal class AndroidXFragmentDestroyWatcher(
  private val objectWatcher: ObjectWatcher,
  private val configProvider: () -> Config
) : (Activity) -> Unit {

  private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() {

    override fun onFragmentCreated(
      fm: FragmentManager,
      fragment: Fragment,
      savedInstanceState: Bundle?
    ) {
      // ViewModel监控
      ViewModelClearedWatcher.install(fragment, objectWatcher, configProvider)
    }

    override fun onFragmentViewDestroyed(
      fm: FragmentManager,
      fragment: Fragment
    ) {
      // View监控
      val view = fragment.view
      if (view != null && configProvider().watchFragmentViews) {
        objectWatcher.watch(
            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监控
      if (configProvider().watchFragments) {
        objectWatcher.watch(
            fragment, "${fragment::class.java.name} received Fragment#onDestroy() callback"
        )
      }
    }
  }

  // lambda表达式执行的时候调用这里,注册FragmentLifecycleCallbacks和ViewMdoel监控逻辑
  override fun invoke(activity: Activity) {
    if (activity is FragmentActivity) {
      val supportFragmentManager = activity.supportFragmentManager
      supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true)
      ViewModelClearedWatcher.install(activity, objectWatcher, configProvider)
    }
  }
}

这里可以看到:

  • onFragmentDestroyed()回调中,使用ObjectWatcher去监控Fragment对象

  • onFragmentViewDestroyed()回调中,使用ObjectWatcher去监控View对象

  • onFragmentCreatedonActivityCreate()的时候,初始化ViewModelClearedWatcher去监控ViewModel对象

    需要注意的是这两处调用传入的参数是不一样的,一个传入的是Fragment对象,一个传入的是Activity对象.

Fragment和Fragment View的都是利用的ObjectWatcher去监控的,再来看一下ViewModel的监控.

监控ViewModel内存泄漏

internal class ViewModelClearedWatcher(
  storeOwner: ViewModelStoreOwner,
  private val objectWatcher: ObjectWatcher,
  private val configProvider: () -> Config
) : ViewModel() {

  private val viewModelMap: Map<String, ViewModel>?

  init {
    viewModelMap = try {
      val mMapField = ViewModelStore::class.java.getDeclaredField("mMap")
      mMapField.isAccessible = true
      @Suppress("UNCHECKED_CAST")
      mMapField[storeOwner.viewModelStore] as Map<String, ViewModel>
    } catch (ignored: Exception) {
      null
    }
  }

  override fun onCleared() {
    if (viewModelMap != null && configProvider().watchViewModels) {
      viewModelMap.values.forEach { viewModel ->
        objectWatcher.watch(
            viewModel, "${viewModel::class.java.name} received ViewModel#onCleared() callback"
        )
      }
    }
  }

  companion object {
    fun install(
      storeOwner: ViewModelStoreOwner,
      objectWatcher: ObjectWatcher,
      configProvider: () -> Config
    ) {
      val provider = ViewModelProvider(storeOwner, object : Factory {
        @Suppress("UNCHECKED_CAST")
        override fun <T : ViewModel?> create(modelClass: Class<T>): T =
          ViewModelClearedWatcher(storeOwner, objectWatcher, configProvider) as T
      })
      provider.get(ViewModelClearedWatcher::class.java)
    }
  }
}

这里其实涉及到几个知识点:

  • ViewModelStore

    public class ViewModelStore {
    
        private final HashMap<String, ViewModel> mMap = new HashMap<>();
    
        final void put(String key, ViewModel viewModel) {
            ViewModel oldViewModel = mMap.put(key, viewModel);
            if (oldViewModel != null) {
                oldViewModel.onCleared();
            }
        }
    
        final ViewModel get(String key) {
            return mMap.get(key);
        }
    
        /**
         *  执行viewModel的onCleared()方法
         */
        public final void clear() {
            for (ViewModel vm : mMap.values()) {
                vm.onCleared();
            }
            mMap.clear();
        }
    }
  • ViewModelStoreOwner

    public interface ViewModelStoreOwner {
        @NonNull
        ViewModelStore getViewModelStore();
    }

    FragmentActivity和Activity均实现了这个接口

  • Activity或者Fragment中执行onDestroy()的时候,会执行ViewModelStoreclear()方法,通知其绑定的ViewModel去clear.

leakcanary中的ViewModelClearedWatcher本身就是一个ViewModel,并与要监控的Activity和Fragment进行绑定,因此当Activity或者Fragment执行 onDestroyed()回调时,也会执行ViewModelClearedWatcherclear()方法,此时遍历ViewModelStore中map存储的ViewModel,并使用ObjectWatcher进行监控.

分析到这里,可以知道leakcanary其实就是注入Activity和Fragment的生命周期回调,然后再onDestoryed()的时候使用ObjectWatcher进行监听.


文章作者: 姜康
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 姜康 !
评论
 上一篇
leakcanary是如何捕获内存泄漏的 leakcanary是如何捕获内存泄漏的
Java中第三方应用如果想判断是否存在内存泄漏,一般都会利用WeakReference + RefercenceQueue的机制去判定. 因为GC之后,理论上会回收掉WeakRefercence对象的内存(如果不存在其他到GCRoot的路径
2020-10-31
下一篇 
leakcanary的自动初始化 leakcanary的自动初始化
目前v2.5版本,已经无需显式的进行初始化了. 由于Android中ContentProvider的onCreate()会在Application的onCreate()之前执行,因此可以在ContentProvider中进行初始化. 恰好有
2020-10-29
  目录