溫馨提示×

溫馨提示×

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

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

java中的垃圾收集器是什么

發(fā)布時(shí)間:2021-08-16 17:22:05 來源:億速云 閱讀:114 作者:chen 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“java中的垃圾收集器是什么”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

目錄
  • 1.經(jīng)典垃圾收集器

    • 1.1 Serial收集器

    • 1.2 ParNew收集器

    • 1.3 Parallel Scavenge 收集器

    • 1.4 Serial Old 收集器

    • 1.5 Parallel Old 收集器

    • 1.6 CMS 收集器

    • 1.7 Garbage First 收集器

  • 2低延遲垃圾收集器

    • 2.1 Shenandoah收集器

    • 2.2 ZGC收集器

  • 總結(jié)

    1.經(jīng)典垃圾收集器

    1.1 Serial收集器

    這個(gè)收集器是一個(gè)單線程工作的收集器,但它的單線程的意義并不僅僅是說明他只會使用一個(gè)處理器或一條收集線程去完成垃圾收集工作,更重要對的是強(qiáng)調(diào)在它進(jìn)行垃圾收集時(shí),必須暫停其他所有工作線程,直到它收集結(jié)束。

    目前已經(jīng)老無可用,但有著優(yōu)于其他收集器的地方:簡單而高效

    1.2 ParNew收集器

    ParNew收集器實(shí)質(zhì)上是Serial收集器的多線程并行版本。因?yàn)樗浅薙erial收集器之外,目前唯一可以與CMS收集器配合工作的收集器,所以在JDK7之前的遺留系統(tǒng)中被作為首選的新生代收集器

    CMS收集器是HotSpot虛擬機(jī)中第一款真正意義上支持并發(fā)的垃圾收集器,首次實(shí)現(xiàn)了讓垃圾收集線程與用戶線程同時(shí)工作。但是當(dāng)選用CMS作為老年代收集器時(shí),新生代收集器只能選擇使用Serial收集器或者ParNew收集器

    隨著垃圾收集器技術(shù)的不斷改進(jìn),G1收集器帶著CMS繼承者和代替者的光環(huán)登場。G1收集器是一個(gè)面向全堆的收集器,不需要其他新生代收集器的配合工作

    1.3 Parallel Scavenge 收集器

    Parallel Scavenge收集器也是一款新生代收集器,同樣是基于標(biāo)記-復(fù)制算法實(shí)現(xiàn)的收集器,也可以并行收集的多線程收集器。它的特點(diǎn)是它的關(guān)注點(diǎn)與其他收集器不同。CMS等收集器的關(guān)注點(diǎn)是盡可能地縮短垃圾收集時(shí)用戶線程的停頓時(shí)間,而Parallel Scavenge收集器的目標(biāo)則是達(dá)到一個(gè)可控制的吞吐量。

    $$

    吞吐量=\frac{運(yùn)行用戶代碼時(shí)間}{運(yùn)行用戶代碼時(shí)間+運(yùn)行垃圾收集時(shí)間}

    $$

    提供了兩個(gè)參數(shù)用于精確控制吞吐量:

    -XX:MaxGCPauseMillis 參數(shù)控制最大垃圾搜集停頓時(shí)間,允許的值是一個(gè)大于0的毫秒數(shù)。收集器將盡力保證內(nèi)存回收花費(fèi)的時(shí)間不超過用戶的設(shè)定值。但是設(shè)定過分小的值并不能起到加快回收花費(fèi)的速度的作用。

    -XX:GCTimeRatio 參數(shù)直接設(shè)置吞吐量大小,允許的值是一個(gè)大于0小于100的整數(shù)。也就是垃圾收集時(shí)間占總時(shí)間的比率。相當(dāng)于吞吐量的倒數(shù)。

    Parallel Scavenge 收集器還有一個(gè)參數(shù):-XX:+UseAdaptiveSizePolicy 這是一個(gè)開關(guān)參數(shù),當(dāng)這個(gè)參數(shù)被激活以后,就不需要人工指定新生代的大小,Eden與Survivor區(qū)的比例等等。虛擬機(jī)會根據(jù)當(dāng)前系統(tǒng)的運(yùn)行情況收集性能監(jiān)控信息,動態(tài)調(diào)整這些參數(shù)。

    1.4 Serial Old 收集器

    Serial Old 是 Serial收集器的老年代版本,同樣是一個(gè)單線程收集器,使用標(biāo)記-整理算法??赡苡袃煞N用途:1. 在JDK5以及之前的版本中與Parallel Scavenge收集器搭配使用 2. 作為CMS收集器發(fā)生失敗時(shí)的后備預(yù)案。

    1.5 Parallel Old 收集器

    Parallel Old 是 Parallel Scavenge收集器的老年代版本,支持多線程并發(fā)收集,基于標(biāo)記-整理算法實(shí)現(xiàn),從JDK6版本開始提供。在注重吞吐量或者處理器資源較為稀缺的場合,都可以優(yōu)先考慮Parallel Scavenge加Parallel Old收集器這個(gè)組合。

    1.6 CMS 收集器

    CMS收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器,基于標(biāo)記-清除算法實(shí)現(xiàn)。整個(gè)運(yùn)作過程分為4步:

    步驟名稱行為
    初始標(biāo)記(CMS initial mark)標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對象,需要Stop The World
    并發(fā)標(biāo)記(CMS concurrent mark)從GC Roots的直接關(guān)聯(lián)對象開始遍歷整個(gè)對象圖的過程,可以與垃圾收集線程一起并發(fā)運(yùn)行
    重新標(biāo)記(CMS remark)修正并發(fā)標(biāo)記期間,因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動的那一部分對象的標(biāo)記記錄,需要Stop the World
    并發(fā)清楚(CMS concurrent sweep)清理刪除掉標(biāo)記階段判斷的已經(jīng)死亡的對象,可以與用戶線程同時(shí)并發(fā)完成

    CMS收集器存在三個(gè)缺點(diǎn):

    1.CMS收集器對處理器資源非常敏感,默認(rèn)啟動的回收線程數(shù)為(處理器核心數(shù)量+3)/ 4。在并發(fā)階段會因?yàn)檎加昧艘徊糠志€程而導(dǎo)致應(yīng)用程序變慢,降低總吞吐量。

    為了緩解這種情況虛擬機(jī)提供了“增量式并發(fā)收集器”(Incremental Concurrent Mark Sweep/i-CMS)作用是在并發(fā)標(biāo)記、清理的時(shí)候讓收集器線程、用戶線程交替運(yùn)行,盡量減少垃圾收集器線程的獨(dú)占資源的時(shí)間,這樣整個(gè)垃圾收集的過程會更長,但是對用戶程序的影響就會顯得較少一些,直觀感受是速度變慢的時(shí)間更多了,但速度下降幅度就沒有那么明顯。效果一般從jdk7開始被聲明為deprecated ,從JDK9發(fā)布后被完全廢棄

    2.由于CMS收集器無法處理“浮動垃圾”(Floating Garbage),有可能出現(xiàn)"Concurrent Mode Failure" 失敗進(jìn)而導(dǎo)致另一完全"Stop The World"的Full GC的產(chǎn)生。

    可以適當(dāng)調(diào)高參數(shù)-XX:CMSInitiatingOccu-pancyFraction的值來提高CMS的觸發(fā)百分比,降低內(nèi)存回收頻率,獲得更好的性能。如果設(shè)置的太高將會很容易導(dǎo)致大量的并發(fā)失敗產(chǎn)生,性能反而降低

    3.由于基于標(biāo)記-清除算法,可能在收集結(jié)束時(shí)會有大量的空間碎片產(chǎn)生

    通過調(diào)節(jié):-XX:+UseCMSCompactAtFullCollection開關(guān)參數(shù),默認(rèn)是開啟的,從jdk9開始廢棄

    *** -XX:CMSFullGCsBeforeCompaction 默認(rèn)值是0,表示每次進(jìn)入Full GC時(shí)都進(jìn)行碎片整理***

    1.7 Garbage First 收集器

    Garbage First 收集器,簡稱 G1收集器,開創(chuàng)了收集器面向局部收集的設(shè)計(jì)思路和基于Region的內(nèi)存布局形式。是一款主要面向服務(wù)端應(yīng)用的垃圾收集器??梢悦嫦蚨褍?nèi)存的任何部分來組成回收集,衡量的標(biāo)準(zhǔn)不再是它屬于哪個(gè)分代,而是哪塊內(nèi)存中存放的垃圾數(shù)量最多,回收收益最大。G1開創(chuàng)的基于Region的堆內(nèi)存布局是它能夠?qū)崿F(xiàn)這個(gè)目標(biāo)的關(guān)鍵,G1不再堅(jiān)持固定大小以及固定數(shù)量的分代區(qū)域劃分,而是把連續(xù)的java堆劃分為多個(gè)大小相等的獨(dú)立區(qū)域(Region),每一個(gè)Region都可以根據(jù)需要,扮演新生代的Eden空間、Survivor空間或者老年代空間。

    Region中還有一類特殊的Humongous區(qū)域,專門用來存儲大對象。G1認(rèn)為只要大小超過了Region容量一半的對象就可以判定為大對象。每個(gè)Region的大小可以通過參數(shù)-XX:G1HeapRegionSize設(shè)定,取值范圍為1MB~32MB。

    G1收集器之所以可以建立可預(yù)測的停頓時(shí)間模型,是因?yàn)樗鼘egion作為單次回收的最小單元,即每次收集到的內(nèi)存空間都是Region大小的整數(shù)倍,這樣可以有計(jì)劃地避免在整個(gè)JAVA堆中進(jìn)行全區(qū)域的垃圾收集。更具體的思路是讓G1收集器區(qū)跟蹤各個(gè)Region里面的垃圾堆積的價(jià)值大小,價(jià)值即回收所獲得的空間大小以及回收所需要的時(shí)間的經(jīng)驗(yàn)值,然后在后臺 維護(hù)一個(gè)優(yōu)先級列表,每次根據(jù)用戶設(shè)定允許的收集停頓時(shí)間(-XX:MaxGCPauseMillis)優(yōu)先處理回收價(jià)值收益最大的那些Region。

    G1的記憶集在存儲結(jié)構(gòu)的本質(zhì)上是一種哈希表,Key是別的Region的起始地址,Value是一個(gè)集合,里面存儲的元素是卡表的索引號。G1收集器通過原始快照(SATB)算法實(shí)現(xiàn)了保證其不能打破原本的對象圖結(jié)構(gòu)的目的。

    G1收集器運(yùn)作過程大致分為四個(gè)步驟:

    步驟行為
    初始標(biāo)記(Initial Marking)標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對象,并且修改TAMS指針的值。這個(gè)階段需要停頓線程,而且是借用進(jìn)行Minor GC的時(shí)候同步完成的
    并發(fā)標(biāo)記(Concurrent Marking)從GC Root開始對堆種對象進(jìn)行可達(dá)性分析,遞歸掃描整個(gè)堆里的對象圖,找出要回收的對象,可以與用戶程序并發(fā)執(zhí)行。對象圖掃描完成以后,還需要重新處理SATB記錄下的在并發(fā)時(shí)有引用變動的對象
    最終標(biāo)記(Final Marking)對用戶線程做另一個(gè)短暫的暫停,用于處理并發(fā)階段結(jié)束后仍遺留下來的最后那少量的SATB記錄
    篩選回收(Live Data Counting and Evacuation)負(fù)責(zé)更新Region的統(tǒng)計(jì)數(shù)據(jù),對各個(gè)Region的回收價(jià)值和成本進(jìn)行排序,根據(jù)用戶所期望的停頓時(shí)間來制定回收計(jì)劃,可以自由選擇任意多個(gè)Region構(gòu)成回收集,然后把決定回收的那一部分Region的存活對象復(fù)制到空的Region中,再清理整個(gè)舊Region的全部空間,必須暫停用戶線程

    2低延遲垃圾收集器

    2.1 Shenandoah收集器

    Shenandoah收集器是一款只有OpenJDK才會包含的。與G1收集器相比,它們兩者有著相似的堆內(nèi)存布局,在初始標(biāo)記、并發(fā)標(biāo)記等許多階段的處理思路上都高度一致。但是在管理內(nèi)存堆方面,與G1收集器至少有三個(gè)方面的明顯的不同之處:

    1.支持并發(fā)的整理算法:G1的回收階段是可以多線程并行的,但不能與用戶線程并發(fā)。Shenandoah后面會講到。

    2.Shenandoah收集器默認(rèn)不使用分代收集。

    3.Shenandoah摒棄了在G1中耗費(fèi)大量內(nèi)存和計(jì)算資源去維護(hù)的記憶集,改名為“連接矩陣”(Connection Matrix)的全局?jǐn)?shù)據(jù)結(jié)構(gòu)來記錄跨Region的引用關(guān)系。降低了處理跨代指針的記憶集維護(hù)消耗,也降低了偽共享問題發(fā)生的概率

    Shenandoah收集器大致工作流程可以分為9個(gè)階段:

    步驟名稱動作
    初始標(biāo)記(Initial Marking)標(biāo)記與GC Roots直接關(guān)聯(lián)的對象,這個(gè)階段是Stop The World的,停頓時(shí)長與堆大小無關(guān),與GC Roots的數(shù)量相關(guān)。
    并發(fā)標(biāo)記(Concurrent Marking)遍歷對象圖,標(biāo)記出全部可達(dá)的對象,這個(gè)階段與用戶線程一起并發(fā)的,時(shí)間長短取決于堆中存活對象的數(shù)量以及對象圖的結(jié)構(gòu)復(fù)雜程度。
    最終標(biāo)記(Final Marking)處理剩余的SATB掃描,在這個(gè)階段統(tǒng)計(jì)出回收價(jià)值最高的Region,將這些Region構(gòu)成一組回收集,最終標(biāo)記階段也會有一小段短暫的停頓。
    并發(fā)清理(Concurrent Cleanup)清理那些整個(gè)區(qū)域內(nèi)連一個(gè)存活對象都沒有找到的Region(這類Region被稱為Immediate Garbage Region)。
    并發(fā)回收(Concurrent Evacuation)核心差異!Shenandoah要把回收集里面的存活對象先復(fù)制一份到其他未被使用的Region之中。Shenandoah會通過讀屏障和被成稱為"Brooks Points"的轉(zhuǎn)發(fā)指針來解決在復(fù)制對象時(shí)遇到的困難。時(shí)間長短取決于回收集的大小。
    初始引用更新(Initial Update Reference)把堆中所有指向舊對象的引用修正到復(fù)制后的新地址,這個(gè)操作稱為引用更新。在此階段,只是建立了一個(gè)線程集合點(diǎn),確保所有的并發(fā)回收階段中進(jìn)行的收集器線程都已完成分配給它們的對象移動任務(wù)而已。時(shí)間會很短,有一個(gè)十分短暫的停頓。
    并發(fā)引用更新(Comcurrent Update Reference)真正開始進(jìn)行引用更新操作,與用戶線程一起并發(fā)的,時(shí)間長短取決于內(nèi)存中涉及的引用數(shù)量的多少。只需要按照內(nèi)存物理地址的順序,線性搜索出引用類型,把舊值改為新值即可。
    最終引用更新(Final Update Reference)解決了堆中的引用更新后,還要修正存在于GC Roots中的引用。這個(gè)階段是最后一次停頓,時(shí)間與GC Roots的數(shù)量有關(guān)。
    并發(fā)清理(Concurrent Cleanup)此時(shí)整個(gè)回收集中所有的Region已再無存活對象,都變成了Immediate Garbage Regions了,最后調(diào)用一次并發(fā)清理過程來回收這些Region的內(nèi)存空間,供以后新對象分配使用。

    Brooks Points:Brooks是一個(gè)人的名字,它提出使用了轉(zhuǎn)發(fā)指針(Forwarding Pointer)的技術(shù)來實(shí)現(xiàn)對象移動與用戶程序并發(fā)的一種解決方案。不需要用到內(nèi)存保護(hù)陷阱,而是在原有對象布局結(jié)構(gòu)的最前面統(tǒng)一增加一個(gè)新的引用字段,在正常不處于并發(fā)移動的情況下,該引用指向?qū)ο笞约?。?shí)際上Shenandoah收集器是通過比較并交換(Compare And Swap, CAS)操作來保證并發(fā)時(shí)對象的訪問正確性的。

    JDK13中Shenandoah的內(nèi)存屏障模型改進(jìn)為基于引用訪問屏障(Load Reference Barrier)的實(shí)現(xiàn),所謂“引用訪問屏障”是指內(nèi)存屏障只攔截對象中數(shù)據(jù)類型為引用類型的讀寫操作,而不去管原生數(shù)據(jù)類型等其他非引用字段的讀寫。這能省去大量對原生類型、對象比較、對象加鎖等場景中設(shè)置內(nèi)存屏障所帶來的消耗。

    2.2 ZGC收集器

    ZGC收集器是一款基于Region內(nèi)存布局的,暫時(shí)不設(shè)分代的,使用了讀屏障、染色指針和內(nèi)存多重映射等技術(shù)來實(shí)現(xiàn)可并發(fā)的標(biāo)記-整理算法的,以低延遲為首要目標(biāo)的一款垃圾收集器。

    ZGC的Region具有動態(tài)性-動態(tài)創(chuàng)建和銷毀,以及動態(tài)的區(qū)域容量大小。

    染色指針(Colored Pointer):一種直接將少量額外的信息存儲在指針上的技術(shù)。盡管在linux下64位指針的高18位不能用來尋址,但是剩余的46位所能支持的64TB內(nèi)存仍然能夠充分滿足需要。鑒于此,將其高4位提取出來存儲四個(gè)標(biāo)記信息。通過這些標(biāo)志位,虛擬機(jī)可以直接從指針中看到其引用對象的三色標(biāo)記狀態(tài)、是否進(jìn)入了重分配集、是否只能通過finalize( )方法才能被訪問到。也使得ZGC能夠管理的內(nèi)存不可以超過4TB。使用染色指針的三大優(yōu)勢:

    1.可以使得一旦某個(gè)Region的存活對象被移走之后,這個(gè)Region立即就能被釋放和重用掉,不必等待整個(gè)堆中所有指向該Region的引用都被修正后才能清理。

    2.可以大幅度減少在垃圾收集過程中的內(nèi)存屏障的使用數(shù)量。到目前為止,ZGC都未使用寫屏障,只使用了讀屏障。

    3.可以作為一種可擴(kuò)展的存儲結(jié)構(gòu)用來記錄更多與對象標(biāo)記、重定位過程相關(guān)的數(shù)據(jù),以便日后進(jìn)一步提高性能。

    Linux/x86-64平臺上的ZGC使用了多重映射將多個(gè)不同的虛擬內(nèi)存地址映射到同一個(gè)物理內(nèi)存地址上,意味著ZGC在虛擬內(nèi)存中看到的地址空間要比實(shí)際的堆內(nèi)存容量來得更大。把染色指針中的標(biāo)志位看作是地址的分段符,只要將這些不同的地址段都映射到同一個(gè)物理內(nèi)存空間,經(jīng)過多重映射轉(zhuǎn)換后,就可以使用染色指針正常進(jìn)行尋址了。

    ZGC的運(yùn)作過程(省略部分與之前介紹的G1和Shenandoah相同的小階段部分):

    步驟動作
    并發(fā)標(biāo)記(Concurrent Mark)遍歷對象圖做可達(dá)性分析的階段,前后也要經(jīng)過初始標(biāo)記、最終標(biāo)記的短暫停頓。ZGC的標(biāo)記是在指針上而不是在對象上進(jìn)行的,標(biāo)記階段會更新染色指針中的Marked 0、Marked 1 標(biāo)志位。
    并發(fā)預(yù)備重分配(Concurrent Prepare for Relocate)根據(jù)特定的查詢條件統(tǒng)計(jì)得出本次收集過程要清理那些Region,將這些Region組成重分配集。與G1收集器的回收集還是有區(qū)別的,ZGC的重分配集只是決定了里面的存活對象會被重新分配復(fù)制到其他的Region中,里面的Region會被釋放,而并不能說回收行為就只是針對這個(gè)集合里面的Region進(jìn)行,因?yàn)闃?biāo)記過程是針對全堆的。
    并發(fā)重分配(Concurrent Reolcate)核心階段!把重分配集中的存活對象復(fù)制到新的Region上,并未重分配集中的每個(gè)Region維護(hù)一個(gè)轉(zhuǎn)發(fā)表,記錄從舊對象到新對象的轉(zhuǎn)向關(guān)系。
    并發(fā)重映射(Concurrent Remap)修正整個(gè)堆中指向重分配集中舊對象的所有引用。

    “java中的垃圾收集器是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

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

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

    AI