以前用eclipse的时候,我们采用的是DDMS和MAT,不仅使用步骤复杂繁琐,而且要手动排查内存泄漏的位置,操作起来比较麻烦。后来随着Android studio的潮流,我也抛弃了eclipse加入了AS。

Android Studio也开始支持自动进行内存泄漏检查,并且操作起来也比较方便。

我们大家都知道,系统是不可能将所有的内存都分配给我们的应用程序的。每个程序都会有可使用的内存上限,这被称为堆大小(Heap Size)。不同的手机,堆大小也不尽相同,随着现在硬件设备不断提高,堆大小也提升了。如果大家想要知道自己手机的堆大小是多少,可以调用如下代码:

ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
int heapSize = manager.getMemoryClass();

结果是以MB为单位进行返回的,我们在开发应用程序时所使用的内存不能超出这个限制,否则就会出现OutOfMemoryError。因此,比如说我们的程序中需要缓存一些数据,就可以根据堆大小来决定缓存数据的容量。

下面介绍下采用Android Studio Monitor来检测内存泄漏,栗子如下:

每次启动MainActivity中时都会调用一个线程,然后这个线程会执行runnable的run方法 由于Runnable是一个匿名内部对象 所以握有MainActivity的引用,因此 
连续启动MainActivity 4次,最后退出。按照常理来说,MainActivity会被销毁回收,可实际可能并不是这样。

打开Android Studio,编译代码,在模拟器或者真机上运行App,在Android Monitor下点击Monitor对应的Tab,进入如下界面

 

在Memory一栏中,可以观察不同时间App内存的动态使用情况,点击可以手动触发GC,点击可以进入HPROF Viewer界面,查看Java的Heap,切换到Package Tree View,方便查看,点击Analyzer Task,Android Monitor就可以为我们自动分析泄漏的Activity,如下图

Reference Tree代表指向该实例的引用,可以从这里面查看内存泄漏的原因,Shallow Size指的是该对象本身占用内存的大小,Retained Size代表该对象被释放后,垃圾回收器能回收的内存总和。

看上图,左边是内存中的对象,右边还存在4个MainActivity实例,我们明明是全部退出的,怎么还存在,这表明出现了内存泄露。

我们查看Reference Tree, 看到 this$0引用了这个MainActivity而this$0是表示内部类的意思,也就是一个内部类引用了MainActivity 而 this$0又被 target引用, target是一个线程。内存泄漏的原因就是MainActivity被内部类引用,而内部类又被线程使用,因此无法释放造成内存泄露。
 

内存泄漏产生的原因在Android中大致分为以下几种:

1.static变量引起的内存泄漏 
因为static变量的生命周期是在类加载时开始 类卸载时结束,也就是说static变量是在程序进程死亡时才释放,如果在static变量中 引用了Activity 那么 这个Activity由于被引用,便会随static变量的生命周期一样,一直无法被释放,造成内存泄漏。

解决办法: 
在Activity被静态变量引用时,使用 getApplicationContext 因为Application生命周期从程序开始到结束,和static变量的一样。

2.线程造成的内存泄漏 
类似于上述例子中的情况,线程执行时间很长,及时Activity跳出还会执行,因为线程或者Runnable是Acticvity内部类,因此握有Activity的实例(因为创建内部类必须依靠外部类),因此造成Activity无法释放。 
AsyncTask 有线程池,问题更严重

解决办法: 
1.合理安排线程执行的时间,控制线程在Activity结束前结束。 
2.将内部类改为静态内部类,并使用弱引用WeakReference来保存Activity实例 因为弱引用 只要GC发现了 就会回收它 ,因此可尽快回收

3.BitMap占用过多内存 
bitmap的解析需要占用内存,但是内存只提供8M的空间给BitMap,如果图片过多,并且没有及时 recycle bitmap 那么就会造成内存溢出。

解决办法: 
及时recycle 压缩图片之后加载图片

4.资源未被及时关闭造成的内存泄漏 
比如一些Cursor 没有及时close 会保存有Activity的引用,导致内存泄漏

解决办法: 
在onDestory方法中及时 close即可

5.Handler的使用造成的内存泄漏 
由于在Handler的使用中,handler会发送message对象到 MessageQueue中 然后 Looper会轮询MessageQueue 然后取出Message执行,但是如果一个Message长时间没被取出执行,那么由于 Message中有 Handler的引用,而 Handler 一般来说也是内部类对象,Message引用 Handler ,Handler引用 Activity 这样 使得 Activity无法回收。

解决办法: 
依旧使用 静态内部类+弱引用的方式 可解决

6.带参数的单例

如果我们在在调用Singleton的getInstance()方法时传入了Activity。那么当instance没有释放时,这个Activity会一直存在。因此造成内存泄露。
解决方法:

可以将new Singleton(context)改为new Singleton(context.getApplicationContext())即可,这样便和传入的Activity没关系了。

