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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

JVM GC参数以及GC算法的应用

發布時間:2025/3/21 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM GC参数以及GC算法的应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

之前一篇Blog已經將GC的機制以及GC的算法講了一下。

而這篇Blog主要是討論這些GC的算法在JVM中的不同應用。

1.?串行收集器

串行收集器是最古老,最穩定以及效率高的收集器
可能會產生較長的停頓,只使用一個線程去回收
-XX:+UseSerialGC

  • 新生代、老年代使用串行回收
  • 新生代復制算法
  • 老年代標記-壓縮

串行收集器的日志輸出:

1 2 3 0.844: [GC 0.844: [DefNew: 17472K->2176K(19648K), 0.0188339 secs] 17472K->2375K(63360K), 0.0189186 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] 8.259: [Full GC 8.259: [Tenured: 43711K->40302K(43712K), 0.2960477 secs] 63350K->40302K(63360K), [Perm : 17836K->17836K(32768K)], 0.2961554 secs] [Times: user=0.28 sys=0.02, real=0.30 secs]

2. 并行收集器

2.1?ParNew

-XX:+UseParNewGC(new代表新生代,所以適用于新生代)

  • 新生代并行
  • 老年代串行

Serial收集器新生代的并行版本
在新生代回收時使用復制算法
多線程,需要多核支持
-XX:ParallelGCThreads 限制線程數量

并行收集器的日志輸出:

