Android内存泄漏检测工具LeakCanary怎么使用

其他教程   发布日期:2025年02月14日   浏览次数:244

这篇“Android内存泄漏检测工具LeakCanary怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Android内存泄漏检测工具LeakCanary怎么使用”文章吧。

LeaksCanary 介绍

LeakCanary是Square公司为Android开发者提供的一个自动检测内存泄漏的工具。

LeakCanary本质上是一个基于MAT进行Android应用程序内存泄漏自动化检测的的开源工具,我们可以通过集成LeakCanary提供的jar包到自己的工程中,一旦检测到内存泄漏,LeakCanary就会dump Memory信息,并通过另一个进程分析内存泄漏的信息并展示出来,随时发现和定位内存泄漏问题,而不用每次在开发流程中都抽出专人来进行内存泄漏问题检测,极大地方便了Android应用程序的开发。

使用方法

1.LeakCanary 如何自动初始化

LeakCanary只需添加依赖就可以实现自动初始化。LeakCanary是通过ContentProvider实现初始化的,在ContentProvider 的 onCreate方法中初始化LeakCanary。并且MainProcessAppWatcherInstaller是在主线程中初始化的。注意:ContentProvider的初始化是在Application的onCreate之前完成的,所以LeakCanary的初始化方法AppWatcher.manualInstall(application)也是在Application的onCreate之前完成的。

  1. internal class MainProcessAppWatcherInstaller : ContentProvider() {
  2. override fun onCreate(): Boolean {
  3. val application = context!!.applicationContext as Application
  4. AppWatcher.manualInstall(application)
  5. return true
  6. }
  7. ... ...
  8. }

2.LeakCanary如何检测内存泄漏

2.1LeakCanary初始化时做了什么

AppWatcher.kt

  1. @JvmOverloads
  2. fun manualInstall(
  3. application: Application,
  4. retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
  5. watchersToInstall: List<InstallableWatcher> = appDefaultWatchers(application)
  6. ) {
  7. checkMainThread()
  8. if (isInstalled) {
  9. throw IllegalStateException(
  10. "AppWatcher already installed, see exception cause for prior install call", installCause
  11. )
  12. }
  13. check(retainedDelayMillis >= 0) {
  14. "retainedDelayMillis $retainedDelayMillis must be at least 0 ms"
  15. }
  16. installCause = RuntimeException("manualInstall() first called here")
  17. this.retainedDelayMillis = retainedDelayMillis
  18. if (application.isDebuggableBuild) {
  19. LogcatSharkLog.install()
  20. }
  21. // Requires AppWatcher.objectWatcher to be set
  22. LeakCanaryDelegate.loadLeakCanary(application)
  23. watchersToInstall.forEach {
  24. it.install()
  25. }
  26. }
  1. fun appDefaultWatchers(
  2. application: Application,
  3. reachabilityWatcher: ReachabilityWatcher = objectWatcher
  4. ): List<InstallableWatcher> {
  5. return listOf(
  6. ActivityWatcher(application, reachabilityWatcher),
  7. FragmentAndViewModelWatcher(application, reachabilityWatcher),
  8. RootViewWatcher(reachabilityWatcher),
  9. ServiceWatcher(reachabilityWatcher)
  10. )
  11. }

在appDefaultWatchers方法中,会默认初始化一些Watcher,在默认情况下,我们只会监控Activity,Fragment,RootView,Service这些对象是否泄漏。

2.2LeakCanary如何触发检测

以ActivityWatcher为例:

  1. /**
  2. * Expects activities to become weakly reachable soon after they receive the [Activity.onDestroy]
  3. * callback.
  4. */
  5. class ActivityWatcher(
  6. private val application: Application,
  7. private val reachabilityWatcher: ReachabilityWatcher
  8. ) : InstallableWatcher {
  9. private val lifecycleCallbacks =
  10. object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
  11. override fun onActivityDestroyed(activity: Activity) {
  12. reachabilityWatcher.expectWeaklyReachable(
  13. activity, "${activity::class.java.name} received Activity#onDestroy() callback"
  14. )
  15. }
  16. }
  17. override fun install() {
  18. application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
  19. }
  20. override fun uninstall() {
  21. application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
  22. }
  23. }

