深入分析JVM:Java垃圾收集算法+常用垃圾收集器解析( 四 )

  • 3、重新标记(remark)需要Stop The World , 这个阶段是为了修正在阶段2标记之后产生了变化的对象
  • 4、并发清除(concurrent sweep)和用户线程同时进行 , 开始正式清除垃圾 , 在此阶段也会产生垃圾 , 产生垃圾后无法清除 , 只能留待下一次GC 。
  • CMS收集过程如下图所示:
    深入分析JVM:Java垃圾收集算法+常用垃圾收集器解析文章插图
    CMS优缺点
    • 优点:并发收集、低停顿 。 其实最主要的是CMS把收集过程中步骤拆分了 , 而最耗时的操作都是并发执行 , 自然就会低停顿了 。
    • 缺点:产生大量空间碎片、并发阶段会降低吞吐量 。 CMS采用的是标记-清除算法 , 所以会产生大量的空间碎片 。 在阶段2和阶段4并发执行的时候 , 会占用CPU资源 , 就会导致应用程序变慢 , 降低了吞吐量 。
    Floating Garbage(浮动垃圾)上面的步骤中 , 步骤2是并发标记 , 所以在标记过程中 , 可能会有新的垃圾产生而没有被标记到 。 比如说对象A , 刚扫描的时候是有效对象 , 然后继续扫描的时候 , 对象A又变成不可用了 , 然后还有并发清除的阶段 , 也可能会有新的垃圾产生 , 这种就称之为浮动垃圾(Floating Garbage) 。 CMS并不能收集浮动垃圾 , 只能等到下一次GC时再回收 。
    Concurrent Mode Failure(并发模式失败)CMS收集器不能和其他收集器一样等到空间满了才开始触发GC , 因为CMS收集的时候是并发的 , 并发的过程肯定会持续产生对象 , 如果因为在垃圾收集期间内存不足而导致了GC失败 , 就称之为Concurrent Mode Failure 。 出现这种情况之后 , Java虚拟机就会启动预备方案 , 启用Serial Old收集器替换CMS收集器 , 这时候整个GC过程都会Stop The World 。
    CMS收集器的触发阈值可以通过参数:-XX:CMSInitiatingOccupancyFraction=来进行设置 , N为(0,100)之间 , 在jdk1.6中默认是92 , 即老年代空间使用率达到92%就会触发CMS收集器开始进行垃圾回收 。
    G1(Garbage-First)收集器G1也是以实现GC时最短停顿时间为目标并发回收的收集器 , 它尝试以高概率满足垃圾收集(GC)暂停时间目标 , 同时实现高吞吐量 。
    在G1之前的其他收集器都是属于分代收集器 , 也就是说一个收集器要不然用于新生代 , 要不然就是用于老年代 , 而G1中 , 将堆的整个内存布局做了很大的修改 , 在G1中 , 将整个Java堆划分为多个大小相等的独立区域(Region) , 虽然在逻辑上还保留了新生代和老年代的概念 , 但是物理上已经没有隔离了 。
    G1收集器中堆内布局如下图所示:
    深入分析JVM:Java垃圾收集算法+常用垃圾收集器解析文章插图
    上图中堆被划分为一组大小相同的Region , 每个Region都是连续的虚拟内存范围 。 G1可以知道哪个Region区域内大部分都是空的 , 这样就可以在每次允许的收集时间内去优先回收价值最大的Region区域(根据回收所获得的空间大小以及回收所需要的时间综合考虑) , 所以这也就是G1为什么叫做Garbage-First的原因 。
    PS:G1是JDK1.9的默认垃圾收集器
    G1特点经过上面的简单介绍 , 可以得出G1主要有以下特点:
    • 1、实现了并行与并发 , 尽可能的缩短了Stop The World时间 。
    • 2、分代收集:逻辑上依然保留了分代概念
    • 3、空间整合:整体来看是基于“标记-整理”算法来实现的(如果从Region来看 , 是基于“复制”算法) , 所以不会产生大量内存空间碎片 。
    • 4、支持可预测的停顿时间:可以通过参数来设置每次GC最大时间
    • 5、非实时收集:因为可以人为设置停顿时间 , 所以在指定时间范围内会进行优先选择收集 , 而不会收集所有被标记好的垃圾 。
    G1工作流程G1收集器在工作流程上和CMS比较相似 , 只是在最后的步骤有所区别 , 主要经过了如下4个步骤:
    • 1、初始标记(Initial Marking):需要Stop The World 。 标记一下GC Roots能够关联的对象 , 并且修改TAMS(Next Top at Mark Start)的值 , 使得下一阶段并发运行时 , 能在正确可用的Region中创建对象 。
    • 2、并发标记(Concurrent Marking):和CMS一样 , 主要是进行GC Roots Tracing , 找出存活对象进行标记 。
    • 3、最终标记(Final Marking):需要Stop The World 。 和CMS一样 , 这个阶段主要是为了修正在并发标记期间因用户程序继续运行而导致产生变动的对象 。
    • 4、筛选回收(Live Data Counting and Evacuation):对各个Region的回收价值和成本进行排序 , 根据 用户所期望的GC停顿时间制定回收计划进行回收 。
    工作流程图如下所示: