總覽
處于不同區(qū)域的垃圾收集器負(fù)責(zé)該區(qū)域(年輕代、老年代)的收集工作。有連線的表示可以搭配使用
Serial收集器
Serial收集器是一個(gè)單線程的垃圾收集器舍沙,這里的單線程強(qiáng)調(diào)的是進(jìn)行立即收集時(shí),其他線程必須暫停(stop the world)。運(yùn)行如下:但該收集器是所有收集中額外耗費(fèi)內(nèi)存(memory Footprint 指的是保證垃圾收集器能夠順利高效的進(jìn)行而存儲(chǔ)的額外信息)最小的歌粥。
ParNew收集器
ParNew其實(shí)是Serial的多線程并行版本,除了Serial之外稍途,目前只有它能配合CMS工作,其工作流程如圖所示:
它默認(rèn)開(kāi)啟的收集線程數(shù)與處理器核心數(shù)量相同砚婆。在這種多核處理器的條件下械拍,效率自然高于serial收集器。這里解釋一下垃圾收集中常匙岸ⅲ混淆的并發(fā)和并行兩個(gè)概念坷虑。
- 并發(fā):并發(fā)描述的是垃圾收集線程和用戶線程之間的關(guān)系,表示同一時(shí)間有多條垃圾收集線程在工作
- 并行:并行描述的是多個(gè)垃圾收集之間的關(guān)系埂奈,說(shuō)明同一時(shí)間迄损,垃圾線程和用戶線程都在運(yùn)行
Parallel Scavenge收集器
Parallel Scavenge收集器跟ParNew很相似,不同點(diǎn)在于該收集器更關(guān)注可控制的吞吐量,吞吐量指的是:
Parallel Scavenge通過(guò)以下兩個(gè)參數(shù)精確控制吞吐量:
- -XX: MaxGCPauseMillis 最大垃圾收集停頓時(shí)間
- -XX: GCTimeRatio 吞吐量大小
-XX: MaxGCPauseMillis是一個(gè)大于0的毫秒數(shù)账磺,當(dāng)然不能指望設(shè)置的越小越好芹敌,收集器只會(huì)盡可能的完成這個(gè)目標(biāo),同時(shí)花費(fèi)時(shí)間減少是通過(guò)犧牲年輕代內(nèi)存大小和吞吐量完成的垮抗。導(dǎo)致垃圾收集更頻繁氏捞,吞吐量下降。
除此之外冒版,Parallel Scavenge收集器還有一個(gè)參數(shù)值得關(guān)注: - -XX:+UseAdaptiveSizePolicy
該參數(shù)被激活后液茎,表示不需要人工指定新生代的大小(-Xmn)、Eden和Survivor區(qū)的比例(-XX:SurvivoRatio)捆等、晉升老年代對(duì)象大小(-XX:PretenureSizeThreshold)等細(xì)節(jié)參數(shù) 虛擬機(jī)會(huì)動(dòng)態(tài)調(diào)整以提供最合適的停頓時(shí)間和吞吐量滞造。
Serial Old收集器
Serial Old收集器是Serial的老年代版本,同樣是單線程收集器栋烤,使用標(biāo)記-整理算法谒养,用途如下:
- 在客戶端模式下,供HotSpot虛擬機(jī)使用
-
服務(wù)端模式下班缎,在Jdk5之前與Parallel Scavenge搭配使用蝴光,另一種是作為CMS收集器的失敗后備預(yù)案。
image.png
Parallel Old收集器
Parallel Old是Parallel Scavenge的老年代版本达址,多線程蔑祟,標(biāo)記整理算法,兩者搭配使用沉唠,成為名副其實(shí)的“吞吐量?jī)?yōu)先”的搭配組合疆虚。在吞吐量和資源稀缺的場(chǎng)合,可以優(yōu)先考慮該搭配組合满葛。
CMS收集器
CMS收集器是一種旨在獲取最短停頓時(shí)間的垃圾收集器径簿,運(yùn)作過(guò)程包含以下四個(gè)步驟:
- 初始標(biāo)記
- 并發(fā)標(biāo)記
- 重新標(biāo)記
-
并發(fā)清除
其中初始標(biāo)記和重新標(biāo)記是需要暫停用戶線程的,并發(fā)標(biāo)記和并發(fā)清除是和用戶線程一起執(zhí)行的嘀韧,執(zhí)行流程圖如下所示:
image.png
雖然CMS收集器是一個(gè)低停頓篇亭、并發(fā)收集的收集器,但還是存在以下缺點(diǎn):
- CMS默認(rèn)啟動(dòng)的回收線程數(shù)是(處理器核心數(shù)量+3) /4锄贷, 也就是說(shuō)译蒂, 如果處理器核心數(shù)在四個(gè)或以上, 并發(fā)回收時(shí)垃圾收集線程只占用不超過(guò)25%的處理器運(yùn)算資源谊却, 并且會(huì)隨著處理器核心數(shù)量的增加而下降柔昼。 但是當(dāng)處理器核心數(shù)量不足四個(gè)時(shí),CMS對(duì)用戶程序的影響就可能變得很大
- 浮動(dòng)垃圾
浮動(dòng)垃圾是指在CMS收集的并發(fā)標(biāo)記和并發(fā)清理過(guò)程中炎辨、由于是和用戶線程一起運(yùn)行的捕透,用戶線程就會(huì)不斷產(chǎn)生新的垃圾對(duì)象,而這些對(duì)象又是在垃圾收集后出現(xiàn)的碴萧。CMS收集器只能在下次垃圾收集時(shí)才能進(jìn)行回收乙嘀,這一部分被稱為“浮動(dòng)垃圾”。同時(shí)不同于其他收集器可以等到老年代滿了才進(jìn)行垃圾回收破喻,CMS是并發(fā)的乒躺,因此要預(yù)留空間給程序運(yùn)行使用。所以通過(guò)-XX: CMSInitiatingOccupancyFraction參數(shù)設(shè)置觸發(fā)CMS收集的老年代空間占用比例低缩。但是這個(gè)參數(shù)調(diào)的過(guò)高可能會(huì)引起Concurrent Mode Failure嘉冒,表示CMS預(yù)留的空間不足于程序新分配的對(duì)象曹货,此時(shí)CMS會(huì)啟動(dòng)后備方案,通過(guò)Serial OLd收集器進(jìn)行老年代回收 - 空間碎片化 因?yàn)镃MS收集器是采用的標(biāo)記-清除算法
Garbage First收集器
開(kāi)創(chuàng)了面向局部收集的設(shè)計(jì)思路和基于Region的內(nèi)存布局形式讳推,是一款面向服務(wù)端的收集器顶籽,從JDK9開(kāi)始,替代了Parallel Scavenge搭配Parallel Old的收集器银觅,成為服務(wù)端默認(rèn)的垃圾收集器礼饱。
G1不再堅(jiān)持固定大小以及固定數(shù)量的分代區(qū)域劃分, 而是把連續(xù)的Java堆劃分為多個(gè)大小相等的獨(dú)立區(qū)域(Region) 究驴, 每一個(gè)Region都可以根據(jù)需要镊绪, 扮演新生代的Eden空間、 Survivor空間洒忧, 或者老年代空間蝴韭。
G1收集器中雖然還是存在新生代、老年代熙侍,但是不再是固定的榄鉴,而是不需要連續(xù)的動(dòng)態(tài)集合,它將Region作為最小的回收單元蛉抓,每個(gè)Region可以通過(guò)-XX:G1HeapRegionSize設(shè)置大小庆尘,Region中包含一個(gè)Humongous區(qū)域,存儲(chǔ)大對(duì)象巷送,對(duì)于超過(guò)Region一半大小的對(duì)象就存放在N個(gè)連續(xù)的Region的Humongous區(qū)域驶忌。
G1的收集思路是跟蹤每個(gè)Region的垃圾收集價(jià)值大小,即回收所獲得的空間大小和回收所需時(shí)間的經(jīng)驗(yàn)值笑跛,維護(hù)一個(gè)優(yōu)先級(jí)列表付魔,回收時(shí)優(yōu)先回收價(jià)值大的。
G1缺點(diǎn):
- 需要為每一個(gè)Region維護(hù)一個(gè)卡表 內(nèi)存占用較高
- 執(zhí)行負(fù)載高
Shenandoah收集器
Shenandoah收集器對(duì)比G1有所改進(jìn)堡牡,例如:
- 支持并發(fā)回收 抒抬,G1雖然可以多線程執(zhí)行回收但是不能和用戶線程并發(fā)執(zhí)行
- Shenandoah不支持分代收集
- 摒棄記憶集 使用連接矩陣記錄跨Region的引用關(guān)系
image.png
該收集器大致分為以下9個(gè)階段:
1.初始標(biāo)記 標(biāo)記與GC Roots直接關(guān)聯(lián)的對(duì)象 需暫停用戶線程
2.并發(fā)標(biāo)記 與G1一樣杨刨, 遍歷對(duì)象圖晤柄, 標(biāo)記出全部可達(dá)的對(duì)象
3.最終標(biāo)記 處理剩余的SATB掃描, 并在這個(gè)階段統(tǒng)計(jì)出回收價(jià)值
最高的Region妖胀, 將這些Region構(gòu)成一組回收集 需暫停用戶線程
4.并發(fā)清理 清理那些整個(gè)區(qū)域內(nèi)連一個(gè)存活對(duì)象都沒(méi)有找到
的Region
5.并發(fā)回收 Shenandoah要把回收集里面的存活對(duì)象先復(fù)制一份到其他未被使用的Region之中芥颈,通過(guò)轉(zhuǎn)發(fā)指針“Brooks Pointers”實(shí)現(xiàn)對(duì)象移動(dòng)后 原本指向這些對(duì)象的引用的改變
6.初始引用更新 并發(fā)回收階段復(fù)制對(duì)象結(jié)束后, 還需要把堆中所有指向舊對(duì)象的引用修正到復(fù)制后的新地址 暫停用戶線程 引用更新的初始化階段實(shí)際上并未做什么具體的處理赚抡, 設(shè)立這個(gè)階段只是為了建立一個(gè)線程集合點(diǎn)爬坑, 確保所有并發(fā)回收階段中進(jìn)行的收
集器線程都已完成分配給它們的對(duì)象移動(dòng)任務(wù)而已
7.并發(fā)引用更新 真正開(kāi)始進(jìn)行引用更新操作
8.最終引用更新 解決了堆中的引用更新后, 還要修正存在于GC Roots中的引用 暫停用戶線程
9.并發(fā)清理
轉(zhuǎn)發(fā)指針 Brooks pointer
原有對(duì)象布局結(jié)構(gòu)的最前面統(tǒng)一增加一個(gè)新的引用字段涂臣, 在正常不處于并發(fā)移動(dòng)的情況下盾计, 該引用指向?qū)ο笞约?/em>
ZGC收集器
ZGC收集器是一款基于Region內(nèi)存布局的售担, (暫時(shí))不設(shè)分代的, 使用了讀屏障署辉、 染色指針和內(nèi)存多重映射等技術(shù)來(lái)實(shí)現(xiàn)可并發(fā)的標(biāo)記-整理算法的族铆, 以低延遲為首要目標(biāo)的一款垃圾收集器。
ZGC雖然也是基于Region收集哭尝,但其將Region劃分為了大哥攘、中、小3類容量
大型Region存放的是4Mb及以上大小的對(duì)象材鹦,容量不固定逝淹,每個(gè)Region只存放一個(gè)大型對(duì)象,同時(shí)該Region中的對(duì)象不會(huì)重分配
染色指針
ZGC收集器采用染色指針使得一旦某個(gè)Region的存活對(duì)象被移走之后桶唐, 這個(gè)Region立即就能夠被釋放和重用掉栅葡, 而不必等待整個(gè)堆中所有指向該Region的引用都被修正后才能清理。
ZGC分為以下四個(gè)階段:
1.并發(fā)標(biāo)記
與G1莽红、 Shenandoah不同的是妥畏, ZGC的標(biāo)記是在指針上而不是在對(duì)象上進(jìn)行的
2.并發(fā)預(yù)備重分配
根據(jù)特定的查詢條件統(tǒng)計(jì)得出本次收集過(guò)程要清理哪些Region, 將這些Region組成重分配集(Relocation Set)
3.并發(fā)重分配
重分配是ZGC執(zhí)行過(guò)程中的核心階段安吁, 這個(gè)過(guò)程要把重分配集中的存活對(duì)象復(fù)制到新的Region上醉蚁, 并為重分配集中的每個(gè)Region維護(hù)一個(gè)轉(zhuǎn)發(fā)表(ForwardTable) , 記錄從舊對(duì)象到新對(duì)象的轉(zhuǎn)向關(guān)系
4.并發(fā)重映射
重映射所做的就是修正整個(gè)堆中指向重分配集中舊對(duì)象的所有引用