垃圾回收相關(guān)概念
System.gc()的理解
●?在默認(rèn)情況下,通過(guò)System.gc()或者Runt ime.getRuntime().gc()的調(diào)用,會(huì)顯式觸發(fā)Full GC,同時(shí)對(duì)老年代和新生代進(jìn)行回收,嘗試釋放被丟棄對(duì)象占用的內(nèi)存。
●?然而System. gc()調(diào)用附帶-一個(gè)免責(zé)聲明,無(wú)法保證對(duì)垃圾收集器的調(diào)用。
●?JVM實(shí)現(xiàn)者可以通過(guò)System.gc ()調(diào)用來(lái)決定JVM的GC行為。而一般情況下,垃圾回收應(yīng)該是自動(dòng)進(jìn)行的,無(wú)須手動(dòng)觸發(fā),否則就太過(guò)于麻煩了。在一些特殊情況下,如我們正在編寫一個(gè)性能基準(zhǔn),我們可以在運(yùn)行之間調(diào)用System.gc()。
內(nèi)存溢出與內(nèi)存泄漏
內(nèi)存溢出(OOM)
●?內(nèi)存溢出相對(duì)于內(nèi)存泄漏來(lái)說(shuō),盡管更容易被理解,但是同樣的,內(nèi)存溢出也是引發(fā)程序崩潰的罪魁禍?zhǔn)字弧?br>
●?由于GC一直在發(fā)展, 所有一般情況下,除非應(yīng)用程序占用的內(nèi)存增長(zhǎng)速度非??欤斐衫厥找呀?jīng)跟不上內(nèi)存消耗的速度,否則不太容易出現(xiàn)O0M的情況。
●?大多數(shù)情況下,GC會(huì)進(jìn)行各種年齡段的垃圾回收,實(shí)在不行了就放大招,來(lái)一次獨(dú)占式的Full GC操作, 這時(shí)候會(huì)回收大量的內(nèi)存,供應(yīng)用程序繼續(xù)使用。
●?javadoc中對(duì)outofMemoryError的解釋是,沒(méi)有空閑內(nèi)存,并且垃圾收集器也無(wú)法提供更多內(nèi)存。
●?首先說(shuō)沒(méi)有空閑內(nèi)存的情況:說(shuō)明Java虛擬機(jī)的堆內(nèi)存不夠。原因有二:
?(1) Java虛擬機(jī)的堆內(nèi)存設(shè)置不夠。
比如:可能存在內(nèi)存泄漏問(wèn)題;也很有可能就是堆的大小不合理,比如我們要處理比較可觀的數(shù)據(jù)量,但是沒(méi)有顯式指定JVM堆大小或者指定數(shù)值偏小。我們可以通過(guò)參數(shù)-Xms、-Xmx來(lái)調(diào)整。
?(2)代碼中創(chuàng)建了大量大對(duì)象,并且長(zhǎng)時(shí)間不能被垃圾收集器收集(存在被引用)
對(duì)于老版本的Oracle JDK,因?yàn)橛谰么拇笮∈怯邢薜模⑶襃VM對(duì)永久代垃圾回收(如,常量池回收、卸載不再需要的類型)非常不積極,所以當(dāng)我們不斷添加新類型的時(shí)候,永久代出現(xiàn)OutOfMemoryError也非常多見(jiàn),尤其是在運(yùn)行時(shí)存在大量動(dòng)態(tài)類型生成的場(chǎng)合;類似intern字符串緩存占用太多空間,也會(huì)導(dǎo)致OOM問(wèn)題。對(duì)應(yīng)的異常信息,會(huì)標(biāo)記出來(lái)和永久代相關(guān):"java.lang.OutOfMemoryError:PermGen space"。
隨著元數(shù)據(jù)區(qū)的引入,方法區(qū)內(nèi)存已經(jīng)不再那么窘迫,所以相應(yīng)的OOM有所改觀,出現(xiàn)OOM,異常信息則變成了:"java.lang.OutOfMemoryError:Metaspace"。 直接內(nèi)存不足,也會(huì)導(dǎo)致OOM。
●?這里面隱含著一層意思是,在拋出OutOfMemoryError之前,通常垃圾收集器會(huì)被觸發(fā),盡其所能去清理出空間。
???例如:在引用機(jī)制分析中,涉及到JVM會(huì)去嘗試回收軟引用指向的對(duì)象等。
???在java.nio.BIts.reserveMemory()方法中,我們能清楚的看到,System.gc()會(huì)被調(diào)用,以清理空間。
●?當(dāng)然,也不是在任何情況下垃圾收集器都會(huì)被觸發(fā)的
???比如,我們?nèi)シ峙湟粋€(gè)超大對(duì)象,類似一一個(gè)超大數(shù)組超過(guò)堆的最大值,JVM可以判斷出垃圾收集并不能解決這個(gè)問(wèn)題,所以直接拋出0utOfMemoryError。
內(nèi)存泄漏(Memory Leak)
也稱作“存儲(chǔ)滲漏”。嚴(yán)格來(lái)說(shuō),只有對(duì)象不會(huì)再被程序用到了,但是GC又不能回收他們的情況,才叫內(nèi)存泄漏。
但實(shí)際情況很多時(shí)候一些不太好的實(shí)踐(或疏忽)會(huì)導(dǎo)致對(duì)象的生命周期變得很長(zhǎng)甚至導(dǎo)致OOM,也可以叫做寬泛意義上的“內(nèi)存泄漏”。
盡管內(nèi)存泄漏并不會(huì)立刻引起程序崩潰,但是一.旦發(fā)生內(nèi)存泄漏,程序中的可用內(nèi)存就會(huì)被逐步蠶食,直至耗盡所有內(nèi)存,最終出現(xiàn)OutOfMemory異常,導(dǎo)致程序崩潰。
注意,這里的存儲(chǔ)空間并不是指物理內(nèi)存,而是指虛擬內(nèi)存大小,這個(gè)虛擬內(nèi)存大小取決于磁盤交換區(qū)設(shè)定的大小。

