JVM-垃圾收集器

来源:互联网 发布:js td赋值 编辑:程序博客网 时间:2024/06/05 21:08

常见的垃圾收集器

上一篇文章中介绍了JVM的GC常见算法,而JVM的垃圾收集器就是这些算法使用编程语言的具体实现,介绍算法的时候,我们默认算法的执行都是单线程的,但是涉及到具体的语言实现就不只是单线程了,具体分为一下三种模式:

  • 串行收集器:一条GC线程,运行的时候需要暂停用户程序(stop the world),包括一下实现:
    • serial:用于新生代,采用复制算法
    • serial old:用于年老代,采用标记/整理算法
  • 并行收集器:多条GC线程,且运行时也需要(stop the world),包括一下实现:
    • ParNew:用于新生代,采用复制算法
    • Parallel Scavenge:用于新生代,采用复制算法
    • Parallel old:用于年老代,采用标记/整理算法
  • 并发收集器:一条或多条GC线程,且它需要在部分阶段(stop the world),部分阶段与用户程序并发执行,包括一下实现:
    • concurrent mark sweep[CMS]:用于年老代,采用标记/清除算法
    • G1:用于新生代和年老代,采用标记整理算法和复制算法

同时根据新生代和老年代使用不同实现的组合
这里写图片描述
上图是作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用。虚拟机所处的区域,则表示它是属于新生代收集器还是老年代收集器。

下面来详细讲解这几种垃圾收集器的详细情况。


Serial收集器

  • 简介:最基本、最悠久的收集器,在JDK 1.3.1之前是虚拟机新生代收集的唯一选择。
  • 算法:复制算法
  • 作用区域:新生代
  • 执行方式:单线程、串行
  • 执行过程:当新生代内存不够用时,先暂停全部用户程序,然后开启一条GC线程使用复制算法对垃圾进行回收,这一过程中可能会有一些对象提升到年老代
  • 使用场景:Serial收集器是虚拟机运行在Client模式下的默认新生代收集器
  • 开启方式:-XX:+UseSerialGC(client模式默认值)

Serial Old收集器

  • 简介:同上
  • 算法:标记整理算法
  • 作用区域:老年代
  • 执行方式:单线程、串行
  • 执行过程:同上
  • 使用场景:Serial收集器是虚拟机运行在Client模式下的默认新生代收集器
  • 开启方式:-XX:+UseSerialGC(client模式默认值)

ParNew收集器

  • 简介:ParNew收集器其实就是Serial收集器的多线程版本
  • 算法:复制算法
  • 作用区域:新生代
  • 执行方式:多线程、并行
  • 执行过程:除了使用多条线程进行垃圾收集之外,其余行为包括Serial收集器可用的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完全一样,在实现上,这两种收集器也共用了相当多的代码。
  • 使用场景:ParNew收集器是许多运行在Server模式下的虚拟机中首选的新生代收集器。很重要的原因是:除了Serial收集器外,目前只有它能与CMS收集器配合工作。
  • 开启方式:-XX:+UseParNewGC

Parallel Scavenge收集器

  • 简介:与ParNew几乎一模一样,都是针对新生代设计,采用复制算法的并行搜集器。它与ParNew最大的不同就是可设置的参数不一样,它可以让我们更精确的控制GC停顿时间以及吞吐量。
  • 算法:复制算法
  • 作用区域:新生代
  • 执行方式:多线程、并行
  • 执行过程:除了使用多条线程进行垃圾收集之外,其余行为包括Serial收集器可用的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完全一样,在实现上,这两种收集器也共用了相当多的代码。
  • 使用场景:ParNew收集器是许多运行在Server模式下的虚拟机中首选的新生代收集器。很重要的原因是:除了Serial收集器外,目前只有它能与CMS收集器配合工作。
  • 使用参数
    • -XX:+UseParallelGC(开启)
    • -XX:ParallelGCThreads=4(指定线程数)
    • -XX:UseAdaptiveSizePolicy(内存区域自适应,开启后不需要手工指定新生代的大小、Eden与Survivor区的比例、晋升老年代对象年龄等细节参数了,这种调节方式称为GC自适应的调节策略GC Ergonomics)

Parallel Old收集器

  • 简介:ParNew的老年代版本,
  • 算法:标记/整理算法
  • 作用区域:老年代
  • 执行方式:多线程、并行
  • 使用场景:他是除了serial old以外唯一一个可以与parallel scavenge搭配工作的年老代搜集器,因此为了避免serial old影响parallel scavenge可控制吞吐量的名声,parallel old就作为了parallel scavenge真正意义上的搭档,它也是在开启parallel scavenge之后默认的年老代搜集器。
  • 使用参数:-XX:-UseParallelOldGC开启

CMS收集器

  • 简介:第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程同时工作,一种以获取最短回收停顿时间为目标的收集器,重视响应速度
  • 算法:标记清除算法
  • 作用区域:老年代
  • 执行方式:多线程、并行、并发
  • 执行过程

    • 初始标记:仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要Stop the World
    • 并发标记:就是进行GC Roots Tracing的过程
    • 重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录仍然需要“Stop The World”。
    • 并发清除:恢复应用程序,并发清除未标记的垃圾对象。

    它比原来的标记/清除算法复杂了点,主要表现在并发标记和并发清除这两个阶段,而这两个阶段也是整个GC阶段中耗时最长的阶段,不过由于这两个阶段皆是与应用程序并发执行的,因此CMS搜集器造成的停顿时间是非常短暂的。

  • 优点:并发收集、低停顿。
  • 缺点
    • 缺点会抢占CPU资源,降低吞吐量
    • 使用标记清除算法,意味着收集结束时会有大量空间碎片产生,将会给大对象分配带来很大麻烦,往往会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC。
    • 无法处理浮动垃圾:由于CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就称为“浮动垃圾”。
      也是由于在垃圾收集阶段用户线程还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分空间提供并发收集时的程序运作使用。要是CMS运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent Mode Failure”失败,这时虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了
  • 使用参数

G1 收集器

  • 简介:HotSpot开发团队开发的初衷是为了未来代替CMS的
  • 算法:标记/整理算法 + 复制算法
  • 作用区域:老年代
  • 执行方式:多线程、并行、并发
  • 特点:G1收集器时,Java堆的内存布局就与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region。这种使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限的时间内可以获取尽可能高的收集效率
  • 执行过程
    • 初始标记
    • 并发标记
    • 最终标记
    • 筛选回收
      -
      …..未完待续
0 0
原创粉丝点击