【性能】Android内存泄漏之问题定位

842 阅读2分钟

背景

随着项目的扩大内存泄漏问题也会日益凸显,那么要解决问题之前需要先定位问题

一个Android项目的内存分布

通过AndroidStudio的Profiler可以看到一个App包含的内存主要有这几种

Java:表示java层的内存占用

Native:表示native层既C++、C层的内存占用

Graphice:图像方面的内存占用、其中包括OpenGL等

直接用LeakCanary不就行了?

LeakCanary是定位和解决内存泄漏的一个很好的工具,项目中也经常会用到。但是有些泄漏却捕获不到,为什么呢?先来看下它的原理。 LeakCanary监听了Application的registerActivityLifecycleCallbacks,在Activity onDestroy的时候将当前activity新建一个弱引用并传入ReferenceQueue(引用队列),利用弱引用原理(当内存被回收时会将包装这个内存引用的包装类 存在引用队列里)判断ReferenceQueue中是否存在activity对象 如果存在说明回收了 如果不存在说明没有回收这个时候,会再手动触发gc然后再去检查一次。如果还是没有在队列里 那么认为内存泄漏开始分析dump文件。

也就是说其实LeakCanary只能监听Activity泄漏,其他的泄漏它并不能监听到

那么怎么分析其他类型的泄漏

模拟一个日常开发中比较常见的场景,加载Bitmap到内存中后没有释放,导致内存一直猛增。现在我们通过AndroidStudio自带的工具去分析,内存的增长点

首先打开Profile一顿操作后发现Native内存成上涨趋势,并且在GC发生时并没有被回收

这时我们可以开始怀疑这里是不是有不合理的内存占用,点击dump按钮后,分析dump文件,发现堆中有508个bitmap对象,这明显是不合理的

点击Bitmap对象可以看到,上方是bitmap对象中引用的对象,下面可以看到是哪个变量引用了Bitmap,这样基本可以确定是一个叫bitmaps的数组引用了bitmap对象,这时就已经定位到真凶,根据自己的业务需求优化就行