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 - 看似内存泄漏,实则不是,记一次内存泄漏的案例分析的更多相关文章

  1. 深入浅出 - Android系统移植与平台开发(十) - led HAL简单设计案例分析

    作者:唐老师,华清远见嵌入式学院讲师. 通过前两节HAL框架分析和JNI概述,我们对Android提供的Stub HAL有了比较详细的了解了,下面我们来看下led的实例,写驱动点亮led灯,就如同写程 ...

  2. 记一次Java调优案例分析

    上周,一同学给我发来,他们那里的案例 一看就是新生代产生过多对象,肯定是批量或者循环操作导致的,导致新生代一直在进行回收导致. 如果是老生代出现这样的问题,大部分情况下是列表或者集合导致的. 因此我们 ...

  3. Android内存管理(5)*官方教程:Logcat内存日志各字段含义,查看当前内存快照,跟踪记录内存分配,用adb查看内存情况时各行列的含义,捕获内存快照的3种方法,如何让程序暴漏内存泄漏的方法

    Investigating Your RAM Usage In this document Interpreting Log Messages                 内存分析日志中各消息的含 ...

  4. Java中关于内存泄漏出现的原因以及如何避免内存泄漏

    转账自:http://blog.csdn.net/wtt945482445/article/details/52483944 Java 内存分配策略 Java 程序运行时的内存分配策略有三种,分别是静 ...

  5. Android内存解析(一)—从Linux系统内存逐步认识Android应用内存

    总述 Android应用程序被限制了内存使用上限,一般为16M或24M(具体看系统设置),当应用的使用内存超过这个上限时,就会被系统认为内存泄漏,被kill掉.所以在android开发时,管理好内存的 ...

  6. 九、Android学习笔记_ Android开发中使用软引用和弱引用防止内存溢出

    在<Effective Java 2nd Edition>中,第6条“消除过期的对象引用”提到,虽然Java有 垃圾回收机制,但是只要是自己管理的内存,就应该警惕内存泄露的问题,例如的对象 ...

  7. Android开发中如何解决加载大图片时内存溢出的问题

    Android开发中如何解决加载大图片时内存溢出的问题    在Android开发过程中,我们经常会遇到加载的图片过大导致内存溢出的问题,其实类似这样的问题已经屡见不鲜了,下面将一些好的解决方案分享给 ...

  8. Android高效内存:让图片占用尽可能少的内存

    Android高效内存:让图片占用尽可能少的内存 一.让你的图片最小化 1.1 大图小图内存使用情况对比 大图:440 * 336    小图:220 * 168 小图的高宽都是大图的1/2--> ...

  9. Java内存泄漏分析系列之五:常见的Thread Dump日志案例分析

    原文地址:http://www.javatang.com 症状及解决方案 下面列出几种常见的症状即对应的解决方案: CPU占用率很高,响应很慢 按照<Java内存泄漏分析系列之一:使用jstac ...

随机推荐

  1. Session_Start

    第一次启动浏览器后,执行了包含Session_Start的方法时触发,当关闭浏览器或者SESSION超时后,自动销毁.

  2. git ignore文件

    创建.gitignore文件来设置git要忽略的文件模式: 官方文件列列表:https://github.com/github/gitignore 1. 所有空行或者以 # 开头的行都会被 Git 忽 ...

  3. 20. js继承的6种方式

    想要继承,就必须要提供个父类(继承谁,提供继承的属性) 一.原型链继承 重点:让新实例的原型等于父类的实例. 特点: 1.实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性.( ...

  4. Android layout布局属性、标签属性总结大全

    RelativeLayout 第一类:属性值为true可false android:layout_centerHrizontal        水平居中 android:layout_centerVe ...

  5. 取消 windows2008 server 禁ping

    windows 2008 server 默认是禁ping的,取消方法如下: 依次打开: 服务器管理器——配置——高级安全windows防火墙——入站规则 找到“文件和打印机共享(回显请求-ICMPv4 ...

  6. Solr学习笔记(2) —— Solr管理索引库

    一.维护索引 1.1 添加/更新文档 1.2 批量导入数据(使用dataimport) 第一步:把mysql的数据驱动.以及dataimport插件依赖的jar包添加到solrcore(collect ...

  7. Oracle外连接与条件的组合

    由于很少使用SQL 92语法,今天写个outer join的时候被搞晕了.参考了一些例子后整理如下.总结,"inter join on"中的条件是对table进行joining的r ...

  8. Java中利用JFrame创建窗体

    1. 一个简单例子: public class Test(){ public static void main(String[] args){ JFrame frame = new JFrame(); ...

  9. MySQL SQL_MODE详解

    http://blog.itpub.net/29773961/viewspace-1813501/

  10. 免费的mysql数据库

    https://blog.csdn.net/kernel_/article/details/53320498