常见的垃圾回收器:Serial、Parallel、ParNew、CMS、G1

常见的垃圾回收器:Serial、Parallel、ParNew、CMS、G1_第1张图片

 

Serial收集器(-XX:+UserSerialGc  -XX:+UseSerialOldGC)
    Serial(串行)收集器,最基础的垃圾收集器,单线程。此处的单线程意味着他只能通过一条线程进行垃圾回收,且垃圾回收的过程中需要SWT(STOP THE WORLD)。用户体验度差,顿挫明显。
    新生代采用的复制算法,老年代采用标记-整理算法。
    优点:简单高效;因为没有多线程的交互开销,Serial收集器单线程收集效率很高。
    用途:JDK1.5以及之前的版本中与Paraller Scavenge搭配使用。CMS后备方案。

常见的垃圾回收器:Serial、Parallel、ParNew、CMS、G1_第2张图片

     
Parallel Scavenge收集器(-XX:+UseParallelGC(年轻代),-XX:+UseParallelOldGC(老年代))
    Parallel就是Serial的多线程版,出了多线程进行垃圾收集外,其他行为(控制参数、收集算法、回收策略)基本与串行收集器一致。默认线程数和CPU核数保持一致,当然可以通过参数控制一般不建议修改。Paraller注重的是吞吐量(高效利用cpu),CMS等注重用户体验度即更短的STW。Paraller提供了许多参数供用户找到最合适的停顿时间或最大吞吐量。
    新生代采用复制算法,老年代采用标记-整理算法。
    优点:多线程进行垃圾回收,STW时间更短,用户体验优于Serial
    用途:JDK1.8默认新生代和老年代使用Paraller和Paraller Old
    常见的垃圾回收器:Serial、Parallel、ParNew、CMS、G1_第3张图片

 

ParNew 收集器(-XX:UseParNewGC)
    ParNew是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为包括Serial收集器可用的所有控制参数(例如:-XX:SurvivorRatio、-XX:PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器一致。
    新生代采用复制算法,老年代采用标记-整理算法。
    优点:在单核的情况下ParNew的效果绝不会比Serial更好,但随着CPU数量增加ParNew的优势越来越明显,原因就是多线程处理,但不是成倍增加,原因是多线程交互开销。(-XX:+UseParNewGC,打开该开关后,使用ParNew(年轻代)+Serial Old(老年代)组合进行GC。另外,ParNew是CMS收集器的默认年轻代收集器)
    用途:-XX:+UseParNewGC,打开该开关后,使用ParNew(年轻代)+Serial Old(老年代)组合进行GC。-XX:+UseConcMarkSweepGC:指定使用CMS后,会默认使用ParNew作为新生代收集器。(为什么不用Parallel配合CMS?CMS作为老年代收集器,但却无法与JDK1.4已经存在的新生代收集器Parallel Scavenge配合工作是因为Parallel Scavenge和G1没有使用传统的GC框架,所以不能配合使用)
    常见的垃圾回收器:Serial、Parallel、ParNew、CMS、G1_第4张图片

 

CMS收集器( -XX:+UseConcMarkSweepGC(old))
    CMS是一款获取最短停顿时间为目标的收集器。是HotSpot虚拟机第一款真正意义上的并发收集器,它实现了让用户线程和垃圾收集线程同时工作。
    采用标记-清除算法

常见的垃圾回收器:Serial、Parallel、ParNew、CMS、G1_第5张图片
    过程:
        初始标记:初始标记会STW(stop the world),记录下gc roots直接能引用的对象,速度非常快。
        并发标记:用户线程和GC线程同时工作,从gcroots直接引用的对象开始遍历整个对象图的过程,因为用户线程也在工作,可能导致已标记的对象状态发生变化。
        重新标记:重新标记就是为了修正并发标记过程中状态发生变化的部分对象,此过程会STW,但时间远远短于并发标记。主要用到三色标记中的增量更新算法做重新标记。
        并发清理:开启用户线程,同时GC线程对未标记的对象做清理。如果这个阶段有新增对象会直接标记为黑色不作处理。
        并发重置:重置本次GC过程中的所以标记数据
    优点:并发收集、低顿挫、高用户体验
    缺点:对CPU资源敏感,会和服务争抢资源;无法处理浮动垃圾(并发标记和并发清除阶段产生的垃圾,只能等下次GC);标记-清除算法产生空间碎片(XX:+UseCMSCompactAtFullCollection参数可以让JVM做完清理后进行内存整理);concurrent mode failure,在上次GC没有完成又触发了full GC,特别是在并
发标记和并发清理阶段会出现,即concurrent mode failure,会导致SWT,且切换成Serial Old垃圾回收器来回收。
    CMS的相关核心参数
        1. -XX:+UseConcMarkSweepGC:启用cms
        2. -XX:ConcGCThreads:并发的GC线程数
        3. -XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩整理(减少碎片)
        4. -XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次,默认是0,代表每次FullGC后都会压缩一次 
        5. -XX:CMSInitiatingOccupancyFraction: 当老年代使用达到该比例时会触发FullGC(默认是92,这是百分比)
        6. -XX:+UseCMSInitiatingOccupancyOnly:只使用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction设定的值),如果不指定,JVM仅在第一次使用设定值,后续则会自动调整
        7. -XX:+CMSScavengeBeforeRemark:在CMS GC前启动一次minor gc,目的在于减少老年代对年轻代的引用,降低CMS GC的标记阶段时的开销,一般CMS的GC耗时 80%都在标记阶段
        8. -XX:+CMSParallellnitialMarkEnabled:表示在初始标记的时候多线程执行,缩短STW
        9. -XX:+CMSParallelRemarkEnabled:在重新标记的时候多线程执行,缩短STW;
        
