Hotspot垃圾收集器一览

news2024/11/15 23:19:42

上篇文章我们介绍了如何判断对象是否为垃圾,有垃圾就要清理,清理就需要 垃圾收集器。

垃圾收集器(Garbage Collector)是垃圾收集GC的实现,根据是否分代收集可将垃圾收集器分为两种类型:分代收集和不分代收集。

垃圾收集器概览

分代收集

Serial垃圾收集器

Serial垃圾收集器是最简单的垃圾回收器的实现,同时它也是最古老的垃圾回收器,在jdk 1.3之前是HotSpot虚拟机新生代收集器的唯一选择。

Serial翻译成中文的意思是“串行的”,顾名思义Serial垃圾收集器就是一个单线程的垃圾回收器,它的这个串行指的是当它要进行垃圾回收时,其他所有的工作线程必须都要暂停,直到它回收结束,也就是我们常说的STW(Stop The World)。这很影响用户体验,如果每运行1个小时,暂停5分钟,用户就要等5分钟,别说5分钟了,哪怕是半分钟不响应,也会让人觉得这个网站真的很垃圾。在多线程应用程序中它不是一个好的选择,比如在服务器端使用,但是对于运行在客户端模式下的虚拟机来说是一个很好的选择,它也是HotSpot虚拟机运行在客户端模式下的默认新生代收集器。Serial垃圾收集器只适合几十兆到一两百兆的堆空间进行垃圾回收,在这种小内存中,它可以控制停顿时间在100ms以内,是可以被用户接受的。

Serial Old收集器用于老年代的回收,一般搭配着Serial收集器使用。Serial Old收集器的主要意义也是供客户端模式下的HotSpot虚拟机使用。如果在服务端模式下,它也可能有两种用途:一种是在JDK 5以及之前的版本中与Parallel Scavenge收集器搭配使用,另外一种就是作为CMS收集器发生失败时的后备预案。它和Serial收集器设计思想是一样的,只是回收的区域不同而已。

Serial/Serial Old收集器运行示意图

特点

  • 古老
  • 简单高效(和其他单线程垃圾回收器比较)
  • 单线程串行
  • 适合在客户端模式下和单CPU环境中使用

ParNew垃圾收集器

ParNewParallel New的缩写,从名字可以看出,它是并行并且是收集新生代的垃圾回收器。ParNew垃圾收集器是Serial垃圾收集器的多线程并行版本,除了并行收集以外,其他的实现基本和Serial垃圾收集器无异。

在JDK 7以前ParNew垃圾收集器是新生代垃圾回收的首选,它主要是配合CMS垃圾收集器使用。不过JDK 9开始将ParNew垃圾收集器合并到了CMS垃圾收集器中。

多线程收集器运行示意图

Parallel 垃圾收集器

Parallel垃圾收集器是JDK 8默认的垃圾收集器,它也是一个并行多线程的垃圾收集器,跟CMS垃圾收集器类似,只不过CMS垃圾收集器侧重点是减少垃圾收集时用户线程停顿的时间,而Parallel垃圾收集器的侧重点是控制吞吐量以达到高效率地利用 CPU时间,尽快完成应用程序的运算任务。所以Parallel垃圾收集器有时也称为吞吐量优先的收集器(Throughput Collector)。吞吐量是根据进行垃圾收集所花费的时间与在垃圾收集之外所花费的时间(称为应用程序时间)进行计算的。

吞吐量=应用程序时间/(应用程序时间+垃圾收集时间)

Parallel垃圾收集器分为Parallel Scavenge和Parallel Old垃圾收集器。Parallel Scavenge垃圾收集器负责新生代的垃圾收集,Parallel Old垃圾收集器负责老年代的垃圾收集。

