jvm的垃圾收集器分為如下幾種類型:
串行:Serial,Serial Old
吞吐量?jī)?yōu)先: parNew, parallel Scavenge, parallel Old
響應(yīng)時(shí)間優(yōu)先:CMS根暑,G1
Serial收集器
單線程收集器甜刻,在進(jìn)行垃圾收集時(shí)灰蛙,必須暫停其他所有的工作線程厌杜,直至Serial收集器收集結(jié)束為止(stop the world)乙嘀。虛擬機(jī)運(yùn)行在Client模式下的默認(rèn)的新生代收集器
ParNew收集器
ParNew收集器就是Serial收集器的多線程版本,它也是一個(gè)新生代收集器,目前只有它能和CMS收集器(Concurrent Mark Sweep)配合工作挂洛。
Parallel收集器(parallel Scavenge, parallel Old)
CMS收集器
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器,作用于老年代斩郎,采用的是標(biāo)記-清除算法。
CMS收集器工作的整個(gè)流程分為以下4個(gè)步驟:
- 初始標(biāo)記(CMS initial mark):僅僅只是標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對(duì)象疮装,速度很快缘琅,需要“Stop The World”。
- 并發(fā)標(biāo)記(CMS concurrent mark):進(jìn)行GC Roots Tracing的過(guò)程斩个,在整個(gè)過(guò)程中耗時(shí)最長(zhǎng)胯杭。
- 重新標(biāo)記(CMS remark):為了修正并發(fā)標(biāo)記期間因用戶程序繼續(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í)間短。此階段也需要“Stop The World”。
-
并發(fā)清除(CMS concurrent sweep)
優(yōu)點(diǎn):
- 并發(fā)收集
- 低停頓
缺點(diǎn): - 因?yàn)槭呛陀脩艄ぷ骶€程并發(fā)執(zhí)行的滚局,所以會(huì)影響用戶線程的CPU使用居暖。
- 無(wú)法處理浮動(dòng)垃圾
由于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)作使用。
*標(biāo)記-清除算法導(dǎo)致的空間碎片
空間碎片過(guò)多時(shí)涨缚,將會(huì)給大對(duì)象分配帶來(lái)很大麻煩轧粟,往往出現(xiàn)老年代空間剩余,但無(wú)法找到足夠大連續(xù)空間來(lái)分配當(dāng)前對(duì)象脓魏。這時(shí)候CMS會(huì)退化為Serial Old兰吟。
G1收集器
G1和其他GC算法最大的區(qū)別是弱化分代概念,引入分區(qū)思想
G1 GC切分堆內(nèi)存為多個(gè)區(qū)間(Region)茂翔,從而避免很多GC操作在整個(gè)Java堆或者整個(gè)年輕代進(jìn)行混蔼。有的分區(qū)內(nèi)垃圾對(duì)象特別多,有的分區(qū)內(nèi)垃圾對(duì)象很少珊燎,G1會(huì)優(yōu)先回收垃圾對(duì)象特別多的分區(qū)拄丰,這樣可以花費(fèi)較少的時(shí)間來(lái)回收這些分區(qū)的垃圾,這也就是G1名字的由來(lái)俐末,即首先收集垃圾最多的分區(qū)料按。
G1的垃圾收集周期主要有4種類型:年輕代收集周期、多級(jí)并發(fā)標(biāo)記周期卓箫、混合收集周期和full GC(轉(zhuǎn)移失敗的安全保護(hù)機(jī)制)
年輕代收集(YGC)
應(yīng)用剛啟動(dòng)载矿,慢慢流量進(jìn)來(lái),開(kāi)始生成對(duì)象烹卒。G1會(huì)選一個(gè)分區(qū)并指定他為eden分區(qū)闷盔,當(dāng)這塊分區(qū)用滿了之后,G1會(huì)選一個(gè)新的分區(qū)作為eden分區(qū)旅急,這個(gè)操作會(huì)一直進(jìn)行下去直到達(dá)到eden分區(qū)上限逢勾,也就是說(shuō)eden分區(qū)已經(jīng)被占滿,那么會(huì)觸發(fā)一次年輕代收集藐吮。
年輕代收集首先做的就是遷移存活對(duì)象溺拱,它使用單eden逃贝,雙survivor進(jìn)行復(fù)制算法,它將存活的對(duì)象從eden分區(qū)轉(zhuǎn)移到survivor分區(qū)迫摔,survivor分區(qū)內(nèi)的某些對(duì)象達(dá)到了任期閾值之后沐扳,會(huì)晉升到老年代分區(qū)中。原有的年輕代分區(qū)會(huì)被整個(gè)回收掉句占。