舉例:
1、單例模式
單例的生命周期和應(yīng)用程序是一樣長(zhǎng)的,所以單例程序中,如果持有對(duì)外部對(duì)象的引用的話,那么這個(gè)外部對(duì)象是不能被回收的,則會(huì)導(dǎo)致內(nèi)存泄漏的產(chǎn)生。
2、一些提供close的資源未關(guān)閉導(dǎo)致內(nèi)存泄漏
數(shù)據(jù)庫(kù)連接(dataSourse.getConnection()),網(wǎng)絡(luò)連接(socket)和io連接必須手動(dòng)close,否則是不能被回收的。
Stop The World
●?Stop-the-World,簡(jiǎn)稱STW,指的是GC事件發(fā)生過(guò)程中,會(huì)產(chǎn)生應(yīng)用程序的停頓。停頓產(chǎn)生時(shí)整個(gè)應(yīng)用程序線程都會(huì)被暫停,沒(méi)有任何響應(yīng),有點(diǎn)像卡死的感覺(jué),這個(gè)停頓稱為STW。
???可達(dá)性分析算法中枚舉根節(jié)點(diǎn)(GC Rootg)會(huì)導(dǎo)致所有Java執(zhí)行線程停頓。
?????分析工作必須在一個(gè)能確保一致性的快照中進(jìn)行
?????一致性指整個(gè)分析期間整個(gè)執(zhí)行系統(tǒng)看起來(lái)像被凍結(jié)在某個(gè)時(shí)間點(diǎn)上
?????如果出現(xiàn)分析過(guò)程中對(duì)象引用關(guān)系還在不斷變化,則分析結(jié)果的準(zhǔn)確性無(wú)法保證
●?被sTw中斷的應(yīng)用程序線程會(huì)在完成GC之后恢復(fù),頻繁中斷會(huì)讓用戶感覺(jué)像是網(wǎng)速不快造成電影卡帶一樣,所以我們需要減少STW的發(fā)生。
●?STW事件 和采用哪款GC無(wú)關(guān),所有的GC都有這個(gè)事件。
●?哪怕是G1也不能完全避免Stop-the-world 情況發(fā)生,只能說(shuō)垃圾回收器越來(lái)越優(yōu)秀,回收效率越來(lái)越高,盡可能地縮短了暫停時(shí)間。
●?STW是JVM在后臺(tái)自動(dòng)發(fā)起和自動(dòng)完成的。在用戶不可見(jiàn)的情況下,把用戶正常的工作線程全部停掉。
●?開發(fā)中不要用System.gc() ;會(huì)導(dǎo)致Stop-the-world的發(fā)生。
辣雞回收的并行與并發(fā)
并發(fā)(Concurrent)
●?在操作系統(tǒng)中,是指一個(gè)時(shí)間段中有幾個(gè)程序都處于已啟動(dòng)運(yùn)行到運(yùn)行完畢之間,且這幾個(gè)程序都是在同一個(gè)處理器上運(yùn)行。
●?并發(fā)不是真正意義上的“同時(shí)進(jìn)行”,只是CPU把一個(gè)時(shí)間段劃分成幾個(gè)時(shí)間片段(時(shí)間區(qū)間),然后在這幾個(gè)時(shí)間區(qū)間之間來(lái)回切換,由于CPU處理的速度非???,只要時(shí)間間隔處理得當(dāng),即可讓用戶感覺(jué)是多個(gè)應(yīng)用程序同時(shí)在進(jìn)行。

