java中的G1回收器怎么用

這篇文章給大家介紹java中的G1回收器怎么用,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

在波密等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站設(shè)計、做網(wǎng)站 網(wǎng)站設(shè)計制作按需開發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),成都全網(wǎng)營銷,外貿(mào)網(wǎng)站建設(shè),波密網(wǎng)站建設(shè)費用合理。

G1 回收器

G1回收器是在jdk1.7中正式使用的全新垃圾回收器,并且是jdk9及之后版本的默認回收器。從分代上看,G1 依然屬于分代垃圾回收器,它會區(qū)分年輕代和老年代,依然有eden區(qū)和survivor區(qū),但從堆的結(jié)構(gòu)上看,它并不要求整個eden區(qū)、年輕代或者老年代都連續(xù)。G1使用了全新的分區(qū)算法,特點如下:

  • 并行性:G1在回收期間,可以由多個GC線程同時工作,有效利用多核計算能力。

  • 并發(fā)性:G1在擁有與應(yīng)用程序交替執(zhí)行的能力,部分工作可以和應(yīng)用程序同時執(zhí)行,一般來說,不會在整個回收期間完全阻塞應(yīng)用程序。

  • 分代GC:G1依然是一個分代回收器,但是和之前的回收器不同,它同時兼顧年輕代和老年代,其他回收器或者工作在年輕代,或者工作在老年代。

  • 空間整理:G1在回收過程中,會進行適當?shù)膶ο笠苿?,不像CMS,只是簡單地標記清理對象,在若干次GC后,CMS必須進行一次碎片整理。而G1不同,它每次回收都會有效地復(fù)制對象,減少碎片空間。

  • 可預(yù)見性:由于分區(qū)的原因,G1可以只選取部分區(qū)域進行內(nèi)存回收,這樣縮小了回收的范圍,全局停頓也能得到較好的控制。

1 G1的內(nèi)存劃分和主要收集過程

G1將堆進行分區(qū),劃分為一個個的區(qū)域,每次回收時,只回收其中幾個區(qū)域,以此來控制垃圾回收產(chǎn)生的一次停頓時間。

G1的回收過程可能有4個階段:

  • 新生代GC

  • 并發(fā)標記周期

  • 混合回收

  • 如果需要,可能會進行FullGC

2. G1的新生代GC

新生代GC的主要工作是回收eden區(qū)和survivor區(qū)。一旦eden區(qū)被占滿,新生代GC就會啟動。新生代GC只處理eden區(qū)和survivor區(qū),回收后所有的eden區(qū)都應(yīng)該被清空,而survivor區(qū)會被回收一部分數(shù)據(jù)。

3. G1 的并發(fā)標記周期

G1 的并發(fā)階段和 CMS 有點類似,它們都是為了降低一次停頓時間,而將可以和應(yīng)用程序并發(fā)的部分單獨提取出來執(zhí)行。

并發(fā)標記周期可以分為以下幾步:

  • 初始標記:標記從根節(jié)點直接可達的對象。這個階段會伴隨一次新生代GC,它是產(chǎn)生全局停頓的,應(yīng)用程序線程在這個階段必須停止執(zhí)行。

  • 根區(qū)域掃描:由于初始標記必然會伴隨一次新生代GC,所以在初始化標記后,eden區(qū)被清空,并且存活對象被移入survivor區(qū)。在這個階段,將掃描由survivor區(qū)直接可達的老年代區(qū)域,并標記這些直接可達的對象。這個過程是可以和應(yīng)用程序并發(fā)執(zhí)行的,但是根區(qū)域掃描不能和新生代GC同時執(zhí)行,因為如果恰巧在此時需要進行新生代GC,就需要等待根區(qū)域掃描結(jié)束后才能進行。如果發(fā)生這種情況,這次新生代GC的時間就會延長。

  • 并發(fā)標記:和CMS類似,并發(fā)標記將會掃描并查找整個堆的存活對象,并做好標記。這是一個并發(fā)的過程,并且這個過程可以被一次新生代GC打斷。

  • 重新標記:和CMS一樣,重新標記也是會產(chǎn)生應(yīng)用程序停頓的。由于并發(fā)標記過程中,應(yīng)用程序依然在運行,因此標記結(jié)果可能需要修正,所以在此對上一次的標記結(jié)果進行補充。在 G1 中,這個過程使用SATB(Snapshot-At-The-Beginning)算法完成,即G1會在標記之初為存活對象創(chuàng)建一個快照,這個快照有助于加速重新標記的速度。

  • 獨占清理:這個階段是會引起停頓的。它將計算各個區(qū)域的存活對象和GC回收比例,并進行排序,識別可供混合回收的區(qū)域。識別可供混合回收的區(qū)域。在這個階段,還會更新記憶集(Remebered Set)。該階段給出了需要被混合回收的區(qū)域并進行了標記,在混合回收階段需要這些信息。

  • 并發(fā)清理:這里會識別并清理完全空閑的區(qū)域。它是并發(fā)的清理,不會引起停頓。

