Android 内存泄漏是一个十分头疼的事情。LeakCanary是一款开源软件,主要作用是检测 Android APP 内存泄露。比起以前的 MAT 工具,LeakCanary 有着十分强大的功能,能够在程序发送内存泄漏的时候提示通知,而且学习成本低。同时提供 log 和 hrpof 日志,便于开发者解决问题。

1.内存泄露的概念
垃圾回收器无法回收原本应该被回收的对象,这个对象就引发了内存泄露。

2.内存泄露的危害
1)导致用户手机可用内存变少
2)程序出现卡顿
3)导致应用莫名退出
4)应用程序Force Close
5)用户流失

3.内存泄露的工具
1)MAT工具
2)YourKit工具
3)LeakCanary工具

LeakCanary:检测所有的内存泄漏

没人喜欢OutOfMemoryError

在Square的注册过程中,我们在bitmap上 绘制了一个用户的签名。这个bitmap和设备的屏幕大小相当,在创建它的时候,我遇到了相当数量的OOM导致的崩溃。

我们试过了几种方法,没有一个解决了我们的问题:

  • 使用Bitmap.Config.ALPHA_8(签名是不需要颜色的)

  • 捕获OutOfMemoryError,触发垃圾回收然后重试几次(从GCUtils 获得的启发)

  • 我们没有考虑过将bitmap分配在堆内存之外,那个时候Fresco 还没出现。

我们看待问题的方式是不对的

bitmap的大小本身不是什么问题。当内存快要满了的时候,OOM随时随地都可能发生。尤其是在创建大对象的时候更容易发生,比如bitmap。OOM一般代表着更深层次的问题:内存泄漏

什么是内存泄漏?

有些对象只有有限的生命周期。当它们的任务完成之后,它们将被垃圾回收。如果在对象的生命周期本该结束的时候,这个对象还被一系列的引用,这就会导致内存泄漏。随着泄漏的累积,app将消耗完内存。

比如,在Activity.onDestroy()被调用之后,view树以及相关的bitmap都应该被垃圾回收。如果一个正在运行的后台线程继续持有这个Activity的引用,那么相关的内存将不会被回收,这最终将导致OutOfMemoryError崩溃。

寻找内存泄漏

寻找内存泄漏是一个人工操作的过程,在Raizlabs的 Wrangling Dalvik 系列中描述得很清楚。

下面是关键的步骤:

  1. 通过 BugsnagCrashlytics, 或者 Developer Console了解OOM

  2. 主动重现问题。你可能需要买或者借或者偷一个遭遇了崩溃的特殊设备(并不是所有的设备上都会发生内存泄漏!)。你还需要找出是什么串在一起导致了内存泄漏。

  3. 当OOM出现时进行堆转储(dump the heap)(这里介绍了如何做).

  4. 使用MAT或YourKit内存检测工具检测内存的变化,并找出哪个对象应该被垃圾回收;

  5. 从那个对象到GC roots推断最短的强引用路径;

  6. 在路径中找出不存在的引用,并修复memory leak;

要是有一个库可以为你做完所有的事情,让你专注于修复内存泄漏的问题,那该有多好。

LeakCanary介绍

LeakCanary 是一个开源的在debug版本中检测内存泄漏的java库。

让我们来看看一个cait的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Cat {
}
class Box {
  Cat hiddenCat;
}
class Docker {
  static Box container;
}
 
// ...
 
Box box = new Box();
Cat schrodingerCat = new Cat();
box.hiddenCat = schrodingerCat;
Docker.container = box;

创建一个RefWatcher实例,然后给它一个对象让它观察:

1
2
// We expect schrodingerCat to be gone soon (or not), let's watch it.
refWatcher.watch(schrodingerCat);

当检测出泄漏的时候,你会自动得到一个漂亮的泄漏线索:

1
2
3
* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance

我们知道你的时间宝贵,因此我们让它非常好设置。只需几行代码,LeakCanary就能自动检测Activity的泄漏:

1
2
3
4
5
6
public class ExampleApplication extends Application {
  @Override public void onCreate() {
    super.onCreate();
    LeakCanary.install(this);
  }
}

当内存不足时,会有一个通知和良好的展示界面:

结论

在启用LeakCanary之后,我们发现和修复了许多内存泄漏的问题。我们甚至发现了一些Android SDK中的泄漏

结果是非常令人惊奇的,我们现在减少了94%的oom崩溃问题。

如果你想终结OOM崩溃,现在就安装LeakCanary!