并行(Parallel)
●?當(dāng)系統(tǒng)有一個(gè)以上CPU時(shí), 當(dāng)一個(gè)CPU執(zhí)行一個(gè)進(jìn)程時(shí),另一個(gè)CPU可以執(zhí)行另一個(gè)進(jìn)程,兩個(gè)進(jìn)程互不搶占CPU資源,可以同時(shí)進(jìn)行,我們稱之為并行(Parallel)。
●?其實(shí)決定并行的因素不是CPU的數(shù)量,而是CPU的核心數(shù)量,比如一個(gè)CPU多個(gè)核也可以并行。

并發(fā)VS并行
二者對(duì)比:
并發(fā),指的是多個(gè)事情,在同一時(shí)間段內(nèi)同時(shí)發(fā)生了。
并行,指的是多個(gè)事情,在同一時(shí)間點(diǎn)上同時(shí)發(fā)生了。
并發(fā)的多個(gè)任務(wù)之間是互相搶占資源的。
并行的多個(gè)任務(wù)之間是不互相搶占資源的。
只有在多CPU或者-一個(gè)CPU多核的情況中,才會(huì)發(fā)生并行。
否則,看似同時(shí)發(fā)生的事情,其實(shí)都是并發(fā)執(zhí)行的。
辣雞回收的并行與并發(fā)
并發(fā)和并行,在談?wù)摾占鞯纳舷挛恼Z(yǔ)境中,它們可以解釋如下:
●?并行(Parallel):指多條垃圾收集線程并行工作,但此時(shí)用戶線程仍處于等待狀態(tài)。
???如ParNew、 Parallel Scavenge、 Parallel Old;
●?串行(Serial)
???相較于并行的概念,單線程執(zhí)行。
???如果內(nèi)存不夠,則程序暫停,啟動(dòng)JVM垃圾回收器進(jìn)行垃圾回收?;厥胀?,再啟動(dòng)程序的線程。


●?并發(fā)(Concurrent):指用戶線程與垃圾收集線程同時(shí)執(zhí)行(但不一定是并行的,可能會(huì)交替執(zhí)行),垃圾回收線程在執(zhí)行時(shí)不會(huì)停頓用戶程序的運(yùn)行。
???用戶程序在繼續(xù)運(yùn)行,而垃圾收集程序線程運(yùn)行于另一個(gè)CPU上;
???如: CMS、G1

