Android Studio Profiler 内存泄漏分析
最近的项目中出现了内存泄漏,在踩了好多坑之后,终于解决了遇到的泄漏问题,为了防止下次忘记,所以把这次的经验记录下来。
前言
内存泄漏有很多种的情况,在安卓里面,大多是因为内部类持有了Activity
或者Context
的引用导致Activity
或者Context
无法释放,最常见的是执行了一个耗时操作,在退出Activity
的时候没有关闭耗时操作,导致Activity
一直被耗时操作持有。
例如网上经常会有讲到使用Handler
的时候需要注意泄漏,需要使用静态内部类,并且弱引用Activity
解决。这样的地方可以在写代码的时候注意到然后解决,但是有些时候我们也不知道哪里出现了内存泄漏,就需要通过工具帮助我们分析了。
Android Studio Profiler
Android Studio自带的Profiler就提供了这样的能力,打开Profiler会看到如下的界面,
然后点击红色选框中的部分,就可以进入内存分析详情如下:
为了查看到内存泄漏,我们需要对app进行一顿操作。如果我们想知道一个TestActivity
有没有内存泄漏,那么我们可以频繁的进出TestActivity
,按照官网的说法横竖屏切换和回退到桌面再进入app也会增加泄漏的风险。一顿操作猛如虎,要知泄漏有没有,且看下面。
当我们频繁操作之后,可以先点击左上角的垃圾桶按钮,进行强制GC,多点几次,接下来点击左上角的下箭头图标生成分析文件,这就是我们判断有没有内存泄漏的关键。
为了方便查看,我们可以把分组方式改为按照包名分组
那么怎么看有没有泄漏呢?在左下角的堆窗口找到我们想要测试的那个class名,点击会出现如下的窗口:
其中左下角的HandlerActivity
和HandlerActivity$1
可能第一次看会很迷,难道说我的这个类有两个实例吗,那不就是内存泄漏了么?其实并不是这个意思,$
符号只是说明这个类有一个内部类而已,因为内部类会持有外部类的引用。
右上角的地方我们可以看到有四个HandlerActivity
,那这个说明是内存泄漏了么?是的,这个Instance View
就是实例窗口,有几个就说明有几个实例,如果按照逻辑这个对象同时只能有一个实例的话,那就是内存泄漏了。
当知道是内存泄漏之后就需要找到泄漏的地方,在右下角有一个引用窗口,可以看到具体是谁引用这个它,导致内存不能及时回收。在右上角的实例窗口选中一个实例,然后在引用窗口选中一条点击右键Jump to Source
就可以看到具体引用的地方,然后观察代码就知道是什么问题导致的内存泄漏了。