JVM垃圾回收算法

原文地址:https://xeblog.cn/articles/23

確定可回收對象

引用計(jì)數(shù)法

給對象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用這個(gè)對象的時(shí)候,計(jì)數(shù)器的值就加1肮塞;當(dāng)對象的引用失效時(shí),計(jì)數(shù)器的值就減1;任何時(shí)刻計(jì)數(shù)器為0的對象就被判定為可回收的對象千康。
存在兩個(gè)對象之間互相循環(huán)引用的問題

Object obj1 = obj2
Object obj2 = obj1

對象 obj1 引用了對象 obj2 ,對象 obj2 又引用著對象 obj1铲掐,兩個(gè)對象互相引用拾弃,使得計(jì)數(shù)器都不能為0,這種情況如果使用 引用計(jì)數(shù)法 就無法判斷對象是否是可回收的摆霉。

可達(dá)性分析算法

通過一系列的稱為 GC Roots 的對象作為起始點(diǎn)豪椿,從這些節(jié)點(diǎn)開始向下搜索,搜索所走過的路徑稱為 引用鏈 携栋,當(dāng)一個(gè)對象到 GC Roots 沒有任何 引用鏈 相連時(shí)搭盾,則證明此對象是可回收的。

image

如圖所示婉支,對象 Object 5鸯隅、Object 6、Object 7 雖然互相有關(guān)聯(lián)向挖,但是它們到 GC Roots 是不可達(dá)的蝌以,所以它們將會被暫定為是可回收的對象。但此時(shí)判定并沒有完全結(jié)束何之,因?yàn)榕卸ㄒ粋€(gè)對象是否是可回收是需要經(jīng)過兩次標(biāo)記過程的跟畅,上述是第一次的標(biāo)記過程,第二次標(biāo)記則是將第一次標(biāo)記的對象進(jìn)行一次篩選:通過判斷該對象是否需要執(zhí)行 finalize() 方法溶推。如果該對象覆蓋了 finalize() 方法徊件,并且系統(tǒng)沒有運(yùn)行過該方法(finalize() 方法全局只運(yùn)行一次),則表示該對象需要執(zhí)行finalize() 方法悼潭,那么這個(gè)對象將會被放入到一個(gè)叫 F-Queue 的隊(duì)列中庇忌,等待虛擬機(jī)中的一個(gè)低優(yōu)先級的Finalizer 線程去執(zhí)行它。在執(zhí)行 finalize() 方法的過程中舰褪,只要該對象沒有和 GC Roots 引用鏈上的任何一個(gè)對象有關(guān)聯(lián)皆疹,這個(gè)對象才能被真正的定為是可回收的對象。

image

可以作為 GC Roots 的對象:

  • 虛擬機(jī)棧(棧幀中的本地變量表)中引用的對象占拍;
  • 方法區(qū)中類靜態(tài)屬性引用的對象略就;
  • 方法區(qū)中常量引用的對象捎迫;
  • 本地方法棧中JNI(Native方法)引用的對象。

JVM就是采用 可達(dá)性分析算法 來判斷對象是否是可回收的表牢。

回收方法區(qū)

方法區(qū)處于JVM的永久代區(qū)域窄绒,且永久代的垃圾回收效率遠(yuǎn)低于堆中(尤其是在新生代中)的回收效率,對于這塊區(qū)域主要是回收兩部分內(nèi)容:廢棄常量和無用類崔兴。

常量回收

回收常量與回收J(rèn)ava堆中的對象非常類似彰导。如果當(dāng)前系統(tǒng)中沒有任何一個(gè)變量與常量A相等,常量A也沒有在任何地方被引用敲茄,則常量A就是可回收的位谋。

類回收

判斷一個(gè)類是否可回收是非常苛刻的堰燎,需要同時(shí)滿足3個(gè)條件:

  • 該類的所有實(shí)例都已經(jīng)被回收掏父,Java堆中不存在該類的任何實(shí)例;
  • 加載該類的 ClassLoader 已經(jīng)被回收秆剪;
  • 該類對應(yīng)的 java.lang.Class 對象沒有在任何地方被引用赊淑,無法在任何地方通過反射訪問該類的方法。

垃圾回收算法

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

首先通過 可達(dá)性分析算法 標(biāo)記出所有需要回收的對象仅讽,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對象陶缺。

