溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么理解垃圾收集器

發(fā)布時(shí)間:2021-10-20 16:43:06 來(lái)源:億速云 閱讀:135 作者:iii 欄目:編程語(yǔ)言

這篇文章主要講解了“怎么理解垃圾收集器”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“怎么理解垃圾收集器”吧!

(一)概述

如果說(shuō)垃圾收集算法是內(nèi)存回收的理論,那么垃圾收集器就是內(nèi)存回收的具體實(shí)現(xiàn)。

垃圾收集器目前存在的有很多,但是依舊沒(méi)有哪個(gè)收集器是萬(wàn)能的存在,我們只能選擇一個(gè)最適合應(yīng)用的收集器。

下面會(huì)介紹目前主流Java虛擬機(jī)中所采用的七種垃圾收集器: Serial、parNew、ParallelScavenge、SerialOld、ParallelOld、CMS、G1 上述垃圾收集器有些適用于新生代,有些適用于老年代,有些在新生代和老年代都適應(yīng)。如下圖所示,連線表示可以配合使用。

怎么理解垃圾收集器

(二)Serial

Serial是一個(gè)單線程的收集器,Serial的特點(diǎn)是它在進(jìn)行垃圾收集時(shí),必須“Stop the World”,意思就是當(dāng)這個(gè)垃圾收集器開(kāi)始工作時(shí),必須停止其他所有的工作線程。聽(tīng)起來(lái)似乎很不靠譜,但是對(duì)于限定單個(gè)CPU的場(chǎng)景下,這種方式簡(jiǎn)單而高效。對(duì)于簡(jiǎn)單的桌面應(yīng)用,分配給虛擬機(jī)的內(nèi)存不會(huì)很大,對(duì)于一兩百兆的新生代,Serial的垃圾收集時(shí)間可以控制在一百毫秒以內(nèi),對(duì)于用戶來(lái)說(shuō)基本上是無(wú)影響的。

Serial收集器在新生代使用復(fù)制算法。

(三)ParNew

ParNew垃圾收集器是Serial的多線程版本,使用多條線程進(jìn)行垃圾收集。除此之外,和Serial基本相同,ParNew在多線程收集垃圾時(shí)依舊需要**“Stop the World”**。ParNew可以使用-XX:ParallelGCThreads參數(shù)來(lái)限制垃圾收集的線程數(shù)量。

ParNew收集器在新生代使用復(fù)制算法

(四)Parallel Scavenge

Parallel Scavenge也是新生代收集器,也同樣是多線程的收集器,但是和ParNew不同,Parallel Scavenge收集器關(guān)注的是一個(gè)可控制的吞吐量(Throughput)。所謂吞吐量指的是CPU用于運(yùn)行代碼的時(shí)間和CPU總消耗的時(shí)間比例。

吞吐量=運(yùn)行代碼的時(shí)間 /(運(yùn)行代碼的時(shí)間+垃圾收集時(shí)間)

理論上吞吐量越高,用戶就越不能感受到停頓時(shí)間。

Parallel Scavenge提供了兩個(gè)參數(shù)用來(lái)控制吞吐量: -XX:MaxGCPauseMillis和**-XX:GCTimeRatio**

-XX:MaxGCPauseMillis設(shè)置內(nèi)存回收花費(fèi)時(shí)間最高毫秒值,但是不要一味地認(rèn)為只要把值設(shè)置很小,垃圾回收就更快了。這個(gè)停頓時(shí)間是以犧牲吞吐量和新生代空間換來(lái)的。

-XX:GCTimeRatio表示垃圾收集時(shí)間占總時(shí)間的比例,(1~100),也就是吞吐量的倒數(shù)。默認(rèn)這個(gè)值是99,就是允許最大百分之1的垃圾手機(jī)時(shí)間(1/(1+99))。

還有一個(gè)參數(shù)**-XX:+UseAdaptiveSizePolicy**,打開(kāi)這個(gè)參數(shù)后,就不需要自己設(shè)置新生代大小、晉升老年代對(duì)象年齡等參數(shù),因此Parallel Scavenge收集器也被叫做吞吐量?jī)?yōu)先垃圾收集器。

Parallel Scavenge采用復(fù)制算法。

(五)Serial Old

一聽(tīng)名字就知道這是Serial收集器的老年代版本,是單線程收集器,采用標(biāo)記-整理算法,其余的和新Serial基本相同。

(六)Parallel Old

Parallel Scavenge收集器的老年版本,多線程收集器,采用標(biāo)記-整理算法,也是吞吐量?jī)?yōu)先。

(七)CMS收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器。CMS是基于標(biāo)記-清除算法的老年代垃圾回收器,CMS是目前應(yīng)用最廣泛的老年代垃圾回收器,它進(jìn)行垃圾回收分為以下四步:

1、初始標(biāo)記:標(biāo)記GC Roots可以直接關(guān)聯(lián)到的對(duì)象,速度很快(stop the world)

2、并發(fā)標(biāo)記:根搜索算法的過(guò)程

3、重新標(biāo)記:為了修正并發(fā)標(biāo)記期間,因程序運(yùn)行導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的對(duì)象。(stop the world)

4、并發(fā)清除:清除垃圾

這個(gè)過(guò)程中耗時(shí)最長(zhǎng)的是并發(fā)標(biāo)記和并發(fā)清除的過(guò)程,但是并不會(huì)stop the world,而初始標(biāo)識(shí)和重新標(biāo)記的速度都很快,即使stop the world也不會(huì)占用太多時(shí)間。

它的優(yōu)點(diǎn)就是并發(fā)收集、并發(fā)清除、低停頓。

