JVM垃圾收集器

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

image

新生代收集器

新生代均采用 復(fù)制 算法來(lái)回收內(nèi)存累驮。

Serial 收集器

最基本的樊拓、發(fā)展歷史最悠久的單線(xiàn)程的收集器。在進(jìn)行垃圾收集時(shí)坟桅,必須暫停其它所有的工作線(xiàn)程(Stop The World)页屠,直到它收集結(jié)束纵穿。它是 JVM 運(yùn)行在 Client 模式下的默認(rèn)新生代收集器,它比其它單線(xiàn)程的收集器更簡(jiǎn)單收毫、更高效攻走∫罂保可與 CMS 收集器 配合工作。

ParNew 收集器

Serial 收集器 的多線(xiàn)程版本昔搂。它是許多運(yùn)行在 Server 模式下的虛擬機(jī)首選的新生代收集器玲销,在使用 -XX:+UseConcMarkSweepGC 選項(xiàng)后的默認(rèn)新生代收集器,也可以通過(guò) -XX:+UseParNewGC 選項(xiàng)強(qiáng)制指定它摘符。它除了是多線(xiàn)程收集之外贤斜,其它和 Serial 收集器 基本一樣,它默認(rèn)開(kāi)啟的收集線(xiàn)程數(shù)與 CPU 的數(shù)量相同逛裤,在 CPU 非常多的環(huán)境下瘩绒,可通過(guò) -XX:ParallelGCThreads 參數(shù)限制垃圾收集的線(xiàn)程數(shù)〈澹可與 CMS 收集器 配合工作锁荔。

Parallel Scavenge 收集器

并行的多線(xiàn)程收集器,它的目標(biāo)是達(dá)到一個(gè)可控的吞吐量(吞吐量是 CPU 用于運(yùn)行用戶(hù)代碼的時(shí)間與 CPU 總消耗時(shí)間的比值)蝙砌。

 吞吐量 = 運(yùn)行用戶(hù)代碼的時(shí)間 / (運(yùn)行用戶(hù)代碼的時(shí)間 + 垃圾收集時(shí)間)

高吞吐量可以高效的利用 CPU 時(shí)間阳堕,盡快的完成程序的運(yùn)算任務(wù),主要適合在后臺(tái)運(yùn)算而不需要太多交互的任務(wù)拍霜。Parallel Scavenge 收集器 提供了兩個(gè)參數(shù)用于精確控制吞吐量: -XX:MaxGCPauseMillis-XX:GCTimeRatio嘱丢。

最大垃圾收集停頓時(shí)間:-XX:MaxGCPauseMillis

允許一個(gè)大于0的毫秒數(shù),收集器將盡可能保證內(nèi)存回收花費(fèi)時(shí)間不超過(guò)這個(gè)設(shè)定的值祠饺,它是以犧牲吞吐量和新生代空間來(lái)縮短 GC 停頓時(shí)間的越驻。

吞吐量大小:-XX:GCTimeRatio

允許一個(gè)大于0且小于100的整數(shù)道偷,垃圾收集時(shí)間占總時(shí)間的比率缀旁。

GC自適應(yīng)調(diào)節(jié)參數(shù):-XX:+UseAdaptiveSizePolicy

這是一個(gè)開(kāi)關(guān)參數(shù),當(dāng)它打開(kāi)后勺鸦,就不需要手動(dòng)指定新生代的大胁⑽ (-Xmn),EdenSurvivor 區(qū)的比例(-XX:SurvivorRatio)换途、晉升老年代對(duì)象年齡(-XX:PretenureSizeThreshold)等細(xì)節(jié)參數(shù)了懊渡,虛擬機(jī)會(huì)根據(jù)當(dāng)前系統(tǒng)的運(yùn)行情況收集性能監(jiān)控信息,動(dòng)態(tài)調(diào)整這些參數(shù)以提供最合適的停頓時(shí)間或最大的吞吐量军拟。

老年代收集器

老年代采用 標(biāo)記-整理標(biāo)記-清除 算法來(lái)回收內(nèi)存剃执。