除了初始標記、重新標記獨占清理,其他幾個階段都可以和應(yīng)用程序并發(fā)執(zhí)行。

在并發(fā)標記周期中,G1會產(chǎn)生如下日志:

3.1 初始標記,它伴隨著一次新生代GC
[GC pause (G1 Humongous Allocation) (young) (initial-mark), 0.0014636 secs]
   ...
   [Eden: 2048.0K(14.0M)->0.0B(13.0M) Survivors: 0.0B->1024.0K Heap: 13.8M(40.0M)->2624.1K(40.0M)]
 [Times: user=0.01 sys=0.00, real=0.00 secs]
3.2 一次并發(fā)的根區(qū)域掃描,并發(fā)掃描過程中不能被新生代GC中斷。
[GC concurrent-root-region-scan-start]
[GC concurrent-root-region-scan-end, 0.0003832 secs]
3.3 并發(fā)標記,并發(fā)標記可以被新生代GC打斷,下面的日志顯示了一次并發(fā)標記被3次新生代GC打斷。
[GC concurrent-mark-start]
[GC pause (young), 0.0003382 secs]
...
  [Eden: 2048.0K(14.0M)->0.0B(13.0M) Survivors: 0.0B->1024.0K Heap: 13.8M(40.0M)->2624.1K(40.0M)]
[Times: user=0.01 sys=0.00, real=0.00 secs] 
...
  [Eden: 2048.0K(14.0M)->0.0B(13.0M) Survivors: 0.0B->1024.0K Heap: 13.8M(40.0M)->2624.1K(40.0M)]
[Times: user=0.01 sys=0.00, real=0.00 secs] 
...
  [Eden: 2048.0K(14.0M)->0.0B(13.0M) Survivors: 0.0B->1024.0K Heap: 13.8M(40.0M)->2624.1K(40.0M)]
[Times: user=0.01 sys=0.00, real=0.00 secs] 
[GC concurrent-mark-end, 0.0003929 secs]
3.4 重新標記:是會引起全局停頓的,它的日志如下:
[GC remark [Finalize Marking, 0.0006027 secs] [GC ref-proc, 0.0000295 secs] [Unloading, 0.0003390 secs], 0.0010737 secs]
 [Times: user=0.01 sys=0.00, real=0.01 secs]
3.5 重新標記后會進行獨占清理,獨占清理會重新計算各個區(qū)域的存活對象,并以此可以得到每個區(qū)域進行GC的效果,它的日志如下:
[GC cleanup 10M->10M(40M), 0.0003016 secs]
 [Times: user=0.00 sys=0.00, real=0.00 secs]
3.6 并發(fā)清理,是并發(fā)執(zhí)行的,它會根據(jù)獨占清理階段計算得出每個區(qū)域的存活對象數(shù)量,直接回收不包含存活對象的區(qū)域。它的日志如下:
[GC concurrent-cleanup-start]
[GC concurrent-cleanup-end, 0.0000016 secs]

4. 混合回收

在并發(fā)標記周期中,雖然有部分對象被回收,但是總體上說,回收的比例是相當?shù)偷?。但是在并發(fā)標記周期后,G1已經(jīng)明確知道哪些區(qū)域含有比較多的垃圾對象,在混合回收階段就可以專門針對這些區(qū)域進行回收。這個階段叫做混合回收,是因為這個階段既會執(zhí)行正常的年輕代GC,又會選取一些被標記的老年代區(qū)域進行回收,它同時處理了新生代和老年代。

