博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LeakCanary: 让内存泄露无所遁形
阅读量:5345 次
发布时间:2019-06-15

本文共 2252 字,大约阅读时间需要 7 分钟。

文章:

github:

本文为的翻译。原文在: 

java.lang.OutOfMemoryError        at android.graphics.Bitmap.nativeCreate(Bitmap.java:-2)        at android.graphics.Bitmap.createBitmap(Bitmap.java:689)        at com.squareup.ui.SignView.createSignatureBitmap(SignView.java:121)

谁也不会喜欢 OutOfMemoryError

在  中, 在签名页面,。 这个 bitmap 的尺寸几乎和屏幕的尺寸一样大,在创建这个 bitmap 对象时,经常会引发 OutOfMemoryError,简称OOM

当时,我们尝试过一些解决方案,但都没解决问题

  • 使用 Bitmap.Config.ALPHA_8 因为,签名仅有黑色。

  • 捕捉 OutOfMemoryError, 尝试 GC 并重试(受  启发)。

  • 我们没想过在 Java heap 内存之外创建 bitmap 。苦逼的我们,那会  还不存在。

路子走错了

其实 bitmap 的尺寸不是真正的问题,当内存吃紧的时候,到处都有可能引发 OO。在创建大对象,比如 bitmap 的时候,更有可能发生。OOM 只是一个表象,更深层次的问题可能是: 内存泄露

什么是内存泄露

一些对象有着有限的生命周期。当这些对象所要做的事情完成了,我们希望他们会被回收掉。但是如果有一系列对这个对象的引用,那么在我们期待这个对象生命周期结束的时候被收回的时候,它是不会被回收的。它还会占用内存,这就造成了内存泄露。持续累加,内存很快被耗尽。

比如,当 Activity.onDestroy 被调用之后,activity 以及它涉及到的 view 和相关的 bitmap 都应该被回收。但是,如果有一个后台线程持有这个 activity 的引用,那么 activity 对应的内存就不能被回收。这最终将会导致内存耗尽,然后因为 OOM 而 crash。

对战内存泄露

排查内存泄露是一个全手工的过程,这在 Raizlabs 的  系列文章中有详细描述。

以下几个关键步骤:

  1. 通过 ,  或者  等统计平台,了解 OutOfMemoryError 情况。

  2. 重现问题。为了重现问题,机型非常重要,因为一些问题只在特定的设备上会出现。为了找到特定的机型,你需要想尽一切办法,你可能需要去买,去借,甚至去偷。 当然,为了确定复现步骤,你需要一遍一遍地去尝试。一切都是非常原始和粗暴的。

  3. 在发生内存泄露的时候,把内存 Dump 出来。具体。

  4. 然后,你需要在  或者  之类的内存分析工具中反复查看,找到那些原本该被回收掉的对象。

  5. 计算这个对象到 GC roots 的最短强引用路径。

  6. 确定引用路径中的哪个引用是不该有的,然后修复问题。

很复杂对吧?

如果有一个类库能在发生 OOM 之前把这些事情全部都搞定,然后你只要修复这些问题就好了,岂不妙哉!

LeakCanary

 是一个检测内存泄露的开源类库。你可以在 debug 包种轻松检测内存泄露。

先看一个例子:

class Cat {}class Box {  Cat hiddenCat;}class Docker {    // 静态变量,将不会被回收,除非加载 Docker 类的 ClassLoader 被回收。    static Box container;}// ...Box box = new Box();// 薛定谔之猫Cat schrodingerCat = new Cat();box.hiddenCat = schrodingerCat;Docker.container = box;

创建一个RefWatcher,监控对象引用情况。

// 我们期待薛定谔之猫很快就会消失(或者不消失),我们监控一下refWatcher.watch(schrodingerCat);

当发现有内存泄露的时候,你会看到一个很漂亮的 leak trace 报告:

  • GC ROOT static Docker.container
  • references Box.hiddenCat
  • leaks Cat instance

我们知道,你很忙,每天都有一大堆需求。所以我们把这个事情弄得很简单,你只需要添加一行代码就行了。然后 LeakCanary 就会自动侦测 activity 的内存泄露了。

public class ExampleApplication extends Application {  @Override public void onCreate() {    super.onCreate();    LeakCanary.install(this);  }}

然后你会在通知栏看到这样很漂亮的一个界面:

结论

使用 LeakCanary 之后,我们修复了我们 APP 中相当多的内存泄露。我们甚至发现了 。

结果是惊艳的,我们减少了 94% 的由 OOM 导致的 crash。

如果你也想消灭 OOM crash,那还犹豫什么,赶快使用 

相关链接:

  • 一个非常简单的 LeakCanary demo: 

转载于:https://www.cnblogs.com/zsw-1993/p/4879098.html

你可能感兴趣的文章
P1452 Beauty Contest 旋转卡壳
查看>>
STM32 Discovery Development On Linux
查看>>
react源码分析 转
查看>>
R语言中abline和lines的区别
查看>>
雅礼集训 Day6
查看>>
请问下./在Linux下是什么意思
查看>>
the evaluation period for visual studio trial edition has ended的解决方法-转发
查看>>
常用的一些前端模板
查看>>
编辑界面组件配置中词典下拉框和词典库下拉框中显示字段 和值字段的区别
查看>>
第九章 结构体与共用体
查看>>
java 使用 引用数据类型(以Scanner、Random模块为例)
查看>>
索引的建立与删除
查看>>
数据库连接池c3p0和dbcp
查看>>
枚举光标当前所在位置的函数包含的指令的数量
查看>>
JavaScript例子1-给网页中所有<p>元素添加onclick事件
查看>>
《Javascript高级程序设计》--读书笔记(一)
查看>>
javaweb学习总结(十四)——JSP原理
查看>>
The V$ Views For Oracle Database 11gR2
查看>>
python安装h5py
查看>>
Keras 中的 verbose 参数
查看>>