1 0.834: [GC 0.834: [ParNew: 13184K->1600K(14784K), 0.0092203 secs] 13184K->1921K(63936K), 0.0093401 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

2.2?Parallel收集器

類似ParNew
新生代復制算法
老年代標記-壓縮
更加關注吞吐量
-XX:+UseParallelGC

  • 使用Parallel收集器+ 老年代串行

-XX:+UseParallelOldGC

  • 使用Parallel收集器+ 老年代并行

Parallel收集器的日志輸出:

1 500: [Full GC [PSYoungGen: 2682K->0K(19136K)] [ParOldGen: 28035K->30437K(43712K)] 30717K->30437K(62848K) [PSPermGen: 10943K->10928K(32768K)], 0.2902791 secs] [Times: user=1.44 sys=0.03, real=0.30 secs]

2.3 其他GC參數

-XX:MaxGCPauseMills

  • 最大停頓時間,單位毫秒
  • GC盡力保證回收時間不超過設定值

-XX:GCTimeRatio

  • 0-100的取值范圍
  • 垃圾收集時間占總時間的比
  • 默認99,即最大允許1%時間做GC

這兩個參數是矛盾的。因為停頓時間和吞吐量不可能同時調優

3. CMS收集器

  • Concurrent Mark Sweep?并發標記清除(應用程序線程和GC線程交替執行)
  • 使用標記-清除算法
  • 并發階段會降低吞吐量(停頓時間減少,吞吐量降低)
  • 老年代收集器(新生代使用ParNew)
  • -XX:+UseConcMarkSweepGC

CMS運行過程比較復雜,著重實現了標記的過程,可分為

1. 初始標記(會產生全局停頓)

  • 根可以直接關聯到的對象
  • 速度快

2. 并發標記(和用戶線程一起)

  • 主要標記過程,標記全部對象

3. 重新標記?(會產生全局停頓)

  • 由于并發標記時,用戶線程依然運行,因此在正式清理前,再做修正

4. 并發清除(和用戶線程一起)

  • 基于標記結果,直接清理對象

這里就能很明顯的看出,為什么CMS要使用標記清除而不是標記壓縮,如果使用標記壓縮,需要多對象的內存位置進行改變,這樣程序就很難繼續執行。但是標記清除會產生大量內存碎片,不利于內存分配。

CMS收集器的日志輸出:

1 2 3 4 5 6 7 8 9 10 1.662: [GC [1 CMS-initial-mark: 28122K(49152K)] 29959K(63936K), 0.0046877 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 1.666: [CMS-concurrent-mark-start] 1.699: [CMS-concurrent-mark: 0.033/0.033 secs] [Times: user=0.25 sys=0.00, real=0.03 secs] 1.699: [CMS-concurrent-preclean-start] 1.700: [CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 1.700: [GC[YG occupancy: 1837 K (14784 K)]1.700: [Rescan (parallel) , 0.0009330 secs]1.701: [weak refs processing, 0.0000180 secs] [1 CMS-remark: 28122K(49152K)] 29959K(63936K), 0.0010248 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 1.702: [CMS-concurrent-sweep-start] 1.739: [CMS-concurrent-sweep: 0.035/0.037 secs] [Times: user=0.11 sys=0.02, real=0.05 secs] 1.739: [CMS-concurrent-reset-start] 1.741: [CMS-concurrent-reset: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

CMS收集器特點:

盡可能降低停頓
會影響系統整體吞吐量和性能

  • 比如,在用戶線程運行過程中,分一半CPU去做GC,系統性能在GC階段,反應速度就下降一半

清理不徹底

  • 因為在清理階段,用戶線程還在運行,會產生新的垃圾,無法清理

因為和用戶線程一起運行,不能在空間快滿時再清理(因為也許在并發GC的期間,用戶線程又申請了大量內存,導致內存不夠)

  • -XX:CMSInitiatingOccupancyFraction設置觸發GC的閾值
  • 如果不幸內存預留空間不夠,就會引起concurrent mode failure
1 2 33.348: [Full GC 33.348: [CMS33.357: [CMS-concurrent-sweep: 0.035/0.036 secs] [Times: user=0.11 sys=0.03, real=0.03 secs] ?(concurrent mode failure): 47066K->39901K(49152K), 0.3896802 secs] 60771K->39901K(63936K), [CMS Perm : 22529K->22529K(32768K)], 0.3897989 secs] [Times: user=0.39 sys=0.00, real=0.39 secs]

一旦?concurrent mode failure產生,將使用串行收集器作為后備。

CMS也提供了整理碎片的參數:

-XX:+ UseCMSCompactAtFullCollection Full GC后,進行一次整理

  • 整理過程是獨占的,會引起停頓時間變長

-XX:+CMSFullGCsBeforeCompaction

  • 設置進行幾次Full GC后,進行一次碎片整理

-XX:ParallelCMSThreads

  • 設定CMS的線程數量(一般情況約等于可用CPU數量)

CMS的提出是想改善GC的停頓時間,在GC過程中的確做到了減少GC時間,但是同樣導致產生大量內存碎片,又需要消耗大量時間去整理碎片,從本質上并沒有改善時間。

4. G1收集器

G1是目前技術發展的最前沿成果之一,HotSpot開發團隊賦予它的使命是未來可以替換掉JDK1.5中發布的CMS收集器。

與CMS收集器相比G1收集器有以下特點:

1. 空間整合,G1收集器采用標記整理算法,不會產生內存空間碎片。分配大對象時不會因為無法找到連續空間而提前觸發下一次GC。

2. 可預測停頓,這是G1的另一大優勢,降低停頓時間是G1和CMS的共同關注點,但G1除了追求低停頓外,還能建立可預測的停頓時間模型,能讓使用者明確指定在一個長度為N毫秒的時間片段內,消耗在垃圾收集上的時間不得超過N毫秒,這幾乎已經是實時Java(RTSJ)的垃圾收集器的特征了。

上面提到的垃圾收集器,收集的范圍都是整個新生代或者老年代,而G1不再是這樣。使用G1收集器時,Java堆的內存布局與其他收集器有很大差別,它將整個Java堆劃分為多個大小相等的獨立區域(Region),雖然還保留有新生代和老年代的概念,但新生代和老年代不再是物理隔閡了,它們都是一部分(可以不連續)Region的集合。

G1的新生代收集跟ParNew類似,當新生代占用達到一定比例的時候,開始出發收集。

和CMS類似,G1收集器收集老年代對象會有短暫停頓。

步驟:

  • 標記階段,首先初始標記(Initial-Mark),這個階段是停頓的(Stop the World Event),并且會觸發一次普通Mintor GC。對應GC log:GC pause (young) (inital-mark)
  • Root Region Scanning,程序運行過程中會回收survivor區(存活到老年代),這一過程必須在young GC之前完成。
  • Concurrent Marking,在整個堆中進行并發標記(和應用程序并發執行),此過程可能被young GC中斷。在并發標記階段,若發現區域對象中的所有對象都是垃圾,那個這個區域會被立即回收(圖中打X)。同時,并發標記過程中,會計算每個區域的對象活性(區域中存活對象的比例)。
  • Remark, 再標記,會有短暫停頓(STW)。再標記階段是用來收集 并發標記階段 產生新的垃圾(并發階段和應用程序一同運行);G1中采用了比CMS更快的初始快照算法:snapshot-at-the-beginning (SATB)。
  • Copy/Clean up,多線程清除失活對象,會有STW。G1將回收區域的存活對象拷貝到新區域,清除Remember Sets,并發清空回收區域并把它返回到空閑區域鏈表中。
  • 復制/清除過程后。回收區域的活性對象已經被集中回收到深藍色和深綠色區域。
  • 5. 安全點

    GC的停頓主要來源于可達性分析上,程序執行時并非在所有地方都能停頓下來開始GC,只有在到達安全點時才能暫停。

    安全點的選定基本上是以程序“是否具有讓程序長時間執行的特征”為標準進行選定的——因為每條指令執行的時間都非常短暫,程序不太可能因為指令流長度太長這個原因而過長時間運行,“長時間執行”的最明顯特征就是指令序列復用,例如方法調用、循環跳轉、異常跳轉等,所以具有這些功能的指令才會產生安全點。

    接下來的問題就在于,如何讓程序在需要GC時都跑到安全點上停頓下來,大多數JVM的實現都是采用主動式中斷的思想。

    主動式中斷的思想是當GC需要中斷線程的時候,不直接對線程操作,僅僅簡單地設置一個標志,各個線程執行時主動去輪詢這個標志,發現中斷標志為真時就自己中斷掛起,輪詢標志的地方和安全點是重合的,另外再加上創建對象需要分配內存的地方。

    其他:

    只要記住流行的組合就這幾種情況
    Serial
    ParNew + CMS
    ParallelYoung + ParallelOld
    G1GC

    Reference:

    1. 《深入理解Java虛擬機》

    2.?http://www.importnew.com/15311.html

    3.?http://www.zhihu.com/question/30538696


    from:?Hosee

    http://www.importnew.com/23146.html

    總結

    以上是生活随笔為你收集整理的JVM GC参数以及GC算法的应用的全部內容,希望文章能夠幫你解決所遇到的問題。

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