JVM的判斷對(duì)象是否已死和四種垃圾回收算法總結(jié)

面試題一:判斷對(duì)象是否已死

判斷對(duì)象是否已死就是找出哪些對(duì)象是已經(jīng)死掉的,以后不會(huì)再用到的至非,就像地上有廢紙钠署、飲料瓶和百元大鈔,掃地前要先判斷出地上廢紙和飲料瓶是垃圾荒椭,百元大鈔不是垃圾谐鼎。判斷對(duì)象是否已死有引用計(jì)數(shù)算法和可達(dá)性分析算法。

1.引用計(jì)數(shù)算法

給每一個(gè)對(duì)象添加一個(gè)引用計(jì)數(shù)器戳杀,每當(dāng)有一個(gè)地方引用它時(shí)该面,計(jì)數(shù)器值加 1;每當(dāng)有一個(gè)地方不再引用它時(shí)信卡,計(jì)數(shù)器值減 1隔缀,這樣只要計(jì)數(shù)器的值不為 0,就說(shuō)明還有地方引用它傍菇,它就不是無(wú)用的對(duì)象猾瘸。如下圖,對(duì)象 2 有 1 個(gè)引用丢习,它的引用計(jì)數(shù)器值為 1牵触,對(duì)象 1有兩個(gè)地方引用,它的引用計(jì)數(shù)器值為 2 咐低。


image.png

這種方法看起來(lái)非常簡(jiǎn)單揽思,但目前許多主流的虛擬機(jī)都沒(méi)有選用這種算法來(lái)管理內(nèi)存,原因就是當(dāng)某些對(duì)象之間互相引用時(shí)见擦,無(wú)法判斷出這些對(duì)象是否已死钉汗,如下圖,對(duì)象 1 和對(duì)象 2 都沒(méi)有被堆外的變量引用鲤屡,而是被對(duì)方互相引用损痰,這時(shí)他們雖然沒(méi)有用處了,但是引用計(jì)數(shù)器的值仍然是 1酒来,無(wú)法判斷他們是死對(duì)象卢未,垃圾回收器也就無(wú)法回收。

2.可達(dá)性分析算法

了解可達(dá)性分析算法之前先了解一個(gè)概念——GC Roots堰汉,垃圾收集的起點(diǎn)辽社,可以作為 GC Roots 的有虛擬機(jī)棧中本地變量表中引用的對(duì)象、方法區(qū)中靜態(tài)屬性引用的對(duì)象翘鸭、方法區(qū)中常量引用的對(duì)象爹袁、本地方法棧中 JNI(Native 方法)引用的對(duì)象。
當(dāng)一個(gè)對(duì)象到 GC Roots 沒(méi)有任何引用鏈相連(GC Roots 到這個(gè)對(duì)象不可達(dá))時(shí)矮固,就說(shuō)明此對(duì)象是不可用的失息,是死對(duì)象譬淳。
如下圖:object1、object2盹兢、object3邻梆、object4 和 GC Roots 之間有可達(dá)路徑,這些對(duì)象不會(huì)被回收绎秒,但 object5浦妄、object6、object7 到 GC Roots 之間沒(méi)有可達(dá)路徑见芹,這些對(duì)象就被判了死刑剂娄。


image.png

上面被判了死刑的對(duì)象(object5、object6玄呛、object7)并不是必死無(wú)疑阅懦,還有挽救的余地。進(jìn)行可達(dá)性分析后對(duì)象和 GC Roots 之間沒(méi)有引用鏈相連時(shí)徘铝,對(duì)象將會(huì)被進(jìn)行一次標(biāo)記耳胎,接著會(huì)判斷如果對(duì)象沒(méi)有覆蓋 Object的finalize() 方法或者 finalize() 方法已經(jīng)被虛擬機(jī)調(diào)用過(guò),那么它們就會(huì)被行刑(清除)惕它;如果對(duì)象覆蓋了 finalize() 方法且還沒(méi)有被調(diào)用怕午,則會(huì)執(zhí)行 finalize() 方法中的內(nèi)容,所以在 finalize() 方法中如果重新與 GC Roots 引用鏈上的對(duì)象關(guān)聯(lián)就可以拯救自己淹魄,但是一般不建議這么做郁惜,周志明老師也建議大家完全可以忘掉這個(gè)方法~

3.方法區(qū)回收

