1、引入库
2、操作APP,分析结果
3、如果是复杂的问题可以导出hprof文件到android studio 中继续分析
官方地址:
GitHub - square/leakcanary: A memory leak detection library for Android and Java.
https://github.com/square/leakcanary
#####1、引入库
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.1'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1'
// Optional, if you use support library fragments:
debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.1'
#####2、初始化
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
return;
}
LeakCanary.install(this);
}
}
为了分析内存泄漏,我们写一个简单的单例泄漏的例子:
public class TestManager {
private static TestManager manager;
private Context context;
private TestManager(Context context) {
this.context = context;
}
/**
* 如果传入的context是activity,service的上下文,会导致内存泄漏
* 原因是我们的manger是一个static的静态对象,这个对象的生命周期和整个app的生命周期一样长
* 当activity销毁的时候,我们的这个manger仍然持有者这个activity的context,就会导致activity对象无法被释放回收,就导致了内存泄漏
*/
public static TestManager getInstance(Context context) {
if (manager == null) {
manager = new TestManager(context);
}
return manager;
}
//正确写法
public static TestManager getInstanceSafe(Context context) {
if (manager == null) {
manager = new TestManager(context.getApplicationContext());
}
return manager;
}
}
然后写两个activity,第一个MainActivity跳转到第二个SecondActivity,然后SecondActivity使用有内存泄漏的单例。
public class MainActivity extends AppCompatActivity {
private Button btnJump;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnJump = findViewById(R.id.btn_jump);
btnJump.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this, SecondActivity.class));
}
});
}
}
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
TestManager manager = TestManager.getInstance(this);
}
}
我们启动app,当检测到内存泄漏的时候,会出现一个弹窗,然后手机桌面会出现一个Leaks的图标
点击即可看到内存泄漏的原因:
我们这个内存泄漏的例子比较简单,可以很明显的看出泄漏的原因
有时候我们会遇到比较复杂的内存泄漏情况,这个时候我们可能需要分析一下hprof文件。
我们打开view->Tool Windows->Device File explorer
然后在一堆目录里找到我们的leaks生成的hprof文件:
那个result文件,我没有查到是什么文件,先不管它啦,我们只要双击hprof文件即可。
稍等一会以后会出现一个分析框:
猛地一看好麻烦啊,不要慌,慢慢来,看多了渐渐就懂了。
这些字段的含义分别是:
名称 | 描述 |
---|---|
Class name | 类名 |
Total Count | 该类的实例总数 |
Heap Count | 所选择的堆中该类的实例的数量 |
Sizeof | 单个实例所占空间大小(如果每个实例所占空间大小不一样则显示0) |
Shallow Size | 堆里所有实例大小总和(Heap Count * Sizeof) |
Retained Size | 该类所有实例所支配的内存大小 |
Instance | 具体的实例 |
Reference Tree | 所选实例的引用,以及指向该引用的引用。 |
Depth | GC根节点到所选实例的最短路径的深度 |
Shallow Size | 所选实例的大小 |
Dominating Size | 所选实例所支配的内存大小 |
然后我们看android studio右边有一个Analyzer Tasks按钮,我们点击打开Analyzer Tasks面板,然后点击运行,就可以在Analysis Results面板看到分析结果啦!
Leaked Activities : 有内存泄漏的activities
Duplicated Strings : 重复定义的字符串(一般可以不理会)
以上就是LeakCanary的使用方式啦 (* ̄︶ ̄)
今天是七夕,我相信只要努力,就可以收获美好的爱情。越优秀的人会遇到越优秀的另一半。