寫在前面:
基于JDK1.7Update14之后的HotSpot虛擬機(jī)(這個(gè)版本中正式提供了商用的GI收集器)
虛擬機(jī)包含的所有收集器如圖所示:
說明:兩個(gè)收集器之間存在連線妙黍,表示可以搭配使用拭嫁。
1筒繁、Serial收集器
單線程收集器,“單線程”:只使用一個(gè)CPU或者一條收集線程去完成垃圾收集工作,并且在垃圾收集時(shí)會(huì)“stop the world”呕缭,即暫停其他所有工作線程修己,直到收集結(jié)束。
優(yōu)勢:簡單高效(與其他收集器的單線程相比)片仿,對(duì)于限定單個(gè)CPU的環(huán)境來說砂豌,沒有線程切換開銷,可以獲得最高的單線程切換效率阳距。
是虛擬機(jī)運(yùn)行在client模式下的默認(rèn)新生代收集器筐摘。
2咖熟、ParNew收集器
Serial收集器的多線程版本;是許多運(yùn)行在Server模式下的虛擬機(jī)中首選的新生代收集器(其中一個(gè)重要非性能原因是郭赐,除了Serial收集器堪置,只有ParNew收集器能與CMS收集器配合工作)
可使用 -XX: ParallelGCThreads參數(shù)來限制垃圾收集的線程數(shù)张惹;
3宛逗、Parallel Scavenge收集器
使用復(fù)制算法的新生代收集器,多線程并行替蔬;
特點(diǎn)(與ParNew的主要不同之處):
- 關(guān)注點(diǎn)與其他收集器不同承桥,目標(biāo)著重于達(dá)到一個(gè)可控制的吞吐量(CPU運(yùn)行時(shí)間/CPU總消耗時(shí)間)而不是盡可能縮短垃圾收集時(shí)用戶的停頓時(shí)間根悼,可以高效率地利用CPU時(shí)間,主要適合在后臺(tái)運(yùn)算而不需要太多交互的任務(wù)剩彬;也經(jīng)常稱為“吞吐量優(yōu)先”收集器
-
自適應(yīng)調(diào)節(jié)策略喉恋。 -XX:+UseAdaptiveSizePolicy 一個(gè)開關(guān)參數(shù),打開后虛擬機(jī)會(huì)根據(jù)當(dāng)前系統(tǒng)運(yùn)行情況自行優(yōu)化/動(dòng)態(tài)調(diào)整新生代大泻簟(-Xmn)轩褐、Eden與Survivor區(qū)的比例(-XX: SurvivorRatio)玖详、晉升老年代對(duì)象年齡(-XX: PretenreSize Threshold)等參數(shù)。
提供了兩個(gè)參數(shù)來控制吞吐量: 最大垃圾收集停頓時(shí)間-XX: MaxGCPauseMillis 吞吐量大小設(shè)置: -XX:GCTimeRatio
其中拗踢,MaxGCPauseMillis最大垃圾收集停頓時(shí)間是一個(gè)大于0的毫秒數(shù)巢墅,收集器將盡可能保證內(nèi)存回收時(shí)間少于這個(gè)數(shù)值券膀。但并不是參數(shù)值設(shè)置得越小,垃圾收集速度越快蓄髓。GC停頓時(shí)間縮短是以犧牲吞吐量和新生代空間為代價(jià)的会喝。比如系統(tǒng)把新生代空間調(diào)小一些玩郊,垃圾收集頻繁一些,這些都會(huì)導(dǎo)致停頓時(shí)間下降预茄,但同時(shí)頁降低了吞吐量反璃。
4假夺、Serial Old收集器
Serial收集器的老年代版本(見圖1)
主要用于Client模式下的虛擬機(jī)已卷;
Server模式下的兩點(diǎn)主要用途:在JDK1.5以及之前的版本中與Parallel Scavenge收集器搭配使用淳蔼;作為CMS收集器的后備方案裁眯,在并發(fā)收集發(fā)生失敶┪取(Concurrent Mode Failure)時(shí)使用逢艘;
5骤菠、Parallel Old收集器
Parallel Scavenge的老年代版本;使用多線程和標(biāo)記整理算法央拖;JDK1.6版本中開始提供鲜戒,在此之前新生代如果選擇了Parallel Scavenge版本抹凳,老年代只能選用Serial Old版本,因?yàn)槠錈o法與CMS收集器搭配使用境输;
6嗅剖、CMS(Concurrent Mark Sweep)收集器
收集器目標(biāo):獲取最短回收停頓時(shí)間信粮;也稱為并發(fā)低停頓收集器趁啸;
運(yùn)作過程:初始標(biāo)記(標(biāo)記GC Roots能直接關(guān)聯(lián)到的對(duì)象)不傅,并發(fā)標(biāo)記(GC Roots Tracing),重新標(biāo)記(修正并發(fā)標(biāo)記期間因用戶程序繼續(xù)執(zhí)行而導(dǎo)致產(chǎn)生變動(dòng)的標(biāo)記記錄)访娶;并發(fā)清除。其中典勇,初始標(biāo)記叮趴、重新標(biāo)記兩個(gè)步驟需要stop the world。
缺點(diǎn):1.對(duì)CPU資源非常敏感(并發(fā)情況下伤溉,可能導(dǎo)致用戶程序的執(zhí)行速度下降谈火,讓人無法接受)舌涨,改進(jìn):增量式并發(fā)收集器(讓GC線程、用戶線程交替執(zhí)行温技,但實(shí)踐效果一般扭粱,已不提倡使用);2.無法處理浮動(dòng)垃圾(Floating Garbage)墨叛,可能出現(xiàn)“Concurrent Mode Failure”而導(dǎo)致另一次Full GC的產(chǎn)生;浮動(dòng)垃圾:并發(fā)清理階段用戶程序產(chǎn)生的新垃圾慕淡;另外峰髓,由于垃圾收集階段用戶線程還需要運(yùn)行,也就需要預(yù)留足夠的內(nèi)存空間給用戶線程使用疾掰,因此CMS收集器不能等到老年代將近填滿了之后進(jìn)行垃圾收集徐紧,需要預(yù)留一部分空間;參數(shù)-XX:CMSInitiatingOccupancyFraction 觸發(fā)百分比(老年代使用了這個(gè)比率的空間后就會(huì)觸發(fā)CMS收集器進(jìn)行垃圾收集)巴柿,該參數(shù)太低內(nèi)存回收次數(shù)會(huì)提高广恢;太高會(huì)容易導(dǎo)致大量的“Concurrent Mode Failure”呀潭,性能反而降低;如果CMS運(yùn)行期間預(yù)留的內(nèi)存無法滿足內(nèi)存需要糠聪,就會(huì)產(chǎn)生“Concurrent Mode Failure”舰蟆,這時(shí)會(huì)臨時(shí)啟用后備方案Serial Old收集器來重新進(jìn)行老年代的垃圾收集狸棍。3.標(biāo)記-清除算法容易產(chǎn)生大量內(nèi)存碎片;解決方案: -XX: +UseCMSCompactAtFullCollection(默認(rèn)開啟)CMS收集器頂不住要進(jìn)行Full GC時(shí)開啟內(nèi)存碎片的合并整理塌鸯,內(nèi)存整理過程無法并發(fā)丙猬,會(huì)導(dǎo)致停頓時(shí)間延長茧球;參數(shù)-XX: CMSFullGCsBeforeCompaction,用于設(shè)置執(zhí)行多少次不壓縮的Full GC后袜腥,跟著來一次帶壓縮的(默認(rèn)值為0羹令,表示每次進(jìn)入Full GC時(shí)都要執(zhí)行碎片整理)
7损痰、G1收集器(Garbage-First)
面向服務(wù)端應(yīng)用的垃圾收集器
運(yùn)作過程:初始標(biāo)記(標(biāo)記GC Roots能直接關(guān)聯(lián)到的對(duì)象)卢未、并發(fā)標(biāo)記(從GC Root開始對(duì)堆中對(duì)象進(jìn)行可達(dá)性分析)堰汉、最終標(biāo)記(修正變動(dòng)標(biāo)記)翘鸭、篩選回收(根據(jù)用戶期望停頓時(shí)間制定回收計(jì)劃,篩選回收部分Region)就乓;
與其他GC收集器相比生蚁,G1具備如下特點(diǎn):
1.并行與并發(fā)(見附解釋):能充分利用多CPU戏自、多核環(huán)境下的硬件優(yōu)勢,使用多CPU/多核來縮短stop the world停頓時(shí)間志衣,其它收集器需要暫停用戶線程執(zhí)行的GC動(dòng)作蠢涝,G1可以與用戶程序并發(fā)執(zhí)行阅懦;
2.分代收集:保留了分代概念耳胎,采用不同的方式去處理新建的對(duì)象、已經(jīng)存活了一段時(shí)間废登、熬過多次GC的舊對(duì)象郁惜,從而獲取更好的收集效果兆蕉;
3、空間整合:整體上基于“標(biāo)記-整理”算法易稠,局部上基于“復(fù)制”算法驶社,這兩種算法意味著G1運(yùn)作期間不會(huì)產(chǎn)生內(nèi)存碎片,收集后能提供規(guī)整的可用內(nèi)存届巩;該特性有利于程序的長期運(yùn)行逊抡,不會(huì)產(chǎn)生大對(duì)象找不到空間分配而導(dǎo)致提前觸發(fā)下一次GC冒嫡;
4孝凌、可預(yù)測的停頓:除了追求停頓外月腋,還能建立可預(yù)測的停頓時(shí)間模型,讓使用者明確制定在M毫秒的時(shí)間片段內(nèi)片拍,消耗在垃圾收集上的時(shí)間不超過N毫秒捌省,這幾乎已經(jīng)是實(shí)時(shí)Java的垃圾收集器的特征了;
另外纲缓,G1使用Region劃分內(nèi)存空間以及有優(yōu)先級(jí)的區(qū)域回收方式祝高,保證了G1收集器在有限的時(shí)間內(nèi)獲取了盡可能高的收集效率污筷;
垃圾收集器參數(shù)總結(jié):
- 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)存回收;
- UseConMarkSweepGC:打開此開關(guān)后使用CMS+ParNew+Serial Old的組合進(jìn)行內(nèi)存回收讲弄,其中Serial Old為CMS出現(xiàn)Concurrent Mode Failure失敗時(shí)的的后備服務(wù)器避除;
- UseParallel GC:運(yùn)行在Server模式下的默認(rèn)值瓶摆,打開此開關(guān)后,使用Parallel Scavenge + Serial Old(PS MarkSweep)的收集器組合回收內(nèi)存群井;
- UseParallelOldGC: 打開此開關(guān)后书斜,使用Parallel Scavenge+Parallel Old的收集器組合回收內(nèi)存酵使;
- Survivor Ratio:新生代中Eden區(qū)與Survivor區(qū)的容量比值荐吉,默認(rèn)為8;
- PretenureSizeThreshold: 直接晉升到老年代對(duì)象大锌谟妗样屠;設(shè)置這個(gè)參數(shù)后,大于該參數(shù)的對(duì)象將直接在老年代分配搓劫;
- MaxTenuringThreshold:晉升到老年代的對(duì)象年齡瞧哟;每個(gè)對(duì)象在堅(jiān)持一次MInor GC后,年齡加1枪向,當(dāng)年齡超過這個(gè)參數(shù)時(shí)就進(jìn)入老年代勤揩;
- UseAdaptivePolicy:動(dòng)態(tài)調(diào)整Java堆中各個(gè)區(qū)域的大小以及進(jìn)入老年代的年齡;
- HandlePromotionFailure:是否運(yùn)行分配擔(dān)保失敗秘蛔,即老年代的剩余空間不足以應(yīng)對(duì)新生代整個(gè)Eden區(qū)和Survivor區(qū)所有對(duì)象都存活的極端情況陨亡;
- ParallelGCThreads: 并行GC時(shí)進(jìn)行內(nèi)存回收的線程數(shù)量;
- GCTimeRatio:GC時(shí)間占總時(shí)間的比率遮糖,默認(rèn)為99屡江;即運(yùn)行1%的GC時(shí)間惩嘉。僅在使用Parallel Scavenge收集器時(shí)生效殿较;
- MaxGCPauseMillis:GC最大停頓時(shí)間抓艳;僅在使用Parallel Scavenge收集器時(shí)生效片任;
- CMSInitiatingOccupancyFraction:設(shè)置CMS收集器在老年代空間使用多少時(shí)觸發(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í)生效错蝴;
讀者若有疑問歡迎留言一起交流,共同學(xué)習(xí)成長
參考
深入理解Java虛擬機(jī)