Android内存泄露检测

一、Android内存分析基础

1、查看进程分配的最大内存

每个App进程可以分配到的最大内存是有限的,当然不同型号的手机,为每个App进程分配的最大内存有可能也不一样

可以通过以下命令查看APP给每个进程分配的最大堆内存:

adb shell getprop | grep dalvik.vm.heapsize

查看手机可分配的最大堆内存.png
2、查看进程的内存使用情况

adb shell dumpsys meminfo [包名]

APP的内存使用情况.png

Pss: 该进程独占的内存+与其他进程共享的内存(按比例分配,比如与其他3个进程共享9K内存,则这部分为3K)

Privete Dirty:该进程独享内存

Heap Size:分配的内存

Heap Alloc:已使用的内存

Heap Free:空闲内存

二、使用Android Profiler查看内存

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


Android Profiler 位置.png

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

Android Profiler查看内存使用情况.jpg

· 进程占用总内存

· javaHeap:这部分内存大小是有限制的,溢出则会OOM,这部分内存也是我们分析优化的重点

· NativeHeap:native层的 so 中调用malloc或new创建的内存,对于单个进程来说大小没有限制,所以可以利用在native层分配内存来缓解javaHeap的压力(比如2.3.3之前Android Bitmap的内存分配就是在native层,之后移到javaHeap, 8.0又回到native)

· Graphics:这部分一般游戏app中用的较多,OpenGL和SurfaceFlinger相关的内存,若没有直接调用到OpenGL,则一般不会涉及到这块内存

· Stack:java虚拟机栈内存

· Code:代码,主要是dex以及so等占用的内存

· Others:就是others

所以我们可以看到事实上我们可以优化的点有:JavaHeap、NativeHeap、Stack、Code所占用的内存

三、 使用Android Studio和MAT进行内存泄露分析

1、Android的内存泄漏分析工具常用有Android Studio和基于eclipse的MAT(Memory Analyzer Tool)。通过两者配合,可以发挥出奇妙的效果。Android Studio能够快速定位内存泄漏的Activity,MAT能根据已知的Activity快速找出内存泄漏的根源。

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

我们都知道Java有一个非常强大的垃圾回收机制,会帮我回收无引用的对象,这些无引用的对象不在我们内存泄漏分析的范畴,Android Studio有一个Android Monitors帮助我们进行强制GC,获取Java Heap文件。

强制GC:点击Force Garbage Collection(1)按钮,建议点击后等待几秒后再次点击,尝试多次,让GC更加充分。然后点击Dump Java Heap(2)按钮,然后等到一段时间,便会生成.hrof文件。

保存hprof文件按钮.jpg

生成的Java Heap文件会在新建窗口打开。我们可以通过点击把.hprof文件保存到本地。

查看引用链按钮.jpg
第二步:分析内存泄漏的Activity

然后可以把上一次生成的.hprof拖拽到Android Studio中,然后点击右边的一个Analyzer Tasks 按钮,如下所示:


Android Profiler 查看引用链.jpg

找到可能产生泄露的Activity,点击绿色按钮,最后便可以查看泄露的引用链,如下所示:

个人感觉AndroidStudio查看泄露不是很准确,如果想准确知道泄露的引用链的话,可以结合MAT来分析。

第三步:转换成标准的hprof文件

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

1、打开cmd窗口,然后进入到Android sdk tools 目录中

2、执行hprof-conv befor.hprof after.hprof 命令

3、把标准的hprof文件拖入到elipse中

MAT查看标准hprof文件.png
第四步:查看内存泄露的引用链
10.jpg
内存泄露引用链.jpg

右击搜索出来的类名,选择Merge Shortest Paths to GC Roots的exclude all phantom/weak/soft etc. references,来到这一步,就可以看到内存泄漏的原因,我们就需要根据内存泄漏的信息集合我们的代码去分析原因。

代码如下

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进行内存泄露检测

只要集成程序自动帮忙抓取内存泄露,gitHub地址如下:

LeakCanarygithub地址

你可能感兴趣的:(Android内存泄露检测)