安全點(diǎn)與安全區(qū)域
安全點(diǎn)(Safepoint)
程序執(zhí)行時(shí)并非在所有地方都能停頓下來(lái)開始GC,只有在特定的位置才能停頓下來(lái)開始GC,這些位置稱為“安全點(diǎn)(Safepoint)”。
Safe Point的選擇很重要,如果太少可能導(dǎo)致GC等待的時(shí)間太長(zhǎng),如果太頻繁可能導(dǎo)致運(yùn)行時(shí)的性能問(wèn)題。大部分指令的執(zhí)行時(shí)間都非常短暫,通常會(huì)根據(jù)“是否具有讓程序長(zhǎng)時(shí)間執(zhí)行的特征”為標(biāo)準(zhǔn)。比如:選擇些執(zhí)行時(shí)間較長(zhǎng)的指令作為Safe Point, 如方法調(diào)用、循環(huán)跳轉(zhuǎn)和異常跳轉(zhuǎn)等。
如何在GC發(fā)生時(shí),檢查所有線程都跑到最近的安全點(diǎn)停頓下來(lái)呢?
●?搶先式中斷: ( 目前沒(méi)有虛擬機(jī)采用了)
首先中斷所有線程。如果還有線程不在安全點(diǎn),就恢復(fù)線程,讓線程跑到安全點(diǎn)。|
●?主動(dòng)式中斷:
設(shè)置一個(gè)中斷標(biāo)志,各個(gè)線程運(yùn)行到Safe Point的時(shí) 候主動(dòng)輪詢這個(gè)標(biāo)志,如果中斷標(biāo)志為真,則將自己進(jìn)行中斷掛起。
安全區(qū)域(Safe Region)
Safepoint機(jī)制保證了程序執(zhí)行時(shí),在不太長(zhǎng)的時(shí)間內(nèi)就會(huì)遇到可進(jìn)入GC的Safepoint 。但是,程序“不執(zhí)行”的時(shí)候呢?例如線程處于Sleep狀態(tài)或Blocked狀態(tài),這時(shí)候線程無(wú)法響應(yīng)JVM 的中斷請(qǐng)求,“走” 到安全點(diǎn)去中斷掛起,JVM 也不太可能等待線程被喚醒。對(duì)于這種情況,就需要安全區(qū)域(Safe Region) 來(lái)解決。
安全區(qū)域是指在一段代碼片段中,對(duì)象的引用關(guān)系不會(huì)發(fā)生變化,在這個(gè)區(qū)域中的任何位置開始GC都是安全的。我們也可以把Safe Region 看做是被擴(kuò)展了的Safepoint。 .
實(shí)際執(zhí)行時(shí):
1、當(dāng)線程運(yùn)行到Safe Region的代碼時(shí), 首先標(biāo)識(shí)已經(jīng)進(jìn)入了Safe Region,如果這段時(shí)間內(nèi)發(fā)生GC,JVM會(huì)忽略標(biāo)識(shí)為Safe Region狀態(tài)的線程;
2、當(dāng)線程即將離開Safe Region時(shí), 會(huì)檢查JVM是否已經(jīng)完成GC,如果完成了,則繼續(xù)運(yùn)行,否則線程必須等待直到收到可以安全離開Safe Region的信號(hào)為止;
引用
我們希望能描述這樣一類對(duì)象: 當(dāng)內(nèi)存空間還足夠時(shí),則能保留在內(nèi)存中;如果內(nèi)存空間在進(jìn)行垃圾收集后還是很緊張,則可以拋棄這些對(duì)象。
【既偏門又非常高頻的面試題】強(qiáng)引用、軟引用、弱引用、虛引用有什么區(qū)別?具體使用場(chǎng)景是什么?
在JDK 1.2版之 后,Java對(duì)引用的概念進(jìn)行了擴(kuò)充,將引用分為強(qiáng)引用(Strong Reference)、軟引用(Soft Reference) 、弱引用(Weak Reference)和虛引用(Phantom Reference)4種,這4種引用強(qiáng)度依次逐漸減弱。
除強(qiáng)引用外,其他3種引用均可以在java. lang. ref包中找到它們的身影。如下圖,顯示了這3種引用類型對(duì)應(yīng)的類,開發(fā)人員可以在應(yīng)用程序中直接使用它們。
Reference子類中只有終結(jié)器引用是包內(nèi)可見(jiàn)的,其他3種引用類型均為public,可以在應(yīng)用程序中直接使用
強(qiáng)引用(StrongReference)——不回收
最傳統(tǒng)的“引用”的定義,是指在程序代碼之中普遍存在的引用賦值,即類似“Object obj=new object( )”這種引用關(guān)系。無(wú)論任何情況下,只要強(qiáng)引用關(guān)系還存在,垃圾收集器就永遠(yuǎn)不會(huì)回收掉被引用的對(duì)象。
在Java程序中,最常見(jiàn)的引用類型是強(qiáng)引用(普通系統(tǒng)99%以上都是強(qiáng)引用),也就是我們最常見(jiàn)的普通對(duì)象引用,也是默認(rèn)的引用類型。
當(dāng)在Java語(yǔ)言中使用new操作符創(chuàng)建一個(gè)新的對(duì)象, 并將其賦值給一個(gè)變量的時(shí)候, 這個(gè)變量就成為指向該對(duì)象的一個(gè)強(qiáng)引用。
強(qiáng)引用的對(duì)象是可觸及的,垃圾收集器就永遠(yuǎn)不會(huì)回收掉被引用的對(duì)象。
對(duì)于一個(gè)普通的對(duì)象,如果沒(méi)有其他的引用關(guān)系,只要超過(guò)了引用的作用域或者顯式地將相應(yīng)(強(qiáng))引用賦值為null,就是可以當(dāng)做垃圾被收集了,當(dāng)然具體回收時(shí)機(jī)還是要看垃圾收集策略。
相對(duì)的,軟引用、弱引用和虛引用的對(duì)象是軟可觸及、弱可觸及和虛可觸及的,在一定條件下,都是可以被回收的。所以,強(qiáng)引用是造成Java內(nèi)存泄漏的主要原因之一。
例子
StringBuffer str = new StringBuffer("hello");
局部變量str指向StringBuffer實(shí)例所在堆空間,通過(guò)str可以操作該實(shí)例,那么str就是StringBuffer實(shí)例的強(qiáng)引用
對(duì)應(yīng)的內(nèi)存結(jié)構(gòu):

