Android記憶體最佳化1 記憶體偵查工具1 Memory Monitor檢測記憶體泄露

來源:互聯網
上載者:User

標籤:卡頓   道具   時間軸   分類   bitmap   記憶體回收行程   main   key   案例   

上篇說了一些效能最佳化的理論部分,主要是回顧一下,有了理論,小平同志又講了,實踐是檢驗真理的唯一標準,對於記憶體泄露的問題,現在通過Android Studio內建工具Memory Monitor 檢測出來。效能最佳化的重要性不需要在強調,但是要強調一下,我並不是一個老司機,嘿嘿!沒用過這個工具的,請睜大眼睛。如果你用過,那麼就不用在看這篇部落格了。

先看一段會發生記憶體泄露的代碼

public class UserManger {    private static UserManger instance;    private Context context;    private UserManger(Context context) {        this.context = context;    }    public static UserManger getInstance(Context context) {        if (instance == null) {            instance = new UserManger(context);        }        return instance;    }}
public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        UserManger userManger = UserManger.getInstance(this);    }}

代碼很簡單,就是一個單利模式泄露的情境,我們現在的關心的不是代碼本身,而是如何將代碼裡面的記憶體泄露給找出來。但是對於上面的代碼發生記憶體泄露的原因還是有必要提一下。

上篇部落格說了,記憶體流失產生的原因是:當一個對象已經不需要再使用了,本該被回收時,而有另外一個正在使用的對象持有它的引用從而就導致,對象不能被回收。這種導致了本該被回收的對象不能被回收而停留在堆記憶體中,就產生了記憶體流失。

在上面的代碼中,發生泄露的不是UserManger,而是MainActivity,UserManger中有一個靜態成員instance,其生命週期和應用程式的生命週期一致,當退出應用時,才能被銷毀,但是當GC準備回收MainActivity時,結果呢MainActivity的對象(this)在被UserManger所引用,UserManger本身又不能被幹掉,所以就發生了記憶體泄露。


monitors.png


Memory Monitor是Android Monitors中的一種,Monitors主要包括四種,Memory Monitor ,CPU Monitor ,NetWork Monitor, GPU Monitor ,今天介紹的是Memory Monitor ,其他的Monitor,在後面也準備講。

  • Memory Monitor介面

Memory Monitor.png
  • 圖中水平方向是時間軸,豎直方向是記憶體的分配情況
  • 圖中深藍色的地區,表示當前正在使用中的記憶體總量,淺藍色或者淺灰色地區,表示空閑記憶體或者叫作未分配記憶體。
  • 記憶體分析的工具列,從上向下一共4個按鈕,依次是:
    1. 終止檢測的開關,沒什麼實質性的作用

      就是手動調用GC,我們在抓記憶體前,一定要手動點擊 Initiate GC按鈕手動觸發GC,這樣抓到的記憶體使用量情況就是不包括Unreachable對象的(Unreachable指的是可以被記憶體回收行程回收的對象,但是由於沒有GC發生,所以沒有釋放,這時抓的記憶體使用量中的Unreachable就是這些對象)

      (Dump Java Heap)點擊可以產生一個檔案(包名+日期+“.hprof”),可以記錄摸一個時間點內,程式記憶體的情況。擷取hprof檔案(hprof檔案是我們使用MAT工具分析記憶體時使用的檔案),但這裡直接產生的檔案MAT還不能直接使用,需用轉換成標準的hprof檔案。可以使用AndroidStudio轉換或者用hprof-conv命令轉化,網上可以查到

      開始分配追蹤,第一次點擊可以指定追蹤記憶體的開始位置,第二次點擊可以結束追蹤的位置。這樣我們截取了一段要分析的記憶體,等待幾秒鐘AndroidStudio會給我們開啟一個Allocation視圖(感覺和MAT工具差不多,不過MAT工具更加強大,我們也可以擷取hprof檔案,使用MAT來分析)

回到我們的程式,多點擊幾次GC,看一下這個應用的記憶體使用量情況。


記憶體使用量情況.jpg

可以看到現在已經分配的記憶體有19.68M,我把手機旋轉一下,在看。


旋轉後記憶體使用量情況.png

可以看到現在的記憶體使用量量是21.09M,還是一樣的介面,卻多了1.41M!!!這很關鍵。

接下來,我們找一下,哪裡發生了泄露。點擊Dump Java Heap,產生快照檔案tool.test.memory.memoryleak_2016.11.13_21.38.hprof,Android Studio 自動彈出HPROF Viewer來分析它。


快照檔案分析.png

現在介紹一下HPROF Viewer的用法

  • HPROF Viewer查看方式
    左上方兩個紅框,是可選列表, 分別是用來選擇Heap地區, 和Class View的展示方式的.
    Heap類型分為:
    App Heap -- 當前App使用的Heap
    Image Heap -- 磁碟上當前App的記憶體映射拷貝
    Zygote Heap -- Zygote進程Heap(每個App進程都是從Zygote孵化出來的, 這部分基本是framework中的通用的類的Heap)
    Class List View -- 類列表方式
    Package Tree View -- 根據包結構的樹狀顯示

