zoukankan      html  css  js  c++  java
  • 垃圾收集器

     在上一篇提到垃圾收集算法,那么在堆中怎么选择呢?

    Young区:复制算法(对象在被分配之后,可能生命周期比较短,Young区复制效率比较高)

    Old区:标记清除或标记整理(Old区对象存活时间比较长,没必要进行复制,直接做标记之后清理)

    • Serial收集器

      Serial搜集器是最基本的收集器。它是一种单线程的收集器,不仅仅以为着他指挥使用一个CPU或者一条收集线程去完成垃圾收集工作,更重要是其在进行垃圾回收的时候需要暂停其他线程。

      优点:简单高效,拥有很高的单线程手机效率

      缺点:手机过程需要暂停的所有线程

      算法:复制算法

      使用范围:新生代

      应用:client模式下的默认新生代收集器

      

    • ParNew收集器

      可以把这个收集器理解为Serial收集器的多线程版本

      优点:在多CPU的时候,比Serial效率高

      缺点:收集过程暂停所有应用程序线程,单CPU时比Serial效率差

      算法:复制算法

      使用范围:新生代

      应用:运行在server模式下的虚拟机中首选的新生代收集器

    • Parallel Scavenge收集器

      Parallel Scavenge收集器是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器,看上去和ParNew一样,但是Parallel Scanvenge更关注系统的吞吐量

      吞吐量=运行用户代码的时间/(运行用户代码的时间+垃圾收集时间)

      如果吞吐量越大,意味着垃圾收集的时间越短,则用户代码可以充分利用CPU的资源,尽快完成程序的运算任务。

    -XX:MaxGCPauseMillis    控制最大的垃圾收集停顿时间
    -XX:GCTimeRatio    直接设置吞吐量的大小
    
    •  Serial Old收集器

      Serial Old收集器是Serial收集器的老年代版本,也是一个单线程收集器,不同的是采用“标记-整理算法”,运行过程和Serial收集器一样。

    • Parallel Old收集器

      Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理算法”进行垃圾回收。吞吐量优先

    • CMS收集器

      CMS(concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。

    采用的是“标记-清除算法”。

      其过程为:

      • 初始标记 CMS initial mark  标记GC Roots能关联到的对象 Stop The World--》速度很快
      • 并发标记 CMS concurrent mark 进行GC Roots Tracing
      • 重新标记 CMS remark。修改并发标记因用户程序变动的内容。Stop The World
      • 并发清除 CMS concurrent sweep

      由于整个过程中,并发标记和并发清除,收集器线程可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程是与用户线程一起并发的执行的。

      优点:并发收集、低停顿

      缺点:产生大量的空间碎片、并发阶段会降低吞吐量

    • G1收集器

    G1的特点:

      • 并行与并发  
      • 分代收集(仍然保留了分代的概念)
      • 空间整合(整体上属于“标记-整理“算法,不会导致空间碎片)
      • 可预测的停顿(比CMS更先进的地方在于能让使用者明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒)
      • G1收集器会先收集存活对象少的区域,也就是垃圾对象多的区域,这样可以有大量的空间释放出来,这就是Garbage First的由来

    使用G1收集器时,Java堆的内存布局与就与其他收集器有很大的差别,它将整个java堆划分为多个大小相等的独立区间(region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分region(不需要连续)的集合。

    工作过程可以分为如下几个步骤:

    • 初始标记(Initial Marking) 标记一下GC Roots能够关联的对象,并且修改TAMS的值,需要暂停用户线程。
    • 并发标记(concurrent Marking) 从GC Roots进行可达性分析,找出存活对象,与用户线程并发执行。
    • 最终标记(Final Marking) 修正在并发标记阶段因为用户程序的并发执行导致变动的数据,需要暂停用户线程
    • 筛选回收(Live Data Counting and Evacuation) 对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间制定回收计划

    如图所示:

    • 垃圾收集器分类

      • 串行收集器-》Serial和Serial Old
        • 只能有一个垃圾回收线程执行,用户线程暂停。适用于内存较小的嵌入式设备
      • 并行收集器【吞吐量优先】-》Parallel Scanvenge、Parallel Old
        • 多余垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。适用于科学计算、后台处理等若交互场景。
      • 并发收集器【停顿时间优先】-》CMS、G1
        • 用户线程和垃圾收集线程同时执行(但不一定是并行的,可能是交替执行的),垃圾收集线程在执行的时候不会停顿用户线程的运行。适用于对时间有要求的场景。比如web
    • 吞吐量和停顿时间

      • 停顿时间-》垃圾收集器进行垃圾回收终端应用执行响应的时间
      • 吞吐量-〉运行用户代码时间/(运行用户代码时间+垃圾收集时间)

        【停顿时间越短就越适合和用户交互的程序,良好的响应速度能提升用户的体验;

         高吞吐量则可以高效的利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多的交互的任务。

         】

    总结:吞吐量和停顿时间是评价垃圾回收器好处的标准,其实调优也就是在观察者两个变量。

    如何选择选择合适的垃圾收集器

    • 优先调整堆的大小让服务器自己来选择
    • 如果内存大小小于100M,使用串行收集器
    • 如果是单核,并且没有停顿时间要求,使用串行或jvm自己选
    • 如果允许停顿时间超过1s,选择并行或jvm自己选
    • 如果响应时间最重要,并且不能超过1s,使用并发收集器

    如何开启需要的垃圾收集器?

    • 串行

      • -XX: +UseSerialGC

      • -XX: +UseSerialOldGC

    • 并行(吞吐量优先)

      • -XX:+UseParallelGC

      • -XX:  +UseParallelOldGC

    • 并发收集器(响应时间优先)
      • -XX: +UseconcMarkSweepGC
      • -XX: +UseG1GC

     有关在不同垃圾收集器中使用的不同的算法的图解参考:https://www.cnblogs.com/LBJLAKERS/p/12287322.html

  • 相关阅读:
    CF1109F Sasha and Algorithm of Silence's Sounds LCT、线段树
    Solution -「CF 757F」Team Rocket Rises Again
    Solution -「ZJOI2012」「洛谷 P2597」灾难
    Solution -「CF 156D」Clues
    「矩阵树定理」学习笔记
    Solution -「JSOI2008」「洛谷 P4208」最小生成树计数
    Solution -「SHOI2016」「洛谷 P4336」黑暗前的幻想乡
    Solution -「Code+#2」「洛谷 P4033」白金元首与独舞
    Solution -「HDU 5498」Tree
    呐~「多项式」全家桶
  • 原文地址:https://www.cnblogs.com/LBJLAKERS/p/12294524.html
Copyright © 2011-2022 走看看