Serial Old 收集器

它是 Serial 收集器 的老年代版本,也是一個(gè)單線(xiàn)程收集器懈息,使用 標(biāo)記-整理 算法肾档。這個(gè)收集器的主要意義也是在于給 Client 模式下的虛擬機(jī)使用,如果是在 Server 模式下,那么它主要還有兩大用途:

  • JDK1.5 以及之前版本中與 Parallel Scavenge 收集器 搭配使用怒见。
  • 作為 CMS收集器 的后備預(yù)案俗慈,在并發(fā)收集發(fā)生 Concurrent Mode Failure 時(shí)使用。

Parallel Old 收集器

它是 Parallel Scavenge 收集器 的老年代版本遣耍,使用多線(xiàn)程和 標(biāo)記-整理 算法闺阱。

CMS 收集器 (Concurrent Mark Sweep)

它是一種并發(fā)的、以獲取最短回收停頓時(shí)間為目標(biāo)的收集器配阵,使用 標(biāo)記-清除 算法實(shí)現(xiàn)的馏颂。運(yùn)行過(guò)程較為復(fù)雜示血,整個(gè)過(guò)程分為4個(gè)步驟:

  • 初始標(biāo)記(CMS Initial Marking)
  • 并發(fā)標(biāo)記(CMS Concurrent marking)
  • 重新標(biāo)記(CMS ReMarking)
  • 并發(fā)清除(CMS Concurrent Sweep)

初始標(biāo)記棋傍、重新標(biāo)記仍需要暫停其它所有的工作線(xiàn)程,初始標(biāo)記僅僅只是標(biāo)記一下 GC Roots 能直接關(guān)聯(lián)到的對(duì)象难审,速度很快瘫拣。并發(fā)標(biāo)記階段就是進(jìn)行 GC Roots 的可達(dá)性分析過(guò)程,而重新標(biāo)記階段則是為了修正并發(fā)標(biāo)記期間因用戶(hù)線(xiàn)程繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄告喊,這個(gè)階段的停頓時(shí)間一般會(huì)比初始標(biāo)記階段稍長(zhǎng)一些麸拄,但遠(yuǎn)比并發(fā)標(biāo)記的時(shí)間短。CMS 收集器 存在3個(gè)明顯的缺點(diǎn):

  • CMS收集器 會(huì)占用一部分線(xiàn)程而導(dǎo)致應(yīng)用程序變慢黔姜,總吞吐量會(huì)降低拢切。CMS 默認(rèn)啟功的回收線(xiàn)程數(shù)是(CPU數(shù)量 + 3)/ 4 ,相當(dāng)于當(dāng) CPU 在4個(gè)以上時(shí)秆吵,并發(fā)回收時(shí)垃圾收集線(xiàn)程不少于 25%CPU 資源淮椰,并隨著 CPU 數(shù)量的增加而下降。當(dāng) CPU 不足4個(gè)時(shí)纳寂,CMS 對(duì)用戶(hù)線(xiàn)程的影響就可能變得更大主穗。
  • CMS收集器 無(wú)法處理浮動(dòng)垃圾,可能出現(xiàn) Concurrent Mode Failure 失敗而導(dǎo)致另一次 Full GC 的產(chǎn)生毙芜。由于 CMS 并發(fā)清除階段用戶(hù)線(xiàn)程還在運(yùn)行著忽媒,伴隨程序運(yùn)行自然就還會(huì)有新的垃圾不斷產(chǎn)生,這一部分垃圾出現(xiàn)在標(biāo)記過(guò)程之后腋粥,CMS 無(wú)法在當(dāng)次收集中處理掉它們晦雨,只好留在下一次 GC 時(shí)再清理掉,這一部分垃圾就稱(chēng)為浮動(dòng)垃圾隘冲。
  • 由于 CMS收集器 使用的是 標(biāo)記-清除 算法闹瞧,所以垃圾回收后會(huì)產(chǎn)生大量的空間碎片。CMS 提供 -XX:+UseCMSCompactAtFullCollection 的開(kāi)關(guān)參數(shù)(默認(rèn)開(kāi)啟)对嚼,用于在 CMS 收集器頂不住要進(jìn)行 Full GC 時(shí)開(kāi)啟內(nèi)存碎片的合并整理過(guò)程夹抗,這個(gè)過(guò)程是無(wú)法并發(fā)執(zhí)行的,雖然空間碎片沒(méi)了纵竖,但是停頓時(shí)間不得不變長(zhǎng)漠烧。

