返回

用GC监听器检测Android APP GC

Android

我们用Java弱引用的特性来监听应用是否发生了GC以及GC的频率,Android的源码中也有应用这种技巧。

一、Java中GC的特点

Java中垃圾回收的触发时机是:

  • JVM中管理的内存用尽
  • 显式调用System.gc()

二、GC原理

GC执行时,JVM中会产生一个临时的大对象,大对象中存放的是即将被回收的对象的引用。GC执行完毕后,GC会释放这个临时对象,临时对象中包含的指向待回收对象引用就会被释放掉。

三、实现原理

Android的源码中,WeakReference实现了java.lang.ref.Reference接口,当与之关联的对象被回收时,WeakReference将会变得不可达,这时通过一个Finalizer的线程,WeakReference会向被观察的对象注册一个死亡引用,当观察对象发生GC时,WeakReference的finalizer方法将会被执行,Finalizer的线程将会触发监听器执行。

四、实现步骤

  • 继承WeakReference,并重写Finalizer方法。
  • 弱引用中包含我们想要监听的对象。
  • 监听器重写onFinalized方法。
public class MyWeakReference extends WeakReference<Context> {
    private Object listener;
    public MyWeakReference(Context referent, Object listener) {
        super(referent);
        this.listener = listener;
    }
    @Override
    public void finalize() {
        if(listener instanceof FinalizedListener){
            ((FinalizedListener)listener).onFinalized();
        }
    }
}

我们通过一个GC监听器实现当发生GC时能够调用的方法。

public class GCListener implements FinalizedListener {
    @Override
    public void onFinalized() {
        Log.i("TAG","GC happened");
    }
}

然后我们通过代码来检测发生GC的频率:

public class GCTest {
    private Context mContext;
    public GCTest(Context context) {
        mContext = context;
    }

    public void start() {
        new MyWeakReference(mContext,new GCListener());
        mContext = null;
        System.gc();
    }
}

这个代码中:

  • 我们通过weakReference持有Context对象。
  • 将Context置为null,然后显式调用System.gc()触发GC。
  • 在Finalizer方法中调用GCListener的onFinalized()方法,打印日志。

如果我们的代码执行完毕,说明我们GC监听器能够监听到GC的发生。

五、总结

通过Java弱引用特性以及Finalizer线程,能够监听Android中的GC事件。