JVM中垃圾收集算法及垃圾收集器詳解

一使鹅、垃圾收集算法

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

最基礎(chǔ)的收集算法是“標(biāo)記-清除”(Mark-Sweep)算法揪阶,如同它的名字一樣,算法分為“標(biāo)記”和“清除”兩個階段患朱。

①首先標(biāo)記出所有需要回收的對象

②在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對象鲁僚。

不足:

效率問題:標(biāo)記和清除兩個過程的效率都不高

空間問題:標(biāo)記清除之后產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會導(dǎo)致以后程序運(yùn)行過程中需要分配較大對象時裁厅,無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動作冰沙。

2.復(fù)制算法

目的: 為了解決效率問題。

將可用內(nèi)存按容量大小劃分為大小相等的兩塊执虹,每次只使用其中的一塊拓挥。當(dāng)一塊內(nèi)存使用完了,就將還存活著的對象復(fù)制到另一塊上面袋励,然后再把已使用過的內(nèi)存空間一次清理掉侥啤。這樣使得每次都是對整個半?yún)^(qū)進(jìn)行內(nèi)存回收当叭,內(nèi)存分配時也就不用考慮內(nèi)存碎片等復(fù)雜情況。

缺點(diǎn): 將內(nèi)存縮小為了原來的一半盖灸。

image.png

現(xiàn)代的商業(yè)虛擬機(jī)都采用這種收集算法來回收新生代蚁鳖,IBM公司的專門研究表明,新生代中對象98%對象是“朝生夕死”的赁炎,所以不需要按照1:1的比例來劃分內(nèi)存空間醉箕,而是將內(nèi)存分為較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中一塊Survivor徙垫。HotSpot虛擬機(jī)中默認(rèn)Eden和Survivor的大小比例是8:1讥裤。

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

復(fù)制收集算法在對象存活率較高時,就要進(jìn)行較多的復(fù)制操作松邪,效率就會變低坞琴。 根據(jù)老年代的特點(diǎn),提出了“標(biāo)記-整理”算法逗抑。

標(biāo)記過程仍然與”標(biāo)記-清除“算法一樣剧辐,但后續(xù)步驟不是直接對可回收對象進(jìn)行清理,而是讓所有存活的對象都向一端移動邮府,然后直接清理掉邊界以外的內(nèi)存荧关。

4.分代收集算法

一般是把Java堆分為新生代和老年代,這樣就可以根據(jù)各個年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ā?/p>

在新生代中褂傀,每次垃圾收集時都發(fā)現(xiàn)有大批對象死去忍啤,只有少量存活,那就選用復(fù)制算法仙辟。

在老年代中同波,因?yàn)閷ο蟠婊盥矢摺]有額外空間對它進(jìn)行分配擔(dān)保叠国,就必須采用“標(biāo)記-清除”或“標(biāo)記-整理”算法來進(jìn)行回收未檩。

二、垃圾回收機(jī)制的一些知識

1.JVM中的年代

JVM中分為年輕代(Young generation)和老年代(Tenured generation)粟焊。

HotSpot JVM把年輕代分為了三部分:1個Eden區(qū)和2個Survivor區(qū)(分別叫from和to)冤狡。默認(rèn)比例為8:1,為啥默認(rèn)會是這個比例项棠,接下來我們會聊到悲雳。

一般情況下,新創(chuàng)建的對象都會被分配到Eden區(qū)(一些大對象特殊處理)香追,這些對象經(jīng)過第一次Minor GC后合瓢,如果仍然存活,將會被移到Survivor區(qū)透典。對象在Survivor區(qū)中每熬過一次Minor GC晴楔,年齡就會增加1歲迁央,當(dāng)它的年齡增加到一定程度時,就會被移動到年老代中滥崩。 因?yàn)槟贻p代中的對象基本都是朝生夕死的(80%以上),所以在年輕代的垃圾回收算法使用的是復(fù)制算法讹语,復(fù)制算法的基本思想就是將內(nèi)存分為兩塊钙皮,每次只用其中一塊,當(dāng)這一塊內(nèi)存用完顽决,就將還活著的對象復(fù)制到另外一塊上面短条。復(fù)制算法不會產(chǎn)生內(nèi)存碎片。

在GC開始的時候才菠,對象只會存在于Eden區(qū)和名為“From”的Survivor區(qū)茸时,Survivor區(qū)“To”是空的。緊接著進(jìn)行GC赋访,Eden區(qū)中所有存活的對象都會被復(fù)制到“To”可都,而在“From”區(qū)中,仍存活的對象會根據(jù)他們的年齡值來決定去向蚓耽。年齡達(dá)到一定值(年齡閾值渠牲,可以通過-XX:MaxTenuringThreshold來設(shè)置)的對象會被移動到年老代中,沒有達(dá)到閾值的對象會被復(fù)制到“To”區(qū)域步悠。經(jīng)過這次GC后签杈,Eden區(qū)和From區(qū)已經(jīng)被清空。這個時候鼎兽,“From”和“To”會交換他們的角色答姥,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”谚咬。不管怎樣鹦付,都會保證名為To的Survivor區(qū)域是空的。Minor GC會一直重復(fù)這樣的過程序宦,直到“To”區(qū)被填滿睁壁,“To”區(qū)被填滿之后,會將所有對象移動到年老代中互捌。

