核心:
- 0 引用 + 内部类
- 1 概述
- 2 使用
- 3 原理
- 4 总结
https://github.com/square/leakcanary
https://square.github.io/leakcanary/
“A small leak will sink a great ship.” - Benjamin Franklin
0 引用 + 内部类
0.1 引用
什么是引用?
引用可以用指针的概念来理解
A B 两个对象 , A 内部可以调用 B 的方法就称,A内有B的引用
即 A 内有个B的指针,可以访问到B
0.1.1 强引用
A a = new A();
a 就是指向 new出对象的一个强引用
a = null
此时 new 出的对象就不再被a强引用
进入垃圾回收流程
0.1.2 软引用
内存不够的时候,会回收发现的软引用
此时的软引用可以被回收
回收后会加入到关联到引用队列
信号——内存不够
0.1.3 弱引用
发生gc就会回收
弱引用的对象
并且将回收的对象加入队列
0.1.4 幻引用
随时会被回收
public class Refer {
@Test
public void main() throws Exception {
Object wfOb = new Object();
Object sfOb = new Object();
Object pfOb = new Object();
ReferenceQueue<Object> wfQ = new ReferenceQueue<>();
ReferenceQueue<Object> sfQ = new ReferenceQueue<>();
ReferenceQueue<Object> pfQ = new ReferenceQueue<>();
WeakReference weakReference = new WeakReference<>(wfOb, wfQ);
SoftReference softReference = new SoftReference<>(sfOb, sfQ);
PhantomReference phantomReference = new PhantomReference<>(pfOb, pfQ);
System.out.println("softReference");
System.out.println(softReference.get() != null);
sfOb = null;
System.gc();
System.out.println(softReference.get() != null);
// System.out.println(sfQ.poll().get() != null);
System.out.println("weakReference");
System.out.println(weakReference.get() != null);
wfOb = null;
System.gc();
System.out.println(weakReference.get() != null);
System.out.println(wfQ.poll().get() != null);
System.out.println("phantomReference");
System.out.println(phantomReference.get() != null);
pfOb = null;
System.gc();
System.out.println(phantomReference.get() != null);
System.out.println(pfQ.poll().get() != null);
}
}
![](https://img.haomeiwen.com/i19741117/69b0d5d237d2e08a.png)
0.2 内部类
放在类的内部(成员内部类)
方法的内部(局部内部类)
方法的参数内(匿名内部类)
静态内部类
非静态的内部类可以访问到外部类的成员或方法
说明
内部类中存有外部类的引用
此时需要提防由于内部类的引用存在导致的内存泄漏
1 概述
雪崩时没有一片雪花是无辜的
遇到生命周期敏感的对象
谨慎处理赋值和引用关系
2 使用
添加依赖
dependencies {
// debugImplementation because LeakCanary should only run in debug builds.
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
}
当泄漏对象达到 threshold 时将会有提示
![](https://img.haomeiwen.com/i19741117/9c138b177abbee36.png)
3 原理
利用 WeakReference 监控对象生命周期
如果 weakReference 引用的对象被回收,就可以在关联的引用队列中找到其引用
当我们监控的Object比如 Activity 执行了 Destroy 后
就又一个弱引用指向他,当指定时间都没有在队列中发现其时,意味着发生了泄漏
官方文档:
https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/
![](https://img.haomeiwen.com/i19741117/cc8b4fc6128e0410.png)
4 总结
分析内存泄漏关键在于看 生命周期长短
短命对象被长寿对象引用,短命对象应该被回收的时候,却被引用
导致了内存泄漏
生命周期长短:
-
线程造成生命周期长
-
handler message的delay发送,存在 messageQueue内
-
单例造成,单例的生命周期往往和进程同步,单例中引用的都不能被释放
网友评论