上面說(shuō)的都是對(duì)堆內(nèi)存中對(duì)象的判斷,方法區(qū)中主要回收的是廢棄的常量和無(wú)用的類甲锡。
判斷常量是否廢棄可以判斷是否有地方引用這個(gè)常量扳炬,如果沒(méi)有引用則為廢棄的常量。
判斷類是否廢棄需要同時(shí)滿足如下條件:
該類所有的實(shí)例已經(jīng)被回收(堆中不存在任何該類的實(shí)例)搔体。
加載該類的 ClassLoader 已經(jīng)被回收。
該類對(duì)應(yīng)的 java.lang.Class 對(duì)象在任何地方?jīng)]有被引用(無(wú)法通過(guò)反射訪問(wèn)該類的方法)半醉。
面試題二:常用四種垃圾回收算法
常用的垃圾回收算法有四種:標(biāo)記-清除算法疚俱、復(fù)制算法、標(biāo)記-整理算法缩多、分代收集算法呆奕。

1.標(biāo)記-清除算法

分為標(biāo)記和清除兩個(gè)階段,首先標(biāo)記出所有需要回收的對(duì)象衬吆,標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象梁钾,如下圖。
缺點(diǎn):標(biāo)記和清除兩個(gè)過(guò)程效率都不高逊抡;標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片姆泻。

image.png

2.復(fù)制算法

把內(nèi)存分為大小相等的兩塊零酪,每次存儲(chǔ)只用其中一塊,當(dāng)這一塊用完了拇勃,就把存活的對(duì)象全部復(fù)制到另一塊上四苇,同時(shí)把使用過(guò)的這塊內(nèi)存空間全部清理掉,往復(fù)循環(huán)方咆,如下圖月腋。

缺點(diǎn):實(shí)際可使用的內(nèi)存空間縮小為原來(lái)的一半,比較適合瓣赂。


image.png

3.標(biāo)記-整理算法

先對(duì)可用的對(duì)象進(jìn)行標(biāo)記榆骚,然后所有被標(biāo)記的對(duì)象向一段移動(dòng),最后清除可用對(duì)象邊界以外的內(nèi)存煌集,如下圖妓肢。


image.png

4.分代收集算法

把堆內(nèi)存分為新生代和老年代,新生代又分為 Eden 區(qū)牙勘、From Survivor 和 To Survivor职恳。一般新生代中的對(duì)象基本上都是朝生夕滅的,每次只有少量對(duì)象存活方面,因此采用復(fù)制算法放钦,只需要復(fù)制那些少量存活的對(duì)象就可以完成垃圾收集;老年代中的對(duì)象存活率較高恭金,就采用標(biāo)記-清除和標(biāo)記-整理算法來(lái)進(jìn)行回收操禀。


image.png

在這些區(qū)域的垃圾回收大概有如下幾種情況:

大多數(shù)情況下,新的對(duì)象都分配在Eden區(qū)横腿,當(dāng) Eden 區(qū)沒(méi)有空間進(jìn)行分配時(shí)颓屑,將進(jìn)行一次 Minor GC,清理 Eden 區(qū)中的無(wú)用對(duì)象耿焊。清理后揪惦,Eden 和 From Survivor 中的存活對(duì)象如果小于To Survivor 的可用空間則進(jìn)入To Survivor,否則直接進(jìn)入老年代)罗侯;Eden 和 From Survivor 中還存活且能夠進(jìn)入 To Survivor 的對(duì)象年齡增加 1 歲(虛擬機(jī)為每個(gè)對(duì)象定義了一個(gè)年齡計(jì)數(shù)器器腋,每執(zhí)行一次 Minor GC 年齡加 1),當(dāng)存活對(duì)象的年齡到達(dá)一定程度(默認(rèn) 15 歲)后進(jìn)入老年代钩杰,可以通過(guò) -XX:MaxTenuringThreshold 來(lái)設(shè)置年齡的值纫塌。

當(dāng)進(jìn)行了 Minor GC 后,Eden 還不足以為新對(duì)象分配空間(那這個(gè)新對(duì)象肯定很大)讲弄,新對(duì)象直接進(jìn)入老年代措左。
占 To Survivor 空間一半以上且年齡相等的對(duì)象,大于等于該年齡的對(duì)象直接進(jìn)入老年代避除,比如 Survivor 空間是 10M怎披,有幾個(gè)年齡為 4 的對(duì)象占用總空間已經(jīng)超過(guò) 5M胸嘁,則年齡大于等于 4 的對(duì)象都直接進(jìn)入老年代,不需要等到 MaxTenuringThreshold 指定的歲數(shù)钳枕。

在進(jìn)行 Minor GC 之前缴渊,會(huì)判斷老年代最大連續(xù)可用空間是否大于新生代所有對(duì)象總空間,如果大于鱼炒,說(shuō)明 Minor GC 是安全的衔沼,否則會(huì)判斷是否允許擔(dān)保失敗,如果允許昔瞧,判斷老年代最大連續(xù)可用空間是否大于歷次晉升到老年代的對(duì)象的平均大小指蚁,如果大于,則執(zhí)行 Minor GC自晰,否則執(zhí)行 Full GC凝化。
當(dāng)在 java 代碼里直接調(diào)用 System.gc() 時(shí),會(huì)建議 JVM 進(jìn)行 Full GC酬荞,但一般情況下都會(huì)觸發(fā) Full GC搓劫,一般不建議使用,盡量讓虛擬機(jī)自己管理 GC 的策略混巧。