可以通过以下参数控制Parallel 垃圾收集器的行为:

  • -XX:MaxGCPauseMillis=<t>:控制最大GC停顿时间,单位毫秒,默认情况下没有值。当设置停顿时间时,JVM会调整堆大小和其他跟垃圾回收相关的参数尽可能的小于设置的这个停顿时间。不过不要想着把MaxGCPauseMillis设置的越小越好,MaxGCPauseMillis设置小了,频率就变快了。比如,堆内存是500M,垃圾收集时间是10s,停顿时间是100ms,如果把MaxGCPauseMillis设置为70ms,为了达到70ms,堆内存就减小变成了300M,垃圾收集时间变成了5s,单次的停顿时间是变短了,整体的效率变低了,之前每隔10s停顿100ms,现在每隔10s停顿140ms,牺牲了吞吐量。而且MaxGCPauseMillis设置了之后不一定就能达到预期,并且如果对垃圾收集器运作原理不了解的话,设不准很容易出现问题。

  • -XX:GCTimeRatio=<N>:设置吞吐量大小。GCTimeRati就是设置垃圾收集时间与应用程序时间之比的,公式为1 / (1 + <N>)。比如:-XX:GCTimeRatio=19,这意味着垃圾回收时间占总时间的1 / (1 + 19)= 1/20,也就是5% ,GCTimeRatio默认值为99,即允许最大的垃圾回收时间为1%

  • -Xmx<N>:设置堆内存大小。收集器的隐式目标是在满足其他参数的情况下最小化堆的大小。

垃圾收集器会先满足参数-XX:MaxGCPauseMillis,然后再满足参数-XX:GCTimeRatio,在这两个参数都没满足的情况下参数才会被考虑-Xmx<N>

-XX:GCTimeRatio=<N>-XX:GCTimeRatio=<N>参数尤其不好控制,所以在Parallel 垃圾收集器中提供了另一个参数-XX:+UseAdaptiveSizePolicy,它是默认开启的,开启之后虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量。

CMS垃圾收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,它负责老年代的垃圾回收,新生代只能选择 ParNew或者Seria收集器中的一个。CMS收集器在JDK 5发布,在JDk 9中被标记过时,在JDK 14中已经被删除,不过这并不影响它是一款具有划时代意义的垃圾收集器,它是HotSpot虚拟机中第一款真正意义上支持并发的垃圾收集器,它首次实现了让垃圾收集线程与用户线程(基本上)同时工作。CMS 收集器也被称为低延迟垃圾收集器。

从名字(包含“Mark Sweep”)上就可以看出CMS收集器是基于标记-清除算法实现的,也是唯一一款基于标记-清除算法实现的老年代收集器,它的运作过程相对于前面几种收集器来说要更复杂一些,整个过程分为四个步骤,包括:

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

其中初始标记、重新标记这两个步骤仍然需要“Stop The World”。由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从总体上来说,CMS 收集器的内存回收过程是与用户线程一起并发执行的。

CMS垃圾收集器运行示意图

CMS垃圾收集器有以下缺陷:

  1. CPU 敏感: CMS对处理器资源敏感,毕竟采用了并发的收集、当处理核心数不足4个时,CMS对用户的影响较大。
  2. 浮动垃圾:由于CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就称为“浮动垃圾” 。
    由于浮动垃圾的存在,因此需要预留出一部分内存,意味着CMS收集不能像其它收集器那样等待老年代快满的时候再回收。如果预留的内存不够存放浮动垃圾,就会出现Concurrent Mode Failure,这时虚拟机将临时启用Serial Old收集器来替代CMS收集器,这样停顿的时间就更长了。
  3. 会产生空间碎片:由于CMS是一款基于“标记-清除”算法实现的收集器,所以肯定会产生不连续的空间碎片。

不分代收集

Garbage First收集器

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

G1也遵循分代收集理论,但是它不像上面分代收集垃圾收集器那样物理分代,而是采用Region的概念逻辑分代,物理分区:每个Region可以扮演新生代的Eden空间、Survivor空间,或者老年代空间收集器能够对扮演不同角色的Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、 熬过多次收集的旧对象都能获取很好的收集效果。

