android 內存優化(三) 內存優化工具-MAT的使用及實例分析

1.mat內存優化分析包下載地址:

https://download.csdn.net/download/u010672559/10548897

說明:此包裏面包含有MAT64位壓縮包,內存泄漏demo-MemoryTest,內存分析工具文件hprof,mat工具直接解壓就可以使用,如果打開報錯,可能是jdk版本不匹配,需要自己去下載64位jdk安裝即可

2.以下以具體實例來講解MAT的使用方法

2.1實例場景爲 點擊button然後new 10000個imageview,使內存增加,然後finish會發現內存不降,手動點擊GC也不會降低

說明:以下爲Androidstudio-monitors-memory查看內存的視圖,點擊手動GC可觸發系統GC回收可回收的資源

手動GC

dump hprop文件

具體主要代碼如下

for (int i = 0; i < 10000; i++) {
    ImageView imageView = new ImageView(this);
    list.add(imageView);
}

此時點擊button2次會發現內存上升很快

說明:以上爲AndroidStudio的Monitors-Memory查看內存的視圖

Allocated app實際使用的內存
Free 爲空閒內存
我理解Allocated+Free爲系統給app分配的總內存,
實際主要是看Allocated內存使用情況,如果這個比較高,則需要優化,具體多高看實際項目要求定義了

然後通過點擊dump hprop圖標導出hprop文件,具體對應mat_test_imageview_0.hprof文件(上面的下載的工具包裏面有),然後通過MAT-File-Open heap dump...打開此文件,點擊finish會看到如下視圖

然後此頁往下翻,找到Histogram

點擊Histogram後再視圖的上方找到圖標,然後點擊展開,點擊Group by package可看到如下視圖

參數解釋:

- Shallow Heap 
Shallow size就是對象本身佔用內存的大小,不包含其引用的對象內存,實際分析中作用不大。在堆上,看起來是一堆原生的byte[], char[], int[],對象本身的內存都很小。所以我們可以看到以Shallow Heap進行排序的Histogram圖中,排在第一位第二位的是byte,char 
- Retained Heap 
Retained size是該對象自己的shallow size,加上從該對象能直接或間接訪問到對象的shallow size之和。換句話說,retained size是該對象被GC之後所能回收到內存的總和。RetainedHeap可以更精確的反映一個對象實際佔用的大小(因爲如果該對象釋放,retained heap都可以被釋放)。

以上視圖是從大到小的順序排列的各個類佔用的內存情況,其中主要是看Shallow Heap的值,這個值比如11593712,單位是B,即android包下面的對象佔用了11M左右的內存,然後右鍵選擇Merge shortest Paths to GC Roots-exclude all phantom/weak/soft etc.references, 意思是查看排除虛引用/弱引用/軟引用等的引用鏈 (這些引用最終都能夠被GC幹掉,所以排除)可看到如下視圖

然後展開排第一的項

然後就幫你定位到是MainActivity中的imageview佔用的內存最多,此時你就能定位內存佔用最多的是哪個地方了。之後便是優化工作,即只要在onDestroy()時將list集合置空就行了,然後你此時可以通過Monitors-Memory查看內存使用情況,發現按了2次button之後內存還是增加,finish後也不變,但是按了GC之後內存就迅速降低了,這就是效果。此時你也可以去導出此時的hprof文件,發現明顯由以前的14.5M變爲3.2M了,此時也可以通過同樣的操作,Histogram-按包查看,看排第一的內存佔用對象,發現不再是Imageview了,而是其他的對象了。這就說明當你在activity銷燬的時候把list置空後imageview也隨之被置空了,此時之前new的20000個imageview全部爲空了,此時處於可回收狀態,當手動按了GC之後,系統便會將其回收,內存一下就降下來了。

關於GC操作的理解:
置空或者加了緩存回收機制,會將超過LRU的內存或者置空的對象處理爲可回收狀態,等待系統GC時,便會回收,將處理過的處於可回收狀態的對象回收掉,我們知道系統GC不會主動觸發,只有系統自己內部回收機制纔會觸發,實際現象有界面跳轉或切換的時候可能會觸發GC,原因是此操作會加載新的內容,app會向系統申請分配多一些的內存,然後系統檢會在此時檢測是否有可以回收的地方,此時就觸發GC回收一部分可以回收的對象,實際現象也是界面跳轉時通過Android studio的Monitors觀看到Allocated會增加,之後如果有回收或手動觸發GC時Allocated會減少,Free增加,即Allocated+Free爲總的系統分配給app的總內存,GC後Allocated減少,Free增加

2.2其他實例:

項目中有個頁面需要gridview顯示很多圖片信息,使用imageload加載數據--------內存使用太高
實際分析:
點擊進入gridview頁面,將數據加載完,然後finish,重複以上操作,觀看內存變化情況,發現反覆finish
沒有繼續增加,說明沒有內存泄漏,但是一直不減少,說明需要內存優化

然後使用MAT分析佔用內存最多的對象,最後定位到了Imageloader對象,然後再通過網上查imageload的內存緩存機制發現最好不要用

options = new DisplayImageOptions.Builder()
        .cacheInMemory(true)

而應該是

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
        context).threadPriority(Thread.NORM_PRIORITY - 2)
        .denyCacheImageMultipleSizesInMemory()
        .memoryCache( new LruMemoryCache(2 * 1024 * 1024))//優化部分
        .memoryCacheSize(2 * 1024 * 1024)//優化部分
        .memoryCacheSizePercentage(13)//優化部分
        .discCacheFileNameGenerator(new Md5FileNameGenerator())
        .tasksProcessingOrder(QueueProcessingType.FIFO)
        .discCacheSize(100 * 1024 * 1024)
        .build();

即增加LRU內存緩存機制,並設置閾值,內存緩存超過一定值的時候會將通過LRU的規則將超過的內存處理掉,使其變爲可回收狀態,之後GC一觸發內存就馬上掉下去了

3.其他:通過以上的方法,也可以通過調簡單的demo去驗證網上的那些內存優化的方法,即找個單獨的因素,如工作線程一直加載圖片,然後銷燬的時候不停止線程,然後返回打開,finish操作,查看內存使用情況,分析佔用內存最高的對象,然後在銷燬的時候去停止工作線程,再和之前的內存情況比較,GC之後會不會降低來驗證問題

https://blog.csdn.net/u010672559/article/details/103178632 android 內存優化(一) 防止內存泄漏注意事項

https://blog.csdn.net/u010672559/article/details/103178663 android 內存優化(二) 性能優化

https://blog.csdn.net/u010672559/article/details/81098534 android 內存優化(三) 內存優化工具-MAT的使用及實例分析

https://blog.csdn.net/u010672559/article/details/81223122 android 內存優化(四) 性能優化-Systrace分析UI性能-含demo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章