Android - 看似内存泄漏,实则不是,记一次内存泄漏的案例分析

  APP中常常会存在内存泄漏的问题,一个简单的测试方法是,多次进入和退出同一页面(Activity),使用adb shell中的dumpsys meminfo com.android.settings | grep "Activities"来查看Activity的数量(以com.android.settings为例)。

如果随着多次进入和退出,Activity的数量一致在增长,没有下降,那么便很大有可能是内存泄漏的问题。当然有可能是GC还没有回收的缘故,如果再显示地对调用GC回收(DDMS工具的Cause GC按钮),如果Acitivity的数量仍然没有降低,那么概率就更大了。需要从代码层面进一步分析。

  今天遇到的例子就是,通过上述方法,看似遇到了内存泄漏,其实不是。

关键点通过MAT工具和代码分析,未回收的对象被system_process进程引用,显示调用system_process GC即可解决问题,不属于内存泄漏。

案例简介:在原生Android Open Source Project的Settings APP代码中,有一个Fragment类叫AccountPreferenceBase,运行在进程com.android.settings中,通过以上方法,发现这个类可能存在内存泄漏,于是在重现问题后,借助MAT工具,来分析,得到与此对象相关的引用链如下:

  由上图可知未被GC回收的AccountPreferenceBase与ContentResolver有关。通过代码分析,在AccountPreferenceBase中,相关的代码是如下,

  进一步分析,在onResume时,调用addStatusChangeListener时,内部会调用RemoteCallbackList的register方法(将callback的binder对象push进一个ArrayMap)。如果不再页面退出时,及时从ArrayMap中delete掉此binder对象,就会有内存泄漏的问题。但是我们在onPause中发现,其实已经调用了removeStatusChangeListener,其内部就会调用unregister方法,从ArrayMap中delete掉正确的binder对象。所以代码的写法没有问题。

那是什么原因导致GC没有回收我们的Activity呢?

  原因就是,此ArrayMap是在system_process进程中,并非在com.android.settings的进程中,delete之后,如果执行一次GC(或者我们显示地对system_process调用一次GC),那么对象就会被回收。引用的settings进程中的Activity也会被回收释放。

  所以在此案例中,内存泄漏不存在。

  因此在遇到内存泄露的情况时,还是需要根据代码来具体分析,GC回收的时机不确定,可通过显示地调用GC来回收对象,排除某些内存泄露的可能。当然跨进程时,要调用正确进程的GC来回收。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏乐沙弥的世界

Linux (RHEL 5.4)下安装 Oracle 10g R2

如转载,请注明出处:http://blog.csdn.net/robinson_0612/archive/2010/03/30/5431428.aspx ...

561
来自专栏北京马哥教育

Varnish 4.0 实战

简介 Varnish 是一款高性能且开源的反向代理服务器和 HTTP 加速器,其采用全新的软件体系机构,和现在的硬件体系紧密配合,与传统的 squid 相比,v...

3294
来自专栏猿天地

Spring Cloud Gateway 之 AddRequestHeader GatewayFilter Factory

今天我们来学习下GatewayFilter Factory,中文解释就是过滤器工厂。

1362
来自专栏乐百川的学习频道

安装和使用MongoDB

MongoDB是一个著名的NoSQL数据库,顾名思义就是不使用SQL的数据库,目前在很多场景都有使用。如果你不喜欢使用笨拙的各种SQL数据库,可以尝试使用一下M...

7776
来自专栏美团技术团队

Linux与JVM的内存关系分析

引言 在一些物理内存为8g的服务器上,主要运行一个Java服务,系统内存分配如下:Java服务的JVM堆大小设置为6g,一个监控进程占用大约600m,Linux...

6307
来自专栏C/C++基础

Linux命令(14)——df命令

用于查看Linux文件系统的磁盘空间占用情况。可以利用该命令来获取硬盘被占用了多少空间,以及剩余空间等信息。

1248
来自专栏芋道源码1024

分布式事务 TCC-Transaction 源码分析 —— 事务恢复

1. 概述 本文分享 TCC 恢复。主要涉及如下二个 package 路径下的类: org.mengyun.tcctransaction.recover Rec...

3533
来自专栏微信终端开发团队的专栏

Android 内存申请分析

做内存方面优化的工作过程,除了关注内存的申请量以及 GC 的情况之外,我们经常需要想方法找出是那些对象占用了大量内存,以及他们是如何导致 GC 的,这意味着我们...

3030
来自专栏平凡文摘

Java程序员最常用的Linux命令

1654
来自专栏Spark生态圈

[spark] 从spark-submit开始解析整个任务调度流程

spark应用程序可以以Client模式和Cluster启动,区别在于Client模式下的Driver是在执行spark-submit命令节点上启动的,而Clu...

3273

扫码关注云+社区