Harlber 授權公眾號獨家推送的文章,
Harlber 的簡書地址 :http://www.jianshu.com/p/04b09d8a1745,也可點擊閱讀原文查看。
話不多說,進入正題:
常見的面試中會有這麼一道題,「談談強引用、 軟引用、 弱引用、虛引用」。A:強引用,通過new出來的都是強引用
Q:那弱引用呢?
A:通過WeakReference構造出的,不再有強引用...
Q:那軟引用呢,這些引用間的區別是什麼?
A:...
面到這個階段這就比較尷尬了。為了避免類似的尷尬,特地花了點時間去整理這些引用,以便下次面試的時候就這個問題能和面試官談笑風生。
首先可以在oracle的文檔中找到相應的api說明
java.lang.ref
Class Reference<T>
java.lang.Object
java.lang.ref.Reference<T>
Direct Known Subclasses:
PhantomReference, SoftReference, WeakReference
Abstract base class for reference objects. This class defines the operations common to all reference objects. Because reference objects are implemented in close cooperation with the garbage collector, this class may not be subclassed directly.
Since:1.2
事實上在JDK 1.2以前的版本中,若一個對象不被任何變量引用,那麼程序就無法再使用這個對象。也就是說,只有對象處於可觸及(reachable)狀態,程序才能使用它。從JDK 1.2版本開始,把對象的引用分為4種級別,從而使程序能更加靈活地控制對象的生命周期。這4種級別由高到低依次為:強引用、軟引用、弱引用和虛引用。
Strong Reference:
強引用是默認實現的引用。垃圾回收器不會回收具有強引用的對象,除非沒有任何對象指向它時才會在一次GC 執行後被回收。當內存空間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內存不足的問題。
至此,也許犀利的你發現了這個現象:java中的Reference的子類中並沒有一個叫StrongReference的,在文章中寫的也是Strong Reference 。stackoverflow上也有類似的討論,點擊查看。
SoftReference:
Soft reference objects, which are cleared at the discretion of the garbage collector in response to memory demand. Soft references are most often used to implement memory-sensitive caches.Suppose that the garbage collector determines at a certain point in time that an object is softly reachable. At that time it may choose to clear atomically all soft references to that object and all soft references to any other softly-reachable objects from which that object is reachable through a chain of strong references. At the same time or at some later time it will enqueue those newly-cleared soft references that are registered with reference queues.
All soft references to softly-reachable objects are guaranteed to have been cleared before the virtual machine throws an OutOfMemoryError. Otherwise no constraints are placed upon the time at which a soft reference will be cleared or the order in which a set of such references to different objects will be cleared. Virtual machine implementations are, however, encouraged to bias against clearing recently-created or recently-used soft references.
Direct instances of this class may be used to implement simple caches; this class or derived subclasses may also be used in larger data structures to implement more sophisticated caches.As long as the referent of a soft reference is strongly reachable, that is, is actually in use, the soft reference will not be cleared.Thus a sophisticated cache can, for example, prevent its most recently used entries from being discarded by keeping strong referents to those entries, leaving the remaining entries to be discarded at the discretion of the garbage collector.
請留意文檔中標註的片段
軟引用對象時刻響應著內存狀態
注意 這裡並未明說內存不足時將回收軟引用對象,內存充裕時則不會回收,待會兒的測試中就能應證這一點。
軟引用常用於實現高速緩存。
這裡的緩存指的是高速內存緩存(區別於DiskLruCache)。
所有引用了軟可及(softly-reachable)的對象將在JVM拋出OutOfMemoryError異常前完成清除,回收工作。
由此可見
1.以SoftReference實現內存緩存是可靠的。
2.軟引用對象存在多種狀態:軟可及(softly-reachable)只是其中一種狀態。
SoftReference可被用來實現簡單的高速緩存;SoftReference類或派生子類也可用於較大的數據結構中實現更複雜的高速緩存。
只要軟引用對象是強可及(strongly reachabl) 在實際應用中軟引用將不會被清除。
至此,我們可以通過一個簡單的Test來驗證。下文是一個通過的測試案例。
@Testpublic void softReference() { Object referent = new Object(); SoftReference<Object> softRerference = new SoftReference<Object>(referent); assertSame(referent, softRerference.get()); System.gc(); assertNotNull(softRerference.get()); assertNotNull(referent); referent = null; System.gc(); assertNotNull(softRerference.get()); }
WeakReference:
Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed. Weak references are most often used to implement canonicalizing mappings.Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object and all weak references to any other weakly-reachable objects from which that object is reachable through a chain of strong and soft references. At the same time it will declare all of the formerly weakly-reachable objects to be finalizable. At the same time or at some later time it will enqueue those newly-cleared weak references that are registered with reference queues.
A "canonicalized" mapping is where you keep one instance of the object in question in memory and all others look up that particular instance via pointers or somesuch mechanism. This is where weaks references can help.The short answer is that Weak Reference objects can be used to create pointers to objects in your system while still allowing those objects to be reclaimed by the garbage-collector once they pass out of scope.
通俗的說,弱引用的對象擁有更短暫的生命周期。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。一個經典的弱引用的使用場景(請自行查閱WeakHashMap源碼):哈希表的接口允許使用任何Java對象作為鍵來使用。當一個鍵值對被放入到哈希表中之後,哈希表對象本身就有了對這些鍵和值對象的引用。如果這種引用是強引用的話,那麼只要哈希表對象本身還存活,其中所包含的鍵和值對象是不會被回收的。如果某個存活時間很長的哈希表中包含的鍵值對很多,最終就有可能消耗掉JVM中全部的內存。
同樣的我們測試一下:
@Testpublic void weakReference() { Object referent = new Object(); WeakReference<Object> weakRerference = new WeakReference<Object>(referent); assertSame(referent, weakRerference.get()); System.gc(); assertNotNull(weakRerference.get()); assertNotNull(referent); referent = null; System.gc(); assertNull(weakRerference.get()); referent = null; System.gc(); assertNull(weakRerference.get()); }
'強可及','軟可及' ,'弱可及' ,'不可及'這些引用狀態簡直看的人一臉懵逼呀。先不要慌,我們來看看oracle是怎麼定義這些狀態的:
Reachability
Going from strongest to weakest, the different levels of reachability reflect the life cycle of an object. They are operationally defined as follows:
An object is strongly reachable if it can be reached by some thread without traversing any reference objects. A newly-created object is strongly reachable by the thread that created it.
An object is softly reachable if it is not strongly reachable but can be reached by traversing a soft reference.
An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.
An object is phantom reachable if it is neither strongly, softly, nor weakly reachable, it has been finalized, and some phantom reference refers to it.
Finally, an object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of the above ways.
Since:1.2
自然而然的Since 1.2 ,看下文檔再對比下Test,現在應該明朗多了吧。
PhantomReference:
Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.If the garbage collector determines at a certain point in time that the referent of a phantom reference is phantom reachable, then at that time or at some later time it will enqueue the reference.
In order to ensure that a reclaimable object remains so, the referent of a phantom reference may not be retrieved: The get method of a phantom reference always returns null.
Unlike soft and weak references, phantom references are not automatically cleared by the garbage collector as they are enqueued. An object that is reachable via phantom references will remain so until all such references are cleared or themselves become unreachable.
第一時間獲得博客更新提醒,以及更多android乾貨,源碼分析,歡迎關注我的微信公眾號,掃一掃下方二維碼或者長按識別二維碼,即可關注。