监听应用是否发生GC

一起养成写作习惯!这是我参与「掘金日新计划 · 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的数组:

扫描二维码关注公众号,回复: 13772951 查看本文章
class Dump1 {
    val data = Array(1000 * 10000) {
        return@Array "$it".repeat(10)
    }
}
复制代码

然后再ActivityonCreate中调用:

override fun onCreate(savedInstanceState: Bundle?) {  
    val dump1 = Dump1()
}
复制代码

这个时候看下logcat信息: image.png

可以看到,GCOwer类的finalize()方法中疯狂的输出日志,这就代表着应用频繁发生了gc。

4.Android源码中的应用

image.png 然后再ActivityThread中会调用:

image.png

通过BinderInternal利用弱引用实现了GC的监听,ActivityThread添加GC监听回调,来处理当内存达到一定阈值后且符合其他一系列条件,执行Activity回收等相关逻辑。

想了解更多Activity回收,可以看下文末参考文章。

参考文章

【解惑】App处于前台,Activity就不会被回收了?

写的很好,主要是从应用层以及系统层两方面来分析Activity相关的内存回收机制

猜你喜欢

转载自juejin.im/post/7083637863341883400