亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android內(nèi)存泄漏檢測(cè)工具LeakCanary

 更新時(shí)間:2023年04月13日 11:27:23   作者:不入流Android開(kāi)發(fā)  
在Android的性能優(yōu)化中,內(nèi)存優(yōu)化是必不可少的點(diǎn),而內(nèi)存優(yōu)化最重要的一點(diǎn)就是解決內(nèi)存泄漏的問(wèn)題,在Android的內(nèi)存泄漏分析工具也不少,比如PC端的有:AndroidStudio自帶的Android?Profiler、MAT等工具;手機(jī)端也有,就是我們今天要介紹的LeakCanary

背景

在Android應(yīng)用中,一個(gè)好的產(chǎn)品,除了功能強(qiáng)大,好的性能也是必不可少的。有調(diào)查顯示,近90%的受訪者會(huì)因?yàn)锳pp卡頓,內(nèi)存大等問(wèn)題而卸載該應(yīng)用,因此手機(jī)的性能問(wèn)題會(huì)影響用戶的體驗(yàn),如果用戶覺(jué)得該應(yīng)用的體驗(yàn)度不好,會(huì)直接卸載或切換其他平臺(tái)。

對(duì)于性能優(yōu)化,很多大公司會(huì)專門招聘性能優(yōu)化的人員。也有些初級(jí)工程師會(huì)接觸到這部分的工作,但是無(wú)從下手,對(duì)專業(yè)工具和專業(yè)代碼使用以及分析比較吃力,排查起來(lái)也比較費(fèi)勁。如果有專業(yè)的工具能夠只管的把這些記錄并標(biāo)記好。這樣初級(jí)工程師也可以通過(guò)詳情的問(wèn)題去排查,那么LeaksCanary就是這款工具了。

LeaksCanary 介紹

LeakCanary是Square公司為Android開(kāi)發(fā)者提供的一個(gè)自動(dòng)檢測(cè)內(nèi)存泄漏的工具。

LeakCanary本質(zhì)上是一個(gè)基于MAT進(jìn)行Android應(yīng)用程序內(nèi)存泄漏自動(dòng)化檢測(cè)的的開(kāi)源工具,我們可以通過(guò)集成LeakCanary提供的jar包到自己的工程中,一旦檢測(cè)到內(nèi)存泄漏,LeakCanary就會(huì)dump Memory信息,并通過(guò)另一個(gè)進(jìn)程分析內(nèi)存泄漏的信息并展示出來(lái),隨時(shí)發(fā)現(xiàn)和定位內(nèi)存泄漏問(wèn)題,而不用每次在開(kāi)發(fā)流程中都抽出專人來(lái)進(jìn)行內(nèi)存泄漏問(wèn)題檢測(cè),極大地方便了Android應(yīng)用程序的開(kāi)發(fā)。

使用方法

1.LeakCanary 如何自動(dòng)初始化

LeakCanary只需添加依賴就可以實(shí)現(xiàn)自動(dòng)初始化。LeakCanary是通過(guò)ContentProvider實(shí)現(xiàn)初始化的,在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如何檢測(cè)內(nèi)存泄漏

2.1LeakCanary初始化時(shí)做了什么

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方法中,會(huì)默認(rèn)初始化一些Watcher,在默認(rèn)情況下,我們只會(huì)監(jiān)控Activity,Fragment,RootView,Service這些對(duì)象是否泄漏。

2.2LeakCanary如何觸發(fā)檢測(cè)

以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時(shí),就會(huì)觸發(fā)檢測(cè)內(nèi)存泄漏。通過(guò)ActivityLifecycleCallbacks監(jiān)聽(tīng)生命周期變化,在onActivityDestroyed方法中調(diào)用ReachabilityWatcher的expectWeaklyReachable方法。

2.3LeakCanary如何檢測(cè)泄漏的對(duì)象

以Activity為例,通過(guò)ReachabilityWatcher的expectWeaklyReachable方法檢測(cè)。

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實(shí)現(xiàn)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.通過(guò)觀察的實(shí)例watchedObject構(gòu)建弱引用KeyedWeakReference實(shí)例,watchedObject與ReferenceQueue關(guān)聯(lián),當(dāng)對(duì)象被回收時(shí),該弱引用對(duì)象將被存入ReferenceQueue當(dāng)中。

2.弱引用KeyedWeakReference實(shí)例會(huì)被被存儲(chǔ)在watchedObjects中(Map)。

3.檢測(cè)過(guò)程中,會(huì)調(diào)用removeWeaklyReachableObjects,將已回收對(duì)象從watchedObjects中移除。

4.如果watchedObjects中沒(méi)有移除對(duì)象,證明它沒(méi)有被回收,那么就會(huì)調(diào)用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 發(fā)現(xiàn)一個(gè)對(duì)象只有弱引用,則就會(huì)回收此弱引用對(duì)象。

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)

到此這篇關(guān)于Android內(nèi)存泄漏檢測(cè)工具LeakCanary的文章就介紹到這了,更多相關(guān)Android LeakCanary內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論