<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      安卓筆記俠

      專注安卓開發

      導航

      Android內存優化(三)詳解內存分析工具MAT

      前言

      在這個系列的前四篇文章中,我分別介紹了DVM、ART、內存泄漏和內存檢測工具的相關知識點,這一篇我們通過一個小例子,來學習如何使用內存分析工具MAT。

      1.概述

      在進行內存分析時,我們可以使用Memory Monitor和Heap Dump來觀察內存的使用情況、使用Allocation Tracker來跟蹤內存分配的情況,也可以通過這些工具來找到疑似發生內存泄漏的位置。但是如果想要深入的進行分析并確定內存泄漏,就要分析
      疑似發生內存泄漏時所生成堆存儲文件。堆存儲文件可以使用DDMS或者Memory Monitor來生成,輸出的文件格式為hpof,而MAT就是來分析堆存儲文件的。
      MAT,全稱為Memory Analysis Tool,是對內存進行詳細分析的工具,它是Eclipse的插件,如果用Android Studio進行開發則需要單獨下載它,下載地址為:http://eclipse.org/mat/,這篇文章MAT的版本為1.6.1。

      2.生成hpof文件

      2.1 準備內存泄漏代碼

      我們需要準備一段發生內存泄漏代碼,如下所示。

      public class MainActivity extends AppCompatActivity {
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              LeakThread leakThread = new LeakThread();
              leakThread.start();
          }
          class LeakThread extends Thread {
              @Override
              public void run() {
                  try {
                      Thread.sleep(60 * 60 * 1000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
      View Code

      上面的代碼是很典型的內存泄漏的例子,原因就是非靜態內部類LeakThread持有外部類MainActivity的引用,LeakThread中做了耗時操作,導致MainActivity無法被釋放,關于內存泄漏可以查看Android內存優化(三)避免可控的內存泄漏這篇文章。

      2.2 DDMS生成hpof文件

      生成hpof文件主要分為以下幾個步驟:

      1. 在Android Studio中打開DDMS,運行程序。
      2. 在Devices中選擇要分析的應用程序進程,點擊Update Heap按鈕(裝有一半綠色液體的圓柱體)開始進行追蹤。
      3. 進行可能發生內存問題的操作(本文的例子就是不斷的切換橫豎屏)。
      4. 點擊Dump HPROP File按鈕結束追蹤,生成并保存hprof文件,如下圖所示。

      DDMS生成的hprof文件并不是標準的,還需要將它轉換為標準的hprof文件,這樣才會被MAT識別從而進行分析,可以使用SDK自帶的hprof-conv進行轉換,它的路徑在sdk/platform-tools中,進入到該路徑執行以下語句即可:

      hprof-conv D:\before.hprof D:\after.hprof

      其中 D:\before.hprof 是要轉換的hprof文件路徑,D:\after.hprof 則是轉換后hprof文件的保存路徑。

      2.3 Memory Monitor生成hpof文件

      除了用DDMS來生成hpof文件,還可以用AS的Memory Monitor來生成hpof文件。
      生成hpof文件主要分為一下幾個步驟:

      1. 在Android Monitor中選擇要分析的應用程序進程。
      2. 進行可能發生內存問題的操作(本文的例子就是不斷的切換橫豎屏)。
      3. 點擊Dump Java Heap按鈕,生成hprof文件,如下圖所示。

      Memory Monitor生成的hpof文件也不是標準的,AS提供了便捷的轉換方式:Memory Monitor生成的hpof文件都會顯示在AS左側的Captures標簽中,在Captures標簽中選擇要轉換的hpof文件,并點擊鼠標右鍵,在彈出的菜單中選擇Export to standard.hprof選項,即可導出標準的hpof文件,如下圖所示。
      QQ截圖20170810232344.pngQQ截圖20170810232344.png

      3.MAT分析hpof文件

      用MAT打開標準的hpof文件,選擇Leak Suspects Report選項。這時MAT就會生成報告,這個報告分為兩個標簽頁,一個是Overview,一個是Leak Suspects(內存泄漏猜想),如下圖所示。

      Leak Suspects中會給出了MAT認為可能出現內存泄漏問題的地方,上圖共給出了3個內存泄漏猜想,通過點擊每個內存泄漏猜想的Details可以看到更深入的分析清理情況。如果內存泄漏不是特別的明顯,通過Leak Suspects是很難發現內存泄漏的位置。

      打開Overview標簽頁,首先看到的是一個餅狀圖,它主要用來顯示內存的消耗,餅狀圖的彩色區域代表被分配的內存,灰色區域的則是空閑內存,點擊每個彩色區域可以看到這塊區域的詳細信息,如下圖所示。

      再往下看,Actions一欄的下面列出了MAT提供的四種Action,其中分析內存泄漏最常用的就是Histogram和Dominator Tree。我們點擊Actions中給出的鏈接或者在MAT工具欄中就可以打開Dorminator Tree和Histogram,如下圖所示。

      其中左邊第二個選項是Histogram,第三個選項是Dorminator Tree,第四個是OQL,下面分別對它們進行介紹。

      3.1 Dominator Tree

      Dorminator Tree意味支配樹,從名稱就可以看出Dorminator Tree更善于去分析對象的引用關系。

      圖中可以看出Dorminator Tree有三列數據。

      • Shallow Heap:對象自身占用的內存大小,不包括它引用的對象。如果是數組類型的對象,它的大小是數組元素的類型和數組長度決定。如果是非數組類型的對象,它的大小由其成員變量的數量和類型決定。
      • Retained Heap:一個對象的Retained Set所包含對象所占內存的總大小。換句話說,Retained Heap就是當前對象被GC后,從Heap上總共能釋放掉的內存。

      Retained Set指的是這個對象本身和他持有引用的對象以及這些引用對象的Retained Set所占內存大小的總和,官方的圖解如下所示。

      從圖中可以看出E的Retained Set為E和G。C的Retained Set為C、D、E、F、G、H。
      MAT所定義的支配樹就是從上圖的引用樹演化而來。在引用樹當中,一條到Y的路徑必然會經過X,這就是X支配Y。X直接支配Y則指的是在所有支配Y的對象中,X是Y最近的一個對象。支配樹就是反映的這種直接支配關系,在支配樹中,父節點直接支配子節點。下圖就是官方提供的一個從引用樹到支配樹的轉換示意圖。

      C直接支配D、E,因此C是D、E的父節點,這一點根據上面的闡述很容易得出結論。C直接支配H,這可能會有些疑問,能到達H的主要有兩條路徑,而這兩條路徑FD和GE都不是必須要經過的節點,只有C滿足了這一點,因此C直接支配H,C就是H的父節點。通過支配樹,我們就可以很容易的分析一個對象的Retained Set,比如E被回收,則會釋放E、G的內存,而不會釋放H的內存,因為F可能還引用著H,只有C被回收,H的內存才會被釋放。

      這里對支配樹進行了講解,我們可以得出一個結論:通過MAT提供的Dominator Tree,可以很清晰的得到一個對象的直接支配對象,如果直接支配對象中出現了不該有的對象,就說明發生了內存泄漏。
      在Dominator Tree的頂部Regex可以輸入過濾條件(支持正則表達式),如果是查找Activity內存泄漏,可以在Regex中輸入Activity的名稱,比如我們這個例子可以輸入MainActivity,效果如下圖所示。


      Dominator Tree中列出了很多MainActivity實例,MainActivity是不該有這么多實例的,基本可以斷定發生了內存泄漏,具體內存泄漏的原因,可以查看GC引用鏈。在MainActivity一項單擊鼠標右鍵,選擇Path To GC Roots,如下圖所示。

      Path To GC Roots選項用來表示從對象到GC Roots的路徑,根據引用類型會有多種選項,比如with all references就是包含所有的引用,這里我們選擇exclude all phantom/weak/soft etc. references,因為這個選項排除了虛引用、弱引用和軟引用,這些引用一般是可以被回收的。這時MAT就會給出MainActivity的GC引用鏈。


      引用MainActivity的是LeakThread,this$0的含義就是內部類自動保留的一個指向所在外部類的引用,而這個外部類就是MainActivity,這將會導致MainActivity無法被GC。

      3.2 Histogram

      Histogram與Dominator Tree不同的是,Dominator Tree是在對象實例的角度上進行分析,注重引用關系分析,而Histogram則在類的角度上進行分析,注重量的分析。
      Histogram中的內容如下圖所示。

      可以看到Histogram中共用四列數據,關于Shallow Heap和Shallow Heap的含義我們在3.1節已經知道了,剩余的 Class Name代表類名,Objects代表對象實例的個數。

      在Histogram的頂部Regex同樣可以輸入過濾條件,這里同樣輸入MainActivity,效果如下圖所示。

      MainActivity和LeakThread實例各為11個,基本上可以斷定發生了內存泄漏。具體內存泄漏的原因,同樣可以查看GC引用鏈。在MainActivity一項單擊鼠標右鍵,選擇Merge Shortest Paths to GC roots ,并在選項中選擇exclude all phantom/weak/soft etc. references如下圖所示。

      Histogram是在類的角度進行分析,而Path To GC Roots是用來分析單個對象的,因此在Histogram無法使用Path To GC Roots查詢,可以使用Merge Shortest Paths to GC roots查詢,它表示從GC roots到一個或一組對象的公共路徑。
      得出的結果和3.1節是相同的,引用MainActivity的是LeakThread,這導致了MainActivity無法被GC。

      3.3 OQL

      OQL全稱為Object Query Language,類似于SQL語句的查詢語言,能夠用來查詢當前內存中滿足指定條件的所有的對象。它的查詢語句的基本格式為:

      SELECT * FROM [ INSTANCEOF ]    <class_name> [ WHERE <filter-expression>]

      當我們輸入select * from instanceof android.app.Activity并按下F5時(或者按下工具欄的紅色嘆號),會將當前內存中所有Activity都顯示出來,如下圖所示。


      如果Activty比較多,或者你想查找具體的類,可以直接輸入具體類的完整名稱:

      select * from com.example.liuwangshu.leak.MainActivity

      通過查看GC引用鏈也可以找到內存泄漏的原因。關于OQL語句有很多用法,具體可以查看官方文檔

      3.4 對比hpof文件

      因為我們這個例子很簡單,可以通過上面的方法來找到內存泄漏的原因,但是復雜的情況就需要通過對比hpof文件來進行分析了。使用步驟為:

      1. 操作應用,生成第一個hpof文件。
      2. 進行一段時間操作,再生成第二個hpof文件。
      3. 用MAT打開這兩個hpof文件。
      4. 將第一個和第二個hpof文件的Dominator Tree或者Histogram添加到Compare Basket中,如下圖所示。
      5. 在Compare Basket中點擊紅色嘆號按鈕生成Compared Tables,Compared Tables如下圖所示。

      在Compared Tables也有頂部Regex,輸入MainActivity進行篩選。

      可以看到MainActivity在這一過程中增加了6個,MainActivity的實例不應該增加的,這說明發生了內存泄漏,可以通過查看GC引用鏈來找到內存泄漏的具體的原因。

      除了上面的對比方法,Histogram還可以通過工具欄的對比按鈕來進行對比:

      生成的結果和Compared Tables類似,我們輸入MainActivity進行篩選:

      可以看到第二個hpof文件比第一個hpof文件多了6個MainActivity實例。

      MAT還有很多功能,這里也只介紹了常用的功能,其他的功能就需要讀者在使用過程中去發現并積累。

      參考資料
      《Android群英傳 神兵利器》
      《Android應用性能優化最佳實踐》
      《高性能Android應用開發》
      利用MAT進行內存泄露分析
      Android最佳性能實踐(二)——分析內存的使用情況
      Memory Analyzer

      posted on 2018-07-18 09:54  安卓筆記俠  閱讀(1831)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 艳妇臀荡乳欲伦69调教视频| 景东| 国产剧情91精品蜜臀一区| 国产成人精品亚洲资源| 亚洲乱色熟女一区二区蜜臀| 不卡一区二区国产精品| 中文字幕国产精品二区| 中文字幕成熟丰满人妻| 国产精品露脸3p普通话| 亚洲天堂一区二区三区三州| 人妻无码中文字幕| 欧美人与动牲猛交A欧美精品| 国产女同疯狂作爱系列| 精品九九热在线免费视频| 97视频精品全国免费观看| 国产精品SM捆绑调教视频| 国产午夜精品福利免费看| 人人爽亚洲aⅴ人人爽av人人片| 男女18禁啪啪无遮挡激烈网站| 久久国产精品无码网站| 亚洲国产成人综合精品| 日韩激情无码av一区二区| 亚洲欧洲中文日韩久久av乱码| 综合人妻久久一区二区精品| 亚洲国产日韩欧美一区二区三区| 国产精品一区二区日韩精品| 日本阿v片在线播放免费| 亚洲人成小说网站色在线| 午夜福利电影| 国产精品亚洲аv无码播放| 国产av无码国产av毛片| 宜城市| 一区二区三区精品视频免费播放 | 国产漂亮白嫩美女在线观看| 免费天堂无码人妻成人av电影| 天堂中文8资源在线8| 湘阴县| 国产日本一区二区三区久久| 欧美人成精品网站播放| 亚洲精品三区二区一区一| 亚洲国产在一区二区三区|