G1前关注停顿时长的场景都会选择CMS

优点:停顿时长可控

缺点:算法复杂,吞吐量不如Parallel

JVM——CMS_jvm

初始标记(STW)、并发标记、预清理(-XX:-CMSPrecleaningEnabled关闭预清理)、重新标记(STW)、并发清除和并发重置

预清理是并发的,除了为正式清理做准备和检查,还会尝试控制一次停顿的时间。由于重新标记是独占CPU的,如果新生代GC发生后,立即触发一次重新标记,那么一次停顿的时间可能很长。为了避免这种情况,预处理时会刻意等待一次新生代GC的发生,然后根据历史性能数据预测下一次新生代GC可能发生的时间,在当前时间和预测时间的中间时刻进行重新标记。这样可尽量避免新生代GC和重新标记重合,尽可能减少一次停顿的时间。


参数

  • ‐XX:MaxTenuringThreshold:对象经历多少次Minor GC才晋升到旧生代,除cms(6)外其他为15(对象头中占4字节)
  • ‐XX:PretenureSizeThreshold:字符串和数组等大对象大于这个值直接在老年代分配默认0,即存入新生代
  • -XX:SurvivorRatio:新生代中eden和S0/S1空间的比例,默认用 8:1:1的比例
  • -XX:-AdaptiveSizePolicy:CMS默认关闭
  • -XX:+UseConcMarkSweepGC 使用CMS
  • -XX:ConcGCThreads:并发的GC线程数
  • -XX:ParallelCMSThreads CMS线程数,参见-XX:+ParallelGCThreads
  • -XX:+ParallelGCThreads 默 认 启 动 的 并 发 线 程 数 是 (ParallelGCThreads+3)/4 。ParallelGCThreads表示GC并行时使用的线程数量,如果新生代使用ParNew,那么ParallelGCThreads也就是新生代GC的线程数量。这意味着有4个ParallelGCThreads时,只有1个并发线程,而有两个并发线程时,有5~8个ParallelGCThreads线程。可 以 通 过 -XX:ConcGCThreads 或 者 -XX:ParallelCMSThreads参数手工设定。
  • -XX:CMSInitiatingOccupancyFraction 使用多少比例老年代后开始CMS收集,默认是68%。当老年代的空间使用率达到68%时,会执行一次CMS回收。如果应用程序的内存使用率增长很快,在CMS的执行过程中,已经出现了内存不足的情况,CMS回收就会失败,虚拟机将启动老年代串行回收器进行垃圾回收。此时,应用程序将完全中断,直到垃圾回收完成如果内存增长缓慢,则可以设置一个稍大的值,大的阈值可以有效降低CMS的触发频率,减少老年代回收的次数,可以较为明显地改善应用程序性能。反之,如果应用程序内存使用率增长很快,则应该降低这个阈值,以避免频繁触发老年代串行回收器
  • -XX:+UseCMSCompactAtFullCollection 在FGC完成后,进行一次内存碎片整理,内存碎片的整理不是并发进行的
  • -XX:CMSFullGCsBeforeCompaction 多少次FGC后进行压缩
  • -XX:CMSInitiatingOccupancyFraction: 当老年代使用达到该比例时会触发FullGC(默认是92)
  • -XX:+UseCMSInitiatingOccupancyOnly:只使用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction设 定的值),如果不指定,JVM仅在第一次使用设定值,后续则会自动调整
  • -XX:+CMSClassUnloadingEnabled
  • -XX:CMSInitiatingPermOccupancyFraction 达到什么比例进行Perm回收(jdk8后没有perm了)GCTimeRatio 设置GC时间占用程序运行时间百分比
  • -XX:MaxGCPauseMillis 停顿时间(建议时间),GC会尝试各种手段达到这个时间,比如减少年轻代
  • -XX:+CMSScavengeBeforeRemark:在CMS GC前启动一次minor gc,目的在于减少老年代对年轻代的引用,降低CMS GC的标记阶段时的开销,一般CMS的GC耗时 80%都在标记阶段
  • -XX:+CMSParallellnitialMarkEnabled:表示在初始标记的时候多线程执行,缩短STW
  • -XX:+CMSParallelRemarkEnabled:在重新标记的时候多线程执行,缩短STW
  • -XX:+CMSIncrementalMode:(jdk8中已被弃用,并且可能会在未来的主要版本中被删除)


官方推荐 To use i-cms in Java SE 8, use the following command-line options:

​-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode \ -XX:+PrintGCDetails -XX:+PrintGCTimeStamps​