1 并發(fā)和并行的垃圾收集器
-
并行
多條垃圾收集線程并行工作栗菜,但此時(shí)用戶線程仍然處于等待狀態(tài)骡男。 -
并發(fā)
用戶線程與垃圾收集線程同時(shí)執(zhí)行(但不一定是并行的赃蛛,可能會(huì)交替執(zhí)行),用戶程序在繼續(xù)執(zhí)行港粱,而垃圾收集程序運(yùn)行于另一個(gè)CPU上螃成。
2 JVM的運(yùn)行模式
- Server
- Client
3 新生代垃圾收集器
3.1 Serial收集器
-
單線程
只會(huì)使用一個(gè)CPU或一條GC線程去完成垃圾收集工作。在它進(jìn)行垃圾收集時(shí),必須暫停其它所有的工作線程(Stop The World)寸宏,直到它收集結(jié)束宁炫。 -
適合運(yùn)行在Client模式下的虛擬機(jī)
在用戶的桌面應(yīng)用場(chǎng)景中,分配給虛擬機(jī)管理的內(nèi)存不會(huì)很大击吱,GC時(shí)間較短淋淀。 -
簡(jiǎn)單高效
沒有線程切換的開銷。 - 采用復(fù)制算法
3.2 ParNew收集器
-
多線程
ParNew收集器是Serial收集器的多線程版本覆醇。 -
許多運(yùn)行在Server模式下的虛擬機(jī)中首選的新生代收集器
除了Serial收集器外朵纷,目前只有ParNew收集器能與CMS收集器配合工作。
3.3 Parallel Scavenge收集器
- 多線程
- 采用復(fù)制算法
-
追求吞吐量
這里的吞吐量是指CPU用于運(yùn)行用戶代碼的時(shí)間與CPU總消耗時(shí)間的比值永脓。CPU總消耗時(shí)間=CPU用于運(yùn)行用戶代碼的時(shí)間+GC的時(shí)間袍辞。高吞吐量可以高效地利用CPU時(shí)間,盡快完成程序的運(yùn)算任務(wù)常摧,主要適合在后臺(tái)運(yùn)算而不需要太多交互的任務(wù)搅吁。 -
參數(shù)
-XX:MaxGCPauseMillis設(shè)置垃圾收集最大停頓時(shí)間。
-XX:GCTimeRatio設(shè)置GC的時(shí)間占CPU總消耗時(shí)間的比率落午。
-XX:+UseAdaptiveSizePolicy開啟GC自適應(yīng)的調(diào)節(jié)策略(和ParNew收集器的一個(gè)重要區(qū)別)谎懦。
4 老年代垃圾收集器
4.1 Serial Old收集器
-
單線程+適合運(yùn)行在Client模式下的虛擬機(jī)
Serial Old收集器是Serial收集器的老年代版本。 - 采用標(biāo)記-整理算法
4.2 Parallel Old收集器
-
多線程+追求吞吐量
Parallel Old收集器是Parallel Scavenge收集器的老年代版本溃斋。 - 采用標(biāo)記-整理算法
4.3 CMS收集器
-
追求最短回收停頓時(shí)間
目前集中在互聯(lián)網(wǎng)站或者B/S系統(tǒng)的服務(wù)端上的Java應(yīng)用尤其重視服務(wù)的響應(yīng)速度界拦,希望系統(tǒng)停頓時(shí)間最短,以給用戶帶來(lái)較好的體驗(yàn)梗劫。 - 采用標(biāo)記-清除算法
-
運(yùn)作過(guò)程
(1)初始標(biāo)記:標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對(duì)象享甸。
(2)并發(fā)標(biāo)記:進(jìn)行GC Roots Tracing的過(guò)程(判斷哪些對(duì)象是存活的)。
(3)重新標(biāo)記:修正并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄梳侨。
(4)并發(fā)清理:清理未被標(biāo)記的對(duì)象蛉威。 -
缺點(diǎn)
(1)CMS收集器對(duì)CPU資源非常敏感。其實(shí)走哺,面向并發(fā)設(shè)計(jì)的程序都對(duì)CPU資源比較敏感蚯嫌。在并發(fā)階段,它雖然不會(huì)導(dǎo)致用戶線程停頓丙躏,但是會(huì)因?yàn)檎加昧艘徊糠志€程(或者說(shuō)CPU資源)而導(dǎo)致應(yīng)用程序變慢齐帚,總吞吐量會(huì)降低。
(2)CMS收集器無(wú)法處理浮動(dòng)垃圾彼哼,可能出現(xiàn)“Concurrent Mode Failure”失敗而導(dǎo)致另一次Full GC產(chǎn)生。由于CMS并發(fā)清理階段用戶線程還在運(yùn)行著湘今,伴隨程序運(yùn)行自然就會(huì)有新的垃圾不斷產(chǎn)生敢朱,這一部分垃圾出現(xiàn)在標(biāo)記過(guò)程之后,CMS無(wú)法在當(dāng)次收集中處理掉它們,只好留待下一次GC時(shí)再清理拴签。這一部分垃圾稱為“浮動(dòng)垃圾”孝常。由于在垃圾收集階段用戶線程還需要運(yùn)行,那也就還需要預(yù)留有足夠的內(nèi)存空間給用戶線程使用蚓哩,因此CMS收集器不能像其它收集器那樣等到老年代幾乎完全被填滿再進(jìn)行收集构灸,需要預(yù)留一部分空間提供并發(fā)收集時(shí)的程序運(yùn)作使用。如果CMS收集器運(yùn)行期間預(yù)留的內(nèi)存無(wú)法滿足程序需要岸梨,就會(huì)出現(xiàn)一次“Concurrent Mode Failure”失敗喜颁。
(3)CMS收集器采用標(biāo)記-清除算法,GC結(jié)束時(shí)會(huì)有大量空間碎片產(chǎn)生曹阔。
5 G1收集器
-
特點(diǎn)
(1)并行與并發(fā):能充分利用多CPU半开、多核環(huán)境下的硬件優(yōu)勢(shì),使用多個(gè)CPU來(lái)縮短“Stop-The-World”停頓的時(shí)間赃份。
(2)分代收集:與其它收集器一樣寂拆,分代概念在G1中依然得以保留。
(3)空間整合:從整體來(lái)看是基于“標(biāo)記-整理”算法實(shí)現(xiàn)的收集器抓韩,從局部(兩個(gè)Region之間)上來(lái)看是基于“復(fù)制”算法實(shí)現(xiàn)的纠永。這意味著G1運(yùn)作期間不會(huì)產(chǎn)生內(nèi)存空間碎片,收集后能提供規(guī)整的可用內(nèi)存谒拴。
(4)可預(yù)測(cè)的停頓:這是G1相對(duì)于CMS的另一大優(yōu)勢(shì)尝江,降低停頓時(shí)間是G1和CMS共同的關(guān)注點(diǎn),但G1除了追求低停頓外彪薛,還能建立可預(yù)測(cè)的停頓時(shí)間模型茂装,能讓使用者明確指定在一個(gè)長(zhǎng)度為M毫秒的時(shí)間片段內(nèi),消耗在垃圾收集上的時(shí)間不得超過(guò)N毫秒善延,這幾乎已經(jīng)是實(shí)時(shí)Java(RTSJ)的垃圾收集器的特征了少态。
在G1之前的其它收集器進(jìn)行收集的范圍都是整個(gè)新生代或者老生代,而G1不再是這樣易遣。使用G1收集器時(shí)彼妻,Java堆的內(nèi)存布局與其它收集器有很大差別,它將整個(gè)Java堆劃分為多個(gè)大小相等的獨(dú)立區(qū)域(Region)豆茫,雖然還保留有新生代和老年代的概念侨歉,但新生代和老年代不再是物理隔離的了,它們都是一部分Region(不需要連續(xù))的集合揩魂。
G1收集器之所以能建立可預(yù)測(cè)的停頓時(shí)間模型幽邓,是因?yàn)樗梢杂杏?jì)劃地避免在整個(gè)Java堆中進(jìn)行全區(qū)域的垃圾收集。G1跟蹤各個(gè)Region里面的垃圾堆積的價(jià)值大谢鹇觥(回收所獲得的空間大小以及回收所需時(shí)間的經(jīng)驗(yàn)值)牵舵,在后臺(tái)維護(hù)一個(gè)優(yōu)先列表 柒啤,每次根據(jù)允許的收集時(shí)間,優(yōu)先回收價(jià)值最大的Region(這也就是Garbage-First名稱的由來(lái))畸颅。這種使用Region劃分內(nèi)存空間以及有優(yōu)先級(jí)的區(qū)域回收方式担巩,保證了G1收集器在有限的時(shí)間內(nèi)可以獲取盡可能高的收集效率。
在G1收集器中没炒,Region之間的對(duì)象引用以及其他收集器中的新生代與老年代之間的對(duì)象引用涛癌,虛擬機(jī)都是使用Remembered Set來(lái)避免全堆掃描的。G1中每個(gè)Region都有一個(gè)與之對(duì)應(yīng)的Remembered Set送火,虛擬機(jī)發(fā)現(xiàn)程序在對(duì)Reference類型的數(shù)據(jù)進(jìn)行寫操作時(shí)拳话,會(huì)產(chǎn)生一個(gè)Write Barrier暫時(shí)中斷寫操作,檢查Reference引用的對(duì)象是否處于不同的Region之中(在分代的例子中就是檢查是否老年代中的對(duì)象引用了新生代中的對(duì)象)漾脂,如果是假颇,便通過(guò)CardTable把相關(guān)引用信息記錄到被引用對(duì)象所屬的Region的Remembered Set之中。當(dāng)進(jìn)行內(nèi)存回收時(shí)骨稿,在GC根結(jié)點(diǎn)的枚舉范圍中加入Remembered Set即可保證不對(duì)全堆掃描也不會(huì)有遺漏躏升。 -
過(guò)程
(1)初始標(biāo)記:標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對(duì)象扯罐,并且修改TAMS(Next Top at Mark Start)的值,讓下一階段用戶程序并發(fā)運(yùn)行時(shí),能在正確可用的Region中創(chuàng)建新對(duì)象纬纪。
(2)并發(fā)標(biāo)記:從GC Roots開始對(duì)堆中對(duì)象進(jìn)行可達(dá)性分析菌羽,找到存活的對(duì)象升略。
(3)最終標(biāo)記:修正在并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分標(biāo)記記錄衷蜓。
(4)篩選回收:對(duì)各個(gè)Region的回收價(jià)值和成本進(jìn)行排序,根據(jù)用戶所期望的GC停頓時(shí)間來(lái)制定回收計(jì)劃判呕。