永久代(方法區(qū))中用于存放類信息枪向,jdk1.6 及之前的版本永久代中還存儲(chǔ)常量、靜態(tài)變量等咧党,當(dāng)永久代的空間不足時(shí)秘蛔,也會(huì)觸發(fā) Full GC,如果經(jīng)過(guò) Full GC 還無(wú)法滿足永久代存放新數(shù)據(jù)的需求傍衡,就會(huì)拋出永久代的內(nèi)存溢出異常深员。
大對(duì)象(需要大量連續(xù)內(nèi)存的對(duì)象)例如很長(zhǎng)的數(shù)組,會(huì)直接進(jìn)入老年代蛙埂,如果老年代沒(méi)有足夠的連續(xù)大空間來(lái)存放倦畅,則會(huì)進(jìn)行 Full GC。

搜索公眾號(hào)【Java耕耘者】點(diǎn)擊小助理绣的,即可獲取大量?jī)?yōu)質(zhì)電子書(shū)和一份Java高級(jí)架構(gòu)資料叠赐、Spring源碼分析、Dubbo被辑、Redis、Netty敬惦、zookeeper盼理、Spring cloud、分布式等視頻資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末俄删,一起剝皮案震驚了整個(gè)濱河市宏怔,隨后出現(xiàn)的幾起案子奏路,更是在濱河造成了極大的恐慌,老刑警劉巖臊诊,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸽粉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡抓艳,警方通過(guò)查閱死者的電腦和手機(jī)触机,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)玷或,“玉大人儡首,你說(shuō)我怎么就攤上這事∑眩” “怎么了蔬胯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)位他。 經(jīng)常有香客問(wèn)我氛濒,道長(zhǎng),這世上最難降的妖魔是什么鹅髓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任舞竿,我火速辦了婚禮,結(jié)果婚禮上迈勋,老公的妹妹穿的比我還像新娘炬灭。我一直安慰自己,他們只是感情好靡菇,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布重归。 她就那樣靜靜地躺著,像睡著了一般厦凤。 火紅的嫁衣襯著肌膚如雪鼻吮。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,182評(píng)論 1 299
  • 那天较鼓,我揣著相機(jī)與錄音椎木,去河邊找鬼。 笑死博烂,一個(gè)胖子當(dāng)著我的面吹牛香椎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播禽篱,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼畜伐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了躺率?” 一聲冷哼從身側(cè)響起玛界,我...
    開(kāi)封第一講書(shū)人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤万矾,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后慎框,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體良狈,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年笨枯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了薪丁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡猎醇,死狀恐怖窥突,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情硫嘶,我是刑警寧澤阻问,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站沦疾,受9級(jí)特大地震影響称近,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哮塞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一刨秆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧忆畅,春花似錦衡未、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至绊诲,卻和暖如春送粱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背掂之。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工抗俄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人世舰。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓动雹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親跟压。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胰蝠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 面試題一:判斷對(duì)象是否已死 判斷對(duì)象是否已死就是找出哪些對(duì)象是已經(jīng)死掉的,以后不會(huì)再用到的,就像地上有廢紙姊氓、飲料瓶...
    風(fēng)平浪靜如碼閱讀 413評(píng)論 0 1
  • JVM架構(gòu) 當(dāng)一個(gè)程序啟動(dòng)之前,它的class會(huì)被類裝載器裝入方法區(qū)(Permanent區(qū))喷好,執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,664評(píng)論 0 7
  • 作者:一字馬胡 轉(zhuǎn)載標(biāo)志 【2017-11-12】 更新日志 日期更新內(nèi)容備注 2017-11-12新建文章初版 ...
    beneke閱讀 2,202評(píng)論 0 7
  • Java和C++之間有一堵由內(nèi)存動(dòng)態(tài)分配和垃圾收集技術(shù)所圍成的“高墻”翔横,墻外面的人想進(jìn)來(lái),墻里面的人想出來(lái)梗搅。 對(duì)象...
    胡二囧閱讀 1,087評(píng)論 0 4
  • 提到90后禾唁,第一反映是什么?叛逆无切?囂張荡短?自我?有沒(méi)有人像我一樣哆键,第一反映是老去掘托? 作為一個(gè)93年出生的名副...
    蔣小八閱讀 186評(píng)論 0 1