LeakCanary
遵循以下四步去解决内存泄漏:
- 找到内存泄漏踪迹
- 缩小疑似的引用范围
- 找到导致泄漏的引用
- 修复泄漏
LeakCanary
可以完成前两步
LeakCanary
的使用
引入 module/build.gradle
中添加以下内容即可
1 | debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7' |
LeakCanary
hook
了Android
生命周期,从而实现了内存泄露的自动检测,当Activity
和Fragment
被销毁需要被回收的时候,这些销毁的对象被传递给了ObjectWatcher
, ObjectWatcher
持有这些对象的弱引用,LeakCanary
自动检测如下对象是否发生泄露.
- 已经销毁的
Activity
实例 - 已经销毁的
Fragment
实例 - 已经销毁的小块
View
实例 - 已经清空的
ViewModel
实例
- 以├─开头的行代表java对象,
- 以│ ↓ 开头的行代表指向下一行java对象的引用
1 | ┬─── |
PathClassLoader
有一个runtimeInternalObjects
属性,这是一个对象数组 这个数组的第43个引用指向了Utils
类 ╰→开头的行指向了泄露对象, 这个Utils
有一个静态helper
指向了一个泄露的对象。
例子
1 | class ExampleApplication : Application() { |
1 | LeakCanary提供了如下的泄露路径 |
来分析这个路径:
这个
FontsContract
类是一个系统类,拥有一个sContext
静态属性,指向了ExampleApplication
对象,这个对象里有一个leakedViews
指向了一个ArrayList
,里面有个对象引用TextView
,里面持有一个Context
指向了一个已经destory
的activity
在
android app
中,Application
是一个不会被回收的单例,
找到造成此次泄露的引用
根据之前的分析,找到导致此次泄露的引用是因为Application
持有了已经销毁的activity
中的View