混合GC會產(chǎn)生如下日志:

[GC pause (mixed), 0.0003382 secs]
...
  [Eden: 2048.0K(14.0M)->0.0B(13.0M) Survivors: 0.0B->1024.0K Heap: 13.8M(40.0M)->2624.1K(40.0M)]
[Times: user=0.01 sys=0.00, real=0.00 secs]

混合GC會執(zhí)行多次,走到回收了足夠多的內(nèi)存空間,然后它會觸發(fā)一次新生代GC。新生代GC后,又可難會發(fā)生一次并發(fā)標記周期的處理,最后又會引起混合GC的執(zhí)行。

5. 必要時的Full GC

和CMS類似,并發(fā)回收由于讓應(yīng)用程序和GC線程交替工作,總是不能完全避免在特別繁忙的場合出現(xiàn)在回收過程中內(nèi)存不充足的情況。當遇到這種情況時,G1也會轉(zhuǎn)入一個FullGC。

當G1在并發(fā)標記時,由于老年代被快速填充,G1會終止并發(fā)標記而轉(zhuǎn)入一個Full GC:

[GC concurrent-mark-start]
[Full GC 898->896(900M), 0.7003382 secs]
  [Eden: 0K(45.0M)->0.0B(45.0M) Survivors: 0.0B->0B Heap: 898.7M(900.0M)->896.2M(900.0M)]
[Times: user=1.01 sys=0.00, real=0.075 secs] 
[GC concurrent-mark-abort]

此外,如果在混合GC時空間不足,或者在新生代GC時survivor區(qū)和老年代無法容納幸存對象,都會導(dǎo)致一次FullGC.

6. G1的日志