Android studio 分析内存泄漏的更多相关文章

  1. 使用 Android Studio 检测内存泄漏与解决内存泄漏问题

    本文在腾讯技术推文上 修改 发布. http://wetest.qq.com/lab/view/63.html?from=ads_test2_qqtips&sessionUserType=BF ...

  2. Android Studio +MAT 分析内存泄漏实战

    对于内存泄漏,在Android中如果不注意的话,还是很容易出现的,尤其是在Activity中,比较容易出现,下面我就说下自己是如何查找内存泄露的. 首先什么是内存泄漏? 内存泄漏就是一些已经不使用的对 ...

  3. 系统剖析Android中的内存泄漏

    [转发]作为Android开发人员,我们或多或少都听说过内存泄漏.那么何为内存泄漏,Android中的内存泄漏又是什么样子的呢,本文将简单概括的进行一些总结. 关于内存泄露的定义,我可以理解成这样 没 ...

  4. 使用新版Android Studio检测内存泄露和性能

    内存泄露,是Android开发者最头疼的事.可能一处小小的内存泄露,都可能是毁于千里之堤的蚁穴.  怎么才能检测内存泄露呢?网上教程非常多,不过很多都是使用Eclipse检测的, 其实1.3版本以后的 ...

  5. 【转】如何使用MAT分析内存泄漏

    原文链接:http://www.lightskystreet.com/2015/09/01/mat_usage/ MAT - Memory Analyzer Tool 使用进阶 Sep 1, 2015 ...

  6. Atitit.提升稳定性-----分析内存泄漏PermGen OOM跟解决之道...java

    Atitit.提升稳定性-----分析内存泄漏PermGen OOM跟解决之道...java 1. 内存区域的划分 1 2. PermGen内存溢出深入分析 1 3. PermGen OOM原因总结 ...

  7. 使用Memory Analyzer tool(MAT)分析内存泄漏(二)

    转载自:http://www.blogjava.net/rosen/archive/2010/06/13/323522.html 前言的前言 写blog就是好,在大前提下可以想说什么写什么,不像投稿那 ...

  8. 使用Memory Analyzer tool(MAT)分析内存泄漏

    前言的前言 写blog就是好,在大前提下可以想说什么写什么,不像投稿那么字字斟酌.上周末回了趟成都办事,所以本文来迟了.K117从达州经由达成线往成都方向走的时候,发现铁路边有条河,尽管我现在也不知道 ...

  9. 使用androidstudio 分析内存泄漏

    分析内存泄漏 http://www.jianshu.com/p/c49f778e7acf

随机推荐

  1. VC++ 6.0远程调试配置

    VC开发环境之所以提供远程调试的能力,是因为有些情况下单机调试会让你崩溃掉...比如,调试GUI程序的WM_PAINT消息,因为要单步调试,所以调试器会对界面的重绘产生副作用(Heisenberg不确 ...

  2. 【原】相煎何太急——input的blur事件与button的click事件

    先来一段引子,最近在写手机h5页面,主要是一些登陆注册方面的,最绕不开的就是表单元素. 我想实现的是:在输入框后边有一个删除图标,当输入东西的时候触发事件,显示删除图标,点击该图标会删除之前输入的内容 ...

  3. CheckedComboBoxEdit 重置初始化值的方法

    CheckedComboBoxEdit ccbgb; ccbgb绑定方式ccbgb .Properties .DataSource =数据集; ccbgb.Properties.DisplayMemb ...

  4. linux yum下载RPM包后再安装LAMP环境

    1.下载yum插件 yum-downloadonly,实现只下载软件包的功能. yum install yum-downloadonly 或者 yum install yum install yum- ...

  5. mssql2000 身份证号码验证

    CREATE VIEW thisDate --返回当前日期,因为自定义函数中不能使用GETDATE() AS ),) AS aDate )) /*mssql2000 返回值=0,身份证校验正确 1:位 ...

  6. mysql 允许远程访问

    原来装mysql数据库的时候就想,这个只要在本地访问就可以了,没有必要让远程访问.可是,今天想把数据放到远程的机器上,却发现,不是简单的将sql语句(指导出的语句)执行一遍就行了,对于那些自增的字段, ...

  7. 移植milo的全局光照渲染器代码

    测试flascc的性能优化程度,http://bbs.9ria.com/thread-162705-1-1.html . 可以对比下猫粮的http://bbs.9ria.com/thread-5820 ...

  8. Percona 5.7安装

    一.从官网下载Percona5.7 地址:https://www.percona.com/downloads/Percona-Server-5.7/LATEST/ 需要注意是服务器的版本.我这里选择的 ...

  9. 给员工授予svn相关权限

    步骤: 了解:地址2.4是代码svn.地址2.16是文档svn 以授予 SVN地址是:http://172.16.2.16/svn/SystemNetworkBU  权限组为mam_group,是只读 ...

  10. 使用Word发布文章到 WordPress 博客

    使用Word发布文章到 WordPress 博客 我们都知道,WordPress 自带的编辑器功能比较弱,而使用 Word 编辑文档却功能强大.其实我们使用 Word 编辑好的文档也是可以直接发布到 ...