摘要:弱引用與軟引用最大的區(qū)別就是弱引用比軟引用的生命周期更短暫。所以對于軟引用弱引用之類,垃圾收集器可能會存在二次確認的問題,以確保處于弱引用狀態(tài)的對象沒有改變?yōu)閺娨谩?/p>
關于強引用、軟引用、弱引用、幻象引用的區(qū)別,在一些大公司的面試題中經(jīng)常出現(xiàn),可能有些小伙伴覺得這個知識點比較冷門,但其實大家在開發(fā)中經(jīng)常用到,如new一個對象的時候就是強引用的應用。
在java語言中,除了原始數(shù)據(jù)類型(boolean、byte、short、char、int、float、double、long)的變量,其他所有都是所謂的引用類型,指向各種不同的對象。理解這些引用的區(qū)別,對于掌握java對象生命周期和JVM內(nèi)部相關機制非常有幫助。也有助于更深刻的理解底層對象生命周期、垃圾收集機制等,對設計可靠的緩存框架、診斷應用OOM等問題也大有裨益。
這四種應用主要的區(qū)別體現(xiàn)在對象不同的可達性狀態(tài)和對垃圾收集的影響,他們之間的可達性狀態(tài)可以參看下圖:
1.強引用(strong reference)強引用就是我們最常見的普通對象引用(如new 一個對象),只要還有強引用指向一個對象,就表明此對象還“活著”。在強引用面前,即使JVM內(nèi)存空間不足,JVM寧愿拋出OutOfMemoryError運行時錯誤(OOM),讓程序異常終止,也不會靠回收強引用對象來解決內(nèi)存不足的問題。對于一個普通的對象,如果沒有其他的引用關系,只要超過了引用的作用域或者顯式地將相應(強)引用賦值為null,就意味著此對象可以被垃圾收集了。但要注意的是,并不是賦值為null后就立馬被垃圾回收,具體的回收時機還是要看垃圾收集策略的。
如Object obj = new Object();
2.軟引用(soft reference)軟引用相對強引用要弱化一些,可以讓對象豁免一些垃圾收集。當內(nèi)存空間足夠的時候,垃圾回收器不會回收它。只有當JVM認定內(nèi)存空間不足時才會去回收軟引用指向的對象。JVM會確保在拋出OOM前清理軟引用指向的對象,而且JVM是很聰明的,會盡可能優(yōu)先回收長時間閑置不用的軟引用指向的對象,對那些剛構建的或剛使用過的軟引用指向的對象盡可能的保留?;谲浺玫倪@些特性,軟引用可以用來實現(xiàn)很多內(nèi)存敏感點的緩存場景,即如果內(nèi)存還有空閑,可以暫時緩存一些業(yè)務場景所需的數(shù)據(jù),當內(nèi)存不足時就可以清理掉,等后面再需要時,可以重新獲取并再次緩存。這樣就確保在使用緩存提升性能的同時,不會導致耗盡內(nèi)存。
軟引用通常可以和一個引用隊列(ReferenceQueue)聯(lián)合使用,如果弱引用所引用的對象被垃圾回收,java虛擬機就會把這個軟引用加入到與之關聯(lián)的引用隊列中。
Object obj = new Object(); SoftReference
通過上面的代碼可以看出sf是對obj的一個軟引用,當sf對象還沒有被銷毀前,sf.get()可以獲取到這個對象,如果已被銷毀,則返回null。
正確使用軟引用的示例代碼如下:
SoftReference> ref = new SoftReference
>(new LinkedList
()); // somewhere else in your code, you create a Foo that you want to add to the list List list = ref.get(); if (list != null) { list.add(foo); } else { // list is gone; do whatever is appropriate }
在使用軟引用的時候必須檢查引用是否為null。因為垃圾收集器可能在任意時刻回收軟引用,如果不做是否null的判斷,可能會出現(xiàn)NullPointerException的異常。
3.弱引用(weak reference)弱引用指向的對象是一種十分臨近finalize狀態(tài)的情況,當弱引用被清除的時候,就符合finalize的條件了。弱引用與軟引用最大的區(qū)別就是弱引用比軟引用的生命周期更短暫。垃圾回收器會掃描它所管轄的內(nèi)存區(qū)域的過程中,只要發(fā)現(xiàn)弱引用的對象,不管內(nèi)存空間是否有空閑,都會立刻回收它。如同前面我說過的,具體的回收時機還是要看垃圾回收策略的,因此那些弱引用的對象并不是說只要達到弱引用狀態(tài)就會立馬被回收。
基于弱引用的這些特性,弱引用同樣可以應用在很多需要緩存的場景。
Object obj = new Object(); WeakReference4.幻象引用(phantom reference)wf = new WeakReference (obj); obj = null; //有時候會返回null wf.get(); //返回是否被垃圾回收器標記為即將回收的垃圾 wf.isEnQueued();
幻象引用,也有被說成是虛引用或幽靈引用?;孟笠貌⒉粫Q定對象的生命周期。即如果一個對象僅持有虛引用,就相當于沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。不能通過它訪問對象,幻象引用僅僅是提供了一種確保對象被finalize以后,做某些事情的機制(如做所謂的Post-Mortem清理機制),也有人利用幻象引用監(jiān)控對象的創(chuàng)建和銷毀。
Object obj = new Object(); PhantomReferencepf = new PhantomReference (obj); obj=null; //永遠返回null pf.get(); //返回是否從內(nèi)存中已經(jīng)刪除 pf.isEnQueued();
幻象引用的get方法永遠返回null,主要用于檢查對象是否已經(jīng)從內(nèi)存中刪除。
通過上面對四種引用類型的分析,你可能發(fā)現(xiàn)對象的可達性是JVM垃圾收集器決定如何處理對象的一個重要考慮指標。
所有引用類型都是抽象類java.lang.ref.Reference的子類,子類里提供了get()方法。通過上面的分析中可以得知,除了幻象引用(因為get永遠返回null),如果對象還沒有被銷毀,都可以通過get方法獲取原有對象。其實有個非常關鍵的注意點,利用軟引用和弱引用,我們可以將訪問到的對象,重新指向強引用,也就是人為的改變了對象的可達性狀態(tài)。所以對于軟引用、弱引用之類,垃圾收集器可能會存在二次確認的問題,以確保處于弱引用狀態(tài)的對象沒有改變?yōu)閺娨谩?/p>
但是有個問題,如果我們錯誤的保持了強引用(比如,賦值給了static變量),那么對象可能就沒有機會變回類似弱引用的可達性狀態(tài)了,就會產(chǎn)生內(nèi)存泄露。所以,檢查弱引用指向?qū)ο笫欠癖焕占彩窃\斷是否有特定內(nèi)存泄露的一個思路,我們的框架使用到弱引用又懷疑有內(nèi)存泄露,就可以從這個角度檢查。
對于軟引用、弱引用、幻象引用可以配合引用隊列(ReferenceQueue)來使用,特別是幻象引用,get方法只返回null,如果再不指定引用隊列,基本就沒有任何意義了。
上面分析了四種引用類型的使用,熟悉這幾種應用類型對深入理解JVM也大有裨益。
參考:
http://www.kdgregory.com/inde...
極客時間《Java核心技術36講》
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/75672.html
摘要:直接對棧的操作只有兩個,就是對棧幀的壓棧和出棧。中將永久代移除,同時增加元數(shù)據(jù)區(qū)。在中,本地方法棧和虛擬機棧是在同一塊兒區(qū)域,這完全取決于技術實現(xiàn)的決定,并未在規(guī)范中強制。 原文:https://github.com/linsheng97... 描述一下 JVM 的內(nèi)存區(qū)域 程序計數(shù)?(PC,Program Counter Register)。在 JVM 規(guī)范中,每個線程都有它自己的...
摘要:在之后,對引用的概念進行了擴充,將引用分為強引用軟引用弱引用虛引用種,這種引用強度依次逐漸減弱。軟引用是用來描述一些還有用但并非必需的對象。虛引用也稱為幽靈引用或者幻影引用,它是最弱的一種引用關系。 以下內(nèi)容摘自《深入理解Java虛擬機 JVM高級特性與最佳實踐》第2版,強烈推薦沒有看過的同學閱讀,讀完的感覺就是原來學的都是些什么瘠薄東西(╯‵□′)╯︵┴─┴ 在JDK1.2以前,Ja...
摘要:一個對象是否有虛引用的存在,完全不會對其生存時間構成影響,也無法通過虛引用來取得一個對象實例。為一個對象設置虛引用關聯(lián)的唯一目的就是能在這個對象被垃圾收集器回收時收到一個系統(tǒng)通知。在之后提供了類來實現(xiàn)虛引用參考深入理解虛擬機 GC $TODO$ 一個對象的生命周期 一個對象的生命周期從它被創(chuàng)建開始,此時虛擬機會給它置一個內(nèi)部標識finalizable,當 GC 到達某一個安全點并檢驗該...
摘要:弱引用弱引用比軟引用更弱,被弱引用關聯(lián)的對象只能存活到發(fā)生下一次垃圾回收之前,也就是說當發(fā)生時,無論當前內(nèi)存是否足夠,都會被回收掉。這是最終的狀態(tài),不能再變?yōu)槠渌鼱顟B(tài)。如下圖所示對象都是可被回收的。 【干貨點】看完該篇文章,就基本可以解答面試熱點【談談對Java中幾種引用的理解】了。 大家都知道我公眾號的副業(yè)是 showImg(https://segmentfault.com/img/...
摘要:深入理解虛擬機高級特性與最佳實踐第二版讀書筆記與常見面試題總結上篇文章傳送門深入理解虛擬機之內(nèi)存區(qū)域本節(jié)常見面試題推薦帶著問題閱讀,問題答案在文中都有提到如何判斷對象是否死亡兩種方法。虛引用主要用來跟蹤對象被垃圾回收的活動。 《深入理解Java虛擬機:JVM高級特性與最佳實踐(第二版》讀書筆記與常見面試題總結 上篇文章傳送門: 深入理解虛擬機之Java內(nèi)存區(qū)域 本節(jié)常見面試題(推薦帶著...
閱讀 1272·2021-09-02 13:36
閱讀 2727·2019-08-30 15:44
閱讀 2982·2019-08-29 15:04
閱讀 3199·2019-08-26 13:40
閱讀 3650·2019-08-26 13:37
閱讀 1181·2019-08-26 12:22
閱讀 1020·2019-08-26 11:36
閱讀 1222·2019-08-26 10:41