日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

总结:G1收集器

發布時間:2023/12/20 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 总结:G1收集器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、介紹

G1 GC?全稱是Garbage First Garbage Collector,垃圾優先垃圾回收器,簡稱G1 。

G1 收集器是一個面向服務器模式的垃圾收集器,主要為多CPU機器和大內存機器設計。它可以盡可能在達到高吞吐量同時滿足垃圾收集暫停時間目標。G1 有以下幾個優點:

1. 能夠像CMS收集器一樣跟應用線程并行操作

2.復制對象的同時對對象進行壓縮和釋放內存

3.靈活分配老年代,年輕代占比,不再固定。?盡管G1堆內存仍然是分代的,但是同一個代的內存不再采用連續的內存結構。

4. 收縮空閑空間不會造成由長GC引起的應用停頓時間。

5. 更精確的預測GC停頓時間

6.理論上內存空間越大越好,因為老年代不是快滿了才進行一次GC,而是平時也會進行多次混合GC

二、GC收集器比較

傳統的垃圾收集器像Serial, Parallel, CMS 全部都將Java堆分成三個固定內存大小的部分,如年輕代,年老代和永久代,所有的內存中的Java對象都在三個部分中結束。

G1 收集器采用了不同的方法,它將整個Java堆分成2048個相同大小的堆區域( 內存分段是物理概念,代表實際的物理內存空間),可以用-XX:G1HeapRegionSize調整內存分段的個數。這些區域集像以前的收集器一樣被分配到不同的角色,每個內存分段都可以被標記為Eden區,Survivor區,Old區,或者Humongous區。但是沒有固定的區域數量被明確固定在某個角色上(所以不要配置年輕代大小),不同區的內存分段就不必是連續內存空間,這將為內存使用上提供了更大的靈活性。

關于對象的內存分配,方式如下

新分配的對象會被分配到Eden區的內存分段上,每一次年輕代的回收過程都會把Eden區存活的對象復制到Survivor區的內存分段上,把Survivor區繼續存活的對象年齡加1,如果Survivor區的存活對象年齡達到某個閾值(比如15,可以設置),Survivor區的對象會被復制到Old區。復制過程是把源內存分段中所有存活的對象復制到空的目標內存分段上,復制完成后,源內存分段沒有了存活對象,變成了可以使用的空的Eden內存分段了;而目標內存分段的對象都是連續存儲的,沒有碎片,所以復制過程可以達到內存整理的效果,減少碎片。Humongous區用于保存大對象,如果一個對象占用的空間超過內存分段的一半(比如上面的8M),則此對象將會被分配在Humongous區。如果對象的大小超過一個甚至幾個分段的大小,則對象會分配在物理連續的多個Humongous分段上。Humongous對象因為占用內存較大并且連續會被優先回收。

