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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

CMS垃圾收集器

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

CMS全稱?ConcurrentMarkSweep,是一款并發的、使用標記-清除算法的垃圾回收器, 如果老年代使用CMS垃圾回收器,需要添加虛擬機參數-“XX:+UseConcMarkSweepGC”
缺點:

  • CMS收集器對CPU資源非常敏感,在并發階段,它雖然不會導致用戶線程停頓,但是由于占用了一部分線程,所以會導致應用程序變慢,總吞吐量降低。CMS默認啟動的回收線程數是(cpu數量+3)/4。
  • CMS收集器無法處理浮動垃圾,可能出現“Concurrent Mode Failure”失敗而導致一次Full GC。在JDK1.6中,CMS收集器當老年代使用了92%的空間后才會進行收集,所以如果CMS運行期間預留的內存無法滿足程序需要,就會出現一次“Concurrent Mode Failure”。通過-XX:CMSInitiatingOccupancyFraction可以調整百分比。
    該參數必須配合UseCMSInitiatingOccupancyOnly使用才有效
  • CMS由于是基于標記-清除算法實現的收集器,所以就可能會在收集結束的時候產生大量空間碎片。如果老年代中沒有足夠大的連續空間來分配當前對象,那么就會可能提前觸發Full GC并進行碎片整理
    JVM參數
  • -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:D:\aa.gc -XX:+PrintTenuringDistribution -XX:+UseConcMarkSweepGC -Xmx1024m -Xms1024m

    日志如下:

    2019-04-11T16:30:48.164+0800: 14.035: [GC (CMS Initial Mark) [1 CMS-initial-mark: 0K(699072K)] 33843K(1013632K), 0.0066881 secs] [Times: user=0.09 sys=0.00, real=0.01 secs] 2019-04-11T16:30:48.179+0800: 14.044: [CMS-concurrent-mark-start] 2019-04-11T16:30:48.179+0800: 14.044: [CMS-concurrent-mark: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 2019-04-11T16:30:48.179+0800: 14.044: [CMS-concurrent-preclean-start] 2019-04-11T16:30:48.179+0800: 14.047: [CMS-concurrent-preclean: 0.003/0.003 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 2019-04-11T16:30:48.179+0800: 14.047: [CMS-concurrent-abortable-preclean-start] 2019-04-11T16:30:52.428+0800: 18.302: [CMS-concurrent-abortable-preclean: 2.860/4.254 secs] [Times: user=9.47 sys=1.09, real=4.25 secs] 2019-04-11T16:30:52.428+0800: 18.302: [GC (CMS Final Remark) [YG occupancy: 203965 K (314560 K)]2019-04-11T16:30:52.428+0800: 18.303: [Rescan (parallel) , 0.0177423 secs]2019-04-11T16:30:52.447+0800: 18.320: [weak refs processing, 0.0001500 secs]2019-04-11T16:30:52.447+0800: 18.320: [class unloading, 0.0287879 secs]2019-04-11T16:30:52.475+0800: 18.349: [scrub symbol table, 0.0121125 secs]2019-04-11T16:30:52.497+0800: 18.362: [scrub string table, 0.0012159 secs][1 CMS-remark: 0K(699072K)] 203965K(1013632K), 0.0623200 secs] [Times: user=0.13 sys=0.00, real=0.07 secs]

    Old GC過程

  • 初始化標記(CMS Initial Mark)
    2019-04-11T16:30:48.164+0800: 14.035: [GC (CMS Initial Mark) [1 CMS-initial-mark: 0K(699072K)] 33843K(1013632K), 0.0066881 secs] [Times: user=0.09 sys=0.00, real=0.01 secs]
    整個過程會STW。
    標記GC Roots可達的老年代對象;
    遍歷新生代對象,標記可達的老年代對象;
  • 并發標記(CMS-concurrent-mark)
  • 2019-04-11T16:30:48.179+0800: 14.044: [CMS-concurrent-mark-start] 2019-04-11T16:30:48.179+0800: 14.044: [CMS-concurrent-mark: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

    該階段GC線程和應用線程并發執行,遍歷InitialMarking階段標記出來的存活對象,然后繼續遞歸標記這些對象可達的對象。

  • 預處理(CMS-concurrent-preclean)
  • 2019-04-11T16:30:48.179+0800: 14.044: [CMS-concurrent-preclean-start] 2019-04-11T16:30:48.179+0800: 14.047: [CMS-concurrent-preclean: 0.003/0.003 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

    處理新生代已經發現的引用,比如在并發階段,在Eden區中分配了一個A對象,A對象引用了一個老年代對象B(這個B之前沒有被標記),在這個階段就會標記對象B為活躍對象。

  • 可中斷的預清理(CMS-concurrent-abortable)
  • 2019-04-11T16:30:48.179+0800: 14.047: [CMS-concurrent-abortable-preclean-start] 2019-04-11T16:30:52.428+0800: 18.302: [CMS-concurrent-abortable-preclean: 2.860/4.254 secs] [Times: user=9.47 sys=1.09, real=4.25 secs]

    該階段發生的前提是,新生代Eden區的內存使用量大于參數?CMSScheduleRemarkEdenSizeThreshold?默認是2M,如果新生代的對象太少,就沒有必要執行該階段,直接執行重新標記階段。
    因為CMS GC的終極目標是降低垃圾回收時的暫停時間,所以在該階段要盡最大的努力去處理那些在并發階段被應用線程更新的老年代對象,這樣在暫停的重新標記階段就可以少處理一些,暫停時間也會相應的降低。

  • 重新標記(CMS Final Remark)
  • 2019-04-11T16:30:52.428+0800: 18.302: [GC (CMS Final Remark) [YG occupancy: 203965 K (314560 K)]2019-04-11T16:30:52.428+0800: 18.303: [Rescan (parallel) , 0.0177423 secs]2019-04-11T16:30:52.447+0800: 18.320: [weak refs processing, 0.0001500 secs]2019-04-11T16:30:52.447+0800: 18.320: [class unloading, 0.0287879 secs]2019-04-11T16:30:52.475+0800: 18.349: [scrub symbol table, 0.0121125 secs]2019-04-11T16:30:52.497+0800: 18.362: [scrub string table, 0.0012159 secs][1 CMS-remark: 0K(699072K)] 203965K(1013632K), 0.0623200 secs] [Times: user=0.13 sys=0.00, real=0.07 secs]

    并發重新標記,STW過程。
    遍歷新生代對象,重新標記根據GC Roots,重新標記。

    針對并發模式失效的調優

    發生并發模式失效往往是由于CMS不能以足夠快的速度清理老年代空間:新生代需要進行垃圾回收時,CMS收集器計算發現老年代沒有足夠的空閑空間可以容納這些晉級對象,不得不先對老年代進行垃圾回收。
    當老年代空間的占用達到某個程度時,并發回收就開始了。一個CMS后臺線程要在老年代剩余空間用盡之前,完成老年代空間的掃描回收工作。如果并發回收速度太慢,就會發生并發模式失效。
    可以通過以下途徑避免這種失效:

  • 想辦法增大老年代空間,要么只移動部分的新生代對象到老年代,要么增加更多的堆空間。
  • 以更高的頻率運行后臺回收線程。
  • 使用更多的后臺回收線程。
    如果有更多的內存可用,更好的方案是增加堆的大小,否則可以嘗試調整后臺線程運行的方式來解決這個問題。
  • 給后臺線程更多的運行機會

    同時設置-XX:CMSInitiatingOccupancyFraction=N和-XX:+UseCMSInitiatingOccupancyOnly。對特定的程序,該標志的更優值可以根據GC日志中CMS周期首次啟動失敗時的值得到。具體方法是,在垃圾回收日志中尋找并發模式失效,找到后再反向查找CMS周期最近的啟動記錄。日志中含有CMS-initial-mark信息的一行包含了CMS周期啟動時,老年代空間的占用情況。

    調整CMS后臺線程

    每個CMS后臺線程都會100%地占用機器上的一顆CPU。如果應用程序發生并發模式失效,同時又有額外的CPU周期可用,可以設置-XX:ConcGCThreads=N標志,增加后臺線程的數目。默認ConcGCThreads =(ParallelGCThreads+3)/4。當有4個并行線程時,有1個并發線程,
    當有5~8個并行線程時,有2個并發線程。ParallelGCThreads表示的是GC并行時使用的線程數,如果新生代使用ParNew,那么ParallelGCThreads也就是新生代GC線程數。默認情況下,當CPU數量小于8時,ParallelGCThreads的值就是CPU的數量,當CPU數量大于8時,ParallelGCThreads的值等于3+5*cpuCount/8。

    java學習筆記/jvm

    轉載于:https://www.cnblogs.com/luozhiyun/p/10699468.html

    總結

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

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