垃圾收集器

文章目录

  • 垃圾收集器
    • 1、Serial 收集器(新生代)
    • 2、Serial Old 收集器(老年代)
    • 3、ParNew 收集器(新生代)
    • 4、Parallel Scavenge 收集器(新生代)
    • 5、Parallel Old 收集器(老年代)
    • 6、CMS 收集器(老年代)
      • (1)工作流程
      • (2)优点和缺点
      • 优点
      • 缺点
    • 7、G1 收集器(老年代)
        • (1)什么是 G1 垃圾收集器
      • (2)G1 垃圾收集器的结构
      • (3)工作流程
      • (4)G1 垃圾收集器的特点
      • (5)G1 与 CMS 的区别

垃圾收集器

多种垃圾收集器一般都是搭配使用,一般都是新生代垃圾收集器和老年代垃圾收集器搭配使用

1、Serial 收集器(新生代)

  • 标记-复制算法
  • 单线程收集器
  • 必须暂停其他所有的工作线程
  • 适合单核处理器或处理器核心数较少的环境

Serial(串行)收集器是最基本、历史最悠久的垃圾收集器,采用==“标记-复制”==算法负责新生代的垃圾收集。它是Hotspot虚拟机运行在客户端模式下的默认新生代收集器

它是一个==单线程收集器==。它会使用一条垃圾收集线程去完成垃圾收集工作,并且它在进行垃圾收集工作的时候,必须暂停其他所有的工作线程“Stop The World” ),直到收集结束

这样的设计,带来的好处就是:简单高效。对于内存资源受限制的环境,它是所有收集器中额外内存消耗最小的收集器。适合单核处理器或处理器核心数较少的环境,每次收集几十MB甚至一两百MB的新生代内存,垃圾收集的停顿时间完全可以控制在十几毫秒或几十毫秒,最多一百多毫秒

2、Serial Old 收集器(老年代)

  • 标记-整理算法
  • 单线程收集器

Serial Old收集器同样是一个单线程收集器,采用**“标记-整理”算法**负责老年代的垃圾收集,主要用于客户端模式下的HotSpot虚拟机使用

如果在服务器端使用,它主要有两种用途:

  1. JDK5及以前版本,与Parallel Scavenge收集器搭配使用;
  2. 作为CMS收集器发生失败时的后备预案;

垃圾收集器_第1张图片

3、ParNew 收集器(新生代)

  • 标记-复制算法
  • 多线程垃圾收集器
  • 可以与 Serial OldCMS 垃圾收集器一起搭配工作

ParNew 收集器是一个多线程的垃圾收集器。它是运行在 Server模式下的虚拟机的首要选择,可以与 Serial OldCMS 垃圾收集器一起搭配工作,采用**“标记-复制”算法**

垃圾收集器_第2张图片

4、Parallel Scavenge 收集器(新生代)

  • 标记-复制算法
  • 多线程收集器
  • 目标则是达到一个可控制的吞吐量
  • 停顿时间越短,就越适合需要与用户交互或需要保证服务响应质量的程序

Parallel Scavenge 收集器是也是一款新生代收集器,使用**“标记-复制”算法实现的多线程收集器**

Parallel Scavenge 收集器预其它收集器的目标不同,CMS等其它收集器目标是尽可能缩短垃圾收集时用户线程的停顿时间。但是Parallel Scavenge 收集器的目标则是达到一个可控制的吞吐量所谓吞吐量就是处理器用于运行用户代码的时间与处理器总消耗时间的比值

在这里插入图片描述

如果虚拟机完成某个任务,用户代码加上垃圾收集总共耗费了 100 分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。停顿时间越短,就越适合需要与用户交互或需要保证服务响应质量的程序,良好的响应速度能提升用户体验;而高吞吐量则可以最高效率地利用处理器资源,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的分析任务

5、Parallel Old 收集器(老年代)

  • 标记-整理算法
  • 多线程收集器
  • 适用注重吞吐量或者处理器资源较为稀缺的应用场景

Parallel Old 收集器是一个多线程的垃圾收集器,使用**“标记-整理”算法**,是Parallel Scavenge收集器的老年代版本。

在注重吞吐量或者处理器资源较为稀缺的应用场景,都可以优先考虑 Parallel Scavenge 收集器 + Parallel Old 收集器这个收集器组合

这个收集器是直到JDK6时才开始提供的,在此之前,新生代的Parallel Scavenge收集器一直处于相当尴尬的状态,原因是如果新生代选择了Parallel Scavenge 收集器,老年代除了Serial Old收集器以外别无选择,其他表现良好的老年代收集器,如CMS无法与它配合工作。由于老年代Serial Old 收集器在服务端应用性能上的“拖累”,使用Parallel Scavenge收集器也未必能在整体上获得吞吐量最大化的效果。同样,由于单线程的老年代收集中无法充分利用服务器多处理器的并行处理能力,在老年代内存空间很大而且硬件规格比较高级的运行环境中,这种组合的总吞吐量甚至不一定比ParNewCMS的组合来得优秀

垃圾收集器_第3张图片

6、CMS 收集器(老年代)

  • 真正意义上的并发收集器
  • 以获取最短回收停顿时间为目标
  • 垃圾收集线程与用户线程(基本上)同时工作

CMSConcurrent Mark Sweep·)收集器是一种以获取最短回收停顿时间为目标的收集器,**基于“标记-复制”算法实现,是 HotSpot 虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作

目前很大一部分的Java应用集中在互联网站点或者基于浏览器的B/S膝盖痛的服务器务端上,这类应用通常都会较为关注服务的响应速度,希望系统停顿时间尽可能短,以给用户带来自好的交互体验。所以,CMS收集器非常符合这类应用的收集场景

