未重写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 classThread.sleep(1000);Reference<?> polled = queue.poll(); // detected reclaimed referenceSystem.out.println(polled);
查看可以获取到 被回收的 PhantomReference
重写Object的finalize方法后
public static class MyObject {@Overrideprotected void finalize() throws Throwable {System.out.println("finalize");super.finalize();}}
再次用上述代码测试:
会发现没有检测到引用被回收的信息。这是由于:
重写了 finalize
方法的对象在被gc线程检测到的时候,需要交由finalizer thread执行自定义的 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 classThread.sleep(1000);System.gc(); // gc round 2, marked as unreachable referenceThread.sleep(1000);Reference<?> polled = queue.poll(); // detected reclaimed referenceSystem.out.println(polled);
这里发现很大可能是可以检测到回收的:
引用
[1] https://www.zhihu.com/question/49760047