• 经典垃圾回收器


    1.各垃圾回收器之间的配合使用关系

     2.垃圾回收器的种类

    2.1 Serial收集器(默认新生代收集器)

           Serial收集器是历史最悠久的收集器,曾经是新生代收集器的唯一选择,它是一个单线程工作的收集器,其“单线程”的意义不仅仅是说明它只会使用一个处理器或者一条收集线程去完成垃圾收集工作,更重要的是强调它在进行垃圾回收的时候,必须暂停其他所有工作线程,直到它收集结束

     优点:

    • 简单而且高效
    • 对于内存资源受限的环境,它是所有收集器中额外内存消耗最小的
    • 对于单核处理器或者处理器核心较少的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率

    2.2 ParNew收集器

    ParNew收集器手机上是Serial收集器的多线程并行版本

     注意:除了Serial收集器之外,目前只有它才可以和CMS进行配合工作

           但是随着垃圾回收器的不断改进,更先进的G1收集器带着CMS的继承者和替代者出现了,G1是一个面向全堆的收集器,不需要其他收集器进行配合工作,从这(JDK9)之后,取消了ParNew+SerialOld 以及Serial+CMS的收集器组合,变相的将ParNew合并到了CMS中,称为它专门处理新生代的组成部分,ParNew可以说是第一个退出历史舞台的垃圾收集器

    2.3 Parallel Scavenge收集器

           Parallel Scavenge收集器(吞吐量优先收集器)也是一款新生代收集器,它同样是基于标记-复制算法实现的收集器,也是能够并行收集多线程收集器,其收集器的特点是它的关注点与其他收集器不同,CMS等收集器关注的是尽可能的缩短垃圾收集时用户的停顿时间,而Parallel Scavenge收集器关注的是达到一个可控制的吞吐量(处理器用于运行用户代码的时间与处理器总消耗时间的比值)

    注意:

    • 停顿时间越短就越适合需要与用户交互或者需要保证服务响应质量的程序、良好的响应速度能提升用户体验
    • 高吞吐量则可以最高效率的利用处理器资源,尽快的完成程序的运算任务,主要适合在后台运算而不需要太多交互的分析任务

    2.4 Serial Old收集器

    Serial Ol是Serial收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法

     2.5 Parallel Old收集器

           Parallel Old是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现,它的出现,“吞吐量优先”收集器终于有了比较名副其实的搭配组合,在注重吞吐量或者处理器资源较为稀缺的场合,都可以优先考虑Parallel Scavenge + Parallel Old收集器这个组合

    2.6 CMS收集器

           CMS收集器是一种以获得最短回收停顿时间为目标的收集器,其基于标记-清除的算法实现,分为4个步骤:

    • 初始标记:初始标记的仅仅只是标记一下GC Roots能够直接关联到的对象,速度非常快
    • 并发标记:从GC Roots的直接关联对象开始遍历整个对象的过程(并发
    • 重新标记:修改并发标记期间,因为用户程序继续运作而导致标记产生变动的那一小部分对象的标记记录(增量更新)
    • 并发清除:清理删除掉标记阶段判断的已经死亡的对象(并发
    2.6.1 CMS的缺点
    • CMS收集器对处理器资源非常敏感
    • CMS无法处理“浮动垃圾”
    • 收集结束后会产生大量的空间碎片

    2.7 Garbage First收集器

           Garbage First(G1)收集器是垃圾收集器技术发展历史上的里程碑式的成果,它开创了收集器面向局部收集的设计思路和基于Region的内存布局形式

    2.7.1 G1的细节问题的解决方法
    • 将Java堆分成多个独立Region后,Region里面存在的跨Region引用对象如何解决?

           使用记忆集避免全堆作为GC Roots的扫描对象,其每个Region都维护有自己的记忆集,这些记忆集会记录下别的Region指向自己的指针,并标记这些指针分别在哪些卡页的范围内,G1的记忆集更像一个哈希表,key值是Region的起始位置,value是集合(卡表的索引),但是由于Region的数量比较多,所以G1收集器要比其他的收集器有着更高的内存占用负担(耗费相当于Java堆的10%~20%的额外内存)

    • 在并发标记阶段如何保证收集线程与用户线程互不干扰的运行?

           G1收集器时采用原始快照算法实现,垃圾收集的过程中肯定会有新的对象被创建,G1为每一个Region设计了两个名为TAMS的指针,把Region中的一部分空间划分出来用于并发回收过程中的对象内存分配,并发回收时新分配的对象地址都必须要在这两个指针位置上,G1收集器默认在这个地址以上的对象是被隐式标记过的(默认是存活的),不纳入回收范围之内,但是如果内存回收的速度赶不上创建对象分配内存的速度,会冻结用户线程,而导致长时间的“Stop the world”

    • 怎么样建立起可靠的停顿预测模型?

           G1收集器的停顿预测模型是以衰减均值为理论基础实现的,在垃圾收集的过程中,G1收集器会记录每个Region的回收耗时以及记忆集里的脏卡数量等各个可测量的步骤花费的成本,并分析得出平均值、标准偏差、置信度等统计信息,Region的统计状态越新越能决定其回收的价值,然后通过这些信息预测回收哪些Region才可以在不超过期望停顿时间的约束下获得最高的利益

    2.7.2 G1的运行步骤
    • 初始标记:只标记一下GC Roots能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行的时候,能正确的在可用的Region中分配内存创建对象
    • 并发标记:从GC Roots开始对堆中的对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,重新处理SATB记录下的在并发时有引用变动的对象(并发
    • 最终标记:对用户线程做一个短暂的暂停,用于处理并发阶段结束后仍然遗留下来的最后的SATB记录
    • 筛选回收:负责更新Region的统计数据,对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制订回收计划,把决定回收的Region中的存活对象复制到空的Region中,再清理到整个旧的Region的全部空间

    3.CMS和G1的比较

    在未来CMS肯定会被G1取代,但是在这个两者并存的时代中,难免会有比较

    • G1相对于CMS的优点:指定最大停顿时间、分Region的内存分布、按收益动态的确定回收集、算法上的优势(整体基于标记-整理,局部基于标记-复制,这两种算法都不会产生内存空间碎片,垃圾收集完成之后能提供比较规整的可用内存)
    • G1相对于CMS的缺点:G1无论是为了垃圾收集产生的内存占用还是程序运行时的额外执行负载都比CMS要高
  • 相关阅读:
    Objective-C网络数据捕获:使用MWFeedParser库下载Stack Overflow示例
    python3和pip源码安装【5步快速搞定】
    电商运营该如何做 AB 测试
    【微机接口】中断系统:中断响应和处理的过程
    【form校验】3.0项目多层list嵌套
    028-从零搭建微服务-搜索服务(二)
    S32K144时钟学习
    使用神经网络实现对天气的预测
    前端时间分片渲染
    Vue学习
  • 原文地址:https://blog.csdn.net/dfdbb6b/article/details/133817017