Reference(T referent, ReferenceQueue<? super T> queue) { this.referent = referent; this.queue = (queue == null) ? ReferenceQueue.NULL : queue; }
下面是一段测试代码:
public class A { } ReferenceQueue queue = new ReferenceQueue(); WeakReference ref = new WeakReference(new A(), queue); Assert.assertNotNull(ref.get()); Object obj = null; obj = queue.poll(); Assert.assertNull(obj); System.gc(); Assert.assertNull(ref.get()); obj = queue.poll(); Assert.assertNotNull(obj);
分析,在GC运行时,检测到new A()生成的对象只有一个WeakReference引用着,所以决定回收它,首先clear WeakReference的referent,然后referent的状态为finalizable,同时或者一段时间后把WeakReference放入监听的ReferenceQueue中。
注意有时候最后的Assert.assertNotNull(obj);有时会失败,因为还没有来的及把WeakReference放入监听的ReferenceQueue中。
下面是一个可自动回收的map实现:
import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.Map; public class WeakIdentityMap { private transient ReferenceQueue<Object> idKeys = new ReferenceQueue<Object>(); private Map<WeakIdKey, Object> objHashcodeToPyId = new HashMap<WeakIdKey, Object>(); @SuppressWarnings("element-type-mismatch") private void cleanup() { Object k; while ((k = idKeys.poll()) != null) { System.out.println("cleanup"); objHashcodeToPyId.remove(k); } } private class WeakIdKey extends WeakReference<Object> { private final int hashcode; WeakIdKey(Object obj) { super(obj, idKeys); hashcode = System.identityHashCode(obj); } @Override public int hashCode() { return hashcode; } @Override public boolean equals(Object other) { Object obj = get(); if (obj != null) { return obj == ((WeakIdKey) other).get(); } else { return this == other; } } } // Used by test_jy_internals public int _internal_map_size() { return objHashcodeToPyId.size(); } public void put(Object key, Object val) { cleanup(); objHashcodeToPyId.put(new WeakIdKey(key), val); } public Object get(Object key) { cleanup(); return objHashcodeToPyId.get(new WeakIdKey(key)); } public void remove(Object key) { cleanup(); objHashcodeToPyId.remove(new WeakIdKey(key)); } public static void main(String[] args) throws InterruptedException { WeakIdentityMap map = new WeakIdentityMap(); map.put("1", "a"); map.put(new Object(), "b"); map.put(new Object(), "2"); System.gc(); Thread.sleep(1000); map.put("1", "a"); } }
参考:http://zhang-xzhi-xjtu.iteye.com/blog/413159