1. 程式人生 > >併發垃圾回收器CMS介紹(日誌詳解)

併發垃圾回收器CMS介紹(日誌詳解)

當使用CMS收集器時,當開始進行收集時,old代的收集過程如下所示: 1,首先jvm根據-XX:CMSInitiatingOccupancyFraction,-XX:+UseCMSInitiatingOccupancyOnly來決定什麼時間開始垃圾收集; 2,如果設定了-XX:+UseCMSInitiatingOccupancyOnly,那麼只有當old代佔用確實達到了-XX:CMSInitiatingOccupancyFraction引數所設定的比例時才會觸發cms gc; 3,如果沒有設定-XX:+UseCMSInitiatingOccupancyOnly,那麼系統會根據統計資料自行決定什麼時候觸發cms gc;因此有時會遇到設定了80%比例才cms gc,但是50%時就已經觸發了,就是因為這個引數沒有設定的原因; 4,當cms gc開始時,首先的階段是CMS-initial-mark,此階段是初始標記階段,是stop the world階段,因此此階段標記的物件只是從root集最直接可達的物件;      CMS-initial-mark:961330K(1572864K),指標記時,old代的已用空間和總空間 5,下一個階段是CMS-concurrent-mark,此階段是和應用執行緒併發執行的,所謂併發收集器指的就是這個,主要作用是標記可達的物件        此階段會列印2條日誌:CMS-concurrent-mark-start,CMS-concurrent-mark 6,下一個階段是CMS-concurrent-preclean,此階段主要是進行一些預清理,因為標記和應用執行緒是併發執行的,因此會有些物件的狀態在標記後會改變,此階段正是解決這個問題因為之後的Rescan階段也會stop the world,為了使暫停的時間儘可能的小,也需要preclean階段先做一部分工作以節省時間      此階段會列印2條日誌:CMS-concurrent-preclean-start,CMS-concurrent-preclean 7,下一階段是CMS-concurrent-abortable-preclean階段,加入此階段的目的是使cms gc更加可控一些,作用也是執行一些預清理,以減少Rescan階段造成應用暫停的時間      此階段涉及幾個引數:      -XX:CMSMaxAbortablePrecleanTime:當abortable-preclean階段執行達到這個時間時才會結束      -XX:CMSScheduleRemarkEdenSizeThreshold(預設2m):控制abortable-preclean階段什麼時候開始執行,       即當eden使用達到此值時,才會開始abortable-preclean階段      -XX:CMSScheduleRemarkEdenPenetratio(預設50%):控制abortable-preclean階段什麼時候結束執行       此階段會列印一些日誌如下:      CMS-concurrent-abortable-preclean-start,CMS-concurrent-abortable-preclean,       CMS:abort preclean due to time XXX 8,再下一個階段是第二個stop the world階段了,即Rescan階段,此階段暫停應用執行緒,對物件進行重新掃描並標記;        YG occupancy:964861K(2403008K),指執行時young代的情況        CMS remark:961330K(1572864K),指執行時old代的情況       此外,還打印出了弱引用處理、類解除安裝等過程的耗時 9,再下一個階段是CMS-concurrent-sweep,進行併發的垃圾清理 10,最後是CMS-concurrent-reset,為下一次cms gc重置相關資料結構 11,full gc: 有2種情況會觸發full gc,在full gc時,整個應用會暫停        A,concurrent-mode-failure:當cms gc正進行時,此時有新的物件要進行old代,但是old代空間不足造成的        B,promotion-failed:當進行young gc時,有部分young代物件仍然可用,但是S1或S2放不下,因此需要放到old代,但此時old代空間無法容納此。 影響cms gc時長及觸發的引數是以下2個:         -XX:CMSMaxAbortablePrecleanTime=5000         -XX:CMSInitiatingOccupancyFraction=80 解決也是針對這兩個引數來的,根本的原因是每次請求消耗的記憶體量過大 解決方式:       A,針對cms gc的觸發階段,調整-XX:CMSInitiatingOccupancyFraction=50,提早觸發cms gc,就可以緩解當old代達到80%,cms gc處理不完,從而造成concurrent mode failure引發full gc      B,修改-XX:CMSMaxAbortablePrecleanTime=500,縮小CMS-concurrent-abortable-preclean階段的時間      C,考慮到cms gc時不會進行compact,因此加入-XX:+UseCMSCompactAtFullCollection        (cms gc後會進行記憶體的compact)和-XX:CMSFullGCsBeforeCompaction=4(在full gc4次後會進行compact)引數