JVM系列——垃圾回收器

文章目录

      • CMS
        • 简介
        • 特点
        • CMS收集器工作流程
        • CMS收集器存在的问题
        • 生产参数配置案例

CMS

简介

cms全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,再jdk1.5中开始使用。

cms设计的目标:是为了达到 最低停顿时间(stop the world停顿时间)
使用场景:GC过程短暂,适合对时延要求较高的服务,对服务器响应要求较高的服务

特点

1、并发
2、基于标记-清除算法实现
3、是一个老年代垃圾收集器,可以和Serial、Parallel New收集器配合使用。当并行模式(concurent mode failure)失败时CMS会退化成Serial Old.

CMS收集器工作流程

  • 初始标记(Initial Mark):只标记和GC Root能直连的对象(可达对象),速度快,会发生"stop the world"。
  • 并发标记(Concurrent Mark):和应用线程并发执行,遍历“初始标记”阶段标记过的对象,标记这些对象的可达对象。
  • 重新标记(Final Remark):由于“并发标记”和应用线程是并发执行的,所以有些标记的对象会发生了变化。“重新标记”比“初始标记”时间长,比“并发标记”时间短。会发生"stop the world"。
  • 并发清理(Concurrent Sweep):和应用线程一起运行。基于标记对象,直接清理对象,回收被占用的空间。
  • 并发重置(Concurrent Reset):并发重置阶段,将清理并恢复在CMS GC过程中的各种状态,重新初始化CMS相关数据结构,为下一个垃圾收集周期做好准备。

常见问题补充
为什么配置了CMS GC,却触发了Full GC?
(1)大对象分配时,年轻代放不下,直接去了老年代,结果老年代也放不下,直接触发Full GC。
(2)使用标记-清除算法存在 内存碎片 问题。
(3)CMS GC失败(Concurrent mode failure导致)
(4)jmap -histo人为执行了命令

CMS收集器存在的问题

  1. 消耗CPU资源
    由于CMS是并发设计的,并发程序都对CPU资源比较敏感。CMS默认启动的回收线程是(cpu数量+3)/4,CMS工作时占用一部分线程,导致系统总吞吐量会降低。所以系统需要提高CPU资源来提高服务的吞吐量。
  2. 内存碎片问题
    由于CMS采用的是标记-清除算法,所以内存碎片问题是不可避免的。
    解决办法:使用-XX:+CMSFullGCsBeforeCompaction=n,意思是在上次CMS并发GC执行过后,还需要做多少次Full GC才做压缩。默认是0,也就是说只要发生Full GC时就压缩整理。
  3. 无法处理浮动垃圾
    • CMS并发清理阶段,用户程序还在执行,会需要预留一部分空间。CMS的做法是是用-XX:CMSInitiatingOccupancyFraction=60参数控制老年代空间占用率达到某个阈值时触发垃圾回收。
    • 如果预留的空间不够使用,就会出现Concurrent Mode Failure,此时会触发一次Full GC,转而使用Serial Old收集器对老年代进行垃圾回收,会产生stop the world,耗时较长。Concurrent Mode Failure一般会伴随ParNew promotion failed,晋升担保失败,就是为了应对新生代GC后产生存活对象过多,Survivor区无法容纳的情况,需要老年代有足够的空间容纳这些对象,如果老年代没有足够的空间,就会产生担保失败。
    • 如何避免Concurrent Mode Failure
      (1)调大老年代的空间
      (2)调低CMSInitiatingOccupancyFraction配置的值,使能够及时回收空间,但是也会造成频繁CMS GC
      (3)代码层面优化,控制对象创建频率
  4. 重新标记阶段时间过长
    解决:使用 -XX:+CMSScavengeBeforeRemark,在执行重新标记前先做一次Young GC,目的在于。。。

生产参数配置案例

jvmparams=-Dcom.sun.management.jmxremote.ssl\=false -Dcom.sun.management.jmxremote.authenticate\=false -Xms2000m -Xmx2000m -Xmn1000m -Xss1000k 
-XX:PermSize\=512M 
-XX:+UseConcMarkSweepGC 
-XX:CMSInitiatingOccupancyFraction\=60 
-XX:+PrintGCApplicationStoppedTime 
-XX:+PrintGCDateStamps 
-XX:+CMSParallelRemarkEnabled 
-XX:+CMSScavengeBeforeRemark 
-XX:+UseCMSCompactAtFullCollection 
-XX:CMSFullGCsBeforeCompaction\=0 -verbosegc 
-XX:+PrintGCDetails 
-XX:ErrorFile\=/usr/local/app/taf/app_log/

你可能感兴趣的:(JAVA,基础总结复习,jvm,java,算法)