Region示意图

G1收集器去跟踪各个Region里面的垃圾堆积的“价值”大小,价值即回收所获得的空间大小以及回收所需时间的经验值, 然后在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值收益最大的那些Region,这也就是“Garbage First”名字的由来。

G1运行过程包括4个步骤:初始标记、并发标记、最终标记和筛选回收,除了并发标记外,其余阶段也是要完全暂停用户线程的。

G1运行流程示意图

G1垃圾收集器是JDK 9开始默认的垃圾收集器,它有如下特点:

  • 并行与并发:G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU来缩短STW的时间。
  • 不会产生内存碎片:G1是基于“标记—整理”算法实现的收集器
  • 可以指定停顿时间-XX:MaxGCPauseMillis参数指定目标的最大停顿时间,G1尝试调整新生代和老年代的比例,堆大小,晋升策略来达到这个目标时间。
  • 局部收集:使用Region划分内存空间,保证了G1收集器在有限的时间内获取尽可能高的收集效率。

ZGC

ZGC(Z Garbage Collector)是一款在JDK 11中新加入的具有实验性质的可扩展的低延迟垃圾收集器 ,在JDK 15中已经可以正式在生产中使用了。ZGC的目标是在任意堆内存大小下都可以把垃圾收集的停顿时间限制在10毫秒以内的低延迟。

ZGC也采用基于Region的堆内存布局,ZGC的Region具有动态性——动态创建和销毁,以及动态的区域容量大小。在x64硬件平台下,ZGC的Region可以具有大、中、小三类容量:

  • 小型Region(Small Region):容量固定为2MB,用于放置小于256KB的小对象。
  • 中型Region(Medium Region):容量固定为32MB,用于放置大于等于256KB但小于4MB的对象。
  • 大型Region(Large Region):容量不固定,可以动态变化,但必须为2MB的整数倍,用于放置4MB或以上的大对象。每个大型Region中只会存放一个大对象,这也预示着虽然名字叫作“大型Region”,但它的实际容量完全有可能小于中型Region,最小容量可低至4MB。

ZGC堆内存布局

ZGC有如下特点:

  • 低延迟、停顿时间短(10ms以内)
  • 支持8M~16T内存的GC
  • 多线程并发GC
  • 采用染色指针技术实现对象引用
  • 不再使用分代收集
  • 支持不同容量的Region分区

垃圾收集器搭配及启动

新生代老年代JVM参数
SerialSerialOld-XX:+UseSerialGC
Parallel ScavengeSerialOld-XX:+UseParallelGC
Parallel ScavengeParallelOld-XX:+UseParallelOldGC
ParNewSerialOld-XX:+UseParNewGC
ParNewCMS + SerailOld-XX:+UseConcMarkSweepGC
G1G1-XX:+UseG1GC
ZGCZGC-XX:+UseZGC

总结

本文主要简单介绍了常见的垃圾收集器。其中ZGC了解学习一下就可以了,ZGC虽然在JDK 15中可以使用,但是具体表现如何不好说,也没有被官方指定为默认垃圾收集器,对比之前的垃圾收集器可以发现,能留下来的都是曾经被官方指定为默认垃圾收集器,不被指定的在后续版本中就被移除了,比如CMS垃圾收集器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/71150.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多线程编程带来的不安全问题

目录 1.观察线程不安全问题 2.出现线程不安全问题原因 2.1 根本原因 2.2 代码结构 2.3 原子性 2.4 内存可见性问题 2.5指令重排序 3.通过原子性解决线程安全问题 4.synchronized的使用方法 4.1 修饰方法 4.2 修饰代码块 1.观察线程不安全问题 如果多线程环境下代码…

餐饮企业提升用户价值,从基于点单链路的精细化运营开始

