一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
1.回顾java的几种引用方式
我们先回顾下java中的引用方式:
强引用
java中普遍存在的引用方式,比如Object object = new Object();
,
只要某个对象有强引用与之关联,JVM必定不会回收这个对象,即使在内存不足的情况下,JVM宁愿抛出OutOfMemory错误也不会回收这种对象
弱引用
private WeakReference<GCOwer> rf = new WeakReference<>(new GCOwer());
只用发生gc就会立马回收
软引用
private SoftReference<GCOwer> rf2 = new SoftReference<>(new GCOwer());
只有内存不足时,
major gc
才能回收
综上所述,由于弱引用不管内存足不足,只要发生gc就会回收,利用此特性我们就可以监听应用是否发生了gc。
2.弱引用监听GC:
public class GCCheck {
private WeakReference<GCOwer> rf = new WeakReference<>(new GCOwer());
public class GCOwer {
@Override
protected void finalize() throws Throwable {
super.finalize();
Log.i("GCCheck", "finalize: app gc occur");
rf = new WeakReference<>(new GCOwer());
}
}
}
复制代码
我们手动构造了一个弱引用实例WeakReference
,持有GCOwer
对象;
然后我们重写GCOwer
类的finalize()
方法;
一旦发生GC就会触发WeakReference
持有的GCOwer
对象被回收,GCOwer
被回收的时候,就会触发其方法finalize()
的调用,我们就可以在该方法中统计gc执行的频率。
需要注意的是,在finalize()
中我们需要重新实例化一个WeakReference<GCOwer>
并赋值给rf
,这是因为之前的弱引用已经被回收,如果要继续监听gc就需要重新创建一个WeakReference<GCOwer>
的弱引用实例
3.实战测试
定义一个类,里面分配一个足够的大的1000 * 10000
的数组:
class Dump1 {
val data = Array(1000 * 10000) {
return@Array "$it".repeat(10)
}
}
复制代码
然后再Activity
的onCreate
中调用:
override fun onCreate(savedInstanceState: Bundle?) {
val dump1 = Dump1()
}
复制代码
这个时候看下logcat信息:
可以看到,GCOwer
类的finalize()
方法中疯狂的输出日志,这就代表着应用频繁发生了gc。
4.Android源码中的应用
然后再ActivityThread
中会调用:
通过BinderInternal
利用弱引用实现了GC的监听,ActivityThread
添加GC监听回调,来处理当内存达到一定阈值后且符合其他一系列条件,执行Activity回收等相关逻辑。
想了解更多Activity
回收,可以看下文末参考文章。
参考文章
写的很好,主要是从应用层以及系统层两方面来分析Activity相关的内存回收机制