在Activity.onDestory时,就会触发检测内存泄漏。通过ActivityLifecycleCallbacks监听生命周期变化,在onActivityDestroyed方法中调用ReachabilityWatcher的expectWeaklyReachable方法。

2.3LeakCanary如何检测泄漏的对象

以Activity为例,通过ReachabilityWatcher的expectWeaklyReachable方法检测。

  1. fun interface ReachabilityWatcher {
  2. /**
  3. * Expects the provided [watchedObject] to become weakly reachable soon. If not,
  4. * [watchedObject] will be considered retained.
  5. */
  6. fun expectWeaklyReachable(
  7. watchedObject: Any,
  8. description: String
  9. )
  10. }
  11. ObjectWatcher.kt
  12. ObjectWatcher实现ReachabilityWatcher接口。
  13. private val watchedObjects = mutableMapOf()
  14. private val queue = ReferenceQueue()
  15. @Synchronized override fun expectWeaklyReachable(
  16. watchedObject: Any,
  17. description: String
  18. ) {
  19. if (!isEnabled()) {
  20. return
  21. }
  22. removeWeaklyReachableObjects()
  23. val key = UUID.randomUUID()
  24. .toString()
  25. val watchUptimeMillis = clock.uptimeMillis()
  26. val reference =
  27. KeyedWeakReference(watchedObject, key, description, watchUptimeMillis, queue)
  28. SharkLog.d {
  29. "Watching " +
  30. (if (watchedObject is Class<*>) watchedObject.toString() else "instance of ${watchedObject.javaClass.name}") +
  31. (if (description.isNotEmpty()) " ($description)" else "") +
  32. " with key $key"
  33. }
  34. watchedObjects[key] = reference
  35. checkRetainedExecutor.execute {
  36. moveToRetained(key)
  37. }
  38. }

1.通过观察的实例watchedObject构建弱引用KeyedWeakReference实例,watchedObject与ReferenceQueue关联,当对象被回收时,该弱引用对象将被存入ReferenceQueue当中。

2.弱引用KeyedWeakReference实例会被被存储在watchedObjects中(Map)。

3.检测过程中,会调用removeWeaklyReachableObjects,将已回收对象从watchedObjects中移除。

4.如果watchedObjects中没有移除对象,证明它没有被回收,那么就会调用moveToRetained。

  1. private fun removeWeaklyReachableObjects() {
  2. // WeakReferences are enqueued as soon as the object to which they point to becomes weakly
  3. // reachable. This is before finalization or garbage collection has actually happened.
  4. var ref: KeyedWeakReference?
  5. do {
  6. ref = queue.poll() as KeyedWeakReference?
  7. if (ref != null) {
  8. watchedObjects.remove(ref.key)
  9. }
  10. } while (ref != null)
  11. }
  1. @Synchronized private fun moveToRetained(key: String) {
  2. removeWeaklyReachableObjects()
  3. val retainedRef = watchedObjects[key]
  4. if (retainedRef != null) {
  5. retainedRef.retainedUptimeMillis = clock.uptimeMillis()
  6. onObjectRetainedListeners.forEach { it.onObjectRetained() }
  7. }
  8. }

2.4弱引用 WeakReference

只要 GC 发现一个对象只有弱引用,则就会回收此弱引用对象。

  1. public class WeakReference<T> extends Reference<T> {
  2. public WeakReference(T referent) {
  3. super(referent);
  4. }
  5. public WeakReference(T referent, ReferenceQueue<? super T> q) {
  6. super(referent, q);
  7. }
  8. }
  1. var str: Any? = Any()
  2. val quque = ReferenceQueue<Any>()
  3. val weakReference = WeakReference<Any>(str, quque)
  4. val weakReference_before_gc = weakReference.get()
  5. Log.v("reference_tag", weakReference_before_gc.toString())
  6. str = null
  7. System.gc()
  8. Handler().postDelayed( {
  9. val weakReference_after_gc = weakReference.get()
  10. Log.v("reference_tag", weakReference_after_gc.toString())
  11. }, 2000)

以上就是Android内存泄漏检测工具LeakCanary怎么使用的详细内容,更多关于Android内存泄漏检测工具LeakCanary怎么使用的资料请关注九品源码其它相关文章!