近几年&#xff0c;餐饮业的经营增长面临着巨大挑战&#xff0c;在这种情况下&#xff0c;餐饮企业如何提升用户价值&#xff0c;提高多风险下持续增长的动力呢&#xff1f;神策数据杨丽月聚焦用户运营&#xff0c;围绕“一条链路&#xff0c;四个指标”&#xff0c;跟大家分享…

C# 标签式导航

一 标签式导航 使用TabControl控件&#xff0c;将多个页面结合起来&#xff0c;每个标签关联一个页面。 TabControl 选项卡容器&#xff1b; TabPage选项页&#xff1b; 可以在设计器里添加页面&#xff0c;也可以代码方式添加。 操作演示&#xff1a; ① 选中TabControl; ②…

框架skywalking部署笔记

一旦你的程序docker化之后,你会遇到各种问题,比如原来采用的本地记日志的方式就不再方便了,虽然你可以挂载到宿主机,但你使用 --scale 的话,会导致 记录日志异常,所以最好的方式还是要做日志中心化,另一个问题,原来一个请求在一个进程中的痉挛失败,你可以在日志中巡查…

linux的内存映射(二)

我们先来看幅图&#xff1a; Linux内存管理的最底层是buddy内存管理方案&#xff0c;即伙伴算法&#xff0c;管理伙伴算法我们不做详诉&#xff0c;有兴趣的可以自行学习&#xff0c;我们这里只要知道buddy内存池中只能分配2^n个page的内存&#xff0c;比如1,2,4,8……个pages…

前端面试指南之JS面试题总结

1. JS 有哪些数据类型&#xff1f; 根据 JavaScript 中的变量类型传递方式&#xff0c;分为基本数据类型和引用数据类型两大类七种。 基本数据类型包括Undefined、Null、Boolean、Number、String、Symbol (ES6新增)六种。 引用数据类型只有Object一种&#xff0c;主要包括对象…

pve扩展lvm空间,重做物理卷

pve扩展lvm空间&#xff0c;重做物理卷pve扩展lvm空间&#xff0c;重做物理卷必备知识扩展步骤1.查看当前机器状况2.查看盘符3.确定是否有可分配空间4.确定物理卷分配情况5.&#xff08;可略&#xff09;如果你的空闲的盘已经挂载了请用以下命令卸掉6.创建物理卷7.查看卷状态8.…

day7_redis学习

文章目录Geo查找附近商铺BitMap实现用户签到UV统计Geo查找附近商铺 Geo是GeoLocation的简称&#xff0c;代表地理坐标&#xff0c;在Redis 3.2中加入了对Geo的支持&#xff0c;允许存储地理坐标信息&#xff0c;常见的命令有: ①GEOADD key x y member [x2 y2 member]&#xf…

(一)SpringBoot项目初始化并引入基础文件【木字楠后台管理系统模板】

&#x1f3b6; 文章简介&#xff1a;SpringBoot项目初始化并引入基础文件【木字楠后台管理系统模板】 &#x1f4a1; 创作目的&#xff1a;为了带大家完整的体验木字楠后台管理系统模版的开发流程 ☀️ 今日天气&#xff1a;天气☁️很好。太阳晒在身上暖暖的 &#x1f4dd; 每…

IB数学怎么学,HL是什么难易程度,和SL的内容差的大吗?

做为刚大学毕业的M20 IBer&#xff0c;数学课以往一直没下过90%&#xff0c;全是7分&#xff0c;IA 校园内得分19/20。尽管final被IBO赏了个6&#xff08;大考撤销&#xff0c;ibo蒙蔽估分orz&#xff09;&#xff0c;但我还是汇总了一些自身的数学学习工作经验&#xff0c;期待…

一个变量命名神器:支持中文转变量名

变量命名的规范&#xff0c;对于我们编程&#xff0c;大家都知道是非常重要的&#xff0c;上次给大家推荐过一个命名辅助工具《程序员还在为变量取名苦恼&#xff0c;那是因为你不知道&#xff0c;这个变量命名神器》&#xff0c;但大家一致反馈存在2个问题&#xff1a; 1、网…