# 表示應(yīng)用程序發(fā)生了一次新生代GC,這是在初始標記時發(fā)生的,耗時0.0018193秒,意味著程序至少暫停了0.0018193秒
[GC pause (G1 Humongous Allocation) (young) (initial-mark), 0.0018193 secs]
   # 后續(xù)并行時間,表示所有GC線程總的花費時間,這里為0.9毫秒,workers為8表示有8個GC線程
   [Parallel Time: 0.9 ms, GC Workers: 8]
      # GC線程的執(zhí)行情況,這里統(tǒng)計了8個線程的統(tǒng)計值,如 平均、最小、最大和差值(最大值與最小值之差),
      # 106.6 表示在應(yīng)用程序啟動 106.6 毫秒后,啟動了該GC線程
      [GC Worker Start (ms): Min: 106.6, Avg: 106.7, Max: 106.7, Diff: 0.1]
      # 根掃描時間的統(tǒng)計值
      [Ext Root Scanning (ms): Min: 0.4, Avg: 0.4, Max: 0.5, Diff: 0.1, Sum: 3.3]
      # 更新記憶集(Remember Set)的耗時。
      # 記憶集是G1中維護的一個數(shù)據(jù)結(jié)構(gòu),簡稱RS。每一個G1區(qū)域都有一個RS與之關(guān)聯(lián)。由于G1回收時是按照區(qū)域
      # 回收的,比如在回收區(qū)域A的對象時,很可能并不回收區(qū)域B的對象,為了回收區(qū)域A的對象,要掃描區(qū)域B甚
      # 至整個堆來判定區(qū)域A中哪些對象不可達,這樣做的代價顯然很大。因此,G1在區(qū)域A的RS中,記錄了在區(qū)域
      # A中被其他區(qū)域引用的對象,這樣在回收區(qū)域A時,只要將RS視為區(qū)域A根集的一部分即可,從而避免做整個堆
      # 的的掃描。由于系統(tǒng)在運行過程中,對象之間的引用關(guān)系是可能時刻變化的,為了更高效地跟蹤這些引用關(guān)系,
      # 會將這些變化記錄在Update Buffers中。這里的Processed Buffers指的就是處理這個Update Buffers數(shù)據(jù)。
      [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
      # 掃描RS的時間 
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      # 在正式回收前,G1 會對被回收區(qū)域的對象進行疏散,即將存活對象放置在其他區(qū)域中,因此需要進行對象復(fù)制
      [Object Copy (ms): Min: 0.2, Avg: 0.3, Max: 0.4, Diff: 0.2, Sum: 2.2]
      # 給出GC工程線程終止的信息,這里的終止時間是線程花在終止階段的耗時。在GC線程終止前,它們會檢查其
      # 他GC線程的工作隊列,查看是否仍然還有對象引用沒有處理完,如果其他線程仍然有沒有處理完的數(shù)據(jù),請求
      # 終止的線程會幫助它盡快完成,隨后再嘗試終止。其中,Termination Attempts 展示了工作線程的終止次數(shù)。
      [Termination (ms): Min: 0.0, Avg: 0.1, Max: 0.2, Diff: 0.2, Sum: 1.0]
         [Termination Attempts: Min: 1, Avg: 2.9, Max: 6, Diff: 5, Sum: 23]
      # 顯示GC線程花費在其他任務(wù)中的耗時
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
      [GC Worker Total (ms): Min: 0.8, Avg: 0.8, Max: 0.9, Diff: 0.1, Sum: 6.6]
      # GC 工作線程的完成時間
      [GC Worker End (ms): Min: 107.5, Avg: 107.5, Max: 107.5, Diff: 0.0]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   # 顯示清空 CardTable的時間,RS 就是依靠CardTable來記錄哪些是存活對象的
   [Clear CT: 0.1 ms]
   # 顯示其他幾個任務(wù)的耗時,比如選擇CSet(Collection Sets,表示被選取的、將要被回收的區(qū)域的集合)的時
   # 間、Ref Proc(處理弱引用、軟引用的時間)、Ref End(弱引用、軟引用入隊時間)和Free CSet(釋放被
   # 回收的CSet中區(qū)域的時間,包括它們的RS)
   [Other: 0.8 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.7 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.1 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.0 ms]
   [Eden: 2048.0K(14.0M)->0.0B(13.0M) Survivors: 0.0B->1024.0K Heap: 13.8M(40.0M)->2656.1K(40.0M)]
 [Times: user=0.00 sys=0.00, real=0.00 secs]

7. 相關(guān)的參數(shù)

  • -XX:+UseG1GC:啟用G1回收器

  • -XX:MaxGCPauseMillis: 用于指定目標最大停頓時間。如果任何一次停頓時間超過這個設(shè)置值,G1就會嘗試調(diào)整新生代和老年代的比例、調(diào)整堆大小、調(diào)整晉升年齡等,試圖達到預(yù)設(shè)目標。對于性能調(diào)優(yōu)來說,總是魚和熊掌不可兼得,如果停頓時間縮短,對于新生代來說,意味著很可能要增加新生代GC的次數(shù)。對于老年代來說,為了獲得短暫的停頓時間,在混合GC時,一次收集的區(qū)域數(shù)量也會變少,這樣無疑增加了進行FullGC的可能性。

  • -XX:ParallelGCThreads: 設(shè)置并行回收時GC的工作線程數(shù)量。

  • -XX:InitatingHeapOccupancyPercent: 指定當整個堆使用率達到多少時,觸發(fā)并發(fā)標記周期的執(zhí)行,默認值是45.InitatingHeapOccupancyPercent一旦設(shè)置,始終都不會被G1修改,這意味著G1不會試圖改變這個值來滿足MaxGCPauseMillis 的目標,那么引起FullGC的可能性也大大增加,反之,一個過小的InitatingHeapOccupancyPercent值會使得并發(fā)標記周期執(zhí)行非常頻繁,大量GC線程搶占CPU,導(dǎo)致應(yīng)用程序的性能有所下降。

關(guān)于java中的G1回收器怎么用就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

網(wǎng)站欄目:java中的G1回收器怎么用
標題網(wǎng)址:http://muchs.cn/article36/pidhsg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計公司面包屑導(dǎo)航、網(wǎng)站排名網(wǎng)站維護、移動網(wǎng)站建設(shè)、網(wǎng)站內(nèi)鏈

廣告

聲明:本網(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)

成都網(wǎng)頁設(shè)計公司