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来回收。
Android - 看似内存泄漏,实则不是,记一次内存泄漏的案例分析的更多相关文章
- 深入浅出 - Android系统移植与平台开发(十) - led HAL简单设计案例分析
作者:唐老师,华清远见嵌入式学院讲师. 通过前两节HAL框架分析和JNI概述,我们对Android提供的Stub HAL有了比较详细的了解了,下面我们来看下led的实例,写驱动点亮led灯,就如同写程 ...
- 记一次Java调优案例分析
上周,一同学给我发来,他们那里的案例 一看就是新生代产生过多对象,肯定是批量或者循环操作导致的,导致新生代一直在进行回收导致. 如果是老生代出现这样的问题,大部分情况下是列表或者集合导致的. 因此我们 ...
- Android内存管理(5)*官方教程:Logcat内存日志各字段含义,查看当前内存快照,跟踪记录内存分配,用adb查看内存情况时各行列的含义,捕获内存快照的3种方法,如何让程序暴漏内存泄漏的方法
Investigating Your RAM Usage In this document Interpreting Log Messages 内存分析日志中各消息的含 ...
- Java中关于内存泄漏出现的原因以及如何避免内存泄漏
转账自:http://blog.csdn.net/wtt945482445/article/details/52483944 Java 内存分配策略 Java 程序运行时的内存分配策略有三种,分别是静 ...
- Android内存解析(一)—从Linux系统内存逐步认识Android应用内存
总述 Android应用程序被限制了内存使用上限,一般为16M或24M(具体看系统设置),当应用的使用内存超过这个上限时,就会被系统认为内存泄漏,被kill掉.所以在android开发时,管理好内存的 ...
- 九、Android学习笔记_ Android开发中使用软引用和弱引用防止内存溢出
在<Effective Java 2nd Edition>中,第6条“消除过期的对象引用”提到,虽然Java有 垃圾回收机制,但是只要是自己管理的内存,就应该警惕内存泄露的问题,例如的对象 ...
- Android开发中如何解决加载大图片时内存溢出的问题
Android开发中如何解决加载大图片时内存溢出的问题 在Android开发过程中,我们经常会遇到加载的图片过大导致内存溢出的问题,其实类似这样的问题已经屡见不鲜了,下面将一些好的解决方案分享给 ...
- Android高效内存:让图片占用尽可能少的内存
Android高效内存:让图片占用尽可能少的内存 一.让你的图片最小化 1.1 大图小图内存使用情况对比 大图:440 * 336 小图:220 * 168 小图的高宽都是大图的1/2--> ...
- Java内存泄漏分析系列之五:常见的Thread Dump日志案例分析
原文地址:http://www.javatang.com 症状及解决方案 下面列出几种常见的症状即对应的解决方案: CPU占用率很高,响应很慢 按照<Java内存泄漏分析系列之一:使用jstac ...
随机推荐
- 21.Longest Palindromic Substring(最长回文子串)
Level: Medium 题目描述: Given a string s, find the longest palindromic substring in s. You may assume ...
- ftp 添加用户及修改用户目录
添加用户 : useradd 用户名 -s /sbin/nologin //限定用户test不能telnet,只能ftp; usermod -s /sbin/bash 用户名 //用户恢复正常 ;该账 ...
- Luogu P4404 [JSOI2010]缓存交换 优先队列
细节题?...调了半天.... 可以发现,每一次从缓存中删除的主存一定是下次访问最晚的,可以用优先队列来处理...还有要离散化...还有链表末尾要多建一些点...否则会死的很惨... #include ...
- 解决mac下ssh空闲一段时间自动断开的问题
之前在公司就遇到过这种问题,使用ssh登录linux服务器后,在后台放置一段时间,会发现会自动断开,解决的方法很简单: vim /etc/ssh/ssh_config 添加这2句即可 ServerAl ...
- stark组件之创建
stark组件之需求 仿照Django中的admin , 开发了自己的stark组件,实现类似数据库客户端的功能,对数据进行增删改查 . stark之创建 1.在项目中 创建stark应用,app01 ...
- JavaScript trim 实现去除字符串首尾指定字符的简单方法
String.prototype.trim = function (char, type) { if (char) { if (type == 'left') { return this.replac ...
- about rand and reflect
select regexp_replace(reflect("java.util.UUID", "randomUUID"), "-", &q ...
- Alibaba Java Coding Guidelines 安装(eclipse)并简单使用
源码地址:https://github.com/alibaba/p3c 1.安装 第1步.help >> Instakll New Software... 第2步.在Work with中输 ...
- spring boot 系统启动时运行代码(1)-@PostConstruct
Application.java import org.springframework.boot.SpringApplication; import org.springframework.boot. ...
- 配置sudo访问
具体操作步骤 1.首先我们建立一个账户,设置密码 [root@VM_0_13_centos home]# useradd 123 [root@VM_0_13_centos home]# passwd ...