1. 程式人生 > >Android記憶體洩露分析

Android記憶體洩露分析

一,記憶體洩露

記憶體洩露:一個不在被使用的物件被另一個存活著的物件引用,在這種情況下垃圾回收器會跳過他,因為這種引用關係足以讓該物件駐留在記憶體中,記憶體洩露是在組織垃圾回收器為未來的記憶體分配提供空間,這些洩露的物件一直佔據著記憶體,導致我們的堆記憶體空間變得更小。也加劇了垃圾回收呼叫的頻繁程度,妨礙應用程式的正常執行。

記憶體溢位:通常的理解就是記憶體不夠,是指堆記憶體大小超出了應用程式的分配記憶體範圍導致的。通常來講記憶體洩漏就是導致記憶體溢位的罪魁禍首。

二,LeakCanary

leakCanary是一款記憶體追蹤工具,可以幫我們定位到記憶體洩露,這裡不做過多講述,

LeakCanary中文使用說明

三,Android Profile

android profile可以幫助我們觀察記憶體波動情況

首先我們進入我們的應用,然後能看到記憶體曲線,一直很平穩,我點手動GC(垃圾箱按鈕),使曲線平穩,進入我們要觀察的頁面,進行操作,發現記憶體向上波動,然後退出頁面,繼續點GC,我們發現記憶體大小並沒有回退到之前的波形,而是維持高位,我們基本可以斷定當前頁面存在記憶體洩露情況。(如下圖)
這裡寫圖片描述

這個時候點選左上角中間按鈕”下箭頭那個(Dump java heap)”,然後就會生成一個當前記憶體的一個堆資訊。在曲線下面的按個框裡面。
這裡寫圖片描述

在這框裡面我們可以看到堆記憶體佔用大小。也可以搜尋你想看的物件。

三,MAT

相對於android profile,MAT更加直觀而且操作更方便。

在上圖中的左邊框的左上角,有一個匯出按鈕,Exprot capture to file,點選此按鈕,可以匯出當前堆資訊到一個hprof檔案中。

官網MAT下載地址https://www.eclipse.org/mat/
這裡寫圖片描述
下載完成以後雙擊MemoryAnalyzer.exe,然後點選File–>open file剛才匯出的.hprof檔案,如果彈出一下錯誤框
這裡寫圖片描述
說明當前不能識別,我們需要用到android sdk下的hprof-conv.exe進行一下轉換
這裡寫圖片描述

開啟命令列cd 到當前目錄.exe所在目錄
這裡寫圖片描述

輸入上圖紅框中的命令,前面的.hprof檔案要轉換的檔案,後面為要轉出的檔案。檔案跟.exe在同一個目錄。轉換完成以後再用MAT開啟。

這裡寫圖片描述

如上圖,即為當前匯出的.hprof檔案的堆資訊圖。
我們點選下面紅框中第一個Histtogram。
這裡寫圖片描述

如上圖:

  • Objects:表示該類在記憶體當中的物件個數。
  • Shallow Heap:這一列中文翻譯過來是“淺堆”,表示的是物件自身所佔用的記憶體大小,不包括它所引用的物件的記憶體大小。
  • Retained Heap:這一列中文翻譯過來是“保留堆”,也就是當該物件被垃圾回收器回收之後,會釋放的記憶體大小。其實也就是當前所有物件所佔用的記憶體大小。

在regex輸入框可以通過關鍵字來過濾我們想要找的檔案。
這裡寫圖片描述

注:因為我是在點選MyCsdnBlogActivity的時候,產生了大量的記憶體抖動,並且在GC的時候,記憶體並沒有恢復,所以我們目標就是該activity

右鍵選中該條目–>list objects–>with incoming references
這裡寫圖片描述

右鍵條目–>path to gc root–>exclude all phantom/weak/soft etc.references。過濾掉軟引用和弱引用
這裡寫圖片描述

然後我們發現在在他的GC節點上有一個ActivityManager下的activitys的引用,至此記憶體洩露被找到。

四,總結

一般來講,我們追蹤記憶體洩露,首先使用leak canary基本就可以定位到洩露的位置,如果問題沒有解決,這個時候我們就可以使用android profile去追蹤記憶體波動,然後去生成.hprof檔案,在用MAT去分析堆資訊,從而找到洩露的位置。

後面我會說一下,避免記憶體洩露的一些注意事項。

文章中有些地方可能說的不夠詳細,大家也可以參考一下面的文章
https://www.jianshu.com/p/fa016c32360f

Android記憶體抖動分析與注意事項
Kotlin之Android專案實戰