Android内存泄露的更多相关文章

  1. (转)专项:Android 内存泄露实践分析

    今天看到一篇关于Android 内存泄露实践分析的文章,感觉不错,讲的还算详细,mark到这里. 原文发表于:Testerhome: 作者:ycwdaaaa ;  原文链接:https://teste ...

  2. android内存泄露调试,Heap,MAT

    三.内存监测工具 DDMS --> Heap 无论怎么小心,想完全避免bad code是不可能的,此时就需要一些工具来帮助我们检查代码中是否存在会造成内存泄漏的地方.Android tools中 ...

  3. Android内存泄露测试

    Android性能测试过程中的一些常用命令: CPU: adb shell top -n | grep "+PackageName 内存: adb shell dumpsys meminfo ...

  4. android内存泄露小谈

    在做android的时候,用的语言大部分情况下都是java.以前最开始做的是编译器开发, 大部分情况都是用c语言和x86与arm架构的汇编,后来接触到ios用的是OC.对比之下, 感觉还是java用起 ...

  5. android 内存泄露之jni local reference table overflow (max=512)

    在android项目中要实现一个需求 为了性能的要求只能用c代码来实现功能. 这样就牺牲了java跨平台性. 通过加载.so的方式,把用c实现的模块集成到app中. android提供jni层,作为一 ...

  6. Android内存泄露---检测工具篇

    内存使用是程序开发无法回避的一个问题.如果我们毫不在意肆意使用,总有一天会为此还账,且痛不欲生...所以应当防患于未然,把内存使用细化到平时的每一行代码中. 内存使用概念较大,本篇先讲对已有app如何 ...

  7. Android内存泄露的原因

    (一)释放对象的引用,误将一个本来生命周期短的对象存放到一个生命周期相对较长的对象中,也称“对象游离“.隐蔽的内部类(Anonymous Inner Class): mHandler = new Ha ...

  8. JVM内存管理概述与android内存泄露分析

    一.内存划分 将内存划分为六大部分,分别是PC寄存器.JAVA虚拟机栈.JAVA堆.方法区.运行时常量池以及本地方法栈. 1.PC寄存器(线程独有):全称是程序计数寄存器,它记载着每一个线程当前运行的 ...

  9. Android 内存泄露测试数据处理--procrank,setprop,getprop(转)

    1.Android内存测试常用的几个概念. VSS--virtual set size 虚拟耗用内存(包含共享库占用的内存)RSS--Resident set size实际使用的物理内存(包含共享库占 ...

随机推荐

  1. (转)Array.prototype.slice.call自解

    很多框架或者库里面都会有这句的使用,最多的还是通过Array.prototype.slice.call(arguments,0)把arguments这个伪数组转换为真正的数组.但为什么可以这么做,却一 ...

  2. Tomcat目录结构及Tomcat Server处理一个http请求的过程

    http://blog.sina.com.cn/s/blog_62cb15980101jh9x.html 1.Tomcat的结构概述     Tomcat服务器是由一系列可配置的组件构成,其核心组件是 ...

  3. Loadrunner脚本录制常见问题整理

    1.LoadRunner录制脚本时为什么不弹出IE浏览器? 当一台主机上安装多个浏览器时,LoadRunner录制脚本经常遇到不能打开浏览器的情况,可以用下面的方法来解决. 启动浏览器,打开Inter ...

  4. 【POJ】2151 Check the difficulty of problems

    http://poj.org/problem?id=2151 题意:T个队伍M条题目,给出每个队伍i的每题能ac的概率p[i][j],求所有队伍至少A掉1题且冠军至少A掉N题的概率(T<=100 ...

  5. 51nod算法马拉松12

    A 第K大区间 不妨考虑二分答案x,则问题转化成计算有多少个区间满足众数出现的次数>=x. 那么这个问题我们使用滑动窗口,枚举右端点,则左端点肯定单调递增,然后维护一个简单的数组就能资瓷添加元素 ...

  6. golang github.com/go-sql-driver/mysql 遇到的数据库,设置库设计不合理的解决方法

    golang github.com/go-sql-driver/mysql 遇到的数据库,设置库设计不合理的解决方法,查询中报了以下这个错 Scan error on column index 2: ...

  7. UVA12532 线段树(单点更新,区间求乘积的正负)

    It’s normal to feel worried and tense the day before a programming contest. To relax, you went out f ...

  8. unity3d插件Daikon Forge GUI 中文教程6-高级控件richtextlabel的使用

    3.5.richtextlabel文本 可以像Word文档一样编辑出多样的内容,图片,字体颜色大小下划线.超链接背景等等. Defaults: 默认字体 默认图集 Blank Texture :空白的 ...

  9. php课程---随机数

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. ActiveMQ: 搭建Broker集群(cluster)

    上一篇介绍了基于Networks of Borkers的2节点HA方案,这一篇继续来折腾Networks of Brokers,当应用规模日渐增长时,2节点的broker可能仍然抗不住访问压力,这时候 ...