5.垃圾收集器

一、垃圾回收器分類(lèi)

image.png

新生代垃圾收集器:Serial 、 ParNew 、Parallel Scavenge
老年代垃圾收集器:Serial Old 、 Parallel Old 、CMS
整理收集器:G1

垃圾回收器組合關(guān)系

image.png

  • JDK7、8中默認(rèn)使用組合是: Parallel Scavenge GC 、ParallelOld GC
  • JDK9默認(rèn)使用G1為垃圾收集器
  • JDK14 棄用了: Parallel Scavenge GC 、Parallel OldGC;移除了 CMS GC

GC性能指標(biāo)

  • 吞吐量:即CPU用于運(yùn)行用戶(hù)代碼的時(shí)間與CPU總消耗時(shí)間的比值(吞吐量 = 運(yùn)行用戶(hù)代碼時(shí)間 / ( 運(yùn)行用戶(hù)代碼時(shí)間 + 垃圾收集時(shí)間 ))。例如:虛擬機(jī)共運(yùn)行100分鐘,垃圾收集器花掉1鐘,那么吞吐量就是99%
  • 暫停時(shí)間:執(zhí)行垃圾回收時(shí),程序的工作線程被暫停的時(shí)間

二、Serial垃圾收集器

串行。針對(duì)新生代;采用標(biāo)記-復(fù)制算法; 進(jìn)行垃圾收集時(shí),必須暫停所有工作線程,直到完成;

  • 使用方式:-XX:+UseSerialGC

三、ParNew垃圾收集器

并發(fā)。針對(duì)新生代;采用標(biāo)記-復(fù)制算法。ParNew收集器實(shí)質(zhì)上是Serial收集器的多線程并行版本, 除了同時(shí)使用多條線程進(jìn)行垃圾收集之外都一樣。

  • 使用方式: 使用方式:-XX:+UseParNewGC

四、Parallel Scavenge垃圾收集器

并行(單核無(wú)并行)。新生代收集器;采用標(biāo)記-復(fù)制算法。是1.8中默認(rèn)的收集器;吞吐量?jī)?yōu)先。

特點(diǎn)
  • Parallel Scavenge收集器的目標(biāo)是達(dá)到一個(gè)可控制的吞吐量(Throughput);
    吞吐量=運(yùn)行用戶(hù)代碼時(shí)間/(運(yùn)行用戶(hù)代碼時(shí)間+垃圾收集時(shí)間) (虛擬機(jī)總共運(yùn)行100分鐘,垃圾收集時(shí)間為1分鐘,那么吞吐量就是99%)
  • 自適應(yīng)調(diào)節(jié)策略,自動(dòng)指定年輕代、Eden、Suvisor區(qū)的比例。
適用場(chǎng)景

適合后臺(tái)運(yùn)算,交互不多的任務(wù),如批量處理,訂單處理,科學(xué)計(jì)算等。

在學(xué)生端的論壇項(xiàng)目中使用這種垃圾收集器,其項(xiàng)目訪問(wèn)刷新頻率較低,但是有
很多后臺(tái)定時(shí)的計(jì)算任務(wù),適合使用這種垃圾收集器

參數(shù)設(shè)置:

使用方式:-XX:+UseParallelGC
吞吐量大小-XX:GCTimeRatio

-XX: GCTimeRatio參數(shù)的值則應(yīng)當(dāng)是一個(gè)大于0小于100的整數(shù), 也就是垃圾收集時(shí)間占總時(shí)
間的 比率, 相當(dāng)于吞吐量的倒數(shù)。 假設(shè)GCTimeRatio的值為n,那么系統(tǒng)將花費(fèi)不超過(guò)1/(1+n)
的時(shí)間用于垃圾收集。譬如把此 參數(shù)設(shè)置為19, 那允許的最大垃圾收集時(shí)間就占總時(shí)間的5%
(即1/(1+19)) , 默認(rèn)值為99, 即允許最大1%(即 1/(1+99)) 的垃圾收集時(shí)間

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