G1收集器(-XX:+UseG1GC)
    G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器和大容量内存的机器,以极高的概率满足停顿时间要求同时还具备高吞吐量。G1将堆划分为多个大小相等的区域(Region),JVM最多可以有2048个Region。一般都是Region大小等于堆/2048。当然也可以用参数"-
XX:G1HeapRegionSize"手动指定Region大小,但是推荐默认的计算方式。G1保留分代概念,只是不再圈定位置,每个region都可能是Eden区或者Survivor区或者Old区或者Humongous区(G1专门分配大对象的Region,大对象判断规则:超过一个Region的50%,一般是1M,过大的对象可能会使用多个连续的Region存放)。默认年轻代占比5%(堆),可以通过“-XX:G1NewSizePercent”设置新生代初始占比,在系统运行中,JVM会不停的给年轻代增加更多
的Region,但是最多新生代的占比不会超过60%,可以通过“-XX:G1MaxNewSizePercent”调整。Eden和Survivor区默认8:1:1。
    YoungGC:根据用户的期望停顿时间触发,如果eden满了,但是回收时间不近于期望停顿时间,会导致Eden扩容,直至靠近期望停顿时间。
    MixedGc:不是fullGC,老年代的堆占有率达到参数(-XX:InitiatingHeapOccupancyPercent)设定的值则触发,回收所以的年轻代、老年代和大对象。一般先做mixedGC,如果没有足够空间拷贝对象,触发full GC。
    Full GC:停止系统程序,采用单线程标记清理和压缩整理内存。好空闲一批Region供下一次MixedGC使用。
    采用复制算法(整体看来标记-整理,局部是复制算法)

常见的垃圾回收器:Serial、Parallel、ParNew、CMS、G1_第6张图片
    过程:
        初始标记(initial mark,STW):会STW,记录下gcRoots能直接引用的对象,速度非常快。
        并发标记(Concurrent Marking):同CMS,用户线程和GC线程同时工作,从gcroots直接引用的对象开始遍历整个对象图的过程,因为用户线程也在工作,可能导致已标记的对象状态发生变化。
        最终标记(Remark,STW):同CMS,为了修正并发标记过程中对象状态发生变化的部分,也会STW,时间很短。主要用到三色标记中的原始快照(STAB)算法做重新标记。
        筛选回收(Cleanup,STW):筛选回收阶段是根据用户所期望的GC停顿时间(可以用JVM参数 -XX:MaxGCPauseMillis指定)来制定回收计划,他维护了一个collection set(要回收的集合),根据回收价值和回收成本来进行回收(优先列表:G1收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的Region(这也就是它的名字
Garbage-First的由来),比如一个Region花200ms能回收10M垃圾,另外一个Region花50ms能回收20M垃圾,在回收时间有限情况下,G1当然会优先选择后面这个Region回收。这种使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限时间内可以尽可能高的收集效率。)。尽量停顿时间控制在规定时间内。这个阶段可以做到和用户线程一起,因为只回收部分region,时间要可控,所以暂停用户线程获取最大吞吐量。回收算法使用的是复制算法,空间碎片少。(CMS并发清理阶段是和用户线程一起的。G1暂时没有实现,他的升级版本shenandoah实现了并发回收)
    优点:
        并行与并发:G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短Stop-The-World停顿时间。部分其他收集器原本需要停顿Java线程来执行GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行。
        分代收集:虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但是还是保留了分代的概念。
        空间整合:与CMS的“标记--清理”算法不同,G1从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。
        可预测的停顿:这是G1相对于CMS的另一个大优势,降低停顿时间是G1 和 CMS 共同的关注点,但G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段(通过参数"-XX:MaxGCPauseMillis"指定)内完成垃圾收集。
    核心参数:
        -XX:+UseG1GC:使用G1收集器
        -XX:ParallelGCThreads:指定GC工作的线程数量
          -XX:G1HeapRegionSize:指定分区大小(1MB~32MB,且必须是2的N次幂),默认将整堆划分为2048个分区
          -XX:MaxGCPauseMillis:期望停顿时间(默认200ms)
          -XX:G1NewSizePercent:新生代内存初始空间(默认整堆5%)
          -XX:G1MaxNewSizePercent:新生代内存最大空间
          -XX:TargetSurvivorRatio:Survivor区的填充容量(默认50%),Survivor区域里的一批对象(年龄1+年龄2+年龄n的多个年龄对象)总和超过了Survivor区域的50%,此时就会把年龄n(含)以上的对象都放入老年代()
          -XX:MaxTenuringThreshold:最大年龄阈值(默认15)
          -XX:InitiatingHeapOccupancyPercent:老年代占用空间达到整堆内存阈值(默认45%),则执行新生代和老年代的混合收集(MixedGC),比如我们之前说的堆默认有2048个region,如果有接近1000个region都是老年代的region,则可能就要触发MixedGC了
         -XX:G1MixedGCLiveThresholdPercent(默认85%)  region中的存活对象低于这个值时才会回收该region,如果超过这个值,存活对象过多,回收的的意义不大。
          -XX:G1MixedGCCountTarget:在一次回收过程中指定做几次筛选回收(默认8次),在最后一个筛选回收阶段可以回收一会,然后暂停回收,恢复系统运行,一会再开始回收,这样可以让系统不至于单次停顿时间过长。

 

 

你可能感兴趣的:(jvm.gc,java,jvm)