Profiler分析內存抖動,Memory Analyzer(mat)分析內存泄漏(不懂砍我)

前言: 最近在系統性的溫習了一遍android性能優化。寫博客是學習也是記錄,但願在記錄的同時也能幫助其餘同窗。最近我以爲我想出一個不懂系列。「不懂揍我」,「不懂砍我」,「不懂捶我」php

1、Profiler分析內存抖動

在咱們開發項目中,若是稍不注意,每每會出現內存抖動的狀況。而有些內存抖動也可能形成咱們的程序卡頓,甚至泄漏。接下來使用Android Studio自帶的Profiler分析內存抖動。java


1.一、模擬內存抖動並打開Profiler

首先在MainActivity建立一段內存抖動的代碼:android

private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            //創造內存抖動
            for (int i = 0; i < 100; i++) {
                String arg[] = new String[100000];
            }
            mHandler.sendEmptyMessageDelayed(0, 30);
        }
    };
複製代碼

而後點擊下圖紅色框內按鈕運行程序


運行以後出現以下圖,面試


鼠標移動到MEMORY上雙擊,進入內存分析


若是你的項目已經運行,也能夠經過View --> Tool Windows --> Profiler打開


1.二、分析內存抖動

點擊按鈕,觸發內存抖動的代碼,來看看咱們的內存狀況,能夠看到呈鋸齒狀數據庫


點擊上圖紅色框內record,而後點擊stop分析一段咱們的鋸齒狀,如圖:性能優化

Allocations: 表示當前分配的數量
Shallow Size: 表示當前內存佔用狀況dom

能夠看到咱們的String[]佔用最多,左鍵點擊String[]後,右側會出現全部的String[],而後左鍵點擊任意一個,會出現Allocation Call Stack:內存分配的堆棧信息:eclipse

能夠很明顯看到在咱們代碼裏,是由於handleMessage:21, MainActivity$1 (com.leo.memoryanalyzertest),形成的內存抖動。右鍵這條,點擊Jump to Source.能夠跳轉到咱們的問題代碼。這就是咱們Profiler分析內存抖動的狀況。ide


1.三、若是用上篇的traceView方式,即CPU Profiler方式

首先咱們推測下,traceView是分析卡頓利器,固然在這裏能測出。但要知道它是偏向耗時狀況的。上篇說過,這裏就不說明了。一樣點擊CPU,而後record,stop記錄一段。如圖來到咱們的Top Down:性能

能夠看到耗時時間在MessageQueue裏,這也正和咱們的內存抖動代碼相關聯,每間隔30ms發送一次,在handleMessage()裏,也指明瞭代碼在com.leo.memoryanalyzertest.MainActivity裏。能夠發現這種方式去分析,並不明顯。

注意:咱們都知道內存抖動,咱們要尋找的話,也是找循環或者頻繁調用的地方。因此這麼看咱們用CPU Profiler的方式也能大概確認問題代碼的位置。


2、Memory Analyzer之分析內存泄漏

一樣咱們先建立一段內存泄漏的代碼,先定義個接口

public interface CallBack {
    void leoFun();
}
複製代碼

而後建立個靜態list,添加CallBack實例

public class CallBackManager {
    public static ArrayList<CallBack> sCallBacks = new ArrayList<>();

    public static void addCallBack(CallBack callBack) {
        sCallBacks.add(callBack);
    }

    public static void removeCallBack(Callback callback) {
        sCallBacks.remove(callback);
    }
}
複製代碼

再建立個BitmapActivity實現CallBack接口,設置一個大圖main_bg,同時把實例假如到靜態sCallBacks中,這樣每次打開BitmapActivity而後退出,都會形成BitmapActivity不能被回收。

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bitmap);

        ImageView imageView = findViewById(R.id.image);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.main_bg);
        imageView.setImageBitmap(bitmap);
        CallBackManager.addCallBack(this);
    }
複製代碼

這樣咱們不停打開這個頁面而後關掉看內存狀況,如圖,能夠看到內存直接上升:

紅色框1:功能是主動發起一次gc。目的是回收一些可回收的,虛引用等。避免內存分析干擾
紅色框2: 堆轉儲,將內存分配狀況轉換成hprof文件。(注意這裏是studio的hprof文件,若是須要用Memory Analyzer分析,還要轉換成標準的hprof文件)

點擊右鍵Export,將文件存儲在文件夾裏。

轉換成mat能識別的hprof文件,只要cmd命令行來到咱們的studio自帶的hprof-conv.exe文件下,輸入命令,便可轉換

hprof-conv 源文件路徑 輸出文件路徑,這樣就生成了咱們的my.hprof


2.一、怎麼使用咱們的Memory Analyzer

生成了hprof文件後,而後就是使用Memory Analyzer。 官網下載地址:www.eclipse.org/mat/downloa…,由於捐贈什麼的,不建議。我這找到了一個比較靠譜的版本,csdn下載

下載好後啓動咱們的MemoryAnalyzer.exe。File --> Open Heap Dump打開咱們的my.hprof文件如圖:

先簡單介紹下Memory Analyzer的信息。

2.1.一、紅色框1: OverView大概信息

  • Size 內存大小
  • Classes : class對象
  • Objects : Objects個數,也就是實例個數
  • Unreachable Objects Histogram :可被回收的對象,扔在內存當中

2.1.二、紅色框2: Histogram直方圖

  • Objects: 這個類有多少個實例
  • Shallow Heap: 單個實例佔用的內存
  • Retained Heap: 單個實例及其引用一共佔有多少內存

咱們能夠利用直方圖,裏的Regex搜索咱們最開始的內存泄漏案例。搜索BitmapActivity如圖,能夠看到咱們的BitmapActivity有3個實例:

咱們能夠右鍵點擊com.leo.me,oryanalyzertest.BitmapActivity --> List objects --> with incoming reference (誰引用了我),如圖能夠看到有3個地方引用了BitmapActivity:

此時咱們右鍵一個實例點擊 Path To GC Roots --> with all refrence,如圖,找到文件下帶小太陽的文件,可能觸發內存溢出的地方。這裏是說咱們的sCallBacks引用了,也證明了在咱們內存泄漏代碼裏的CallBackManager裏的靜態集合sCallBacks添加了它。


2.1.三、紅色框3:dominator tree展現每一個實例的內存和所佔比例

能夠看到咱們這裏的大頭是bitmap。

一樣咱們能夠經過右鍵一個實例Path To GC Roots --> with all refrence如圖,也能看到是咱們的sCallBacks引用了:


2.1.四、紅色框4:OQL,相似於數據庫搜索咱們的內存狀況

寫入命令後,點擊紅色感嘆號運行,如圖


2.1.五、紅色框5:thread overview,展現線程狀況


2.1.六、紅色框6:Top Consumers (重點),直接展現出咱們內存中的大內存

展現咱們內存中佔有比較大的內存,能夠看到這裏都是被3個大bitmap佔據着。直觀利於分析


2.1.七、紅色框7:Leak Suspects(重點),直接給出分析,分析出咱們代碼中可能會出現內存泄漏的地方

這裏我啓動了3次BitmapActivity,它也給了我3個分析。點擊details。看詳情,也直接把問題定在了sCallBacks中:


個人公衆號

會發一些大白話實用的文章。也一直在尋找最有利的面試技巧。有想法的同窗能夠一塊兒

相關文章
相關標籤/搜索