Android內(nèi)存泄露檢測

一、Android內(nèi)存分析基礎(chǔ)

1、查看進程分配的最大內(nèi)存

每個App進程可以分配到的最大內(nèi)存是有限的,當然不同型號的手機,為每個App進程分配的最大內(nèi)存有可能也不一樣

可以通過以下命令查看APP給每個進程分配的最大堆內(nèi)存:

adb shell getprop | grep dalvik.vm.heapsize

查看手機可分配的最大堆內(nèi)存.png
2、查看進程的內(nèi)存使用情況

adb shell dumpsys meminfo [包名]

APP的內(nèi)存使用情況.png

Pss: 該進程獨占的內(nèi)存+與其他進程共享的內(nèi)存(按比例分配,比如與其他3個進程共享9K內(nèi)存,則這部分為3K)

Privete Dirty:該進程獨享內(nèi)存

Heap Size:分配的內(nèi)存

Heap Alloc:已使用的內(nèi)存

Heap Free:空閑內(nèi)存

二、使用Android Profiler查看內(nèi)存

在AndroidStudio中通過 View -> Tool Windows -> Android Profiler 可以找到Android Profiler窗口。


Android Profiler 位置.png

打開Android Profiler窗口,如下所示:

Android Profiler查看內(nèi)存使用情況.jpg

· 進程占用總內(nèi)存

· javaHeap:這部分內(nèi)存大小是有限制的,溢出則會OOM,這部分內(nèi)存也是我們分析優(yōu)化的重點

· NativeHeap:native層的 so 中調(diào)用malloc或new創(chuàng)建的內(nèi)存,對于單個進程來說大小沒有限制,所以可以利用在native層分配內(nèi)存來緩解javaHeap的壓力(比如2.3.3之前Android Bitmap的內(nèi)存分配就是在native層,之后移到javaHeap, 8.0又回到native)

· Graphics:這部分一般游戲app中用的較多,OpenGL和SurfaceFlinger相關(guān)的內(nèi)存,若沒有直接調(diào)用到OpenGL,則一般不會涉及到這塊內(nèi)存

· Stack:java虛擬機棧內(nèi)存

· Code:代碼,主要是dex以及so等占用的內(nèi)存

· Others:就是others

所以我們可以看到事實上我們可以優(yōu)化的點有:JavaHeap、NativeHeap、Stack、Code所占用的內(nèi)存

三、 使用Android Studio和MAT進行內(nèi)存泄露分析

1、Android的內(nèi)存泄漏分析工具常用有Android Studio和基于eclipse的MAT(Memory Analyzer Tool)。通過兩者配合,可以發(fā)揮出奇妙的效果。Android Studio能夠快速定位內(nèi)存泄漏的Activity,MAT能根據(jù)已知的Activity快速找出內(nèi)存泄漏的根源。

第一步:強制GC,生成Java Heap文件

我們都知道Java有一個非常強大的垃圾回收機制,會幫我回收無引用的對象,這些無引用的對象不在我們內(nèi)存泄漏分析的范疇,Android Studio有一個Android Monitors幫助我們進行強制GC,獲取Java Heap文件。

強制GC:點擊Force Garbage Collection(1)按鈕,建議點擊后等待幾秒后再次點擊,嘗試多次,讓GC更加充分。然后點擊Dump Java Heap(2)按鈕,然后等到一段時間,便會生成.hrof文件。

保存hprof文件按鈕.jpg

生成的Java Heap文件會在新建窗口打開。我們可以通過點擊把.hprof文件保存到本地。

查看引用鏈按鈕.jpg
第二步:分析內(nèi)存泄漏的Activity

然后可以把上一次生成的.hprof拖拽到Android Studio中,然后點擊右邊的一個Analyzer Tasks 按鈕,如下所示:


Android Profiler 查看引用鏈.jpg

找到可能產(chǎn)生泄露的Activity,點擊綠色按鈕,最后便可以查看泄露的引用鏈,如下所示:

個人感覺AndroidStudio查看泄露不是很準確,如果想準確知道泄露的引用鏈的話,可以結(jié)合MAT來分析。

第三步:轉(zhuǎn)換成標準的hprof文件

前提:安裝elipse和MAT(https://blog.csdn.net/u010335298/article/details/52233689

1、打開cmd窗口,然后進入到Android sdk tools 目錄中

2、執(zhí)行hprof-conv befor.hprof after.hprof 命令

3、把標準的hprof文件拖入到elipse中

MAT查看標準hprof文件.png
第四步:查看內(nèi)存泄露的引用鏈
10.jpg
內(nèi)存泄露引用鏈.jpg

右擊搜索出來的類名,選擇Merge Shortest Paths to GC Roots的exclude all phantom/weak/soft etc. references,來到這一步,就可以看到內(nèi)存泄漏的原因,我們就需要根據(jù)內(nèi)存泄漏的信息集合我們的代碼去分析原因。

代碼如下

public class AppSetting {

  private static AppSetting sInstance;

  private static Context mContext;//傳的是Activity

  private AppSetting(Context context) {

    mContext = context;
  }

  public static AppSetting getInstance(Context context) {

    if (sInstance == null) {
      sInstance = new AppSetting(context);
    }
    return sInstance;
  }

  public void doSomeThing(){
  }
}

四、使用LeakCanary進行內(nèi)存泄露檢測

只要集成程序自動幫忙抓取內(nèi)存泄露,gitHub地址如下:

LeakCanarygithub地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容