但是它有三個(gè)顯著的缺點(diǎn):

1、對(duì)CPU資源十分敏感,因?yàn)椴l(fā)標(biāo)記和并發(fā)清除都是和程序同時(shí)運(yùn)行,因此會(huì)占用CPU導(dǎo)致應(yīng)用程序變慢。

2、無(wú)法處理浮動(dòng)垃圾,浮動(dòng)垃圾就是在并發(fā)清除過(guò)程中新生成的垃圾,這部分垃圾CMS無(wú)法在本次被清理,可能出現(xiàn)Concurrent Mode Failed報(bào)錯(cuò),因此需要預(yù)留一定的內(nèi)存空間,無(wú)法等到老年代快被占滿時(shí)再清除。默認(rèn)情況下,CMS在老年代使用了68%后就會(huì)被激活。可以設(shè)置-XX:CMSInitiatingOccupancyFraction設(shè)置這個(gè)值。

3、產(chǎn)生空間碎片,由于采用的是標(biāo)記-清除算法,那就無(wú)法避免會(huì)產(chǎn)生空間碎片的問(wèn)題,這會(huì)給分配大對(duì)象帶來(lái)困難。

(八)G1

上面的垃圾回收器基本上都是按新生代和老年代去區(qū)分,但是G1不一樣

堆結(jié)構(gòu)

G1的堆結(jié)構(gòu)就是把一整塊內(nèi)存區(qū)域劃分為多個(gè)固定大小的塊,JVM一般把堆劃分為2000個(gè)region,然后每個(gè)region從1M到32M不等。

內(nèi)存的分配

所有的region會(huì)被劃分為Eden、Survivor、Old和Humongous,其中對(duì)Eden、Survivor和Old的理解用其他垃圾回收器去理解,這里多了一種類型Humongous,這個(gè)類型主要用來(lái)存儲(chǔ)比標(biāo)準(zhǔn)塊大百分之50或者更大的對(duì)象。

G1中的YGC

第一次YGC時(shí),Eden塊中存活的對(duì)象會(huì)被轉(zhuǎn)移到一個(gè)或多個(gè)survivor塊中,存活時(shí)間達(dá)到閾值,這些對(duì)象就會(huì)晉升到老年代。年輕代 GC 通過(guò)多線程并行進(jìn)行。

此時(shí)會(huì)有一次 stop the world暫停,會(huì)計(jì)算出 Eden大小和 survivor 大小,用于下次young GC。統(tǒng)計(jì)信息會(huì)被保存下來(lái),用于輔助計(jì)算size。比如暫停時(shí)間之類的指標(biāo)也會(huì)納入考慮。

一旦發(fā)生一次新生代回收,整個(gè)新生代都會(huì)被回收(根據(jù)對(duì)暫停時(shí)間的預(yù)測(cè)值,新生代的大小可能會(huì)動(dòng)態(tài)改變)

G1中的老年代垃圾收集

老年代回收不會(huì)回收全部老年代空間,只會(huì)選擇一部分收益最高的 Region,回收時(shí)一般會(huì)搭便車——把待回收的老年代 Region 和所有的新生代 Region 放在一起進(jìn)行回收,這個(gè)過(guò)程一般被稱為 Mixed GC

G1中的老年代垃圾收集和CMS收集器很相似

1、初始標(biāo)記:附加在正常的YGC過(guò)程中,標(biāo)記所有的根。(stop the world)

2、掃描根區(qū)域:掃描Survivor Regions中指向老年代的被初始標(biāo)記標(biāo)記的引用及引用的對(duì)象,這個(gè)階段是并發(fā)執(zhí)行的,但是在年輕代GC發(fā)生之前必須完成。(stop the world)

3、并發(fā)標(biāo)記:在整個(gè)堆中查找活著的元素,此階段可被YGC打斷

4、再次標(biāo)記:類似CMS的重新標(biāo)記,處理并發(fā)標(biāo)記階段產(chǎn)生的新的對(duì)象引用,這階段使用了SATB(snapshot-at-the-beginning)算法,該算法比CMS中所采用的快很多。(stop the world)

5、清理階段:G1 GC 會(huì)識(shí)別完全空閑的區(qū)域和可供進(jìn)行混合垃圾回收的區(qū)域進(jìn)行清理。(stop the world)

你可以發(fā)現(xiàn),有四個(gè)階段都需要stop the world,為了降低stop the world的時(shí)間,G1使用了RSet(Remembered Set)來(lái)記錄不同代之間的引用關(guān)系。

RSet

RSet記錄了“誰(shuí)引用了我”,RSet記錄了以下兩種引用:

1、老年代 Region 間的引用

2、老年代 Region 到新生代 Region 的引用,Young GC 時(shí)直接將這種引用加入 GC Roots。

RSet的工作原理是這樣的,進(jìn)行 Young GC 時(shí),選擇新生代所在的 Region 作為 GC Roots,這些 Region 中的 RSet 記錄了老年代->新生代的的跨代引用(「誰(shuí)引用了我」),從而可以避免了掃描整個(gè)老年代。進(jìn)行 Mixed GC 時(shí),「老年代->老年代」之間的引用,可以通過(guò)待回收 Region 中的 RSet 記錄獲得,「新生代->老年代」之間的引用通過(guò)掃描全部的新生代獲得(前面提到過(guò) Mixed GC 會(huì)搭 Young GC 的便車),也不需要掃描全部老年代。總之,引入 RSet 后,GC 的堆掃描范圍大大減少了。

感謝各位的閱讀,以上就是“怎么理解垃圾收集器”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)怎么理解垃圾收集器這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI