網站首頁 編程語言 正文
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)
2022-02-27 17:43:04.181 16634-16634/com.example.myapplication V/reference_tag: java.lang.Object@c87946a
2022-02-27 17:43:06.182 16634-16634/com.example.myapplication V/reference_tag: null
原文鏈接:https://blog.csdn.net/zhangying1994/article/details/123168404
相關推薦
- 2023-07-30 el-table自定義合并行或列
- 2022-10-04 python中numpy矩陣的零填充的示例代碼_python
- 2022-09-28 C語言關于二叉樹中堆的創建和使用整理_C 語言
- 2022-06-19 C++深入探究引用的本質與意義_C 語言
- 2022-04-11 socket連接關閉問題分析_python
- 2023-01-15 React報錯Too?many?re-renders解決_React
- 2022-10-16 python3里gbk編碼的問題解決_python
- 2022-03-16 C++?NFS掛載及掛載命令_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支