在執行垃圾收集時,G1操作十分類似于CMS收集器。G1執行一個并發全局標記階段貫穿整個Java堆去判斷對象的活躍度,標記階段結束后,收集器知道哪一些區域是空的或者接近空的,它將先收集這些空的區域,通常會釋放大量的內存空間,G1將其收集和壓縮活動集中在可能充滿可回收對象的堆區域上, 這也是收集器命名為G1的原因(即優先收集垃圾占比比較高的堆區域。G1使用了一個停頓預測模型根去滿足用戶自定義的停頓時間目標并且根據該目標選擇一定數量的區域進行回收。

G1通過轉移的方法將已被G1標識為區域當作可回收的垃圾進行回收, 它把對象從1個或者多個區域中復制到單個區域,在復制的同時進行 壓縮對象和釋放內存(這里的壓縮不是對對象的壓縮,而是通過對對象內存碎片進行整理而騰出連續空間的意思,如多個堆區域的數據復制到一個或較少的堆區域中),所有的轉移過程通過多個處理器并行處理(可以考慮增加線程數)以降低暫停時間和增加吞吐量。因此,每一次垃圾回收,G1收集器持續地在用戶預定的暫停時間內減少內存碎片。相對而言,CMS收集器不會做壓縮,而PARALlelOld 收集器是對整個Java堆執行壓縮,那么將導致較長停頓時間。

如果應用從CMS收集器或者ParallelOldGC到G1,你可能會發現相同數據規模情況下G1占用的內存比以前多了一些,多出的一些內存主要是用于存儲賬單數據結果,如Remembered Sets和Collection Sets.

- Remembered Sets, RSets跟蹤每一個區域的對象引用,每一個區域都有一個Rsets, 它在區域啟用一個獨立且并行的集合,RSets大約增加5%左右的Overhead。

- Collection Sets, CSets是放置可被收集器回收的區域集合,所有在這個集合的數據對象在垃圾回收期間均可被轉移,這些區域可能是Eden,Survivor 或者老年代。CSets大約有增加1%左右的overhead.

和CMS對比:

G1CMS
設計原則首先收集盡可能多的垃圾(Garbage First)盡可能少而塊地執行GC,以停頓時間為目標
垃圾回收時機?啟發式算法,在老年代找出具有高收集收益的分區進行收集?內存耗盡(新生代)或者快耗盡(老年代)
?內存劃分將內存劃分為一個個相等大小的內存分區(Region),每個區域都可能有四種狀態:E(eden)、S(Survial)、O(old)、空閑?分為新生代和老年代2塊連續的內存空間
?是否產生垃圾碎片 將一組或多組區域(稱為回收集 (CSet))中的存活對象以增量、并行的方式復制到不同的新區域來實現壓縮,從而減少堆碎片 采用標記刪除,會產生碎片?

三、G1 回收步驟



四、G1 調優注意事項

1. 年輕代大小

避免使用-Xmn選項或-XX:NewRatio等其他相關選項顯式設置年輕代大小,因為固定年輕代的大小會覆蓋暫停時間目標。

G1會動態調節年輕代和總堆的比例。?

G1可以根據用戶設置的暫停時間目標自動調整年輕代和總堆大小, 暫停目標越短年輕代空間越小(年輕代小,需要回收的空間可能就會小,但是回收次數也就會更多)

整個年輕代內存會在初始空間-XX:G1NewSizePercent(默認整堆5%)與最大空間-XX:G1MaxNewSizePercent(默認60%)之間動態變化,
且由參數目標暫停時間-XX:MaxGCPauseMillis(默認200ms)、需要擴縮容的大小以及分區的已記憶集合(RSet)計算得到。
當然,G1依然可以設置固定的年輕代大小(參數-XX:NewRatio、-Xmn),但同時暫停目標將失去意義。

2. 暫停時間目標

每當對垃圾回收進行評估或調優時,都會涉及到延遲與吞吐量的權衡。G1是增量垃圾回收器, 其吞吐量目標是 90% 的應用程序時間和 10%的垃圾回收時間。因此,暫停時間目標不要太嚴苛。目標太過嚴苛表示您愿意承受更多的垃圾回收開銷,而這會直接影響到吞吐量(很明顯的是Alarm組件,為了滿足P99和P95的延時目標,設置了 -XX:MaxGCPauseMillis=300 ,導致總的GC時間提升了將近一倍,這顯然會降低Alarm組件的吞吐量,因為CPU時間是固定的,GC時間多就會影響應用程序的CPU時間)

G1有一個及其重要的特性:軟實時(soft real-time)。所謂的實時垃圾回收,是指在要求的時間內完成垃圾回收。“軟實時”則是指,用戶可以指定垃圾回收時間的限時,G1會努力在這個時限內完成垃圾回收,但是G1并不擔保每次都能在這個時限內完成垃圾回收。通過設定一個合理的目標,可以讓達到90%以上的垃圾回收時間都在這個時限內。

五、G1 主要參數配置

六、垃圾回收過程

G1垃圾回收過程主要包括三個:

  • 年輕代回收(young gc)過程
  • 老年代并發標記(concurrent marking)過程
  • 混合回收過程(mixed gc)。

1、YGC

在Eden充滿時觸發,在回收之后所有之前屬于Eden的區塊全變成空白。然后把剩余的存活對象移動到S區。

很多情況下,S區的對象會有部分晉升到Old區,另外如果S區已滿、Eden存活的對象會直接晉升到Old區,這種情況下Old的空間就會漲(詳見下圖,Old區在Eden區回收后,使用率漲了一點,S區滿,導致存活對象無法放到S區,從而直接放入了老年代

這個過程會對年輕代的對象有一個短暫的停頓

年輕代回收過程如下【回收時機:當所有的Eden區都滿了】:

JVM啟動時,G1先準備好Eden區,程序在運行過程中不斷創建對象到Eden區,當所有的Eden區都滿了,G1會啟動一次年輕代垃圾回收過程。年輕代只會回收Eden區和Survivor區。首先G1停止應用程序的執行(Stop-The-World),G1創建回收集(Collection Set),回收集是指需要被回收的內存分段的集合,年輕代回收過程的回收集包含年輕代Eden區和Survivor區所有的內存分段。然后開始如下回收過程:

第一階段,掃描根。

根是指static變量指向的對象,正在執行的方法調用鏈條上的局部變量等。根引用連同RS記錄的外部引用作為掃描存活對象的入口。

第二階段,更新RS。

處理dirty card queue中的card,更新RS。此階段完成后,RS可以準確的反映老年代對所在的內存分段中對象的引用。

第三階段,處理RS。

識別被老年代對象指向的Eden中的對象,這些被指向的Eden中的對象被認為是存活的對象。

第四階段,復制對象。

此階段,對象樹被遍歷,Eden區內存段中存活的對象會被復制到Survivor區中空的內存分段,Survivor區內存段中存活的對象如果年齡未達閾值,年齡會加1,達到閥值會被會被復制到Old區中空的內存分段。

第五階段,處理引用。

處理Soft,Weak,Phantom,Final,JNI Weak?等引用。

2、 G1老年代并發標記過程【發生時機:整個堆內存被占滿一定大小的時候,默認是45%

注意:這個階段會回收百分之百為垃圾的內存分段,并不只是做標記。

當整個堆內存(包括老年代和新生代)被占滿一定大小的時候(默認是45%,可以通過-XX:InitiatingHeapOccupancyPercent進行設置),老年代回收過程會被啟動。具體檢測堆內存使用情況的時機是年輕代回收之后(即經過一次YGC之后,整個堆仍然使用了超過45%,則處罰OGC)或者houmongous對象分配之后。老年代回收包含標記老年代內的對象是否存活的過程,標記過程是和應用程序并發運行的(不需要Stop-The-World)。應用程序會改變指針的指向,并發執行的標記過程怎么能保證標記過程沒有問題呢?并發標記過程有一種情形會對存活的對象標記不到。假設有對象A,B和C,一開始的時候B.c=C,A.c=null。當A的對象樹先被掃描標記,接下來開始掃描B對象樹,此時標記線程被應用程序線程搶占后停下來,應用程序把A.c=C,B.c=null。當標記線程恢復執行的時候C對象已經標記不到了,這時候C對象實際是存活的,這種情形被稱作對象丟失。G1解決的方法是在對象引用被設置為空的語句(比如B.c=null)時,把原先指向的對象(C對象)保存到一個隊列,代表它可能是存活的。然后會有一個重新標記(Remark)過程處理這些對象,重新標記過程是Stop-The-World的,所以可以保證標記的正確性。上述這種標記方法被稱為開始時快照技術(SATB,Snapshot At The Begging)。這種方式會造成某些是垃圾的對象也被當做是存活的,所以G1會使得占用的內存被實際需要的內存大。

具體標記過程如下:

  1. 先進行一次年輕代回收過程,這個過程是Stop-The-World的,同時會進行一次初始標記。

   ??老年代的回收基于年輕代的回收(比如需要年輕代回收過程對于根對象的收集,初始的存活對象的標記)。

  2. 恢復應用程序線程的執行。

  3. 開始老年代對象的標記過程。

   此過程是與應用程序線程并發執行的。標記過程會記錄弱引用情況,還會計算出每個分段的對象存活數據(比如分段內存活對象所占的百分比)。

  4. Stop-The-World。

  5. 重新標記(Remark)。

   此階段重新標記前面提到的STAB隊列中的對象(例子中的C對象),還會處理弱引用。

????????? ? 注意:如果標記過程沒有被其它線程打斷的話,就不需要重新標記了。

  6. 回收百分之百為垃圾的內存分段。

   注意:不是百分之百為垃圾的內存分段并不會被處理,這些內存分段中的垃圾是在混合回收過程(Mixed GC)中被回收的。

   由于Humongous對象會獨占整個內存分段,如果Humongous對象變為垃圾,則內存分段百分百為垃圾,所以會在第一時間被回收掉。

  7. 恢復應用程序線程的執行。

G1并發標記周期可以分成幾個階段、其中有些需要暫停應用線程(所以G1也會STW)。有些是后臺并行處理,不需要暫停應用

3、混合GC(也會SWT)

并發標記過程結束以后,緊跟著就會開始一系列的混合GC?;旌匣厥盏囊馑际悄贻p代和老年代會同時被回收。這個時期因為會同時進行YGC和清理上面已標記為X的區域(意思可以理解為同時進行YGC和Old GC),所以稱之為混合階段。 混合回收的算法和年輕代回收的算法完全一樣,只是回收集多了老年代的內存分段。具體過程請參考上面的年輕代回收過程。?

每次混合GC只是清理一部分的O區內存,整個GC會一直持續到幾乎所有的標記區域垃圾對象都被回收(即多次混合GC),這個階段完了之后G1會重新回到正常的YGC階段。周期性的,當O區內存占用達到一定數量之后G1又會開啟一次新的并行GC階段.

由于老年代中的內存分段默認分8次回收,G1會優先回收垃圾多的內存分段。垃圾占內存分段比例越高的,越會被先回收。并且有一個閾值會決定內存分段是否被回收,-XX:G1MixedGCLiveThresholdPercent,默認為65%,意思是垃圾占內存分段比例要達到65%才會被回收。如果垃圾占比太低,意味著存活的對象占比高,在復制的時候會花費更多的時間。?

混合回收并不一定要進行8次。有一個閾值-XX:G1HeapWastePercent,默認值為10%,意思是允許整個堆內存中有10%的空間被浪費,意味著如果發現可以回收的垃圾占堆內存的比例低于10%,則不再進行混合回收。因為GC會花費很多的時間但是回收到的內存卻很少。

4、FullGC

如果對象內存分配速度過快,mixed gc來不及回收,導致老年代被填滿,就會觸發 一次full gc,G1的full gc算法就是單線程執行的serial old gc,會導致異常長時間的暫停時間,需要進行不斷的調優,盡可能的避免full gc.

七、G1相較于其它垃圾收集器的優勢

1、啟發式算法,在老年代找出具有高收集收益的分區進行收集

這樣的好處是什么?分析下,假設有A,B,C,D,E五個堆區域,A的垃圾對象占比為90%,對象垃圾占比805,CDE三個對象占比都在10% ~ 40%之間,很顯然,回收AB兩個區域能騰出更大的空間,且回收速度更快,因此受益是最好的,所以對于G1來說,某一次垃圾回收可以只回收AB兩個區域,假設此次回收耗時1秒;下次進行GC的時候,CDE的垃圾占比達到了70%,那么回收CDE的收益又好了,所以進行回收CDE,耗時1秒;

經過以上分析,我們發現兩次GC時間總共是:1 + 1 = 2秒,GC次數是2次;

如果換成CMS或其它垃圾回收器會怎么樣呢?

仍然是ABCDE五個區間,此時由于是老年代,所以只有O區快慢了才會進行一次全量的回收,那么就同時需要回收ABCDE五個區域,AB回收時間和G1是一樣的,但是CDE就明顯要打了,因為CDE的垃圾占比低,也就是說需要復制更多的對象,假設我們算這個時間是2秒,GC次數是1次。

經過以上分析,CMS的GC總時間是1 + 2 = 3秒。GC次數是1次。

總結:G1的按照收益的方式去收集比CMS的GC總耗時更少,但是收集次數會更多。

2、年輕代和老年代空間不再固定

這樣比較靈活,系統會根據各個代的大小動態的調節,這樣可以控制GC的時間

3、充分利用系統大內存

目前服務器內存一般比較高,而G1非常適合大內存服務器,避免其它收集器fullgc時間過長的問題,其它收集器的fullgc幾乎是不可避免的,放內存很大的時候,fullgc會非常耗時

參考:

G1垃圾收集器入門

Java G1 GC 垃圾回收深入淺出

深入理解Java G1垃圾收集器

老大難的GC原理及調優,這下全說清楚了

總結

以上是生活随笔為你收集整理的总结:G1收集器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。