JVM 垃圾回收器 详解

本文详细介绍了JVM中的不同垃圾回收器,包括Serial、ParNew、ParallelScavenge、SerialOld、ParallelOld和CMS收集器,重点讲解了它们的工作原理、特点、应用场景以及并发和并行收集的区别。
摘要由CSDN通过智能技术生成

JVM 垃圾回收器



前言

Jvm的垃圾收集器(serial收集器、parnew收集器、parallel scavenge收集器、serial old 收集器、parallel old收集器、cms收集器、g1收集器)

  • 新生代收集器:Serial、ParNew、Parallel Scavenge
  • 老年代收集器:CMS、Serial Old、Parallel Old
  • 整堆收集器: G1

收集方式

  • 并行收集:指多条垃圾收集线程并行工作,但此时用户线程仍处于等待状态。
  • 并发收集:指用户线程与垃圾收集线程同时工作(不一定是并行的可能会交替执行)。用户程序在继续运行,而垃圾收集程序运行在另一个CPU上。

一:Serial 收集器

特点:
Serial== 串行,也就是说它以串行的方式执行,单线程、简单高效(限定单个CPU的环境来说),Serial(串行)收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。收集器进行垃圾回收时,必须暂停其他所有的工作线程,直到它结束 STW(Stop The World)。

运行示例图:
在这里插入图片描述

二:ParNew收集器

ParNew收集器其实就是Serial收集器的多线程版本。除了使用多线程外其余行为均和Serial收集器一模一样。

特点:
多线程、ParNew收集器默认开启的收集线程数与CPU的数量相同,在CPU非常多的环境中,可以使用
-XX:ParallelGCThreads参数来限制垃圾收集的线程数。和Serial收集器一样存在STW问题。

ParNew收集器是许多运行在Server模式下的虚拟机中首选的新生代收集器,因为它是除了Serial收集器外,唯一一个能与CMS收集器配合工作的

运行示例图:

在这里插入图片描述

三:Parallel Scavenge 收集器(吞吐量优先收集器)

特点:
属于新生代收集器 ,采用复制算法的收集器,并行的多线程收集器。该收集器的目标是达到一个可控制的吞吐量。

GC自适应调节策略:Parallel Scavenge收集器可设置**-XX:+UseAdptiveSizePolicy参数。当开关打开时不需要手动指定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRation)、晋升老年代的对象年龄(-XX:PretenureSizeThreshold)等,虚拟机会根据系统的运行状况收集性能监控信息,动态设置这些参数以提供最优的停顿时间和最高的吞吐量**,这种调节方式称为GC的自适应调节策略。

四:Serial Old 收集器

Parallel Old是Parallel Scavenge收集器的老年代。

特点:单线程收集器,采用标记-整理算法

在这里插入图片描述

五:Parallel Old 收集器

Parallel Old是Parallel Scavenge收集器的老年代版。

特点:多线程,采用标记-整理算法。

应用场景:注重高吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge+Parallel Old 收集器。

在这里插入图片描述

六:CMS收集器

一种以获取最短回收停顿时间为目标的收集器。

特点:基于标记-清除算法实现。并发收集、低停顿

应用场景:适用于注重服务的响应速度,希望系统停顿时间最短,给用户带来更好的体验等场景下。如web程序、b/s服务。

CMS收集器的GC周期主要由7个阶段组成,其中有两个阶段会发生STW,其他阶段都是并发执行的。

阶段一: Initial Mark(初始化标记)

主要工作是标记GC Roots可直达的存活对象。

主要标记过程:

  • 从GC Roots遍历可直达的老年代对象
  • 遍历被新生代存活对象所引用的老年代对象

特点:

  • 支持单线程或并行标记

  • 发生STW,暂停所有应用线程

阶段二: Concurrent Mark(并发标记)

在该阶段,GC线程和应用线程将并发执行。也就是说,在第一个阶段(Initial Mark)被暂停的应用线程将恢复运行。

并发标记阶段的主要工作是,通过遍历Initial Mark标记出来的存活对象,继续递归遍历老年代,并标记可直接或间接到达的所有老年代存活对象。

由于在并发标记阶段,应用线程和GC线程是并发执行的,因此可能产生新的对象或对象关系发生变化,例如:

  • 新生代的对象晋升到老年代
  • 直接在老年代分配对象
  • 老年代对象的引用关系发生变更

对于这些对象,后面需要重新标记以防止被遗漏(漏标)。为了提高重新标记的效率,本阶段会把这些发生变化的对象所在的Card标识为Dirty,这样后续就只需要扫描这些Dirty Card的对象,从而避免扫描整个老年代。

阶段三: Concurrent Preclean(并发预清理)

该阶段将会重新扫描前一个阶段标记的Dirty对象,并标记被Dirty对象直接或间接引用的对象,然后清除Card标识。

  • 标记被Dirty对象直接或间接引用的对象
  • 清除Dirty对象的Card标识

阶段四: Concurrent Abortable Preclean(可中止的并发预清理)

本阶段尽可能承担更多的并发预处理工作,从而减轻在Final Remark阶段的stop-the-world。

在该阶段,主要循环的做两件事:

  • 处理 From 和 To 区的对象,标记可达的老年代对象
  • 扫描处理Dirty Card中的对象

阶段五: Final Remark(重新标记)

预清理阶段是并发执行的,并不一定是所有存活对象都会被标记,因为在并发标记的过程中对象及其引用关系还在不断变化中。

因此,需要有一个STW的阶段来完成最后的标记工作,这就是重新标记阶段(CMS标记阶段的最后一个阶段)。主要目的是重新扫描之前并发处理阶段的所有残留更新对象。

主要工作:

  • 遍历新生代对象,重新标记(新生代会被分块,多线程扫描)
  • 根据GC Roots,重新标记
  • 遍历老年代的Dirty Card,重新标记。这里的Dirty Card,大部分已经在Preclean(并发预清理)阶段被处理过了

阶段六: Concurrent Sweep(并发清理)

并发清理阶段,主要工作是清理所有的死亡对象,回收被占用的空间。

阶段七: Concurrent Reset(并发重置)

并发重置阶段,将清理并恢复在CMS GC过程中的各种状态,重新初始化CMS相关数据结构,为下一个垃圾收集周期做好准备

  • 75
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值