2020-03-18

理解JVM之垃圾收集器詳解

目錄


回到頂部

前言

垃圾收集器作為內(nèi)存回收的具體表現(xiàn)嗦董,Java虛擬機(jī)規(guī)范并未對(duì)垃圾收集器的實(shí)現(xiàn)做規(guī)定,因而不同版本的虛擬機(jī)有很大區(qū)別瘦黑,因而我們?cè)谶@里主要討論基于Sun HotSpot虛擬機(jī)1.6版本Update22,此虛擬機(jī)包含的收集器如下所示:


image

如圖展示了7種作用于不同分代的收集器京革,若兩個(gè)收集器之間存在連線,說明他們可以搭配使用幸斥。我們堆收集器進(jìn)行比較就是為了針對(duì)具體的情況選擇最合適的收集器匹摇。
回到頂部

一、Serial收集器

Serial是最基本甲葬,最早的收集器廊勃,曾是JDK1.3.1之前的虛擬機(jī)新生代唯一選擇,這個(gè)收集器是單線程收集器经窖,它不僅僅只會(huì)使用一個(gè)單線程或一條收集線程區(qū)完成垃圾收集工作坡垫,更重要的是當(dāng)進(jìn)行垃圾收集時(shí),其他工作線程必須暫停画侣,直到收集結(jié)束冰悠。下圖為Serial/Serial Old收集器運(yùn)行過程:


image

從JDK1.3到JDK1.7,HoSpot虛擬機(jī)開發(fā)團(tuán)隊(duì)一直在為消除或減少工作線程因內(nèi)存回收而導(dǎo)致停頓的現(xiàn)象而努力著,從Serial收集器配乱,到Parallel收集器屿脐,再到Concurrent Mark Sweep(CMS)用戶線程停頓時(shí)間不斷縮減,但此現(xiàn)象并未完全消除宪卿。
到目前為止的诵,Serial是虛擬機(jī)運(yùn)行在Client模式下的默認(rèn)的新生代收集器,它也有很多優(yōu)點(diǎn):簡(jiǎn)單高效(與其他收集器單線程相比)佑钾,對(duì)于限定單個(gè)CPU西疤,由于沒有線程交互開銷,垃圾收集獲得最高的單線程收集效率休溶。Serial收集器是運(yùn)行在Client模式下的虛擬機(jī)的好的選擇代赁。

回到頂部

二、ParNew收集器

ParNew收集器是Serial收集器的多線程版本兽掰,除使用多線程進(jìn)行垃圾收集外芭碍,其余行為包括扣Serial收集器可用的控制參數(shù)、收集算法孽尽、Stop The World 窖壕、對(duì)象分配規(guī)則、回收策略等與Serial完全一樣。ParNew收集器的工作過程如下圖所示:


image

ParNew是運(yùn)行在Server模式下虛擬機(jī)種的首選新生代收集器瞻讽,因?yàn)槌薙erial收集器鸳吸,目前只有它能夠與CMS收集器配合工作。ParNew收集器由于存在線程交互速勇,可能不會(huì)有比Serial更好的效果但隨著CPU數(shù)量的增加晌砾,它對(duì)于GC時(shí)系統(tǒng)資源的利用有很大好處。
此處區(qū)分以下并行和并發(fā):
并行(Parallel):多條垃圾收集線程并行工作烦磁,此時(shí)用戶線程仍處于等待狀態(tài)养匈。
并發(fā)(Concurrent):指用戶線程與垃圾收集線程同時(shí)執(zhí)行(不一定并行,可能交替執(zhí)行)都伪,用戶程序繼續(xù)運(yùn)行乖寒,垃圾收集程序運(yùn)行在另一個(gè)CPU上。

回到頂部

三院溺、Parallel Scavenge收集器

Parallel Scavenge收集器是一個(gè)新生代收集器,它時(shí)復(fù)制算法的收集器磅轻,也是并行的多線程收集器珍逸,它的關(guān)注點(diǎn)與其他收集器不同,其它收集器盡可能縮短用戶線程停頓時(shí)間,Parallel Scavenge收集器則是達(dá)到一個(gè)可控制的吞吐量(吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行代碼時(shí)間+垃圾收集時(shí)間))聋溜。停頓時(shí)間越短越適合需要用戶交互程序谆膳,良好相應(yīng)速度能提升用戶體驗(yàn);高吞吐量則可以最高效率的利用CPU時(shí)間撮躁,盡快完成程序任務(wù)漱病,適用于后臺(tái)運(yùn)算而不需要太多交互的任務(wù)。