-XX: MaxGCPauseMillis參數(shù)允許的值是一個(gè)大于0的毫秒數(shù), 收集器將盡力保證內(nèi)存回收
花費(fèi)的 時(shí)間不超過(guò)用戶(hù)設(shè)定值。 不過(guò)大家不要異想天開(kāi)地認(rèn)為如果把這個(gè)參數(shù)的值設(shè)置得更
小一點(diǎn)就能使得 系統(tǒng)的垃圾收集速度變得更快, 垃圾收集停頓時(shí)間縮短是以犧牲吞吐量和新
生代空間為代價(jià)換取的: 系統(tǒng)把新生代調(diào)得小一些, 收集300MB新生代肯定比收集500MB
快, 但這也直接導(dǎo)致垃圾收集發(fā)生得 更頻繁, 原來(lái)10秒收集一次、 每次停頓100毫秒, 
現(xiàn)在變成5秒收集一次、 每次停頓70毫秒。 停頓時(shí)間 的確在下降, 但吞吐量也降下來(lái)了。

五、 Serial Old垃圾收集器

串行。針對(duì)老年代;采用標(biāo)記-整理算法;
使用方式:-XX:+UseSerialGC

六、 Parallel Old垃圾收集器

并行。是Parallel Scavenge收集器的老年代版本, 支持多線程并發(fā)收集, 基于標(biāo)記-整理算法實(shí)現(xiàn)。

應(yīng)用場(chǎng)景
  • JDK1.6及之后用來(lái)代替老年代的Serial Old收集器;
  • 特別是在Server模式,多CPU的情況下;
  • 這樣在注重吞吐量以及CPU資源敏感的場(chǎng)景,就有了Parallel Scavenge加Parallel Old收集器的"給力"應(yīng)用組合;

七、CMS 垃圾收集器

并發(fā)。老年代的垃圾回收器。是以獲取最短垃圾收集停頓時(shí)間為目標(biāo)的收集器。使用的算法是標(biāo)記-清除算法

適用場(chǎng)景

目前很大一部分的java應(yīng)用幾種在互聯(lián)網(wǎng)的B/S系統(tǒng)服務(wù)器上,這類(lèi)應(yīng)用尤其注重服務(wù)器的響應(yīng)速度,系統(tǒng)停頓時(shí)間最短,給用戶(hù)帶來(lái)良好的體驗(yàn)。

在管理端和學(xué)生端的交互性比較強(qiáng)的項(xiàng)目中可以使用這種垃圾回收

參數(shù)設(shè)置:XX:+UseConcMarkSweepGC

收集過(guò)程

1) 初始標(biāo)記
2) 并發(fā)標(biāo)記
3) 重新標(biāo)記
4) 并發(fā)清除

- 初始標(biāo)記(Initial-Mark)階段:這個(gè)階段程序所有的工作線程都將會(huì)因?yàn)?Stop-the-Wold"機(jī)制
而出現(xiàn)短暫的的暫停,這個(gè)階段的主要任務(wù)標(biāo)記處GC Roots 能夠關(guān)聯(lián)到的對(duì)象.一旦標(biāo)記完成后
就恢復(fù)之前被暫停的的所有應(yīng)用。 由于直接關(guān)聯(lián)對(duì)象比較小,所以這里的操作速度非???。
- 并發(fā)標(biāo)記(Concurrent-Mark)階段:從GC Roots的直接關(guān)聯(lián)對(duì)象開(kāi)始遍歷整個(gè)對(duì)象圖的過(guò)程,
這個(gè)過(guò)程耗時(shí)較長(zhǎng),但是不需要暫停用戶(hù)線程, 用戶(hù)線程可以與垃圾回收器一起運(yùn)行。
- 重新標(biāo)記(Remark)階段:由于并發(fā)標(biāo)記階段,程序的工作線程會(huì)和垃圾收集線程同時(shí)運(yùn)行
或者交叉運(yùn)行,因此,為了修正并發(fā)標(biāo)記期間因?yàn)橛脩?hù)繼續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一
部分對(duì)象的標(biāo)記記錄,這個(gè)階段的停頓時(shí)間通常比初始標(biāo)記階段長(zhǎng)一些,但也遠(yuǎn)比并發(fā)標(biāo)記
階段時(shí)間短。
- 清除并發(fā)(Concurrent-Sweep)階段: 此階段清理刪除掉標(biāo)記判斷已經(jīng)死亡的對(duì)象,并釋放
內(nèi)存空間。由于不需要移動(dòng)存活對(duì)象,所以這個(gè)階段可以與用戶(hù)線程同時(shí)并發(fā)運(yùn)行。
三色標(biāo)記
  • 白色:尚未訪問(wèn)過(guò)。
  • 黑色:本對(duì)象已訪問(wèn)過(guò),而且本對(duì)象 引用到 的其他對(duì)象 也全部訪問(wèn)過(guò)了。
  • 灰色:本對(duì)象已訪問(wèn)過(guò),但是本對(duì)象 引用到 的其他對(duì)象尚未全部訪問(wèn)完。全部訪問(wèn)后,會(huì)轉(zhuǎn)換為黑色。
