Java GC是否通过将弱引用放在分配给该引用的ReferenceQueue上来自动清除弱引用?换句话说,如果对WeakReference.get()的调用返回null,则WeakReference是否在队列中?
让我们剖析WeakReference 的Javadoc:
假设垃圾收集器在某个时间点确定某个对象是弱可达的。
那时,它将以原子方式清除对该对象的所有弱引用以及对任何其他可通过强引用和软引用链访问该对象的其他弱可访问对象的所有弱引用。
同时它将声明所有以前弱可达的对象都是可终结的。
同时或稍后的某个时间,它将 把那些新清除的注册到引用队列的弱引用放入队列。
看起来步骤是:
确定对象是否弱可达。
从其 中清除该对象WeakReference。WeakReference.get
将返回null。
将该对象标记为可终结。
之后或在其他时间将其排入
WeakReference队列(如果WeakReference是使用队列创建的)。
这意味着即使WeakReference.get()返回也null不能保证 WeakReference.enqueue会true或ReferenceQueue.poll不会返回null。
有关更多信息,请参阅https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references。
参考队列
一旦 WeakReference 开始返回 null,它指向的对象就变成了垃圾,并且 WeakReference 对象几乎毫无用处。这通常意味着需要进行某种清理;例如,WeakHashMap 必须删除此类失效条目,以避免保留数量不断增加的 deadWeakReference。
ReferenceQueue 类可以轻松跟踪死引用。如果将ReferenceQueue传递给弱引用的构造函数,则当它指向的对象变成垃圾时,引用对象将自动插入到引用队列中。然后,您可以定期处理 ReferenceQueue 并执行死引用所需的任何清理操作。
显示它的示例代码:
public static class A {
}
public static void main(String[] args) throws Exception{
A a = new A();
ReferenceQueue<A> rq = new ReferenceQueue<A>();
WeakReference<A> aref = new WeakReference<A>(a, rq);
a = null;
//aref.get() should be a, aref.isEnqueued() should return false, rq.poll() should return null
System.out.println( "0: " + aref + " : " + aref.get() + " : " + aref.isEnqueued() + " " + rq.poll() );
Thread.sleep(1000);
System.out.println("Running GC.");
Runtime.getRuntime().gc(); //let GC clear aref
System.out.println("GC ran.");
//aref.get() should be null, aref.isEnqueued() should return false, rq.poll() should return null
System.out.println( "1: " + aref + " : " + aref.get() + " " + aref.isEnqueued() + " " + rq.poll() );
//give some time for GC to enqueue aref
Thread.sleep(1000);
//ref.get() should be null, aref.isEnqueued() should return true, rq.poll() should return aref
System.out.println( "2: " + aref + " : " + aref.get() + " " + aref.isEnqueued() + " " + rq.poll() );
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
293 次 |
| 最近记录: |