回到頂部

四把曼、Serial Old收集器

Serial Old是Serial的老年版本杨帽,它也是單線程收集器,使用“標(biāo)記-整理“算法嗤军。它主要是被Client模式下的虛擬機(jī)使用注盈。在Server模式下,它有兩個(gè)用途:一是在JDK1.5及之前的本本種與Parallel Scavenge收集器搭配使用叙赚;二是作為CMS收集器的后備份預(yù)案老客,在并發(fā)收集發(fā)生Corrent Model Failure時(shí)候使用。Serial Old的工作過程如下圖所示:


image

回到頂部

五震叮、Parallel Old收集器

Parallel Old使用多線程和“標(biāo)記-整理”算法胧砰,于JDK1.6開始提供,是Parallel Scavenge收集器的老年代版本苇瓣。在其出現(xiàn)前尉间,老年代除了Serial old外別無選擇,由于Serial old的“拖累”,使用Parallel Scavenge未必能夠在整體上實(shí)現(xiàn)吞吐量最大化的效果乌妒。Parallel Old出現(xiàn)后汹想,“吞吐量”的黃金組合出現(xiàn)了,在注重吞吐量及CPU資源的敏感場(chǎng)合撤蚊,優(yōu)先考慮Parallel Old與Parallel Scavenge收集器組合古掏。Parallel Old工作過程如圖 所示:


image

回到頂部

六、CMS收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器侦啸。CMS收集器應(yīng)用于那些重視服務(wù)響應(yīng)速度槽唾,系統(tǒng)停頓短的場(chǎng)景。CMS應(yīng)用了“標(biāo)記-清除”算法光涂,他的運(yùn)作過程包括四個(gè)場(chǎng)景:

  1. 初始標(biāo)記(CMS initial mark)
  2. 并發(fā)標(biāo)記(CMS concurrent mark)
  3. 重新標(biāo)記(CMS ermark)
  4. 并發(fā)清除(CMS concurrent sweep)

由于在整個(gè)過程中耗時(shí)最長(zhǎng)的并發(fā)標(biāo)記與并發(fā)清除過程收集器線程可與用戶線程一起工作庞萍,因而,可看做并發(fā)標(biāo)記與并發(fā)清除的收集器線程是與用戶線程一起并發(fā)執(zhí)行的忘闻,其運(yùn)行過程如下圖所示:


image

CMS是一款優(yōu)秀的收集器钝计,他的主要優(yōu)點(diǎn)有:并發(fā)收集,低停頓齐佳,因而也稱為并發(fā)低停頓收集器私恬,但其仍有缺點(diǎn),主要表現(xiàn)在三個(gè)方面:

  1. CMS收集器對(duì)CPU資源非常敏感炼吴。面向并發(fā)設(shè)計(jì)的程序都對(duì)CPU比較敏感本鸣,在并發(fā)階段,它會(huì)占用一部分線程導(dǎo)致應(yīng)用程序變慢硅蹦,降低總吞吐量荣德。CMS默認(rèn)自動(dòng)回收線程數(shù)為(cpu數(shù)+3)/4,故當(dāng)cpu總數(shù)小于4 時(shí)童芹,幾乎要拿出50%的資源執(zhí)行線程收集器涮瞻。增量式并發(fā)收集器(i-CMS)就是為解決這種情況而創(chuàng)造的,他的思想是:并發(fā)標(biāo)記和并發(fā)清理時(shí)假褪,讓GC線程饲宛、用戶線程交替運(yùn)行,盡量減少GC獨(dú)占資源時(shí)間嗜价,雖然使得垃圾回收時(shí)間變長(zhǎng)艇抠,但降低了對(duì)用戶程序的影響。目前久锥,i-CMS已經(jīng)不再提倡用戶使用家淤。
  2. CMS收集器無法處理浮動(dòng)垃圾。當(dāng)出現(xiàn)“Concurrent Mode Failure”導(dǎo)致另一次Full GC的產(chǎn)生瑟由。此時(shí)絮重,CMS并發(fā)清理階段用戶線程還在運(yùn)行著,無法集中處理運(yùn)行程序產(chǎn)生的垃圾。由于垃圾收集階段用戶線程還在運(yùn)行青伤,需給線程預(yù)留內(nèi)存督怜,要是預(yù)留的內(nèi)存無法滿足需求,就會(huì)出現(xiàn)“Concurrent Mode Failure”失敗狠角,此時(shí)号杠,臨時(shí)啟用Serial Old進(jìn)行老年代垃圾回收,耗費(fèi)時(shí)間過長(zhǎng)丰歌。
  3. CMS算法是基于“標(biāo)記-清除”的收集器姨蟋,收集借書產(chǎn)生大量的空間碎片,當(dāng)無法找到足夠的連續(xù)空間存放對(duì)象就會(huì)觸動(dòng)Full GC立帖。未解決這個(gè)問題眼溶,CMS增加一個(gè)碎片整理時(shí)間,此過程無法并發(fā)晓勇,停頓時(shí)間變長(zhǎng)堂飞。

