概述
Java中一共有四種Reference, 其中 SoftReference, WeakReference, PhantomReference內有一個Referent和ReferenceQueue
- Referent: 被引用對象
- RefernceQueue: 當引用的Referent被回收后該引用會被enqueue到這個ReferenceQueue中
一個對象可以同時擁有多種引用, 可以通過Reference.get()方法獲取Referent
StrongReference (強引用)
強引用時Java中使用得最多的引用, 我們使用的普通引用就是Java強應用例如
Object o = new Object();
o就是一個強引用, 強引用不會被JVM GC, 即使內存不夠拋出OutOfMemoryError也不會被回收
SoftReference (軟引用)
軟引用是Java中一個類, 它的Referent只有在內存不夠的時候在拋出OutOfMemoryError前會被 JVM GC, 軟引用一般用來實現內存敏感緩存(memory-sensitive caches)
軟引用可以和一個ReferenceQueue一起使用, 當SoftReference的Referent被回收以后,這個SoftReference會被自動enqueue到這個queue中,如下:
ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); SoftReference<Object> softReference = new SoftReference<Object>(o, queue);
WeakReference (弱引用)
弱引用相較於軟引用生命周期更弱, 當一個對象僅有一個弱引用時它的Referent會在JVM GC執行以后被回收, 但是由於GC線程(如 System.gc())是一個低優先級線程,手動調用System.gc()未必會立即執行GC, 因此弱引用的Referent不一定會馬上被回收.同樣, 弱引用也可以和一個ReferenceQueue共同使用
Object o = new Object(); ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); WeakReference<Object> ref = new WeakReference<Object>(o, queue); o = null; System.out.println(ref.get()); System.gc(); System.out.println(ref.get());
輸出
java.lang.Object@1a758cb
null
PhantomReference (虛引用)
虛引用不會影響對象的生命周期, 他僅僅是一個對象生命周期的一個標記, 他必須與ReferenceQueue一起使用, 構造方法必須傳入ReferenceQueue, 因為它的作用就是在對象被JVM決定需要GC后, 將自己enqueue到RQ中. 他通常用來在一個對象被GC前作為一個GC的標志,以此來做一些finalize操作
另外,PhantomReference.get()方法永遠返回null
ReferenceQueue (引用隊列)
如果Reference在構造方法加入ReferenceQueue參數, Reference在它的Referent被GC的時,會將這個Reference加入ReferenceQueue
WeakHashMap
WeakHashMap是HashMap的WeakReference實現, 他使用WeakReference封裝了Entry的Key, 如果這個WeakHashMap的key僅有這個Map持有弱引用,則當JVM GC執行時,它的key和value會被GC. 如果這個key還有別的引用則不會被GC.
WeakHashMap<Object, String> map = new WeakHashMap<Object, String>(); map.put(new Object(), "test"); System.out.println(map); System.gc(); System.out.println(map);
輸出
{java.lang.Object@1a758cb=test}
{}