2.Minor GC和Full GC的區(qū)別

Minor GC:指發(fā)生在新生代的垃圾收集動作潘明,該動作非常頻繁。

Full GC/Major GC:指發(fā)生在老年代的垃圾收集動作秕噪,出現(xiàn)了Major GC钳降,經(jīng)常會伴隨至少一次的Minor GC。Major GC的速度一般會比Minor GC慢10倍以上腌巾。

3. 空間分配擔(dān)保

在發(fā)生Minor GC之前遂填,虛擬機(jī)會先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對象的總空間铲觉,如果這個條件成立,那么Minor GC可以 確保是安全的吓坚。如果不成立撵幽,則虛擬機(jī)會查看HandlePromotionFailure設(shè)置值是否允許擔(dān)保失敗。如果允許礁击,那會繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對象的平均大小盐杂,如果大于,則將嘗試進(jìn)行一次Minor GC哆窿,盡管這個Minor GC是有風(fēng)險的链烈。如果小于,或者HandlePromotionFailure設(shè)置不允許冒險挚躯,那這時也要改為進(jìn)行一次Full GC强衡。

以上便是在垃圾回收過程中,需要了解的一些必要的知識码荔。下面我們就來介紹具體的垃圾收集器漩勤。

三、垃圾收集器

上圖展示了7種作用于不同分代的收集器目胡,如果兩個收集器之間存在連線锯七,說明它們可以搭配使用。

1.Serial收集器

是最基本誉己、發(fā)展歷史最悠久的收集器眉尸。這是一個單線程收集器。但它的“單線程”的意義并不僅僅說明它只會使用一個CPU或一條收集線程去完成垃圾收集工作巨双,更重要的是它在進(jìn)行垃圾收集時噪猾,必須暫停其他所有的工作線程,直到它收集結(jié)束筑累。

image.png

是虛擬機(jī)運(yùn)行在Client模式下的默認(rèn)新生代收集器袱蜡。

優(yōu)勢: 簡單而高效(與其他收集器的單線程比),對于限定單個CPU的環(huán)境來說慢宗,Serial收集器由于沒有線程交互的開銷坪蚁,專心做垃圾收集自然可以獲得最高的單線程效率。

2.ParNew收集器

ParNew收集器其實(shí)就是Serial收集器的多線程版本镜沽。

是許多運(yùn)行在Server模式下的虛擬機(jī)中首選的新生代收集器敏晤,其中一個與性能無關(guān)但很重要的原因是,除了Serial收集器外缅茉,目前只有它能與CMS收集器配合工作嘴脾。

ParNew收集器默認(rèn)開啟的收集線程數(shù)與CPU的數(shù)量相同。 下圖是ParNew/Serial Old收集器運(yùn)行示意圖

image.png

3.Parallel Scavenge收集器

Parallel Scavenge收集器是一個新生代收集器,使用復(fù)制算法译打,又是并行的多線程收集器耗拓。

最大的特點(diǎn)是: Parallel Scavenge收集器的目標(biāo)是達(dá)到一個可控制的吞吐量。

所謂吞吐量就是CPU用于運(yùn)行用戶代碼的時間與CPU總消耗時間的比值奏司,即吞吐量=運(yùn)行用戶代碼時間/(運(yùn)行用戶代碼時間+垃圾收集時間)乔询。

高吞吐量則可以高效率地利用CPU時間,盡快完成程序的運(yùn)算任務(wù)韵洋,主要適合在后臺運(yùn)算而不需要太多交互的任務(wù)哥谷。

4.Serial Old收集器

Serial Old是Serial收集器的老年代版本,同樣是一個單線程收集器麻献,使用“標(biāo)記-整理”算法。這個收集器的主要意義也是在于給Client模式下虛擬機(jī)使用猜扮。

如果在Server模式下勉吻,它主要還有兩大用途

1.與Parallel Scavenge收集器搭配使用

2.作為CMS收集器的后備預(yù)案,在并發(fā)收集發(fā)生Conurrent Mode Failure使用旅赢。

5.Parallel Old收集器

Parallel Old是Parallel Scavenge收集器的老年代版本齿桃,使用多線程和“標(biāo)記-整理”算法。

在注重吞吐量以及CPU資源敏感的場合煮盼,都可以優(yōu)先考慮Parallel Scavenge+Parallel Old收集器

6.CMS(Concurrent Mark Sweep)收集器

是HotSpot虛擬機(jī)中第一款真正意義上的并發(fā)收集器短纵,它第一次實(shí)現(xiàn)了讓垃圾收集線程與用戶線程同時工作。

關(guān)注點(diǎn): 盡可能地縮短垃圾收集時用戶線程的停頓時間僵控。

CMS收集器是基于“標(biāo)記-清除”算法實(shí)現(xiàn)的香到,整個過程分為4個步驟

①初始標(biāo)記

②并發(fā)標(biāo)記

③重新標(biāo)記

④并發(fā)清除