回到頂部

七、 G1收集器

G1收集器與CMS相比有兩點(diǎn)改進(jìn):一是G1是基于“標(biāo)記-整理”的收集器绑咱,不會(huì)產(chǎn)生空間碎片绰筛。二是他可以精確地控制停頓,能讓使用者指定在一個(gè)時(shí)間片段內(nèi)消耗在垃圾收集上的時(shí)間羡玛。G1可以在不犧牲吞吐量的前提下完成低停頓 內(nèi)存回收。G1將java堆劃分為多個(gè)大小獨(dú)立的區(qū)域宗苍,并根據(jù)區(qū)域的垃圾堆積程度稼稿,維護(hù)一個(gè)優(yōu)先列表,每次根據(jù)收集時(shí)間讳窟,優(yōu)先回收垃圾最多的區(qū)域让歼,保證來G1收集器在有效時(shí)間內(nèi)的的回收效率。

回到頂部

附:垃圾收集器參數(shù)匯總

參數(shù) 描述
UseSerialGC 虛擬機(jī)運(yùn)行在Client模式下的默認(rèn)值丽啡,打開此開關(guān)谋右,使用Serial+Serial Old收集器組合進(jìn)行內(nèi)存回收
UseParNewGC 打開此開關(guān)后,使用ParNew+Serial Old的收集器組合進(jìn)行內(nèi)存回收
UseConcMarkSweepGC 打開此開關(guān)后补箍,使用ParNew+CMS+Serial Old的收集器組合進(jìn)行內(nèi)存回收改执。Serial Old收集器將作為CMS收集器出現(xiàn)Concurrent Mode Failure失敗后的后備收集器使用
UseParallelGC 虛擬機(jī)運(yùn)行在Server模式下的默認(rèn)值,打開此開關(guān)后坑雅,使用Parallel Scavenge + Serial Old(PS MarkSweep)的收集器組合進(jìn)行內(nèi)存回收
UseParallelOldGC 打開此開關(guān)后辈挂,使用Parallel Scavenge + Parallel Old的收集器組合進(jìn)行內(nèi)存回收
SurvivorRatio 新生代中Eden區(qū)域與Survivor區(qū)域的容量比值,默認(rèn)值為8裹粤,代表Eden:Survivor=8:1
PretenureSizeThreshold 直接晉升到老年代的對(duì)象大小终蒂,設(shè)置這個(gè)參數(shù)后,大于這個(gè)參數(shù)的對(duì)象將直接在老年代分配
MaxTenuringThreshold 晉升到老年代的對(duì)象年齡,每個(gè)對(duì)象在堅(jiān)持過一次Minor GC之后拇泣,年齡就增加1噪叙,當(dāng)超過這個(gè)參數(shù)時(shí)就進(jìn)入老年代
UseAdaptiveSizePolicy 動(dòng)態(tài)調(diào)整Java堆中各個(gè)區(qū)域的大小以及進(jìn)入老年代的年齡
HandlePromotionFailure 是否允許分配擔(dān)保失敗,即老年代的剩余空間不足以應(yīng)付新生代的整個(gè)Eden和Survivor區(qū)的所有對(duì)象都存活的極端情況
ParallelGCThreads 設(shè)置并行GC時(shí)進(jìn)行內(nèi)存回收的線程數(shù)
GCTimeRatio GC時(shí)間占總時(shí)間的比率霉翔,默認(rèn)值為99睁蕾,即允許1%的GC時(shí)間。僅在使用Parallel Scavenge收集器時(shí)生效
MaxGCPauseMillis 設(shè)置GC的最大停頓時(shí)間早龟,僅在使用Parallel Scavenge收集器時(shí)生效
CMSInitingOccupancyFraction 設(shè)置CMS收集器在老年代空間被使用多少后觸發(fā)垃圾收集惫霸。默認(rèn)值為68%,僅在使用CMS收集器時(shí)生效
UseCMSCompactAtFullCollection 設(shè)置CMS收集器在完成垃圾收集后是否要進(jìn)行一次內(nèi)存碎片整理葱弟,僅在使用CMS收集器時(shí)生效
CMSFullGCsBeforeCompaction 設(shè)置CMS收集器在進(jìn)行若干次垃圾收集后再啟動(dòng)一次內(nèi)存碎片整理壹店。僅在使用CMS收集器時(shí)生效

