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. Android MultiDex

    出现的原因: 当Android系统安装一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt.DexOpt的执行过程是在第一次加载Dex文件的时候执行的.这个过程会生 ...

  2. 洛谷 P1991 无线通讯网 Label:最小生成树 || 二分

    题目描述 国防部计划用无线网络连接若干个边防哨所.2 种不同的通讯技术用来搭建无线网络: 每个边防哨所都要配备无线电收发器:有一些哨所还可以增配卫星电话. 任意两个配备了一条卫星电话线路的哨所(两边都 ...

  3. [BZOJ2793][Poi2012]Vouchers

    2793: [Poi2012]Vouchers Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 316  Solved: 148[Submit][Stat ...

  4. iOS 开发小结

    一,经历 1> 在编写以前有过的类似的新功能时,如果以前的开发人员没有写明明确的注释和开发需求,一定要仔细阅读所有代码,每一句代码都有它存在的意义. 2> 例如,只以为是[self.ful ...

  5. (转)如何将数据库从SQL Server迁移到MySQL

    一.迁移Database Schema. 首 先使用Sybase Powerdesigner的逆向工程功能,逆向出SQL Server数据库的物理模型.具体操作是在Powerdesigner中选择“F ...

  6. R中创建not-yet-evaluated对象

    create not-yet-evaluated object在R中创建 not-yet-evaluated(就是some code we will evaluated later!!)对象;然后执行 ...

  7. Java_Eclipse_Maven插件部署

    方法一:在线; Eclipse-help-Install New Software 1.下载地址: m2e - http://download.eclipse.org/technology/m2e/r ...

  8. java中用过滤器解决字符编码问题

    java的web程序经常出现中文乱码的问题,用一个实现了Filter接口的过滤器类可以较好地解决这个问题. 方式一 EncodingFilter import java.io.IOException; ...

  9. Python之路(二)

    (1)python的内置函数(BIF) python3中内置了70多个BIF,常用的几个有: list():创建一个新的空列表. range():输入次数参数,返回一个迭代固定次数的迭代器. enum ...

  10. 关于Jquery获取Table中td内的内容

    $(this).children().eq(1).text()获取的是显示的值$(this).children().eq(1).html()获取的是<td></td>之间的所有 ...