有时候会需要监听虚拟机的 的gc 事件。直接上源码了。
使用如下:
GcWatcherInternal.addGcWatcher(new Runnable() {
@Override
public void run() {
System.out.println("gc 事件");
}
});
源码如下:
package com.ttp.newcore.apm;
import android.os.SystemClock;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
/**
* gc 监听器
* 参考自com.android.internal.os.BinderInternal
*/
public class GcWatcherInternal {
private static WeakReference<GcWatcher> sGcWatcher;
private static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
private static Object lock=new Object();
private static long sLastGcTime;
private static final class GcWatcher {
@Override
protected void finalize() throws Throwable {
sLastGcTime = SystemClock.uptimeMillis();
ArrayList<Runnable> sTmpWatchers;
synchronized (lock) {
sTmpWatchers = sGcWatchers;
try{
for (int i = 0; i < sTmpWatchers.size(); i++) {
if (sTmpWatchers.get(i) != null) {
sTmpWatchers.get(i).run();
}
}
}catch (Throwable e){
e.printStackTrace();
}
sGcWatcher = new WeakReference<>(new GcWatcher());
}
}
}
public static void addGcWatcher(Runnable watcher) {
synchronized (lock) {
sGcWatchers.add(watcher);
if(sGcWatcher==null)
sGcWatcher = new WeakReference<>(new GcWatcher());
}
}
public static void removeGcWatcher(Runnable watcher) {
synchronized (lock) {
sGcWatchers.remove(watcher);
if(sGcWatchers.isEmpty())
sGcWatcher=null;
}
}
}
源码是参考自 android 系统 类 com.android.internal.os.BinderInternal
的,有兴趣的可以去看下。
大致原理如下:
1、首先创建 一个软引用WeakReference,引用的普通对象GcWatcher,而软引用的特性是当发生gc 时就会被回收,而当对象回收时会调用对象的finalize 的方法,通过重写 finalize 就知道发生gc 了。回调给外层使用者,然后循环创建软引用就行了。原理比较巧妙。