其中,初始標(biāo)記报破,重新標(biāo)記這兩個步驟仍然需要“Stop The World”悠就。初始標(biāo)記僅僅只標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對象,速度很快充易。并發(fā)標(biāo)記階段就是 進(jìn)行GC Roots Tracing的過程梗脾。

重新標(biāo)記階段則是為了修正并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動的那一部分對象的標(biāo)記幾率,這個階段的停頓時間一般會比初始標(biāo)記階段稍長盹靴,但遠(yuǎn)比并發(fā)標(biāo)記時間短炸茧。

整個過程耗時最長的階段是并發(fā)標(biāo)記,并發(fā)清除過程稿静,但這兩個過程可以和用戶線程一起工作梭冠。

缺點(diǎn):

①CMS收集器對CPU資源非常敏感。在并發(fā)階段自赔,它雖然不會導(dǎo)致用戶線程停頓妈嘹,但是會因?yàn)檎加昧艘徊糠志€程(或者說CPU資源)而導(dǎo)致應(yīng)用程序變慢,總吞吐量會降低绍妨。

②CMS收集器無法處理浮動垃圾润脸,可能出現(xiàn)“Conurrent Mode Failure”失敗而導(dǎo)致另一次Full GC的產(chǎn)生柬脸。由于CMS并發(fā)清理階段用戶線程還在運(yùn)行著,伴隨程序運(yùn)行自然就還會產(chǎn)生新的垃圾毙驯,這一部分垃圾出現(xiàn)在標(biāo)記過程之后倒堕,CMS無法在檔次收集中處理掉它們,只好留待下一次GC時再清理掉爆价。這部分垃圾就稱為“浮動垃圾”垦巴。因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進(jìn)行收集,需要預(yù)留一部分空間提供并發(fā)收集時程序運(yùn)作使用铭段。在JDK1.5的默認(rèn)設(shè)置下骤宣,CMS收集器當(dāng)老年代使用了68%的空間后就會被激活。如果預(yù)留空間無法滿足程序需要序愚,就會出現(xiàn)一次“Concurrent Mode Failure”失敗憔披,這時虛擬機(jī)將啟動后備預(yù)案Serial Old。

③CMS是一款基于“標(biāo)記-清除”算法實(shí)現(xiàn)的收集器爸吮,所以會有大量空間碎片問題芬膝。

7.G1收集器

是當(dāng)今收集器技術(shù)發(fā)展的最前沿成果之一。是一款面向服務(wù)端應(yīng)用的垃圾收集器形娇。

特點(diǎn):

①并行與并發(fā)

能充分利用多CPU锰霜,多核環(huán)境下的硬件優(yōu)勢,縮短Stop-The-World停頓的時間桐早,同時可以通過并發(fā)的方式讓Java程序繼續(xù)執(zhí)行

②分代收集

可以不需要其他收集器的配合管理整個堆癣缅,但是仍采用不同的方式去處理分代的對象。

③空間整合

G1從整體上來看哄酝,采用基于“標(biāo)記-整理”算法實(shí)現(xiàn)收集器

G1從局部上來看所灸,采用基于“復(fù)制”算法實(shí)現(xiàn)。

④可預(yù)測停頓

使用G1收集器時炫七,Java堆內(nèi)存布局與其他收集器有很大差別爬立,它將整個Java堆劃分成為多個大小相等的獨(dú)立區(qū)域。 G1跟蹤各個Region里面的垃圾堆積的價值大型蚰摹(回收所獲得的空間大小以及回收所需時間的經(jīng)驗(yàn)值)侠驯,在后臺維護(hù)一個優(yōu)先列表,每次根據(jù)允許的收集時間奕巍,優(yōu)先回收價值最大的Region吟策。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市的止,隨后出現(xiàn)的幾起案子檩坚,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匾委,死亡現(xiàn)場離奇詭異拖叙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)赂乐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門薯鳍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人挨措,你說我怎么就攤上這事挖滤。” “怎么了浅役?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵斩松,是天一觀的道長。 經(jīng)常有香客問我觉既,道長砸民,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任奋救,我火速辦了婚禮,結(jié)果婚禮上反惕,老公的妹妹穿的比我還像新娘尝艘。我一直安慰自己,他們只是感情好姿染,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布背亥。 她就那樣靜靜地躺著,像睡著了一般悬赏。 火紅的嫁衣襯著肌膚如雪狡汉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天闽颇,我揣著相機(jī)與錄音盾戴,去河邊找鬼。 笑死兵多,一個胖子當(dāng)著我的面吹牛尖啡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播剩膘,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼衅斩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了怠褐?” 一聲冷哼從身側(cè)響起畏梆,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后奠涌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宪巨,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年铣猩,在試婚紗的時候發(fā)現(xiàn)自己被綠了揖铜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡达皿,死狀恐怖天吓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情峦椰,我是刑警寧澤龄寞,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站汤功,受9級特大地震影響物邑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜滔金,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一色解、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧餐茵,春花似錦科阎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至道批,卻和暖如春错英,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背隆豹。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工椭岩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人璃赡。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓簿煌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鉴吹。 傳聞我的和親對象是個殘疾皇子姨伟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

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