中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android內存泄漏檢測工具LeakCanary怎么使用

發布時間:2023-04-13 16:12:05 來源:億速云 閱讀:153 作者:iii 欄目:開發技術

這篇“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之前完成的。

internal class MainProcessAppWatcherInstaller : ContentProvider() {
   override fun onCreate(): Boolean {
      val application = context!!.applicationContext as Application
      AppWatcher.manualInstall(application)
      return true
    }
     ... ...
}

2.LeakCanary如何檢測內存泄漏

2.1LeakCanary初始化時做了什么

AppWatcher.kt

@JvmOverloads
fun manualInstall(
  application: Application,
  retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
  watchersToInstall: List<InstallableWatcher> = appDefaultWatchers(application)
) {
  checkMainThread()
  if (isInstalled) {
    throw IllegalStateException(
      "AppWatcher already installed, see exception cause for prior install call", installCause
    )
  }
  check(retainedDelayMillis >= 0) {
    "retainedDelayMillis $retainedDelayMillis must be at least 0 ms"
  }
  installCause = RuntimeException("manualInstall() first called here")
  this.retainedDelayMillis = retainedDelayMillis
  if (application.isDebuggableBuild) {
    LogcatSharkLog.install()
  }
  // Requires AppWatcher.objectWatcher to be set
  LeakCanaryDelegate.loadLeakCanary(application)
  watchersToInstall.forEach {
    it.install()
  }
}
fun appDefaultWatchers(
  application: Application,
  reachabilityWatcher: ReachabilityWatcher = objectWatcher
): List<InstallableWatcher> {
  return listOf(
    ActivityWatcher(application, reachabilityWatcher),
    FragmentAndViewModelWatcher(application, reachabilityWatcher),
    RootViewWatcher(reachabilityWatcher),
    ServiceWatcher(reachabilityWatcher)
  )
}

在appDefaultWatchers方法中,會默認初始化一些Watcher,在默認情況下,我們只會監控Activity,Fragment,RootView,Service這些對象是否泄漏。

2.2LeakCanary如何觸發檢測

以ActivityWatcher為例:

/**
 * Expects activities to become weakly reachable soon after they receive the [Activity.onDestroy]
 * callback.
 */
class ActivityWatcher(
  private val application: Application,
  private val reachabilityWatcher: ReachabilityWatcher
) : InstallableWatcher {
  private val lifecycleCallbacks =
    object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
      override fun onActivityDestroyed(activity: Activity) {
        reachabilityWatcher.expectWeaklyReachable(
          activity, "${activity::class.java.name} received Activity#onDestroy() callback"
        )
      }
    }
  override fun install() {
    application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
  }
  override fun uninstall() {
    application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
  }
}

在Activity.onDestory時,就會觸發檢測內存泄漏。通過ActivityLifecycleCallbacks監聽生命周期變化,在onActivityDestroyed方法中調用ReachabilityWatcher的expectWeaklyReachable方法。

2.3LeakCanary如何檢測泄漏的對象

以Activity為例,通過ReachabilityWatcher的expectWeaklyReachable方法檢測。

fun interface ReachabilityWatcher {
  /**
   * Expects the provided [watchedObject] to become weakly reachable soon. If not,
   * [watchedObject] will be considered retained.
   */
  fun expectWeaklyReachable(
    watchedObject: Any,
    description: String
  )
}
ObjectWatcher.kt
ObjectWatcher實現ReachabilityWatcher接口。
private val watchedObjects = mutableMapOf()
private val queue = ReferenceQueue()
@Synchronized override fun expectWeaklyReachable(
  watchedObject: Any,
  description: String
) {
  if (!isEnabled()) {
    return
  }
  removeWeaklyReachableObjects()
  val key = UUID.randomUUID()
    .toString()
  val watchUptimeMillis = clock.uptimeMillis()
  val reference =
    KeyedWeakReference(watchedObject, key, description, watchUptimeMillis, queue)
  SharkLog.d {
    "Watching " +
      (if (watchedObject is Class<*>) watchedObject.toString() else "instance of ${watchedObject.javaClass.name}") +
      (if (description.isNotEmpty()) " ($description)" else "") +
      " with key $key"
  }
  watchedObjects[key] = reference
  checkRetainedExecutor.execute {
    moveToRetained(key)
  }
}

1.通過觀察的實例watchedObject構建弱引用KeyedWeakReference實例,watchedObject與ReferenceQueue關聯,當對象被回收時,該弱引用對象將被存入ReferenceQueue當中。

2.弱引用KeyedWeakReference實例會被被存儲在watchedObjects中(Map)。

3.檢測過程中,會調用removeWeaklyReachableObjects,將已回收對象從watchedObjects中移除。

4.如果watchedObjects中沒有移除對象,證明它沒有被回收,那么就會調用moveToRetained。

private fun removeWeaklyReachableObjects() {
  // 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) {
      watchedObjects.remove(ref.key)
    }
  } while (ref != null)
}
@Synchronized private fun moveToRetained(key: String) {
  removeWeaklyReachableObjects()
  val retainedRef = watchedObjects[key]
  if (retainedRef != null) {
    retainedRef.retainedUptimeMillis = clock.uptimeMillis()
    onObjectRetainedListeners.forEach { it.onObjectRetained() }
  }
}
2.4弱引用 WeakReference

只要 GC 發現一個對象只有弱引用,則就會回收此弱引用對象。

public class WeakReference<T> extends Reference<T> {
    public WeakReference(T referent) {
        super(referent);
    }
    public WeakReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }
}
var str: Any? = Any()
val quque = ReferenceQueue<Any>()
val weakReference = WeakReference<Any>(str, quque)
val weakReference_before_gc = weakReference.get()
Log.v("reference_tag", weakReference_before_gc.toString())
str = null
System.gc()
Handler().postDelayed( {
    val weakReference_after_gc = weakReference.get()
    Log.v("reference_tag", weakReference_after_gc.toString())
}, 2000)

以上就是關于“Android內存泄漏檢測工具LeakCanary怎么使用”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

沂南县| 闽清县| 英山县| 楚雄市| 武鸣县| 武宣县| 临泉县| 清水县| 民权县| 沧源| 新乡市| 抚松县| 黄大仙区| 政和县| 常德市| 财经| 星子县| 吴忠市| 青冈县| 新郑市| 汉寿县| 舞阳县| 襄城县| 安吉县| 广德县| 仙游县| 秦皇岛市| 栾川县| 泗阳县| 兴化市| 吴忠市| 长宁县| 永新县| 彝良县| 仁寿县| 新昌县| 金秀| 新野县| 乐亭县| 东源县| 清水县|