過程html
初始標記java
從roots(例如:thread stack引用的對象,static對象),新生代對象,標記直接引用的老年代對象。併發
併發標記oracle
利用初始標記階段標記的對象,遞歸標記整個老年代。線程
該階段與用戶線程並行執行,產生變化的對象(新建,晉升,引用變化(不引用)等)所在的Card標記爲Dirty。htm
從新標記對象
使用roots,新生代對象,僅標記老年代中Dirty Card中的對象。遞歸
併發清除內存
清除未標記的對象。it
與用戶線程並行執行。
調優
ConcurrentMode Failure
併發標記,併發清除都是與用戶線程同時進行,可能會產生太多新對象,致使老年代空間不夠。
出現ConcurrentMode Failure,退化爲stop-the-world的serial old gc。
設置CMSInitiatingOccupancyFraction UseCMSInitiatingOccupancyOnly,調低觸發cms的時機,預留足夠空間,避免發生CMF。
CMSScavengeBeforeRemark
從新標記以前,進行一次young gc,減小source。
UseCMSCompactAtFullCollection & CMSFullGCsBeforeCompaction=5
開啓碎片壓縮,解決內存碎片問題。但沒必要每次都壓縮,影響gc效率。
設置併發gc的線程數
參考:
https://docs.oracle.com/en/java/javase/13/gctuning/concurrent-mark-sweep-cms-collector.html#GUID-937A32AD-E2EA-4109-823D-A66D001A1807 https://www.jianshu.com/p/2a1b2f17d3e4