日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Android LeakCanary檢測內存泄露原理

瀏覽:17日期:2022-09-20 10:44:56

以LeakCanary2.6源碼分析LeakCanary檢測內存泄露原理,為減少篇幅長度,突出關鍵點,不粘貼大量源碼,閱讀時需搭配源碼食用。

如何獲取context

LeakCanary只需引入依賴,不需要初始化代碼,就能執行內存泄漏檢測了,它是通過ContentProvider獲取應用的context。這種獲取context方式在開源第三方庫中十分流行。如下AppWatcherInstaller在LeakCanary的aar包中manifest文件中注冊。

internal sealed class AppWatcherInstaller : ContentProvider() { override fun onCreate(): Boolean { val application = context!!.applicationContext as Application AppWatcher.manualInstall(application)//1 return true } ...}默認檢測哪些類對象的內存泄露

(1)處的方法將調用如下方法注冊需要檢測泄露的對象:

fun appDefaultWatchers( application: Application, reachabilityWatcher: ReachabilityWatcher = objectWatcher ): List<InstallableWatcher> { return listOf( ActivityWatcher(application, reachabilityWatcher), FragmentAndViewModelWatcher(application, reachabilityWatcher), RootViewWatcher(reachabilityWatcher), ServiceWatcher(reachabilityWatcher) ) }

可以看到LeakCanary會把Activity,Fragment,ViewModel,RootView和Service納入檢測,這些對象都是有明確的生命周期,而且占用內存較高,它們的內存泄露是需要我們重點關注的。

如何將這些生命周期對象納入監測

(1)處的manualInstall方法將遍歷調用上述Watcher的install方法以適時將這些生命周期對象納入檢測。

ActivityWatcher

ActivityWatcher中install方法通過向application注冊Application.ActivityLifecycleCallbacks接口回調實現對Activity生命周期的檢測。這里有一個很棒的技巧,利用Kotlin委托與Java動態代理,將不需要關注的方法給出默認空實現,(2)(3)處代碼提取出來,可以在平時開發中有需求的地方使用。

//ActivityWatcher private val lifecycleCallbacks = object : Application.ActivityLifecycleCallbacks by noOpDelegate() { override fun onActivityDestroyed(activity: Activity) { reachabilityWatcher.expectWeaklyReachable( activity, '${activity::class.java.name} received Activity#onDestroy() callback' )//4 } }internal inline fun <reified T : Any> noOpDelegate(): T { val javaClass = T::class.java return Proxy.newProxyInstance( javaClass.classLoader, arrayOf(javaClass), NO_OP_HANDLER ) as T}//2private val NO_OP_HANDLER = InvocationHandler { _, _, _ -> // no op}//3

(4)調用的objectWatcher.expectWeaklyReachable方法是將對象納入監測的通用方法,如其名稱所示,WeaklyReachable相較的是StronglyReachable,當一個對象不再需要時,我們希望它從WeaklyReachable變為StronglyReachable。

我們可以在不再需要某對象時主動調用該方法,檢測任意對象(除上節的默認對象)的內存泄露:

AppWatcher.objectWatcher.expectWeaklyReachable(obj, '')

onActivityDestroyed回調中就通過該方式將activity納入監測。

通過上述對Activity的納入內存泄露源碼的分析,可以發現其中2個關鍵點,首先需要能獲取應用中所有待檢測對象的引用,其次需要一個待檢測對象生命周期結束的時機。而這兩點通過注冊Application.ActivityLifecycleCallbacks接口能夠同時滿足,可對于其他類對象,就沒有如此便捷的方式了。

下面介紹Fragment,ViewModel,RootView和Service這些類對象是如何納入檢測的。

FragmentAndViewModelWatcher

Fragment為了兼容在Android源碼中幾個不同包名的實現,對它們的檢測也需要分別實現,我們在FragmentAndViewModelWatcher中只關注AndroidXFragmentDestroyWatcher對AndroidX中Fragment的內存泄露檢測即可,其他幾個實現類似。

FragmentAndViewModelWatcher先同樣通過注冊Application.ActivityLifecycleCallbacks回調,適時獲取Activity引用,并在AndroidXFragmentDestroyWatcher獲取Activity的supportFragmentManager,向其注冊FragmentManager.FragmentLifecycleCallbacks。在其中的onFragmentDestroyed與onFragmentViewDestroyed回調中將Fragment和Fragment的View納入內存泄露檢測。

對于ViewModel的檢測,則需要關注ViewModelClearedWatcher,通過用上一步獲取的Activity引用,添加名為ViewModelClearedWatcher的spy ViewModel,來獲得收到onCleared回調的能力,因為對于一個ViewModelStoreOwner(Activity,Fragment)來說,自己的一個ViewModel回調了onCleared,則其他ViewModel的onCleared也應該被調用。這些ViewModel是通過ViewModelStore的mMap屬性反射獲取的。在spy ViewModel的onCleared回調中,納入內存泄露檢測。

RootViewWatcher

對于Android里Window中的RootView,即DecorView,可以通過注冊addOnAttachStateChangeListener在View的onViewDetachedFromWindow時進行檢測。而獲取待檢測對象的引用就不像Activity和Fragment一樣有回調可以依賴了。LeakCanary采取了Hook的方式在install方法對RootView的容器進行替換,具體來說就是通過反射機制將WindowManagerGlobal中的mViews(包含所有Window中的DecorView)的ArrayList容器的實現修改,在其add方法中獲取DecorView的引用,之后設置OnAttachStateChangeListener回調進行檢測。

ServiceWatcher

而Android中Service,無論是獲取引用還是監測時機的確定都沒有系統的回調可以依賴,LeakCanary都是采用Hook的方式達到目的。首先通過反射拿到ActivityThread中的mServices,這是包含app中全部Service的一個Map。在install方法中有兩個Hook點,首先是Android 消息機制的中轉中心,名為H的Handler,系統側對應用側的全部回調都需要經過它的周轉。因為Handler中mCallback執行的優先級大于handleMessage方法,Leakcanary替換H的mCallback實現,當消息為STOP_SERVICE時,便從mServices取出該消息對應的Service作為待檢測Service引用。第二個Hook點為ActivityManagerService,通過動態代理修改它的serviceDoneExecuting方法,在其真正實現前增加內存泄露檢測,其余方法保持不變。

這些類納入檢測納入檢測的時機,可總結為如下表格:

如何獲取引用 何時納入監測 Activity ActivityLifecycleCallbacks回調 onActivityDestroyed Fragment FragmentLifecycleCallbacks回調 onFragmentDestroyed Fragment中的View FragmentLifecycleCallbacks回調 onFragmentViewDestroyed ViewModel 反射獲取ViewModelStore的mMap spy ViewModel的onCleared Window中的DecorView Hook WindowManagerGlobal中的mViews onViewDetachedFromWindow Service Hook H的mCallback實現,當消息為STOP_SERVICE時,從ActivityThread中的mServices獲取 Hook ActivityManagerService,serviceDoneExecuting中檢測

如何確定內存泄露的對象

在確定待檢測對象與時機后,查看ObjectWatcher的expectWeaklyReachable方法,可以得知如何實現將泄露對象從待檢測對象(默認即上節我們分析的那些有生命周期的類對象)挑出來的。確定內存泄露對象的原理是我們常用的WeakReference,其雙參數構造函數支持傳入一個ReferenceQueue,當其關聯的對象回收時,會將WeakReference加入ReferenceQueue中。LeakCanary的做法是繼承ReferenceQueue,增加一個值為UUID的屬性key,同時將每個需要監測的對象WeakReference以此UUID作為鍵加入一個map中。這樣,在GC過后,removeWeaklyReachableObjects方法通過遍歷ReferenceQueue,通過key值刪除map中已回收的對象,剩下的對象就基本可以確定發生了內存泄露。

如何確定從GC root到泄露對象的引用鏈

在確定內存泄露的對象后,就需要其他手段來確定泄露對象引用鏈了,這一過程開始于checkRetainedObjects方法,跟蹤調用可以看到啟動了前臺服務HeapAnalyzerService,這在我們使用LeakCanary時可以在通知欄看到。服務中調用了HeapAnalyzer的analyze方法進行堆內存分析,由Shark庫實現該功能,就不再進行追蹤。

以上就是分析LeakCanary檢測內存泄露原理的詳細內容,更多關于LeakCanary檢測內存泄露的資料請關注好吧啦網其它相關文章!

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日韩精品一二三| 久久精品不卡| 视频在线观看国产精品| 成人小电影网站| 涩涩av在线| 欧美福利一区| 中文字幕成人| 日韩和欧美的一区| 欧美日韩中文| 精品视频黄色| 电影亚洲精品噜噜在线观看| 欧美黄色网页| 狠狠久久婷婷| 亚洲五月综合| 久久精品资源| 亚洲二区精品| 亚洲精品在线二区| 精品国产亚洲一区二区三区| 日韩综合一区| 欧美中文日韩| 精品国产中文字幕第一页| 日韩精品一区二区三区免费观看| 91精品亚洲| 亚洲精品在线二区| 欧美丰满日韩| 99国产一区| 麻豆精品视频在线观看| 群体交乱之放荡娇妻一区二区| 欧美极品中文字幕| 日本91福利区| 亚洲一区资源| 99成人在线视频| 日韩一区二区三区免费视频| 午夜精品影视国产一区在线麻豆| 91看片一区| 欧美精品中文| 久久爱www.| 久久大逼视频| а√在线中文在线新版| 一区二区国产在线观看| 日韩精品不卡一区二区| 欧美中文一区| 91精品观看| 福利一区和二区| 婷婷综合六月| 亚洲欧美日本日韩| 91成人小视频| 国产精品日韩久久久| 国产精品一区三区在线观看| 欧美 日韩 国产一区二区在线视频 | 成人羞羞视频在线看网址| 免费在线观看不卡| 偷拍欧美精品| 99久久久久国产精品| 国产欧美日韩一区二区三区四区 | 亚洲免费资源| 亚洲国产专区校园欧美| 久久中文字幕一区二区三区| 亚洲精品日本| 免费在线欧美视频| 在线视频亚洲| 先锋影音久久久| 一本色道精品久久一区二区三区| 中文字幕在线看片| xxxxx性欧美特大| av综合电影网站| 精品一级视频| 国产精品久久久久蜜臀| 98精品久久久久久久| 毛片在线网站| 美女网站一区| 亚洲五月综合| 国产欧美一区二区三区国产幕精品 | 免费在线看一区| 蜜臀精品久久久久久蜜臀| 欧美精品自拍| 91精品美女| 日韩av二区| 香蕉久久久久久久av网站| 日韩在线麻豆| 精品国产乱码久久久久久樱花| 在线中文字幕播放| 亚洲天堂免费| 成人在线视频免费看| 一区二区亚洲视频| 99亚洲视频| 综合激情网...| 久久国产精品色av免费看| 91嫩草精品| 亚洲伊人av| 亚洲成人精选| 国产福利电影在线播放| 日韩中文字幕无砖| 日韩高清在线不卡| 欧美www视频在线观看| 亚洲中字黄色| 国产日韩一区二区三区在线| 91久久午夜| 中国字幕a在线看韩国电影| 亚洲久久一区| 免费成人av在线播放| 国产精品成人一区二区网站软件| 偷拍欧美精品| 91在线成人| 国产精品久久久久久久久久妞妞 | 国产欧美日韩综合一区在线播放| 欧美精品国产白浆久久久久| 麻豆成人在线观看| 欧洲一区二区三区精品| 国产欧美一区二区三区米奇| 久久先锋影音| av在线资源| 午夜精品一区二区三区国产| 福利一区和二区| 久久九九精品| 亚洲字幕久久| 国际精品欧美精品| 伊人久久大香伊蕉在人线观看热v| 午夜亚洲福利| 亚洲一区黄色| 日韩在线麻豆| 国产精品片aa在线观看| 国产欧美日韩影院| 黄色在线观看www| 国产视频亚洲| 久久精品国产大片免费观看| 国产欧美日韩| 亚洲1区在线| 亚洲欧美一区在线| 中文在线一区| 911精品国产| 国产精品白浆| 麻豆亚洲精品| 国产66精品| 国产高清精品二区| 久久影院午夜精品| 亚洲日产国产精品| 国产精品久久久久久久免费观看| 伊人久久大香线蕉av不卡| 欧美日韩1区| 日韩专区欧美专区| 亚洲精品福利电影| 国产精品久久| 精品久久不卡| 日韩手机在线| 午夜精品成人av| 久久久噜噜噜| 福利片在线一区二区| 日韩成人精品一区二区三区| 亚洲第一区色| 久久精品免费一区二区三区 | 青青草国产成人99久久| 国产精品午夜一区二区三区| 精品91久久久久| 岛国av在线播放| 欧美亚洲福利| 在线日韩成人| 亚洲精品乱码日韩| 国产精品久久久久77777丨| 亚洲久久一区| 欧美中文日韩| 日韩激情啪啪| 国产乱码精品一区二区三区亚洲人| 亚洲人成网77777色在线播放| 亚洲一区二区动漫| 丝袜美腿成人在线| 日本不卡不码高清免费观看| 在线一区av| 亚洲视频国产| 快播电影网址老女人久久| 91日韩在线| 丰满少妇一区| 国产日韩欧美| 精品国产乱码| 国产视频亚洲| 日韩高清不卡一区| 日本亚州欧洲精品不卡| 免费成人在线影院| 国产欧美日韩影院| 亚洲天堂资源| 日韩精品亚洲aⅴ在线影院| 日本精品在线播放| 婷婷激情一区| 少妇精品久久久一区二区| 日韩高清在线观看一区二区| 国产麻豆精品久久| 97在线精品| 中文亚洲免费| 日韩超碰人人爽人人做人人添| 婷婷激情久久| 日韩精品第一| 国产精品国产三级在线观看| 中文字幕高清在线播放| 婷婷成人在线| 国语对白精品一区二区| 久久亚洲欧洲| 国产日韩亚洲| 久久久久久久久久久9不雅视频| 国产真实久久| 欧美一区=区三区|