從面試題中看Java的Reference(引用)

2021-02-20 碼農突圍
前言:四大引用,是一個古老的知識,今天看下

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乾貨,源碼分析,歡迎關注我的微信公眾號,掃一掃下方二維碼或者長按識別二維碼,即可關注。

相關焦點

  • SAP ABAP和Java裡的弱引用(WeakReference)和軟引用(SoftReference)
    這就意味著,在ABAP垃圾回收器開始工作的時候,如果一個對象實例並未有任何強引用指向它,此時無論有無弱引用指向它,該對象實例都無法逃脫被回收的命運。看個具體的例子。這個30行的ABAP報表,實現了一個簡單的LCL_PERSON類。第17行創建了一個該類的實例,該實例的強引用存儲在引用變量lo_person裡。
  • Java中的 "弱" 引用有啥用?
    對於簡單的情況, 手動置空是不需要程式設計師來做的, 因為在java中, 對於簡單對象, 當調用它的方法執行完畢後, 指向它的引用會被從棧中彈出, 所以它就能在下一次GC執行時被回收了。但是, 也有特殊例外.
  • 面試中經常被問到 Java 引用類型原理,帶你深入剖析
    2.網上大多數文章對於虛引用的介紹是:形同虛設,虛引用並不會決定對象的生命周期。主要用來跟蹤對象被垃圾回收器回收的活動。真的是這樣嗎?3.虛引用在Jdk中有哪些場景下用到了呢?公眾號:Java後端 發布的面試相關文章已經整理完畢,可以關注 Java後端 後後臺回復 666 獲取。
  • 面試官:說說強引用、軟引用、弱引用、虛引用吧
    儘管將一切都「看作」對象,但操縱的標識符實際是指向一個對象的「引用」(reference)。」在 JDK 1.2 之前,Java 中的引用的定義很傳統:如果 reference 類型的數據中存儲的數值代表的是另外一塊內存的起始地址,就稱該 refrence 數據是代表某塊內存、某個對象的引用。這種定義很純粹,但是太過狹隘,一個對象在這種定義下只有被引用或者沒有被引用兩種狀態,對於如何描述一些「食之無味,棄之可惜」的對象就顯得無能為力。
  • 面試題之java基礎
    應部分網友的建議,從今天起會逐步的總結一些java、php相關的面試題,由簡單到複雜歸納一個系列:【金三銀四】,中間部分題目的答案來源於網絡,如若不嚴謹還望諒解。java基礎面試題 1、簡述Java程序編譯和運行的過程:答:①  Java編譯程序將Java源程序翻譯為JVM可執行代碼--字節碼,創建完源文件之後,程序會先被編譯成 「.class」 文件。
  • Android常識面試題,onSaveInstanceState
    協程看上去也是子程序,但是不同的是可以在子程序內部中斷轉而去執行其他子程序,然後在合適的時候再返回中斷位置繼續執行。協程特點:執行效率高:沒有多線程的線程間切換的開銷;不需要多線程的鎖機制:因為只有一個線程,所以不需要面試題3.synchronized和lock的區別?
  • Java經典面試題答案解析(1-80題)
    ,把收藏的800道Java經典面試題都發出來,有小夥伴私聊我要答案。說說反射的用途及實現原理,Java獲取反射的三種方法這道面試題,看我這篇文章哈:談談Java反射:從入門到實踐,再到原理Java獲取反射的三種方法:15. 面向對象的特徵面向對象的三大特徵:16.
  • 面試前必看Java線程面試題
    下面是Java線程相關的熱門面試題,你可以用它來好好準備面試。1.面向對象的特徵有哪些方面?答:面向對象的特徵主要有以下幾個方面:- 抽象:抽象是將一類對象的共同特徵總結出來構造類的過程,包括數據抽象和行為抽象兩方面。
  • Java 最常見的 200+ 面試題:面試必備
    聊回面試題這件事,這份面試清單原本是我們公司內部使用的,可到後來有很多朋友在微信上聯繫到我,讓我幫他們找一些面試方面的資料,而且這些關係也不太好拒絕,一呢,是因為這些找我,要面試題的人,不是我的好朋友的弟弟妹妹,就是我的弟弟妹妹們;二呢,我也不能馬馬虎虎的對付,受人之事忠人之命,我也不能辜負這份信任。
  • Java四種引用類型:強引用、軟引用、弱引用、虛引用
    Java為什麼要設計這四種引用Java的內存分配和內存回收,都不需要程式設計師負責,都是由偉大的JVM去負責,一個對象是否可以被回收,主要看是否有引用指向此對象,說的專業點,叫可達性分析。Java設計這四種引用的主要目的有兩個:可以讓程式設計師通過代碼的方式來決定某個對象的生命周期;有利用垃圾回收。
  • 在Java 中安全使用接口引用
    = null) {4   callback.onXXXX();5}這看起來並沒有什麼問題,因為我們平時就是這樣書寫代碼的,所以我們的項目中存在大量的對接口引用的非空判斷,即使有參數型註解@NonNull 的標記,但仍無法阻止外部傳入一個null 對象。
  • 2019 最新 200 道 Java 面試題
    ,我做了大量的「功課」,首先我研究了幾乎所有大廠的面試題,還和負責招聘工作的幾個朋友,詳細的探討了 Java 面試所要涉及的知識點,於是就有了今天大家看到的這 200 多道面試題。有了這些面試題不意味著,死記硬背之後就能進入企業工作,尤其是 BAT 等工作崗位競爭更為激烈,這些面試題只能成為面試體系中的一道「開胃菜」,從而提高了整個 Java 面試的壁壘,讓願與學的人,變的更加優秀,從而和懶惰的人拉開差距,讓企業也能更輕易的甄別。這些面試題包含哪些內容?
  • java程式設計師面試遇到string題如何不涼?
    最近看到好多同學都在儲備面試知識,以備來年輕鬆應對面試官,拿到心儀offer,之前好多同學反映遇到string,都只能送給自己一首涼涼。別涼,今天小編就為大家準備了面試中常遇到的string題,讓你輕鬆愉快拿offer~首先跟大家說說如何創建string~創建字符串較簡單的方式如下String str = "Runoob";在代碼中遇到字符串常量時,這裡的值是 "Runoob"",編譯器會使用該值創建一個 String 對象。
  • Java面試總結之Java基礎
    無論是工作多年的高級開發人員還是剛入職場的新人,在換工作面試的過程中,Java基礎是必不可少的面試題之一。能不能順利通過面試,拿到自己理想的offer,在準備面試的過程中,Java基礎也是很關鍵的。對於工作多年的開發人員來說,Java基礎往往是會被大家所忽略的,但在面試的過程中,確是必不可少的問題。在這篇文章裡就來為大家總結一下經常會被問到的Java基礎題。
  • Java面試寶典---Java基礎部分(7)
    所謂內存洩露就是指一個不再被程序使用的對象或變量一直被佔據在內存中。java中有垃圾回收機制,它可以保證一對象不再被引用的時候,即對象編程了孤兒的時候,對象將自動被垃圾回收器從內存中清除掉。中的內存洩露的情況:長生命周期的對象持有短生命周期對象的引用就很可能發生內存洩露,儘管短生命周期對象已經不再需要,但是因為長生命周期對象持有它的引用而導致不能被回收,這就是java中內存洩露的發生場景,通俗地說,就是程式設計師可能創建了一個對象,以後一直不再使用這個對象,這個對象卻一直被引用,即這個對象無用但是卻無法被垃圾回收器回收的,這就是java中可能出現內存洩露的情況,例如,緩存系統,我們加載了一個對象放在緩存中
  • Java面試題
    方法重寫(子類繼承父類並重寫父類中已有的或抽象的方法);2). 對象造型(用父類型引用引用子類型對象,這樣同樣的引用調用同樣的方法就會根據子類對象的不同而表現出不同的行為)。2、訪問修飾符public,private,protected,以及不寫(默認)時的區別?
  • 2020最新Java後端面試題(帶答案),重點都給畫出來了!你不看?
    前言金九銀十,金三銀四確實是跳槽旺季,但是拋除這個之外,每天都有人在面試,有些人迷茫,有些人躊躇滿志,可能人們總在想,如果能知道面試內容就好了,其實我們可以從網上找到80%的面試題,自己去提前準備。有準備的面試總是讓人信心滿滿的。
  • 你見過老外的 Java 面試題嗎 (上)?
    畢竟不是專業的後臺開發,所以我在面試到後臺知識的時候果斷的退了出來,才讓自己免受了侮辱。不過鑑於我手速出眾,飛速的記錄下了 Java 的基礎題,所以準備貢獻出來,供大家享樂。鑑於題目比較多,會分成上下 2 篇 來整理,主要是面對 Java 的基礎,看看老外的面試題和我們有什麼區別。當然問題是老外問的,答案是我編的。
  • 50道Java集合經典面試題(收藏版)
    前言來了來了,50道Java集合面試題也來啦~ 已經上傳github:https://github.com/whx123/JavaHome1.jdk8中put方法:先判斷Hashmap是否為空,為空就擴容,不為空計算出key的hash值i,然後看table[i]是否為空,為空就直接插入,不為空判斷當前位置的key和table[i]是否相同,相同就覆蓋,不相同就查看table[i]是否是紅黑樹節點,如果是的話就用紅黑樹直接插入鍵值對,如果不是開始遍歷鍊表插入,如果遇到重複值就覆蓋,否則直接插入,如果鍊表長度大於8,轉為紅黑樹結構,執行完成後看
  • 【Java面試題】常見Java面試知識點總結-1
    我是:小職(z_zhizuobiao)找我:✅ 解鎖高薪工作 ✅ 免費獲取乾貨教程這裡整理了部分較為重點的Java面試題內容,而且對於答案有困惑,補充了解釋內容,便於理解。1. 什麼是Java虛擬機?為什麼Java被稱作是「平臺無關的程式語言」?