JVM學(xué)習(xí)筆記13(垃圾回收相關(guān)概念)

垃圾回收相關(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ò)于麻煩了。在一些特殊情況下镣屹,如我們正在編寫(xiě)一個(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ì)永久代垃圾回收(如溢豆,常量池回收蜒简、卸載不再需要的類(lèi)型)非常不積極,所以當(dāng)我們不斷添加新類(lèi)型的時(shí)候漩仙,永久代出現(xiàn)OutOfMemoryError也非常多見(jiàn)臭蚁,尤其是在運(yùn)行時(shí)存在大量動(dòng)態(tài)類(lèi)型生成的場(chǎng)合;類(lèi)似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ì)象,類(lèi)似一一個(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)存大小取決于磁盤(pán)交換區(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)的情況下奥裸,把用戶正常的工作線程全部停掉险掀。
●?開(kāi)發(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è)核也可以并行蒿叠。

●?適合科學(xué)計(jì)算,后臺(tái)處理等弱交互場(chǎng)景

并發(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)開(kāi)始GC宿稀,只有在特定的位置才能停頓下來(lái)開(kā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ū)域中的任何位置開(kāi)始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)線程即將離開(kāi)Safe Region時(shí)揽祥, 會(huì)檢查JVM是否已經(jīng)完成GC,如果完成了掠归,則繼續(xù)運(yùn)行,否則線程必須等待直到收到可以安全離開(kāi)Safe Region的信號(hào)為止;


引用

我們希望能描述這樣一類(lèi)對(duì)象: 當(dāng)內(nèi)存空間還足夠時(shí)绩鸣,則能保留在內(nèi)存中;如果內(nèi)存空間在進(jìn)行垃圾收集后還是很緊張,則可以拋棄這些對(duì)象纱兑。

【既偏門(mén)又非常高頻的面試題】強(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種引用類(lèi)型對(duì)應(yīng)的類(lèi)榜掌,開(kāi)發(fā)人員可以在應(yīng)用程序中直接使用它們优妙。

Reference子類(lèi)中只有終結(jié)器引用是包內(nèi)可見(jiàn)的,其他3種引用類(lèi)型均為public憎账,可以在應(yīng)用程序中直接使用

強(qiáng)引用(StrongReference)——不回收

最傳統(tǒng)的“引用”的定義套硼,是指在程序代碼之中普遍存在的引用賦值,即類(lèi)似“Object obj=new object( )”這種引用關(guān)系胞皱。無(wú)論任何情況下邪意,只要強(qiáng)引用關(guān)系還存在,垃圾收集器就永遠(yuǎn)不會(huì)回收掉被引用的對(duì)象朴恳。

在Java程序中抄罕,最常見(jiàn)的引用類(lèi)型是強(qiáng)引用(普通系統(tǒng)99%以上都是強(qiáng)引用),也就是我們最常見(jiàn)的普通對(duì)象引用于颖,也是默認(rèn)的引用類(lèi)型呆贿。

當(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 )白粉。

類(lèi)似弱引用传泊,只不過(guò)Java虛擬機(jī)會(huì)盡量讓軟引用的存活時(shí)間長(zhǎng)一些,迫不得已才清理鸭巴。

在JDK 1.2版本之后提供了java.lang.ref.SoftReference類(lèi)來(lái)實(shí)現(xiàn)軟引用

Object obj = new Object(); //聲明強(qiáng)引用
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null; //銷(xiāo)毀強(qiáng)引用
//或者可以這樣寫(xiě)
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)來(lái)實(shí)現(xiàn)弱引用

Object obj = new Object(); //聲明強(qiáng)引用
WeakReference<Object> wr = new WeakReference<Object>(obj);
obj = null; //銷(xiāo)毀強(qiáng)引用
//或者可以這樣寫(xiě)
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回收。

面試題:你開(kāi)發(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)通知磕瓷。

也稱為“幽靈引用”或者“幻影引用”,是所有引用類(lèi)型中最弱的一一個(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)來(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ì)象墓捻。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市坊夫,隨后出現(xiàn)的幾起案子砖第,更是在濱河造成了極大的恐慌,老刑警劉巖环凿,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梧兼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡智听,警方通過(guò)查閱死者的電腦和手機(jī)羽杰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)渡紫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人考赛,你說(shuō)我怎么就攤上這事腻惠。” “怎么了欲虚?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)悔雹。 經(jīng)常有香客問(wèn)我复哆,道長(zhǎng),這世上最難降的妖魔是什么腌零? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任梯找,我火速辦了婚禮,結(jié)果婚禮上益涧,老公的妹妹穿的比我還像新娘锈锤。我一直安慰自己,他們只是感情好闲询,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布久免。 她就那樣靜靜地躺著,像睡著了一般扭弧。 火紅的嫁衣襯著肌膚如雪阎姥。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天鸽捻,我揣著相機(jī)與錄音呼巴,去河邊找鬼。 笑死御蒲,一個(gè)胖子當(dāng)著我的面吹牛衣赶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播厚满,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼府瞄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了痰滋?” 一聲冷哼從身側(cè)響起摘能,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎敲街,沒(méi)想到半個(gè)月后团搞,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡多艇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年逻恐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡复隆,死狀恐怖拨匆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挽拂,我是刑警寧澤惭每,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站亏栈,受9級(jí)特大地震影響台腥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绒北,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一黎侈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闷游,春花似錦峻汉、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至业簿,卻和暖如春蛛碌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辖源。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工蔚携, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人克饶。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓酝蜒,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親矾湃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子亡脑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354