本文主要參考自《深入理解Java虛擬機(jī)——JVM高級(jí)特性與最佳實(shí)踐》一書

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市芝加,隨后出現(xiàn)的幾起案子硅卢,更是在濱河造成了極大的恐慌,老刑警劉巖藏杖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件将塑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蝌麸,警方通過查閱死者的電腦和手機(jī)点寥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來来吩,“玉大人敢辩,你說我怎么就攤上這事〉芙” “怎么了戚长?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)怠苔。 經(jīng)常有香客問我同廉,道長(zhǎng),這世上最難降的妖魔是什么柑司? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任迫肖,我火速辦了婚禮,結(jié)果婚禮上攒驰,老公的妹妹穿的比我還像新娘咒程。我一直安慰自己,他們只是感情好讼育,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布帐姻。 她就那樣靜靜地躺著稠集,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饥瓷。 梳的紋絲不亂的頭發(fā)上剥纷,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音呢铆,去河邊找鬼晦鞋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛棺克,可吹牛的內(nèi)容都是我干的悠垛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼娜谊,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼确买!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起纱皆,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤湾趾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后派草,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搀缠,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年近迁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了艺普。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鉴竭,死狀恐怖歧譬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拓瞪,我是刑警寧澤缴罗,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布助琐,位于F島的核電站祭埂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏兵钮。R本人自食惡果不足惜蛆橡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掘譬。 院中可真熱鬧泰演,春花似錦、人聲如沸葱轩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至垃喊,卻和暖如春猾普,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背本谜。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工初家, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乌助。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓溜在,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親他托。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掖肋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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

  • 如果說垃圾收集算法是內(nèi)存回收的方法論,垃圾收集器就是內(nèi)存回收的具體實(shí)現(xiàn)上祈。Java虛擬機(jī)規(guī)范中對(duì)垃圾收集器應(yīng)該如何實(shí)...
    平頭哥2015閱讀 270評(píng)論 0 0
  • Java和C++之間有一堵由內(nèi)存動(dòng)態(tài)分配和垃圾收集技術(shù)所圍成的“高墻”培遵,墻外面的人想進(jìn)來,墻里面的人想出來登刺。 對(duì)象...
    胡二囧閱讀 1,089評(píng)論 0 4
  • 《深入理解Java虛擬機(jī)》筆記_第一遍 先取看完這本書(JVM)后必須掌握的部分籽腕。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,093評(píng)論 1 34
  • 1、java虛擬機(jī)發(fā)展史 1.1 Sun Classic jdk1.0-jdk1.4只能用解釋器方式解...
    茨菇雪菜閱讀 410評(píng)論 0 0
  • 來自: Android夢(mèng)想特工隊(duì)作者: Aaron主頁: http://www.wxtlife.com/原...
    技術(shù)特工隊(duì)閱讀 4,373評(píng)論 0 28