本篇內(nèi)容主要講解“G1垃圾回收器與CMS的區(qū)別有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“G1垃圾回收器與CMS的區(qū)別有哪些”吧!
創(chuàng)新互聯(lián)主營名山網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,重慶APP開發(fā),名山h5小程序制作搭建,名山網(wǎng)站營銷推廣歡迎名山等地區(qū)企業(yè)咨詢
在G1之前的垃圾收集器,將堆區(qū)主要劃分了Eden區(qū),Old區(qū),Survivor區(qū)。其中對于Eden,Survivor對回收過程來說叫做“年輕代垃圾收集”。并且年輕代和老年代都分別是連續(xù)的內(nèi)存空間。G1將堆分成了若干Region,Region的大小可以通過G1HeapRegionSize參數(shù)進行設(shè)置,其必須是2的冪,范圍允許為1Mb到32Mb。 JVM的會基于堆內(nèi)存的初始值和最大值的平均數(shù)計算分區(qū)的尺寸,平均的堆尺寸會分出約2000個Region。分區(qū)大小一旦設(shè)置,則啟動之后不會再變化。
Eden regions(年輕代-Eden區(qū))
Survivor regions(年輕代-Survivor區(qū))
Old regions(老年代)
Humongous regions(巨型對象區(qū)域)
Free resgions(未分配區(qū)域,也會叫做可用分區(qū))
1)G1還是采用分代回收,但是不同的分代之間內(nèi)存不一定是連續(xù)的,不同分代的Region的占用數(shù)也不一定是固定的(不建議通過相關(guān)選項顯式設(shè)置年輕代大小。會覆蓋暫停時間目標)。年輕代的Eden,Survivor數(shù)量會隨著每一次GC發(fā)生相應(yīng)的改變。
2)分區(qū)是不固定屬于哪個分代的,所以比如一次ygc過后,原來的Eden的分區(qū)就會變成空閑的可用分區(qū),隨后也可能被用作分配巨型對象,成為H區(qū)等。
3)G1中的巨型對象是指,占用了Region容量的50%以上的一個對象。Humongous區(qū),就專門用來存儲巨型對象。如果一個H區(qū)裝不下一個巨型對象,則會通過連續(xù)的若干H分區(qū)來存儲。因為巨型對象的轉(zhuǎn)移會影響GC效率,所以并發(fā)標記階段發(fā)現(xiàn)巨型對象不再存活時,會將其直接回收。ygc也會在某些情況下對巨型對象進行回收。
4)分區(qū)可以有效利用內(nèi)存空間,因為收集整體是使用“標記-整理”,Region之間基于“復制”算法,GC后會將存活對象復制到可用分區(qū)(未分配的分區(qū)),所以不會產(chǎn)生空間碎片。
5)G1類似CMS,也會在比如一次fullgc中基于堆尺寸的計算重新調(diào)整(增加)堆的空間。但是相較于執(zhí)行fullgc,G1 GC會在無法分配對象或者巨型對象無法獲得連續(xù)分區(qū)來分配空間時,優(yōu)先嘗試擴展堆空間來獲得更多的可用分區(qū)。原則上就是G1會計算執(zhí)行GC的時間,并且極力減少花在GC上的時間(包括ygc,mixgc),如果可能,會通過不斷擴展堆空間來滿足對象分配、轉(zhuǎn)移的需要。
6)因為G1提供了“可預測的暫停時間”,也是基于G1的啟發(fā)式算法,所以G1會估算年輕代需要多少分區(qū),以及還有多少分區(qū)要被回收。younggc觸發(fā)的契機就是在Eden分區(qū)數(shù)量達到上限時。一次younggc會回收所有的Eden和survivor區(qū)。其中存活的對象會被轉(zhuǎn)移到另一個新的survivor區(qū)或者old區(qū),如果轉(zhuǎn)移的目標分區(qū)滿了,會再將可用區(qū)標記成S或者O區(qū)。
TLAB(Thread Local Allocation Buffer)本地線程緩沖區(qū)
G1 GC會默認會啟用Tlab優(yōu)化。其作用就是在并發(fā)情況下,基于CAS的獨享線程(mutator threads)可以優(yōu)先將對象分配在一塊內(nèi)存區(qū)域(屬于Java堆的Eden中),只是因為是Java線程獨享的內(nèi)存區(qū),沒有鎖競爭,所以分配速度更快,每個Tlab都是一個線程獨享的。如果待分配的對象被判斷是巨型對象,則不使用TLAB。
PLAB(Promotion Local Allocation Buffer) 晉升本地分配緩沖區(qū)
在younggc中,對象會將全部Eden區(qū)存活的對象轉(zhuǎn)移(復制)到S區(qū)分區(qū)。也會存在S區(qū)對象晉升(Promotion)到老年代。這個決定晉升的閥值可以通過MaxTenuringThreshold設(shè)定。晉升的過程,無論是晉升到S還是O區(qū),都是在GC線程的PLAB中進行。每個GC線程都有一個PLAB。
Collection Sets(CSets)待收集集合
GC中待回收的region的集合。CSet中可能存放著各個分代的Region。CSet中的存活對象會在gc中被移動(復制)。GC后CSet中的region會成為可用分區(qū)。
Remembered Sets(RSets)已記憶集合
已記憶集合在每個分區(qū)中都存在,并且每個分區(qū)只有一個RSet。其中存儲著其他分區(qū)中的對象對本分區(qū)對象的引用,是一種points-in結(jié)構(gòu)。ygc的時候,只要掃描RSet中的old區(qū)對象對于本young區(qū)的引用,不需要掃描所有old區(qū)。mixed gc時,掃描Old區(qū)的RSet中,其他old區(qū)對于本old分區(qū)的引用,一樣不用掃描所有的old區(qū)。提高了GC效率。因為每次GC都會掃描所有young區(qū)對象,所以RSet只有在掃描old引用young,old引用old時會被使用。
Card Table 卡表
將Java堆劃分為相等大小的一個個區(qū)域,這個小的區(qū)域(一般size在128-512字節(jié))被當做Card,而Card Table維護著所有的Card。Card Table的結(jié)構(gòu)是一個字節(jié)數(shù)組,Card Table用單字節(jié)的信息映射著一個Card。當Card中存儲了對象時,稱為這個Card被臟化了(dirty card)。 對于一些熱點Card會存放到Hot card cache。同Card Table一樣,Hot card cache也是全局的結(jié)構(gòu)。
CMS收集器僅作用于老年代的收集,是基于標記-清除算法的,它的運作過程分為4個步驟:
初始標記(CMS initial mark)獨占CPU(STW),僅標記GCroots能直接關(guān)聯(lián)的對象
并發(fā)標記(CMS concurrent mark)可以和用戶線程并行執(zhí)行,標記所有可達對象
重新標記(CMS remark)獨占CPU(STW),對并發(fā)標記階段用戶線程運行產(chǎn)生的垃圾對象進行標記修正
并發(fā)清除(CMS concurrent sweep)可以和用戶線程并行執(zhí)行,清理垃圾
其中,初始標記、重新標記這兩個步驟仍然需要Stop-the-world。初始標記僅僅只是標記一下GC Roots能直接關(guān)聯(lián)到的對象,速度很快,并發(fā)標記階段就是進行GC Roots Tracing的過程,而重新標記階段則是為了修正并發(fā)標記期間因用戶程序繼續(xù)運作而導致標記產(chǎn)生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始階段稍長一些,但遠比并發(fā)標記的時間短。
并發(fā)收集、低停頓
1)對CPU非常敏感:在并發(fā)階段雖然不會導致用戶線程停頓,但是會因為占用了一部分線程使應(yīng)用程序變慢
2)無法處理浮動垃圾:在最后一步并發(fā)清理過程中,用戶線程執(zhí)行也會產(chǎn)生垃圾,但是這部分垃圾是在標記之后,所以只有等到下一次gc的時候清理掉,這部分垃圾叫浮動垃圾
3)CMS使用“標記-清理”法會產(chǎn)生大量的空間碎片:當碎片過多,將會給大對象空間的分配帶來問題,會出現(xiàn)老年代還有很大的空間但無法找到足夠大的連續(xù)空間來分配當前對象,不得不提前觸發(fā)一次FullGC,為了解決這個問題CMS提供了一個開關(guān)參數(shù)(-XX:+UseCMSCompactAtFullCollection默認開啟),用于在FullGC完成之后進行一次碎片整理,但是內(nèi)存整理的過程是無法并發(fā)的,會導致停頓時間變長
年輕代垃圾回收只會回收Eden區(qū)和Survivor區(qū)。YGC時,首先G1停止應(yīng)用程序的執(zhí)行(Stop-The-World),G1創(chuàng)建回收集(Collection Set),回收集是指需要被回收的內(nèi)存分段的集合,年輕代回收過程的回收集包含年輕代Eden區(qū)和Survivor區(qū)所有的內(nèi)存分段。
1)第一階段,掃描根。根是指static變量指向的對象,正在執(zhí)行的方法調(diào)用鏈條上的局部變量等。跟引用連同RSet記錄的外部引用作為掃描存活對象的入口。
2)第二階段,更新RSet。處理dirty card queue中的card,更新RSet。此階段完成后,RSet可以準確的反映老年代對所在的內(nèi)存分段中對象的引用。
3)第三階段,處理RSet。識別被老年代對象指向的Eden中的對象,這些被指向的Eden中的對象被認為是存活的對象。
4)第四階段,復制對象。此階段,對象樹被遍歷,Eden區(qū)內(nèi)存段中存活的對象會被復制到Survivor區(qū)中空的內(nèi)存分段,Survivor區(qū)內(nèi)存段中存活的對象如果年齡未達閾值,年齡會加1,達到閾值會被復制到Old區(qū)中空的內(nèi)存分段。如果Survivor空間不夠,Eden空間的部分數(shù)據(jù)會直接晉升到老年代空間。
5)第五階段,處理引用。處理Soft,Weak,Phantom,Final,JNI Weak 等引用。最終Eden空間的數(shù)據(jù)為空,GC停止工作,而目標內(nèi)存中的對象都是連續(xù)存儲的,沒有碎片,所以復制過程可以達到內(nèi)存整理的效果,減少碎片。
當整個堆大小在jvm堆??臻g中占比達到IHOP閾值-XX:InitiatingHeapOccupancyPercent(默認45%)時,G1就會啟動一次混合垃圾收集周期。Mix GC不僅進行正常的新生代垃圾收集,同時也回收部分后臺掃描線程標記的老年代分區(qū)。進行Mix GC之前,會先進行全局并發(fā)標記。
1)初始標記(InitingMark):標記GC Roots,會STW,一般會復用YoungGC的暫停時間。初始標記會設(shè)置好所有分區(qū)的NTAMS值。
2)根分區(qū)掃描(RootRegionScan):根據(jù)初始標記階段確定的GC根元素,掃描這些元素所在region,獲取對老年代的引用,并標記被引用的對象。 該階段與應(yīng)用線程并發(fā)執(zhí)行,也就是說沒有STW停頓,必須在下一次年輕代GC開始之前完成。
3)并發(fā)標記(ConcurrentMark):遍歷整個堆,查找所有可達的存活對象。若發(fā)現(xiàn)區(qū)域?qū)ο笾械乃袑ο蠖际抢?那這個區(qū)域會被立即回收。 此階段與應(yīng)用線程并發(fā)執(zhí)行, 也允許被年輕代GC打斷。
4)最終標記(Remark):此階段有一次STW暫停,以完成標記周期。 G1會清空SATB緩沖區(qū),跟蹤未訪問到的存活對象,并進行引用處理。
5)清除階段(Clean UP): 這是最后的子階段,G1在執(zhí)行統(tǒng)計和清理RSet時會有一次STW停頓。 在統(tǒng)計過程中,會把完全空閑的region標記出來,也會標記出適合于進行混合模式GC的候選region。 清理階段有一部分是并發(fā)執(zhí)行的,比如在重置空閑region并將其加入空閑列表時。
清除階段之后,還會對存活對象進行轉(zhuǎn)移(復制算法),轉(zhuǎn)移到其他可用分區(qū),所以當前的分區(qū)就變成了新的可用分區(qū)。復制轉(zhuǎn)移主要是為了解決分區(qū)內(nèi)的碎片問題。
1)并發(fā)標記結(jié)束以后,老年代中百分百為垃圾的內(nèi)存分段被回收了,部分為垃圾的內(nèi)存分段被計算了出來。默認情況下,這些老年代的內(nèi)存分段會分8次(可以通過-XX:G1MixedGCCountTarget設(shè)置)被回收。
2)混合回收的回收集(Collection Set)包括八分之一的老年代內(nèi)存分段,Eden區(qū)內(nèi)存分段,Survivor區(qū)內(nèi)存分段?;旌匣厥盏乃惴ê湍贻p代回收的算法完全一樣,只是回收集多了老年代的內(nèi)存分段。具體過程請參考年輕代回收過程。
3)由于老年代中的內(nèi)存分段默認分8次回收,G1會優(yōu)先回收垃圾多的內(nèi)存分段。垃圾占內(nèi)存分段比例越高,越會被先回收。并且有一個閾值會決定內(nèi)存分段是否被回收。-XX:G1MixedGCLiveThresholdPercent,默認為65%,意思是垃圾占內(nèi)存分段比例要達到65%才會被回收。如果垃圾占比太低,意味著存活的對象占比高,在復制的時候會花費更多的時間。
4)混合回收并不一定要進行8次。有一個閾值-XX:G1HeapWastePercent,默認值為10%,意思是允許整個堆內(nèi)存中有10%的空間被浪費,意味著如果發(fā)現(xiàn)可以回收的垃圾占堆內(nèi)存的比例低于10%,則不再進行混合回收。因為GC會花費很多的時間但是回收到的內(nèi)存卻很少。
1)并行與并發(fā):G1能充分利用多CPU、多核環(huán)境下的硬件優(yōu)勢,使用多個CPU來縮短Stop-the-world停頓的時間,部分其他收集器原來需要停頓Java線程執(zhí)行的GC操作,G1收集器仍然可以通過并發(fā)的方式讓Java程序繼續(xù)運行。
2)分代收集
3)空間整合:與CMS的標記-清除算法不同,G1從整體來看是基于標記-整理算法實現(xiàn)的收集器,從局部(兩個Region之間)上來看是基于“復制”算法實現(xiàn)的。但無論如何,這兩種算法都意味著G1運作期間不會產(chǎn)生內(nèi)存空間碎片,收集后能提供規(guī)整的可用內(nèi)存。這種特性有利于程序長時間運行,分配大對象時不會因為無法找到連續(xù)內(nèi)存空間而提前觸發(fā)下一次GC。
4)可預測的停頓:這是G1相對于CMS的另一大優(yōu)勢,降低停頓時間是G1和CMS共同的關(guān)注點,但G1除了追求低停頓外,還能建立可預測的停頓時間模型,能讓使用這明確指定一個長度為M毫秒的時間片段內(nèi),消耗在垃圾收集上的時間不得超過N毫秒。
到此,相信大家對“G1垃圾回收器與CMS的區(qū)別有哪些”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學習!
名稱欄目:G1垃圾回收器與CMS的區(qū)別有哪些
轉(zhuǎn)載來于:http://jinyejixie.com/article48/jjhjhp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標簽優(yōu)化、Google、網(wǎng)站導航、微信公眾號、企業(yè)網(wǎng)站制作、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)