我通常點擊App heap下面的Classs Name把Heap中所有類按照字母順序排序,然後按照字母順序尋找。

  • HPROF Viewer主要分ABC三大板塊
    板塊A:這個應用中所有類的名字
    版塊B:左邊類的所有執行個體
    板塊C:在選擇B中的執行個體後,這個執行個體的引用樹
  • A板塊左上方列名解釋
列名 解釋
Class Name 類名,Heap中的所有Class
Total Count 記憶體中該類這個對象總共的數量,有的在棧中,有的在堆中
Heap Count 堆記憶體中這個類 對象的個數
Sizeof 每個該執行個體佔用的記憶體大小
Shallow Size 所有該類的執行個體佔用的記憶體大小
Retained Size 所有該類對象被釋放掉,會釋放多少記憶體
  • B板塊右上方上角列名解釋
列名 解釋
Instance 該類的執行個體
Depth 深度, 從任一GC Root點到該執行個體的最短跳數
Dominating Size 該執行個體可支配的記憶體大小

B板塊右上方有個"的按鈕, 點擊會進入HPROF Analyzer的hprof的分析介面:


Analyzer Tasks.png

點擊Analyzer Tasks右邊的綠色運行箭頭,Android Studio會自動的根據此hprof檔案分析有哪些類是有記憶體流失的,如所示:


下面分析一下MainActivity的泄露情況
MainActivity發生記憶體泄露.png在這個介面中可以直接把記憶體泄露可能的類找出來。
  • 一個Activity應該只有一個執行個體,但是從A地區來看 total count的值為2,heap count的值也為2,說明有一個是多餘的。
  • 在B地區中可以看見兩個MainActivity的執行個體,點擊一個看他的引用樹情況
  • 在C地區中可以看到MainActivity的執行個體Context被UserManger的 instance引用了,引用深度為1.
  • 在Analyzer Tasks 地區中,直接告訴你Leaked Activities,MainActivity包含其中

多方面的證據表明MainActivity發生了記憶體泄露

解決方案

public class UserManger {    private static UserManger instance;    private Context context;    private UserManger(Context context) {        this.context = context;    }    public static UserManger getInstance(Context context) {        if (instance == null) {            if(context!=null){                instance = new UserManger(context.getApplicationContext());            }        }        return instance;    }}

不要用Activity的Context,因為Activity隨時可能被回收,我們用Application的Context,Application的Context的生命週期是整個應用,不回收也沒有關係。

Memory Monitor獲得記憶體的動態視圖,Heap Viewer顯示堆記憶體中儲存了什麼,可惜Heap Viewer不能顯示你的資料具體分配在代碼的何處,如果還不過癮,想知道具體是哪些代碼使用了記憶體,還有一個功能是Allocation Tracker,用來記憶體配置追蹤。在記憶體配置圖中點擊途中標紅的部分,啟動追蹤,再次點擊就是停止追蹤,隨後自動產生一個alloc結尾的檔案,這個檔案就記錄了這次追蹤到的所有資料,然後會在右上方開啟一個資料面板
Allocation Tracker啟動追蹤


Allocation Tracker啟動追蹤.png

Allocation Tracker查看方式


Allocation Tracker查看方式

有兩種查看方式,預設是Group by Method方式

  • Group by Method:用方法來分類我們的記憶體配置
  • Group by Allocator:用記憶體 Clerk來分類我們的記憶體配置

從可以看出,首先以線程對象分類,Size是記憶體大小,Count是分配了多少次記憶體,點擊一下線程就會查看每個線程裡所有分配記憶體的方法

  • Group by Method方式


    每個線程裡所有分配記憶體的方法.png


    OK,-Memory Monitor

  • Group by Allocator方式


    EY%HY_B74%BUE22C6$G~CTP.png


    右鍵可以直接跳到源碼

- 扇形統計圖


[email protected]_1`[email protected]%S%6.png

點擊統計圖按鈕,會產生,扇形統計圖是以圓心為起點,最外層是其記憶體實際分配的對象,每一個同心圓可能被分割成多個部分,代表了其不同的子孫,每一個同心圓代表他的一個後代,每個分割的部分代表了某一帶人有多人,你雙擊某個同心圓中某個分割的部分,會變成以你點擊的那一代為圓心再向外展開。

 

Memory Monitor可以發現的問題

Memory Monitor工具為監控工具,是一種發現型或者說監控性質的工具,比如醫生的四大技能[望聞問切],[望]是第一步。這裡的Memory Monitor就是一種[望]的工具,目前我主要用它來看下面幾個記憶體問題:
1.發現記憶體抖動的情境
2.發現大記憶體對象分配的情境
3.發現記憶體不斷增長的情境
4.確定卡頓問題是否因為執行了GC操作

案例分析

上面的第一區段標記顯示記憶體突然增加了7M,我們也能看的很清楚,所以這個點我們要去定位了一下問題在哪裡,是Bitmap還是什麼原因造成的,第二區段標記是記憶體抖動,很明顯在很短的時間了發生了多次的記憶體配置和釋放。而且在發生記憶體抖動的時候,也能感覺到App的卡頓,可以看出來是由於執行了GC操作造成的。
記憶體的不斷增加通過Memory monitor很容易看出來,藍色的曲線是一路高歌猛進的,一看便知。

Android記憶體最佳化1 記憶體偵查工具1 Memory Monitor檢測記憶體泄露

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.