全干工程師:G1收集器

G1收集器 是當(dāng)今收集器技術(shù)發(fā)展的最前沿成果之一杏愤。

上面所介紹的收集器,都只是負(fù)責(zé) Java堆 中的一部分內(nèi)存(新生代或老年代)已脓,而 G1 就不同了珊楼,它全干。
G1 將整個(gè) Java堆 劃分為多個(gè)大小相等的獨(dú)立區(qū)域(Region)度液,雖然還保留有新生代和老年代的概念厕宗,但是這兩部分內(nèi)存不再是物理隔離的,它們都是一部分不需要連續(xù)的 Region 的集合了堕担。

具備的特點(diǎn):

  • 并行與并發(fā):G1 能充分利用多 CPU 已慢、多核環(huán)境下的硬件優(yōu)勢(shì),使用多個(gè) CPU 來(lái)縮短 Stop The World 的停頓時(shí)間霹购。
  • 分代收集(全干工程師):G1 可以不需要與其它收集器配合就能獨(dú)立管理整個(gè) GC堆佑惠,根據(jù) 分代收集 的概念采用不同的方式去處理。
  • 空間整合:基于 標(biāo)記-整理復(fù)制 算法齐疙,不會(huì)產(chǎn)生內(nèi)存空間碎片膜楷。
  • 可預(yù)測(cè)的停頓:G1 可以建立可預(yù)測(cè)的停頓時(shí)間模型,將垃圾收集消耗的時(shí)間限制在一定的時(shí)間內(nèi)贞奋。

可預(yù)測(cè)的停頓時(shí)間模型

G1 之所以能夠建立可預(yù)測(cè)的停頓時(shí)間模型赌厅,是因?yàn)樗梢杂杏?jì)劃的避免在整個(gè) Java堆 中進(jìn)行全區(qū)域的垃圾收集。G1 通過(guò)跟蹤各個(gè) Region 里面的內(nèi)存堆積的價(jià)值大薪嗡(回收所獲得的空間大小以及回收所需時(shí)間的經(jīng)驗(yàn)值)特愿,在后臺(tái)維護(hù)一個(gè)優(yōu)先回收隊(duì)列,每次根據(jù)允許的收集時(shí)間催训,優(yōu)先回收價(jià)值最大的 Region洽议。這種使用 Region 劃分內(nèi)存空間以及有優(yōu)先級(jí)的區(qū)域回收方式,保證了 G1 收集器在有限的時(shí)間內(nèi)可以獲取盡可能高的收集效率漫拭。

避免全堆掃描且保證準(zhǔn)確性

G1 收集器中亚兄,Region 之間的對(duì)象引用以及其它收集器中的新生代與老年代之間的對(duì)象引用,虛擬機(jī)都是使用 Remembered Set 來(lái)避免全堆掃描的采驻。G1 中的每一個(gè) Region 都有一個(gè)與之對(duì)應(yīng)的 Remembered Set审胚,在對(duì) Reference 類(lèi)型的數(shù)據(jù)進(jìn)行寫(xiě)操作的時(shí)間,虛擬機(jī)會(huì)產(chǎn)生一個(gè)屏障暫時(shí)中斷寫(xiě)操作礼旅,然后檢查這個(gè)引用的對(duì)象是否處于不同的 Region 之中膳叨,如果是,就會(huì)通過(guò) CardTable 把相關(guān)引用信息記錄到被引用對(duì)象所屬的 RegionRemembered Set 中痘系。當(dāng)進(jìn)行內(nèi)存回收時(shí)菲嘴,在 GC Roots 的枚舉范圍內(nèi)加入 Remembered Set 即可保證不對(duì)全堆掃描也不會(huì)有遺漏。

