使用Android Monitor分析項目查找內(nèi)存泄漏

前言:
在開發(fā)項目的過程中 或多或少都有些地方不注意造成內(nèi)存泄漏導致App卡頓的情況發(fā)生 Android Studio也為我們提供了一些查找內(nèi)存泄漏的組件 今天就先學習下 如何使用Android Monitor來分析和查找項目中內(nèi)存泄漏的地方

案例:

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

        CommUtil instance = CommUtil.getInstance(this);
    }
}

將Activity的實例被一個單例對象所持有,相信這樣的代碼錯誤大家應該不會去犯,這里主要學習如何使用Android Monitor 就遷就一下,然后我們運行起來 ,再將手機屏幕旋轉(zhuǎn)幾下(旋轉(zhuǎn)屏幕的時候 Activity會被銷毀重新創(chuàng)建,但是這里的單例會持有銷毀Activity的實例就造成內(nèi)存泄漏)。


  1. 先看看Android Studio 的Android Monitor都有哪些功能 先只關注Memory這塊


    Initiate Gc:點擊主動去回收垃圾內(nèi)存
    Dump java Heap: 點擊就會生成app運行內(nèi)存快照.hprof文件
    Free :代表還剩下的內(nèi)存
    Allocated:代表已經(jīng)使用的內(nèi)存

  2. Dump java Heap點擊就會生成app運行內(nèi)存快照.hprof文件

  3. 通過內(nèi)存快照 看到MainActivity 在內(nèi)存中有3個實例 點擊進行進一步查看


    Depth:對象被引用的深度
    Shallow Size:對象實例的大小
    Dominating Size:對象管轄范圍的內(nèi)存大小

  4. 在Instance區(qū)域我們看到了MainActivity的3個實例對象 已經(jīng)各個對象的引用深度和大小等 這里就明顯看到了MainActivtiy內(nèi)存泄漏了 這里說明一下 (在運行項目的時候 手機屏幕旋轉(zhuǎn)了3下 所以生成了3個MianActivity實例 但是第二個MainActivity已經(jīng)被回收 因為當GC回收的時候會將除了第0個和最后這一個留著其他的都會被回收 所以當你把手機屏幕旋轉(zhuǎn)3次以上的時候 內(nèi)存里面只會有2個Activity實例)
    點擊編號2的MianActivity進行查看:


    Depth:對象被引用的深度
    Shallow Size:對象實例的大小
    Dominating Size:對象管轄范圍的內(nèi)存大小

  5. 根據(jù)上面的內(nèi)存對象引用樹就能得出結(jié)論分析(除CommUtil以外的地方是系統(tǒng)級的引用這里暫時先不用管) :

    • CommUtil引用了MainActivity的context
    • 引用深度Depth為1 對象大小為12 該對象管轄范圍大小為60781
      然后改代碼:
public class MainActivity extends AppCompatActivity {

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

        CommUtil instance = CommUtil.getInstance(getApplicationContext());
    }
}
  1. 該代碼運行 且旋轉(zhuǎn)屏幕后 再生成內(nèi)存快照.hprof文件查看:



    將this改為getApplicationContext()后 MainActivity在幾次旋轉(zhuǎn)屏幕后始終保持一個實例

總結(jié):

  • 以上是通過已知案例來進行對Android Monitor的簡單學習 在實際開發(fā)過程中還需要去仔細的分析(這個相對來講較困難 需要根據(jù)自己的一些經(jīng)驗來看)

最后:

  • 其實還有一個工具叫MAT Memory Analyzer 如何使用在下篇文章進行講解
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容