注意:在并發(fā)標(biāo)記的時(shí)候可能會(huì)出現(xiàn)多標(biāo)和漏標(biāo)的情況,多標(biāo)會(huì)產(chǎn)生浮動(dòng)垃圾,漏標(biāo)會(huì)將引用中
的對(duì)象清除會(huì)導(dǎo)致程序出錯(cuò),需要在重新標(biāo)記的時(shí)候(會(huì)stop the world)做出修改防止這種情況出現(xiàn)
缺點(diǎn)

1.CMS收集器對(duì)CPU資源非常敏感。在并發(fā)階段,它雖然不會(huì)導(dǎo)致用戶(hù)線程停頓,但是會(huì)因?yàn)檎加谩⒘艘徊糠志€程而導(dǎo)致應(yīng)用程序變慢,總吞吐量會(huì)降低。是當(dāng)處理器核心數(shù)量不足四個(gè)時(shí), CMS對(duì)用戶(hù)程序的影響就可能變得很大。
2.CMS收集器無(wú)法處理浮動(dòng)垃圾,可能出現(xiàn)"Concurrent Mode Failure"失敗而導(dǎo)致另一次Full GC的產(chǎn)生。
3.空間碎片:CMS是一款基于標(biāo)記-清除算法實(shí)現(xiàn)的收集器,所有會(huì)有空間碎片的現(xiàn)象
concurrent mode failure是什么?
  CMS垃圾收集器特有的錯(cuò)誤,CMS的垃圾清理和引用線程是并行進(jìn)行的,如果在并行清理的過(guò)程中老年代的空間不足以容納應(yīng)用產(chǎn)生的垃圾(也就是老年代正在清理,從年輕代晉升了新的對(duì)象,或者直接分配大對(duì)象年輕代放不下導(dǎo)致直接在老年代生成,這時(shí)候老年代也放不下),則會(huì)拋出“concurrent mode failure”。

八、G1垃圾收集器

Garbage First是一款面向服務(wù)端應(yīng)用的垃圾收集器,主要針對(duì)配備多核CPU及大容量?jī)?nèi)存的機(jī)器,以極高概率滿(mǎn)足GC停頓時(shí)間的同時(shí),還兼具高吞吐量的性能特征。

G1收集器特點(diǎn)
  1. G1把內(nèi)存劃分為多個(gè)獨(dú)立的區(qū)域Region
  2. G1仍然保留分代思想,保留了新生代和老年代,但他們不再是物理隔離,而是一部分Region的集合
  3. G1能夠充分利用多CPU、多核環(huán)境硬件優(yōu)勢(shì),盡量縮短STW
  4. G1整體整體采用標(biāo)記整理算法,局部是采用復(fù)制算法,不會(huì)產(chǎn)生內(nèi)存碎片
  5. G1的停頓可預(yù)測(cè),能夠明確指定在一個(gè)時(shí)間段內(nèi),消耗在垃圾收集上的時(shí)間不超過(guò)設(shè)置時(shí)間
  6. G1跟蹤各個(gè)Region里面垃圾的價(jià)值大小,會(huì)維護(hù)一個(gè)優(yōu)先列表,每次根據(jù)允許的時(shí)間來(lái)回收價(jià)值最大的區(qū)域,從而保證在有限事件內(nèi)高效的收集垃圾
Region

G1不再堅(jiān)持固定大小以及固定數(shù)量的 分代區(qū)域劃分, 而是把連續(xù)的Java堆劃分為多個(gè)獨(dú)立區(qū)域(Region) , 每一個(gè)Region都可以根據(jù)需要, 扮演新生代的Eden空間、 Survivor空間, 或者老年代空間。Region是G1回收器一次回收的最小單元。即每一次回收都是回收N個(gè)Region。

