package com.karl.reference; import static org.junit.Assert.*; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; import org.junit.Test; public class TestReference { @Test public void weakReference() { Object referent = new Object(); WeakReference<Object> weakRerference = new WeakReference<Object>(referent); assertSame(referent, weakRerference.get()); referent = null; System.gc(); /** * 一旦没有指向 referent 的强引用, weak reference 在 GC 后会被自动回收 */ assertNull(weakRerference.get()); } @Test public void strongReference() { Object referent = new Object(); /** * 通过赋值创建 StrongReference */ Object strongReference = referent; assertSame(referent, strongReference); referent = null; System.gc(); /** * StrongReference 在 GC 后不会被回收 */ assertNotNull(strongReference); } @Test public void weakHashMap() throws InterruptedException { Map<Object, Object> weakHashMap = new WeakHashMap<Object, Object>(); Object key = new Object(); Object value = new Object(); weakHashMap.put(key, value); assertTrue(weakHashMap.containsValue(value)); key = null; System.gc(); /** * 等待无效 entries 进入 ReferenceQueue 以便下一次调用 getTable 时被清理 */ Thread.sleep(1000); /** * 一旦没有指向 key 的强引用, WeakHashMap 在 GC 后将自动删除相关的 entry */ assertFalse(weakHashMap.containsValue(value)); } @Test public void hashMap() throws InterruptedException { Map<Object, Object> hashMap = new HashMap<Object, Object>(); Object key = new Object(); Object value = new Object(); hashMap.put(key, value); assertTrue(hashMap.containsValue(value)); key = null; System.gc(); /** * 等待无效 entries 进入 ReferenceQueue 以便下一次调用 getTable 时被清理 */ Thread.sleep(1000); /** * 没有指向 key 的强引用, HashMap 在 GC 后将无法删除相关的 entry */ assertTrue(hashMap.containsValue(value)); } @Test public void softReference() { Object referent = new Object(); SoftReference<Object> softRerference = new SoftReference<Object>(referent); assertNotNull(softRerference.get()); referent = null; System.gc(); /** * soft references 只有在 jvm OutOfMemory 之前才会被回收, 所以它非常适合缓存应用 */ assertNotNull(softRerference.get()); } @Test public void referenceQueue() throws InterruptedException { Object referent = new Object(); ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>(); WeakReference<Object> weakReference = new WeakReference<Object>(referent, referenceQueue); assertFalse(weakReference.isEnqueued()); Reference<? extends Object> polled = referenceQueue.poll(); assertNull(polled); referent = null; System.gc(); assertTrue(weakReference.isEnqueued()); Reference<? extends Object> removed = referenceQueue.remove(); assertNotNull(removed); } }