(1)工作流程

  1. 初始标记(CMS initial mark):标记一下GC Roots 能直接关联到的对象,速度很快;
  2. 并发标记(CMS concurrent mark):从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长,但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行;
  3. 重新标记(CMS remark):重新标记阶段,是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间长,远远比并发标记阶段时间短
  4. 并发清除(CMS concurrent sweep):清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的

垃圾收集器_第4张图片

(2)优点和缺点

优点

并发收集、低停顿

缺点

  • 影响用户线程的执行效率:并发标记和并发清除时,是和用户线程一起运行的,收集过程中肯定占用了用户程序的CPU资源。CMS默认启动的回收线程数是(CPU数量+3)/4,当CPU数量在4个以上时,垃圾回收线程占用不少于25%CPU资源,势必影响用户线程的执行效率。
  • 无法处理浮动垃圾:在并发清除阶段,用户线程并没有停止,所以还会继续产生新的垃圾,只能等待下一次收集时才能进行回收,这部分垃圾被称为“浮动垃圾”。
  • 产生大量空间碎片:因为CMS收集器是基于“标记-清除”算法实现的,所以在进行大量的垃圾回收时,会产生很多不连续的内存空间。这是使用“标记-清除”算法都会有的缺点

由于垃圾收集阶段用户线程还需要持续运行,所以需要预留足够的内存空间提供给用户线程使用,因此CMS收集器不能像其它收集器那样等到老年代几乎完全被填满了再进行收集。

  • JDK6的默认设置中,CMS收集器的启动阈值为92%,代表老年代使用了92%的空间后,就会启动CMS收集器
  • 如果CMS运行期间,无法满足程序分配新对象的需要,就会出现一次“并发失败”,这时候虚拟机将临时启动 Serial Old 收集器进行老年代的垃圾收集

7、G1 收集器(老年代)

(1)什么是 G1 垃圾收集器

  • 是面向服务器的垃圾收集器
  • 主要针对配备多颗处理器、大容量内存的机器
  • G1采用局部性收集的设计思路和基于Region的内存布局形式

(2)G1 垃圾收集器的结构

  • G1 采用局部性收集的思想,对于堆空间的划分,采用Region为单位的内存划分方式
  • G1 垃圾回收器把堆划分成2048大小相同的独立区域(Region)
  • 每个 Region 都会代表某一种角色
    • E: 代表Eden
    • S:代表 Survivor
    • O:代表的是 Old
    • H:代表的是 Humongous(G1用来分配大对象的区域,对于 Humongous 也分配不下的超大对象,会分配在连续的 NHumongous中**)**
    • 灰色区域:代表的是空闲的 region

G1可以面向堆内存任何部分来组成回收集来进行回收,衡量标准不再是它属于哪个分代,而是哪块内存存放的垃圾最多,回收收益最大,这就是G1收集器的 Mixed GC模式,即混合GC模式

垃圾收集器_第5张图片

(3)工作流程

  1. 初始标记Initial Marking

    这个阶段仅仅只是标记GC Roots能直接关联到的对象,这阶段需要停顿线程,但是耗时很短

  2. 并发标记Concurrent Marking

    从GC Roots开始对堆的对象进行可达性分析,递归扫描整个堆里的对象图,找出存活的对象,这阶段耗时较长,但是可以与用户程序并发执行

  3. 最终标记Final Marking

    对用户线程做另一个短暂的暂停,用于处理并发阶段结束后遗留记录

  4. 筛选回收Live Data Counting and Evacuation

    • 负责更新 Region 的统计数据,对各 Region 的回收价值和成本进行排序根据用户所期望的停顿时间来制定回收计划
    • 可以自由选择多个Region来构成回收集
    • 然后把回收的那一部分Region中的存活对象== >复制 ==>到空的Region中
    • 最后对那些Region进行清空

垃圾收集器_第6张图片

(4)G1 垃圾收集器的特点

  • 并行与并发

    G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPUCPU 或者 CPU 核心)来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 java 程序继续执行

  • 分代收集

    虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但是还是保留了分代的概念。但它能够采用不同方式去处理新创建的对象和已存活一段时间、熬过多次GC的旧对象来获取更好的收集效果

  • 空间整合

    • G1整体来看是基于**“标记-整理”**算法实现的收集器
    • 局部(两个Region之间)上来看是基于**“标记-复制”**算法实现的
    • 这意味着G1运行期间不会产生内存空间碎片,收集后能提供规整的可用内存。此特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC
  • 用户指定期望停顿

    • 允许用户指定期望的停顿时间
    • 设置不同的期望停顿时间,可以让G1在不同的场景下取得吞吐量和延迟之间的最佳平衡
    • G1的默认停顿目标为200毫秒,一般来说,设置为一百毫秒至两百毫秒这个区间都很正常
    • 如果期望停顿时间设置过短,会导致由于停顿目标时间太短,导致每次筛选出来的回收集只占堆内存很小的一部分,收集器的收集速度会跟不上分配速度,导致垃圾慢慢堆积

(5)G1 与 CMS 的区别

  1. 算法不同
    • CMS采用“标记-清除”容易产生内存碎片,执行若干次GC后进行1次碎片整理
    • G1从整体来看是基于“标记-整理”算法实现的收集器,从局部(两个Region之间)上来看是基于“标记-复制”算法实现
  2. 场景不同
    • 小内存应用上CMS的表现大概率优于G1
    • 大内存应用中,G1则能发挥优势
    • 大小内存的参考值分水岭大概在6GB-8GB

你可能感兴趣的:(java,jvm,开发语言)