一次内存泄漏导致的OOM实例分析和解决

原创 2016年05月31日 13:27:15

一: 问题描述

   在B公司项目中的一个界面,ViewPager展示20多张照片,进行一些操作比如:左右滑动照片,点击编辑问题,退出问题详情再进去等,会导致问题详情的照片ViewPager部分照片显示不出,甚至直接OOM崩溃。

 

二:解决方法

   通过Log查看,发现确实是OOM,导致APP崩溃。(只不过ImageLoader框架作了简单Cash 以至于有时不会崩溃,只是加载不出图片)    


第一步,获取设备的heapSzie,如下:


 

ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
int heapSize = manager.getMemoryClass();
int maxHeapSize = manager.getLargeMemoryClass();  // manafest.xml   android:largeHeap="true"

 

   heapSize是设备分配给app的最大堆内存   maxHeapSize 是当配置了android:largeHeap="true" 才有的最大堆内存,一般是heapSize的2-3倍

以HTC ONE为例,两个值分别是: 192M和512M,之前这个OOM解决办法是设置 大堆内存,才避免了OOM,现在关闭这个设置,那就是192M为上限


第二步,尝试复现问题 ,造成OOM无非两个原因  要么是加载较大资源一般是图片,直接导致内存超过了heapSize, 要么是某些Activity(Fragment)有内存泄漏,多次创建没有回收导致超过heapSize。在本例中,因为加载图片用的ImageLoader这个成熟框架,并且在详情界面加载30张图片来回滑动也没有OOM,heapSize一直稳定在120M左右。所以考虑是内存泄漏,尝试点击编辑问题并且返回,然后退出问题详情界面  多次操作,复现了该问题:

  内存上升到171M不再下降,并且此时照片已经加载不出来了,显示默认图。


   第三步,用AndroidStudio自带的内存分析工具分析,点击Dump Java Heap:

会在代码区  生成当前时间点的 .hprof格式文件,里面当前的每个对象 内存占用情况,我们现在怀疑ViewDefectPhotoActivity 可能内存泄漏  看一下:ViewDefectPhotoActivity 确实占用了很高的内存  而且有8个实例化对象,足以证明它有内存泄漏,随便点击其中一个,发现都和EditDefectActivity的内部类 ShowEditDefectHelper有关。而且ShowEditDefectHelpe前面带有 黄蓝三角树 这个图标表示,他可以被GC访问到,也就是无法回收


          接下来看看ShowEditDefectHelper这个对象持有什么引用,右键点击 Go To Instance:

 

       发现这个内部类也被实例化多次,即使不在编辑界面 ,他也没有被回收。随便点击一个,发现属于EventBus的引用  ,并且EventBus带有黄蓝图标,那么问题就大概找到了,因为EventBus一直持有这个内部类的引用,导致这个内部类无法被回收,而这个内部类持有ViewDefectPhotoActivity引用,导致ViewDefectPhotoActivity无法被回收  这个界面有很多图片资源  当实例化7,8次之后  出现了OOM。

     看下是不是EventBus是不是没有解绑定,在ShowEditDefecthelper中:

 

    红框是旧代码,这一句是个低级错误   this指向了CancelResult.AsyncCancelCallback这个匿名内部类,导致ShowEditDefecthelper注册的EvnetBus无法被解绑定!所以问题正确复现方式是,在问题详情界面加载很多图片,然后点击编辑问题马上取消,不要跳到编辑界面,多次操作就OOM。当问题照片很多的时候,获取编辑问题需要时间,就有了取消的机会,这也就造成是照片过多加载导致OOM的错像!

     改成上图这句注释代码,问题解决!类似的还有广播注册等等,一定要注意确保正确的解除绑定!

ImageView的scaleType设置不当,导致使用Glide时出现OOM

转载地址:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0606/3002.html 来源 http://www.lich...
  • lijinhua7602
  • lijinhua7602
  • 2015年06月14日 22:27
  • 4867

Android内存泄漏解决方案(OOM)

为什么会有内存泄漏?一个不会被使用的对象,因为另一个正在使用的对象持有该对象的引用,导致它不能正常被回收,而停留在堆内存中,内存泄漏就产生了Android系统为每个应用分配的内存是有限的,内存泄漏会使...
  • imuhao
  • imuhao
  • 2016年06月16日 19:25
  • 4550

Android内存泄漏产生的原因以及解决方案(OOM)

为什么会有内存泄漏? 一个不会被使用的对象,因为另一个正在使用的对象持有该对象的引用,导致它不能正常被回收,而停留在堆内存中,内存泄漏就产生了 Android系统为每个应用分配的内存是有限的,内存...
  • u012181885
  • u012181885
  • 2016年09月04日 15:48
  • 564

内存溢出(OOM)and内存泄露---及其解决

那么问题来了什么是内存溢出out of memory?(OOM)已有数据超出其分配内存所能存储的范围 比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。什么是内存泄露me...
  • TaooLee
  • TaooLee
  • 2015年11月08日 14:56
  • 2365

关于ViewPager加载多个导致OOM内存溢出的问题。

其实,暂时还没有解决方案。
  • parcool
  • parcool
  • 2014年11月06日 17:36
  • 3409

内存溢出(oom)和内存泄漏(leak)

一、概念介绍: 1、内存溢出 out of memory: 是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了lon...
  • juelingfeng
  • juelingfeng
  • 2017年01月06日 14:55
  • 526

【Android性能优化】内存泄露和内存溢出(OOM)的引发原因及优化方案

一、内存泄露 垃圾回收器无法回收原本应该被回收的对象,这个对象就引发了内存泄露。 内存泄露的危害: (1)过多的内存泄露最终会导致内存溢出(OOM) (2)内存泄露导致可用内存不足,会触发频繁GC,...
  • mxm691292118
  • mxm691292118
  • 2016年03月30日 22:21
  • 13735

内存泄露或内存碎片问题的解决

内存泄露    内存泄露通常sh
  • fengliang191
  • fengliang191
  • 2014年07月04日 16:50
  • 2699

用正确的姿势来说说Android上的内存泄漏问题

用正确的姿势来说说Android上的内存泄漏问题相信大家对[App的内存管理][6]都是相当关心的,在项目上线前的几天时间也会借助相关工具突击下严重的泄漏问题;针对内存泄漏先提出几个疑问 什么是内存泄...
  • hongbingfans
  • hongbingfans
  • 2016年07月12日 19:13
  • 920

内存泄漏导致内存溢出(OOM)

开发中遇到这样一个bug,调整之前做的一个意见反馈页面布局,输入框中限制字数200字,超过时自动删除不显示。页面截图: 如图所示是自定义了一个可监听并限制输入字数的EditText,贴上代码...
  • cunjicsdn
  • cunjicsdn
  • 2016年09月26日 11:03
  • 730
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一次内存泄漏导致的OOM实例分析和解决
举报原因:
原因补充:

(最多只允许输入30个字)