项目管理(如何进行项目采购管理)

项目采购管理包括从项目团队外部采购或获取所需产品、服务或成果的各个过程。项目采购管 理包括编制和管理协议所需的管理和控制过程,例如,合同、订购单、协议备忘录 (MOA),或服务 水平协议 (SLA)。被授权采购项目所需货物和(或)服务的人员可以是项目团队、管理层或组织采…

使用winhex对fat16文件系统分析

“FAT16”是“File Allocation Table,16-bit”的英文缩写,意思是“文件分配表,16位” 。FAT16文件系统是从微软的DOS 3.0系统开始使用的&#xff0c;它能够支持大于16MB小于2GB的分区&#xff0c;Windows 2000以上操作系统可以创建4GB的FAT16分区&#xff0c;但与传统的FAT16不…

【观察】深度剖析,为什么说帆软的文化决定了FineBI6.0的易用和好用

毫无疑问&#xff0c;今天国家对数字经济给予了前所未有的高度重视&#xff0c;《“十四五”数字经济发展规划》中&#xff0c;就明确将继续坚持推进数字产业化和产业数字化&#xff0c;赋能传统产业转型升级&#xff0c;为构建数字中国提供有力支撑&#xff0c;并提出到2025年…

FFmpeg之硬解码

导读 众所周知&#xff0c;软解码虽然兼容性一流&#xff0c;但是却非常依赖CPU&#xff0c;所以性能消耗笔记大&#xff1b;硬解码使用内置的DSP芯片进行解码&#xff0c;性能高&#xff0c;但是兼容性一般。 虽说硬解码兼容性不太好&#xff0c;但是在实际开发中出于对性能的…

智能化煤矿-设备管理系统、故障诊断、全生命周期管理

随着智能化煤矿的建设&#xff0c;煤矿设备、传感器数量在增加、煤矿设备的自动化、智能化程度也相对提高。保证设备稳定运行&#xff0c;减少故障时间是提高煤矿安全生产的一种重要途径。另外随着信息技术的发展&#xff0c;像云计算、物联网、大数据等相关技术的运用&#xf…

vue2的 webpack-bundle-analyzer 打包体积 看优化包

1、 先安装 npm i webpack-bundle-analyzer -D 2、 vue.config 文件中 配置 /* webpack相关配置 *该对象将会被 webpack-merge 合并入最终的 webpack 配置 */ if (process.env.use_analyzer) { // 分析 config .plugin(webpack-bundle-analyzer) .use(require(webpa…

XuperSocial首个明星DApp上线,探索区块链分布式通信基础设施

12月7日&#xff0c;星际口袋上线星际社区&#xff0c;为广大藏友提供稳定、可信的交流场所。星际社区基于百度超级链团队重磅发布的去平台化社交解决方案XuperSocial搭建&#xff0c;XuperSocial是架设在百度超级链开放网络&#xff08;XuperOS&#xff09;上的DApp&#xff0…

Oracle PrimaveraUnifier 之数据要素(Data Element)

目录 一&#xff1a;什么是数据要素 二&#xff1a;常用的数据要素 一&#xff1a;什么是数据要素 数据要素是Oracle Primavera Unifier维护业务单据/表达的最小单元&#xff0c;也就是我们常说的字段&#xff0c;它将数据定义与字段标签相结合&#xff0c;成为我们用户在 P…

Runtime源码解析-类中bits

Runtime源码解析-类中bits class_rw_t ro_or_rw_ext_t 成员变量方法 初始化方法存取方法类型判断 公有方法 获取class_rw_ext_t获取/设置class_ro_t方法、属性、协议列表 class_rw_ext_tclass_ro_t总结 1. 为什么ro_or_rw_ext 会有两种类型&#xff0c;class_rw_ext_t或者cla…