G1運(yùn)行過(guò)程

如果不計(jì)算維護(hù) Remembered Set 的操作,G1 收集器的運(yùn)行過(guò)程大致可以分為4個(gè)步驟:

  • 初始標(biāo)記(G1 Initial Marking)
  • 并發(fā)標(biāo)記(G1 Concurrent Marking)
  • 最終標(biāo)記(G1 Final Marking)
  • 篩選回收(G1 Live Data Counting And Evacuation)

初始標(biāo)記階段只是簡(jiǎn)單的標(biāo)記一下 GC Roots 能直接關(guān)聯(lián)到的對(duì)象龄坪,并且修改TAMS(Next Top At Mark Start)的值昭雌,讓下一階段用戶(hù)程序并發(fā)運(yùn)行時(shí),能在正確可用的 Region 中創(chuàng)建新對(duì)象健田,這個(gè)階段需要停頓線(xiàn)程烛卧,但耗時(shí)很短。并發(fā)標(biāo)記階段也是進(jìn)行 GC Roots 的可達(dá)性分析過(guò)程妓局,耗時(shí)很長(zhǎng)但是可與用戶(hù)程序一起工作总放。最終標(biāo)記階段是為了修正并發(fā)標(biāo)記期間因用戶(hù)線(xiàn)程繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄,虛擬機(jī)將這段時(shí)間對(duì)象變化記錄在線(xiàn)程的 Remembered Set Logs 中好爬,這個(gè)階段需要把 Remembered Set Logs 中的數(shù)據(jù)合并到 Remembered Set 里局雄,需要停頓線(xiàn)程,但是可以并行執(zhí)行抵拘。
最后的篩選回收階段會(huì)對(duì) Region 的回收價(jià)值和成本進(jìn)行排序哎榴,根據(jù)用戶(hù)所期望的 GC 停頓時(shí)間來(lái)制定回收計(jì)劃型豁。

查看JVM所使用的收集器

java -XX:+PrintCommandLineFlags -version

在終端執(zhí)行上述命令后僵蛛,即可查看 JVM 所使用的收集器。

image

-XX:+UseParallelGC : 是虛擬機(jī)運(yùn)行在 Server 模式下的默認(rèn)值迎变,打開(kāi)此開(kāi)關(guān)后充尉,使用 Parallel Scavenge + Serial Old (PS MarkSweep) 的收集器組合進(jìn)行內(nèi)存回收。

參考

  • 《深入理解Java虛擬機(jī):JVM高級(jí)特性與最佳實(shí)踐 第二版》
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末衣形,一起剝皮案震驚了整個(gè)濱河市驼侠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谆吴,老刑警劉巖倒源,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異句狼,居然都是意外死亡笋熬,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)腻菇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)胳螟,“玉大人,你說(shuō)我怎么就攤上這事筹吐√撬剩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵丘薛,是天一觀(guān)的道長(zhǎng)嘉竟。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么舍扰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任铡俐,我火速辦了婚禮,結(jié)果婚禮上妥粟,老公的妹妹穿的比我還像新娘审丘。我一直安慰自己,他們只是感情好勾给,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布滩报。 她就那樣靜靜地躺著,像睡著了一般播急。 火紅的嫁衣襯著肌膚如雪脓钾。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天桩警,我揣著相機(jī)與錄音可训,去河邊找鬼。 笑死捶枢,一個(gè)胖子當(dāng)著我的面吹牛握截,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播烂叔,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼谨胞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蒜鸡?” 一聲冷哼從身側(cè)響起胯努,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逢防,沒(méi)想到半個(gè)月后叶沛,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忘朝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年灰署,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辜伟。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡氓侧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出导狡,到底是詐尸還是另有隱情约巷,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布旱捧,位于F島的核電站独郎,受9級(jí)特大地震影響踩麦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜氓癌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一谓谦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贪婉,春花似錦反粥、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至尤蒿,卻和暖如春郑气,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背腰池。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工尾组, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人示弓。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓讳侨,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親避乏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子爷耀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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