未重写Object的finalize方法
public static class MyObject {
}
使用 PhantomReference
来监听引用是否被回收
ReferenceQueue<Object> queue = new ReferenceQueue<>();
MyObject object = new MyObject();
PhantomReference<MyObject> phantomReference = new PhantomReference<>(object, queue);
object = null;
System.gc(); // gc round 1, referenced by finalizer class
Thread.sleep(1000);
Reference<?> polled = queue.poll(); // detected reclaimed reference
System.out.println(polled);
查看可以获取到 被回收的 PhantomReference
重写Object的finalize方法后
public static class MyObject {
@Override
protected void finalize() throws Throwable {
System.out.println("finalize");
super.finalize();
}
}
再次用上述代码测试:
会发现没有检测到引用被回收的信息。这是由于:
重写了 finalize
方法的对象在被gc线程检测到的时候,需要交由finalizer thread执行自定义的 finalize
方法,所以无法直接被标记回收,只能等待下一轮gc
所以大量使用
finalize
方法可能导致较大的gc压力
这里调用 System.gc()
建议jvm再增加一轮gc检测下是否会被回收
ReferenceQueue<Object> queue = new ReferenceQueue<>();
MyObject object = new MyObject();
PhantomReference<MyObject> phantomReference = new PhantomReference<>(object, queue);
object = null;
System.gc(); // gc round 1, referenced by finalizer class
Thread.sleep(1000);
System.gc(); // gc round 2, marked as unreachable reference
Thread.sleep(1000);
Reference<?> polled = queue.poll(); // detected reclaimed reference
System.out.println(polled);
这里发现很大可能是可以检测到回收的: