LeakCanary:Android和Java的内存泄漏检测库。
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崩溃
在正方形寄存器中,我们在位图缓存上绘制客户的签名。这个位图是设备屏幕的大小,我们在创建它时发生了大量的内存不足(OOM)崩溃。
我们尝试了几种方法,但都没有解决问题:
- 使用Bitmap.Config.ALPHA_8(签名不需要颜色)。
- 捕获OutOfMemoryError,触发GC并重试几次(灵感来自GCUtils)。
- 我们没有想过从Java堆中分配位图。我们还不幸运。
我们看错了
位图大小不是问题。当内存几乎满的时候,OOM可以发生在任何地方。在创建大对象(如位图)的地方,这种情况更容易发生。OOM是一个更深层次问题的征兆:内存泄漏。
什么是内存泄漏?
某些对象的寿命有限。当他们的工作完成后,他们会被垃圾收集起来。如果一个引用链在一个对象的预期生存期结束后将其保存在内存中,这将导致内存泄漏。当这些漏洞累积起来时,应用程序的内存就会耗尽。
例如,在调用Activity.onDestroy()
时,其视图层次结构及其关联的位图都应该是可垃圾回收的。如果在后台运行的线程持有对活动的引用,则无法回收相应的内存。这最终导致OutOfMemoryError崩溃。
定位内存泄漏
查找内存泄漏是一个手动过程,以下是关键步骤:
- 通过Bugsnag、Crashlytics或开发人员控制台了解OutOfMemoryError崩溃。
- 试图重现问题。您可能需要购买、借用或窃取发生崩溃的特定设备。(并非所有设备都会出现泄漏!)您还需要弄清楚是什么导航序列触发了泄漏,可能是暴力造成的。
- 当OOM发生时转储堆。
- 用MAT或YourKit在垃圾堆周围搜索,找到一个应该被垃圾收集的对象。
- 从强引用计算最短路径。
- 找出路径中不应存在的引用,并修复内存泄漏。
如果一个库可以在你到达OOM之前完成所有这些,让你专注于修复内存泄漏呢?
引进LeakCanary
LeakCanary是一个开源Java库,用于检测调试版本中的内存泄漏。
让我们看一个猫的例子:
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
实例并为其指定要监视的对象:
// We expect schrodingerCat to be gone soon (or not), let's watch it.
refWatcher.watch(schrodingerCat);
当检测到泄漏时,您会自动获得一个泄漏跟踪:
* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance
我们知道你正忙着写功能,所以我们很容易设置。只需一行代码,LeakCanary就会自动检测活动泄漏:
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}
}
你会得到一个通知和一个很好的开箱即用的显示:
结论
启用LeakCanary后,我们发现并修复了应用程序中的许多内存泄漏。我们甚至在Android SDK中发现了一些漏洞。
结果是惊人的。现在,OOM错误导致的崩溃减少了94%。
如果你想消除OOM崩溃,现在就安装LeakCanary!
除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/1239.html
暂无评论