LeakCanary:检测Android中的内存泄漏
16lz
2021-01-26
Square开源了一个内存泄露自动探测神器——LeakCanary,它是一个Android和Java的内存泄露检测库,可以大幅度减少了开发中遇到的OOM问题,对于开发者来说,无疑是个福音,下面对该库的使用进行简单的介绍。
一 什么是内存泄漏:
有些对象只有有限的生命周期。当它们的任务完成之后,它们将被垃圾回收。如果在对象的生命周期本该结束的时候,这个对象还被一系列的引用,这就会导致内存泄漏。随着泄漏的累积,app将消耗完内存。
比如,在Activity.onDestroy()被调用之后,view树以及相关的bitmap都应该被垃圾回收。如果一个正在运行的后台线程继续持有这个Activity的引用,那么相关的内存将不会被回收,这最终将导致OutOfMemoryError崩溃。
二 LeakCanary介绍:
一个用于检测Android&Java的内存泄漏检测库
A memory leak detection library for Android and Java.
“A small leak will sink a great ship.” - Benjamin Franklin
小漏不补沉大船。——本杰明 富兰克林
三 DEMO使用:
(1)在build.gradle中添加依赖:
dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2' testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2' }
(2)在Application中初始化Leak:
public class MyApp extends Application { private static MyApp instance; @Override public void onCreate() { super.onCreate(); instance = this; LeakCanary.install(this);//初始化LeakCanary } public static final MyApp getInstance() { return instance; } @Override public void onTerminate() { super.onTerminate(); }}
或者这样初始化:
public class MyApplication extends Application {//在自己的Application中添加如下代码 public static RefWatcher getRefWatcher(Context context) { ExampleApplication application = (MyApplication) context.getApplicationContext(); return application.refWatcher; } private RefWatcher refWatcher; @Override public void onCreate() { super.onCreate(); refWatcher = LeakCanary.install(this); }}
(3)在Activity中制造一个内存泄漏的场景:
MainActivity.java:
public class MainActivity extends AppCompatActivity { public static MainActivity instance = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); instance = this;//创建一个静态对象instance,保持其对当前activity的引用; findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(); intent.setClass(MainActivity.this, SecondActivity.class); MainActivity.this.startActivity(intent); } }); } @Override protected void onDestroy() { super.onDestroy(); //instance=null; //当要销毁activity的时候,instance并未置空,仍然保持对MainActivity的引用,因此MainActivity不会销毁; }}
SecondActivity.java:
public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { MainActivity.instance.finish();//通过instance关闭MainActivity; } }); }}
在finish的时候会出现内存泄漏,instance仍然保持对activity的引用。
(4)运行结果如下:
然后点击桌面的Leaks图标可以看到:
Leaks指出了内存泄漏的位置是instance。
(5)LeakCanary的检测工作机制:
LeakCanary检测内存泄漏的原理大概分为7个步骤,从创建被关联对象的弱引用、检查该应用是否被清除等。
1、创建:RefWatcher.watch() 创建一个 KeyedWeakReference 到要被监控的对象。2、检查:然后在后台线程检查引用是否被清除,如果没有,调用GC。3、存放:如果引用还是未被清除,把 heap 内存 dump 到 APP 对应的文件系统中的一个 .hprof 文件中。4、解析:在另外一个进程中的 HeapAnalyzerService 有一个 HeapAnalyzer 使用HAHA 解析这个文件。5、定位:得益于唯一的 reference key, HeapAnalyzer 找到 KeyedWeakReference,定位内存泄露。6、计算:HeapAnalyzer 计算 到 GC roots 的最短强引用路径,并确定是否是泄露。如果是的话,建立导致泄露的引用链。7、展示:引用链传递到 APP 进程中的 DisplayLeakService, 并以通知的形式展示出来。
图形路程图如下所示:
参考致谢:
1 利用 LeakCanary 来检查 Android 内存泄漏
2 LeakCanary Github介绍
3 LeakCanary开源项目
更多相关文章
- [置顶] Android内存泄漏查找和解决
- Android系统篇之----Android中的智能指针
- Android——最佳性能实战
- Android(安卓)内存泄露的检查分析方法
- mtk6589显示子系统笔记(一)
- [Android] Android制作自己的依赖库让别人引用(1)
- Handler内存泄漏和解决方法
- Lenovo LePhone S2 不仅运行 Android,也将运行 Windows Phone 7
- Android(安卓)的属性系统