LeakCanary 原理淺析

AkilahCutts 7年前發布 | 12K 次閱讀 Android開發 移動開發 LeakCanary

Android 應用內存泄漏問題,一直是性能優化的重點。在不清楚內存泄漏的大致范圍時,通過人為測試模擬重現或無目的地分析 heap dump等方法來檢測,都太繁瑣、耗時且定位不準。

什么是內存泄漏?

在 Java 世界中,一切對象都有生命周期,如同人的壽命。人死燈滅,入輪回,轉世投胎。Java 對象的生命周期結束后,將被 GC 回收,原先占用的內存會有新的用途。但凡是總有例外,就如孫悟空可以修改生死譜長生不死,聶小倩能殘存人間人鬼相戀。Java 對象有時也會”長死不死“,GC 拿它沒有辦法,這種情況就是內存泄漏。造成這種情況的原因是:Java 對象被另一個生命周期更長對象持有,具有 可達性 ,這并不是我們想要的。

問:有沒有一種簡單直接且能有效定位內存泄漏位置的方法呢?

答:有,那就是 LeakCanary 。我們可以簡單地人為:將一個 App 作為輸入,通過 LeakCanary 檢測后,就會得到內存泄漏位置結果(如果存在的話)。

LeakCanary

知其然知其所以然, LeakCanary 如此強大實用,那么: LeakCanary 是怎么實現的?

  • Android 應用的整個生命周期由其組件的生命周期組成,如下圖中所示。用戶使用應用的過程中,在不同界面之間跳轉,每個界面都經歷著”生死“的轉換,可在此建立檢測點。 Activity / Fragment 都有 onDestory() 回調方法, 進入此方法后, Activity / Fragment 生命周期結束,應該被回收。

簡述聲明周期

  • 然后我們需要解決:如何得到未被回收的對象。 ReferenceQueue + WeakReference + 手動調用 GC 可實現這個需求。

    WeakReference 創建時,傳入一個 ReferenceQueue 對象。當被 WeakReference 引用的對象的生命周期結束,一旦被 GC 檢查到,GC 將會把該對象添加到 ReferenceQueue 中,待ReferenceQueue處理。當 GC 過后對象一直不被加入 ReferenceQueue,它可能存在內存泄漏。

獲得未被回收的 Object

  • 找到了未被回收的對象,如何確認是否真的內存泄漏?這里可以將問題轉換為:未被回收的對象,是否被其他對象引用?找出其最短引用鏈。 VMDebug + HAHA 完成需求。

    VM 會有堆內各個對象的引用情況,并能以 hprof 文件導出。HAHA 是一個由 square 開源的 Android 堆分析庫,分析 hprof 文件生成 Snapshot 對象。 Snapshot 用以查詢對象的最短引用鏈。

解析hprof

  • 找到最短引用鏈后,定位問題,排查代碼將會事半功倍。

如下泳道圖分析, LeakCanary 各個模塊如何配合達到檢測目的。

泳道圖

 

 

來自:http://www.jianshu.com/p/3f1a1cc1e964

 

 本文由用戶 AkilahCutts 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!