缺點(diǎn)

  • 標(biāo)記和清除的效率都不高。
  • 標(biāo)記清除后會產(chǎn)生大量不連續(xù)的內(nèi)存碎片洁灵,空間碎片太多可能會導(dǎo)致程序在運(yùn)行過程中需要分配較大對象時(shí)组哩,無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動作。

復(fù)制算法

將可用內(nèi)存按容量分為大小相等的兩塊处渣,每次只使用其中的一塊伶贰,當(dāng)這一塊內(nèi)存用完時(shí),就將還存活的對象復(fù)制到另外一塊上罐栈,然后把已使用過的內(nèi)存空間一次性清理掉黍衙。這樣使得每次都是對整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收,內(nèi)存分配時(shí)也就不用考慮內(nèi)存碎片等復(fù)雜情況荠诬,只要移動堆頂指針琅翻,按順序分配內(nèi)存即可,簡單高效柑贞。

缺點(diǎn)

  • 將可用內(nèi)存縮小為原來的一半了方椎。

優(yōu)點(diǎn)

  • 解決了內(nèi)存碎片的問題。
  • 新生代中采用這種算法效率較高钧嘶。

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

復(fù)制收集算法在對象存活率較高時(shí)就要進(jìn)行較多的復(fù)制操作棠众,效率將會變低,老年代一般不能直接選用這種算法。
根據(jù)老年代的特點(diǎn)闸拿,提出了一種“標(biāo)記-整理”算法空盼,標(biāo)記過程與“標(biāo)記-清除”算法一樣,不同的是這種算法不直接對可回收對象進(jìn)行清理新荤,而是讓所有存活的對象都向一端移動揽趾,然后直接清理掉端邊界以外的內(nèi)存。

缺點(diǎn)

  • 標(biāo)記和整理的效率都不高苛骨。

優(yōu)點(diǎn)

  • 解決了內(nèi)存碎片的問題篱瞎。

分代回收算法

根據(jù)對象存活周期的不同,將 Java堆內(nèi)存 劃分為 新生代老年代痒芝,這樣可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)幕厥账惴ā?/p>

新生代: 每次垃圾回收時(shí)都發(fā)現(xiàn)有大批對象死去奔缠,只有少量對象存活,可采用 復(fù)制算法吼野,只需要付出少量存活對象的復(fù)制成本就可以完成回收。

老年代: 對象存活率高两波,沒有額外空間對它進(jìn)行分配擔(dān)保瞳步,必須使用 標(biāo)記-清除標(biāo)記-整理 算法進(jìn)行回收。

參考

  • 《深入理解Java虛擬機(jī):JVM高級特性與最佳實(shí)踐 第二版》
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腰奋,一起剝皮案震驚了整個(gè)濱河市单起,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌劣坊,老刑警劉巖嘀倒,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異局冰,居然都是意外死亡测蘑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門康二,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碳胳,“玉大人,你說我怎么就攤上這事沫勿“ぴ迹” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵产雹,是天一觀的道長诫惭。 經(jīng)常有香客問我,道長蔓挖,這世上最難降的妖魔是什么夕土? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮瘟判,結(jié)果婚禮上隘弊,老公的妹妹穿的比我還像新娘哈踱。我一直安慰自己,他們只是感情好梨熙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布开镣。 她就那樣靜靜地躺著,像睡著了一般咽扇。 火紅的嫁衣襯著肌膚如雪邪财。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天质欲,我揣著相機(jī)與錄音树埠,去河邊找鬼。 笑死嘶伟,一個(gè)胖子當(dāng)著我的面吹牛怎憋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播九昧,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼绊袋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铸鹰?” 一聲冷哼從身側(cè)響起癌别,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蹋笼,沒想到半個(gè)月后展姐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡剖毯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年圾笨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逊谋。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡墅拭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涣狗,到底是詐尸還是另有隱情谍婉,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布镀钓,位于F島的核電站穗熬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏丁溅。R本人自食惡果不足惜唤蔗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧妓柜,春花似錦箱季、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至作煌,卻和暖如春掘殴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粟誓。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工奏寨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鹰服。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓病瞳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親悲酷。 傳聞我的和親對象是個(gè)殘疾皇子套菜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

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