image.png

將整個(gè)堆空間細(xì)分為若干個(gè)小的區(qū)域。
  • ①使用G1收集器時(shí),它將整個(gè)Java堆劃分成約2048個(gè)大小相同的獨(dú)立Region塊,每個(gè)Region塊大小根據(jù)堆空間的實(shí)際大小而定,為2的N次冪,即1MB, 2MB, 4MB, 8MB, 16MB,32MB。
  • ② 雖然還保留有新生代和老年代的概念,但新生代和老年代不再是物理隔離的了,它們都是一部分Region (不需要連續(xù))的集合。通過(guò)Region的動(dòng)態(tài)分配方式實(shí)現(xiàn)邏輯上的連續(xù)。
  • ③ G1垃圾收集器還增加了一種新的內(nèi)存區(qū)域,叫做Humongous內(nèi)存區(qū)域,如圖中的H塊。主要用于存儲(chǔ)大對(duì)象,如果超過(guò)1 .5個(gè)region,就放到H。一般被視為老年代.
卡片 Card

在每個(gè)分區(qū)內(nèi)部又被分成了若干大小為512 Byte卡片(Card),標(biāo)識(shí)堆內(nèi)存最小可用粒度所有分區(qū)的卡片將會(huì)記錄在全局卡片表(Global Card Table)中,分配的對(duì)象會(huì)占用物理上連續(xù)的若干個(gè)卡片,當(dāng)查找對(duì)分區(qū)內(nèi)對(duì)象的引用時(shí)便可通過(guò)記錄卡片來(lái)查找該引用對(duì)象(見(jiàn)RSet)。每次對(duì)內(nèi)存的回收,都是對(duì)指定分區(qū)的卡片進(jìn)行處理。
G1對(duì)內(nèi)存的使用以分區(qū)(Region)為單位,而對(duì)對(duì)象的分配則以卡片(Card)為單位。

G1的gc過(guò)程

G1提供了兩種GC模式,Young GC和Mixed GC,兩種均是完全Stop The World的。

  • Young GC:對(duì)年輕代的gc
  • Mixed GC:對(duì)年輕代和老年的gc
在G1 GC垃圾回收的過(guò)程一個(gè)有四個(gè)階段:
  • 初始標(biāo)記 :和CMS一樣
    只標(biāo)記GC Roots直接關(guān)聯(lián)的對(duì)象
  • 并發(fā)標(biāo)記 :進(jìn)行GC Roots Traceing過(guò)程
  • 最終標(biāo)記 :修正并發(fā)標(biāo)記期間,因程序運(yùn)行導(dǎo)致發(fā)生變化的那一部分對(duì)象
  • 篩選回收 :根據(jù)時(shí)間來(lái)進(jìn)行價(jià)值最大化收集。把一部分region的活對(duì)象拷貝到空Region里面去,然后回收原本的Region空間,該階段是STW(stop-the-world)的。整理堆分區(qū),為混合收集周期識(shí)別回收收益高(基于釋放空間和暫 停目標(biāo))的老年代分區(qū)集合;

隨著老年代內(nèi)存增長(zhǎng),當(dāng)?shù)竭_(dá)IHOP閾值-XX:InitiatingHeapOccupancyPercent(老年代占整堆比,默認(rèn)45%)時(shí),G1開(kāi)始著手準(zhǔn)備收集老年代空間。首先經(jīng)歷并發(fā)標(biāo)記周期,識(shí)別出高收益的老年代分區(qū),前文已述。但隨后G1并不會(huì)馬上開(kāi)始一次混合收集,而是讓?xiě)?yīng)用線程先運(yùn)行一段時(shí)間,等待觸發(fā)一次年輕代收集。在這次STW中,G1將保準(zhǔn)整理混合收集周期。接著再次讓?xiě)?yīng)用線程運(yùn)行,當(dāng)接下來(lái)的幾次年輕代收集時(shí),將會(huì)有老年代分區(qū)加入到CSet中,即觸發(fā)混合收集,這些連續(xù)多次的混合收集稱(chēng)為混合收集周期

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容