此時(shí)如果再進(jìn)行一個(gè)賦值語(yǔ)句:
StringBuffer str1 = str;
對(duì)應(yīng)的內(nèi)存結(jié)構(gòu):

本例中的兩個(gè)引用,都是強(qiáng)引用,強(qiáng)引用具備以下特點(diǎn):
●?強(qiáng)引用可以直接訪問(wèn)目標(biāo)對(duì)象。
●?強(qiáng)引用,所指向的對(duì)象在任何時(shí)候都不會(huì)被系統(tǒng)回收,虛擬機(jī)寧愿拋出OOM異常,也不會(huì)回收強(qiáng)引用所指向?qū)ο蟆?br>
●?強(qiáng)引用可能導(dǎo)致內(nèi)存泄漏。
軟引用(SoftReference)——內(nèi)存不足即回收
在系統(tǒng)將要發(fā)生內(nèi)存溢出之前,將會(huì)把這些對(duì)象列入回收范圍之中進(jìn)行第二次回收。如果這次回收后還沒(méi)有足夠的內(nèi)存,才會(huì)拋出內(nèi)存溢出異常。
軟引用是用來(lái)描述一些還有用,但非必需的對(duì)象。只被軟引用關(guān)聯(lián)著的對(duì)象,在系統(tǒng)將要發(fā)生內(nèi)存溢出異常前,會(huì)把這些對(duì)象列進(jìn)回收范圍之中進(jìn)行第二次回收,如果這次回收還沒(méi)有足夠的內(nèi)存,才會(huì)拋出內(nèi)存溢出異常。
軟引用通常用來(lái)實(shí)現(xiàn)內(nèi)存敏感的緩存。比如:高速緩存就有用到軟引用。如果還有空閑內(nèi)存,就可以暫時(shí)保留緩存,當(dāng)內(nèi)存不足時(shí)清理掉,這樣就保證了使用緩存的同時(shí),不會(huì)耗盡內(nèi)存。
垃圾回收器在某個(gè)時(shí)刻決定回收軟可達(dá)的對(duì)象的時(shí)候,會(huì)清理軟引用,并可選地把引用存放到一個(gè)引用隊(duì)列(Reference Queue )。
類似弱引用,只不過(guò)Java虛擬機(jī)會(huì)盡量讓軟引用的存活時(shí)間長(zhǎng)一些,迫不得已才清理。
在JDK 1.2版本之后提供了java.lang.ref.SoftReference類來(lái)實(shí)現(xiàn)軟引用
Object obj = new Object(); //聲明強(qiáng)引用
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null; //銷毀強(qiáng)引用
//或者可以這樣寫
SoftReference<Object> sf1 = new SoftReference<Object>(new Object());
弱引用(WeakReference)——發(fā)現(xiàn)即回收
被弱引用關(guān)聯(lián)的對(duì)象只能生存到下一次垃圾收集之前。當(dāng)垃圾收集器工作時(shí),無(wú)論內(nèi)存空間是否足夠,都會(huì)回收掉被弱引用關(guān)聯(lián)的對(duì)象。
弱引用也是用來(lái)描述那些非必需對(duì)象,只被弱引用關(guān)聯(lián)的對(duì)象只能生存到下一次垃圾收集發(fā)生止。在系統(tǒng)GC時(shí),只要發(fā)現(xiàn)弱引用,不管系統(tǒng)堆空間使用是否充足,都會(huì)回收掉只被弱引用關(guān)聯(lián)的對(duì)象。
但是,由于垃圾回收器的線程通常優(yōu)先級(jí)很低,因此,并不一定能很快地發(fā)現(xiàn)持有弱引用的對(duì)象。在這種情況下,弱引用對(duì)象可以存在較長(zhǎng)的時(shí)間。
弱引用和軟引用一樣,在構(gòu)造弱引用時(shí),也可以指定一個(gè)引用隊(duì)列,當(dāng)弱引用對(duì)象被回收時(shí),就會(huì)加入指定的引用隊(duì)列,通過(guò)這個(gè)隊(duì)列可以跟蹤對(duì)象的回收情況。
軟引用、弱引用都非常適合來(lái)保存那些可有可無(wú)的緩存數(shù)據(jù)。如果這么做,當(dāng)系統(tǒng)內(nèi)存不足時(shí),這些緩存數(shù)據(jù)會(huì)被回收,不會(huì)導(dǎo)致內(nèi)存溢出。而當(dāng)內(nèi)存資源充足時(shí),這些緩存數(shù)據(jù)又可以存在相當(dāng)長(zhǎng)的時(shí)間,從而起到加速系統(tǒng)的作用。
在JDK 1.2版本之后提供了java.lang.ref.WeakReference類來(lái)實(shí)現(xiàn)弱引用
Object obj = new Object(); //聲明強(qiáng)引用
WeakReference<Object> wr = new WeakReference<Object>(obj);
obj = null; //銷毀強(qiáng)引用
//或者可以這樣寫
WeakReference<Object> wr1 = new WeakReference<Object>(new Object());
弱引用對(duì)象與軟引用對(duì)象的最大不同就在于,當(dāng)GC在進(jìn)行回收時(shí),需要通過(guò)算法檢查是否回收軟引用對(duì)象,而對(duì)于弱引用對(duì)象,GC總是進(jìn)行回收。弱引用對(duì)象更容易、更快被GC回收。
面試題:你開發(fā)中使用過(guò)WeakHashMap嗎?
虛引用(PhantomReference)——對(duì)象回收跟蹤
一個(gè)對(duì)象是否有虛引用的存在,完全不會(huì)對(duì)其生存時(shí)間構(gòu)成影響,也無(wú)法通過(guò)虛引用來(lái)獲得一個(gè)對(duì)象的實(shí)例。 為一個(gè)對(duì)象設(shè)置虛引用關(guān)聯(lián)的唯一目的就是能在這個(gè)對(duì)象被收集器回收時(shí)收到一個(gè)系統(tǒng)通知。
也稱為“幽靈引用”或者“幻影引用”,是所有引用類型中最弱的一一個(gè)。
一個(gè)對(duì)象是否有虛引用的存在,完全不會(huì)決定對(duì)象的生命周期。如果一個(gè)對(duì)象僅持有虛引用,那么它和沒(méi)有引用幾乎是一樣的,隨時(shí)都可能被垃圾回收器回收。
它不能單獨(dú)使用,也無(wú)法通過(guò)虛引用來(lái)獲取被引用的對(duì)象。當(dāng)試圖通過(guò)虛引用的get()方法取得對(duì)象時(shí),總是null。
為一個(gè)對(duì)象設(shè)置虛引用關(guān)聯(lián)的唯一目的在于跟蹤垃圾回收過(guò)程。比如:能在這個(gè)對(duì)象被收集器回收時(shí)收到一個(gè)系統(tǒng)通知。
●?虛引用必須和引用隊(duì)列一起使用。虛引用在創(chuàng)建時(shí)必須提供一個(gè)引用隊(duì)列作為參數(shù)。當(dāng)垃圾回收器準(zhǔn)備回收一個(gè)對(duì)象時(shí),如果發(fā)現(xiàn)它還有虛引用,就會(huì)在回收對(duì)象后,將這個(gè)虛引用加入引用隊(duì)列,以通知應(yīng)用程序?qū)ο蟮幕厥涨闆r。
●?由于虛引用可以跟蹤對(duì)象的回收時(shí)間,因此,也可以將- -些資源釋放操作放置在虛引用中執(zhí)行和記錄。
●?在JDK 1.2版之后提供了PhantomReference類來(lái)實(shí)現(xiàn)虛引用。
object obj = new object();
ReferenceQueue phantomQueue = new ReferenceQueue();
PhantomReference<object> pf = new PhantomReference<Object>(obj, phantomQueue);
obj = null;
終結(jié)器引用
●?它用以實(shí)現(xiàn)對(duì)象的finalize()方法,也可以稱為終結(jié)器引用
●?無(wú)需手動(dòng)編碼,其內(nèi)部配合引用隊(duì)列使用。
●?在GC時(shí),終結(jié)器引用入隊(duì)。由Finali zer線程通過(guò)終結(jié)器引用找到被引用對(duì)象并調(diào)用它的finalize()方法,第二次GC時(shí)才能回收被引用對(duì)象。