JVM笔记3-经典的垃圾收集器

image.png上图展示了7种,适用于不同分代中的收集器。如果两者之间由连线,说明可以搭配使用。
PS:在JDK8中将Serial+CMS和ParNew+Serial Old的组合声明为废弃,并且在JDK9中完全取消了这两种组合的支持。

1、Serial收集器

Serial收集器是JVM中最早、最基础的一个收集器。这个收集器是一个单线程工作的收集器。采用标记复制算法。它的“单线程”并不仅仅说明它是使用一个处理器或单个收集线程去完全收集工作,更重要的是强调,在它进行垃圾收集工作时,需要将其他所有工作线程(包括用户的工作线程)全部停掉,直到它收集结束(Stop The World)。
下图所示,是Serial/Serial Old收集器的运行过程:
image.png

由于Serial收集器的简单高效(与其他收集器的单线程相比)、额外内存消耗最小的特点,Serial收集器更适合用于在单核处理器或者处理器核心较小的的环境上。

2、ParNew收集器

ParNew实际上是Serial收集器的多线程的并行版本。采用的也是标记复制算法。除了使用多线程进行垃圾收集之外,其他的行为包括Serial收集器可用的参数(例如:-XX:SurvivorRatio、-XX:PretenureSizeThreshold)、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器一致。

ParNew+Serial Old收集器的运行过程:
image.png
但是由于,在JDK9版本中不在支持ParNew+Serial Old的组合,因此只有CMS才能配合ParNew使用。

在JDK5中,HotSpot发布一个跨时代的垃圾收集器,CMS收集器。这款收集器是HotSpot虚拟机中第一个支持并发的垃圾收集器,它首次实现了让垃圾收集线程和用户线程(几乎)同时工作。
但是CMS作为,老年代的垃圾收集器,CMS却不能配合Parallel Scavenge收集器一起使用。所以在选择使用CMS收集器收集老年代时,只能选择使用Serial(JDK9之后废弃)和ParNew收集器其中的一个来收集新生代。ParNew是激活CMS后(使用-XX:+UseConcMarkSweepGC)的默认新生代收集器。也可以使用-XX:+/-UseParNewGC选项来强制指定或者禁用它。但是在JDK9中,官方希望新发布的G1收集器能取代ParNew+CMS的组合来作为服务端的垃圾收集方案。并且直接取消了Serial+CMS和ParNew+Serial Old的组合支持,甚至还取消了-XX:+UseParNewGC参数。这也就意味着,ParNew和CMS从此只能搭配使用。

PS:CMS不能配合Parallel Scavenge使用的原因:
1、CMS面向低延迟、Parallel Scavenge面向高吞吐量。目标不一致。
2、Parallel Scavenge和G1收集器都没在使用HotSpot中原本设计的垃圾收集器的分带框架,而选择另外独立实现。

3、Parallel Scavenge收集器

Parallel Scavenge收集器是新生代的垃圾收集器,采用的也是标记复制算法。也是能够并行收集的多线程收集器。
Parallel Scavenge收集器关注点和其他的垃圾收集器不同,CMS等垃圾收集器关注点是尽可能的缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标是达到一个可控制的吞度量。所谓的吞吐量就是处理器用户执行用户代码的时间与处理器总耗时的比值。
如果虚拟机完成某个任务,总耗时是100min,执行用户的代码时间是99min那么吞吐量就是99%。停顿时间越短,越适合需要与用户交互或者需要保证服务响应质量的程序。
Parallel Scavenge提供两个参数用户精准控制吞吐量,分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMills参数以及直接设置吞吐量大小的-XX:GCTimeRatio参数。
1、-XX:MaxGCPauseMills:允许用户设置一个大于0的毫秒数。收集器将尽量保证内存回收的时间不超过用户设定的值。但是这个值不是越短越好,垃圾收集的停顿时间是以牺牲新生代大小和吞吐量换取的。
2、-XX:GCTimeRatio:这个值是一个在0到100之间的整数。也就是垃圾收集时间占总时间的比率。相当于吞吐量的倒数。比如:将此值设置为19,那么允许最大的垃圾收集时间就占总时间的5%(即 1 / ( 1 + 19 ) 1/(1+19) 1/(1+19))。

由于和吞吐量关系密切,Parallel Scavenge收集器也经常被称为“吞吐量优先收集器”。除了上述两个参数,Parallel Scavenge还有个参数-XX:+UseAdaptiveSizePolicy。这是一个开关参数,当这个参数被激活后,就不要人工指定新生代(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象大小(-XX:PretenureSizeThreshold)等细节参数,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大吞吐量。这种调节方式称为垃圾收集器的自适应的调节策略。

4、Serial Old收集器

Serial Old收集器是老年代版本,它同样是一个单线程的收集器。采用标记-整理算法。这个收集器和Serial收集器类似都是主要用在客户端模式下的HotSpot虚拟机中。
用在服务端模式下,可能存在两种场景:
1、在JDK5及之前的版本,与Parallel Scavenge收集器搭配使用(因为Parallel Old在JDK6才发布)。
2、作为CMS收集器发生失败时的备选方案。在并发收集发生Concurrent Mode Failure时使用。
Serial+Serial Old工作流程如图所示:
image.png

5、Parallel Old收集器

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,支持多线程并发收集。也是基于标记-整理算法。
这个收集器是JDK6才提供的。在之前的版本中,如果想使用Parallel Scavenge收集器,老年代只有Serial Old收集器可供选择。其他表现良好的收集器,如CMS无法搭配他使用(无法搭配使用的原因在本章ParNew收集器中介绍)。
由于Serial Old收集器在服务端应用性能上的“拖累”,使用Parallel Scavenge收集器也未必能在整体上获得吞吐量最大化的效果。
直到Parallel Old的出现,“吞吐量优先”收集器才有了名副其实的搭配组合。在注重吞吐量或者处理器资源比较稀缺的场合,都可以优先考虑Parallel Scavenge+Parallel Old收集器这个组合。
Parallel Scavenge+Parallel Old的工作流程如下:
image.png

6、CMS收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。常常用来注重服务的响应速度这类应用上的。与前面介绍的5中收集器都不同,CMS采用的是标记-清楚算法。

CMS的整个运行过程,相比较于前面的几种收集器,更加的负责,整个过程可以分为以下4个步骤:
1、初始标记(CMS initial mark)
2、并发标记(CMS concurrent mark)
3、重新标记(CMS remark)
4、并发清楚(CMS concurrent sweep)

其中,初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记只是标记一下GC Roots能直接到达的对象,速度很快。并发标记阶段就是从GC Roots的直接关联对象遍历整个对象图的过程,这个过程耗时比较长,但是不需要停顿用户线程。重新标记阶段,则是为了修正在并发标记阶段由于程序运行而产生变动的那一部分标记记录。这个阶段的停顿时间通常会比初始阶段稍长一些,但是也远比并发标记阶段短。最后是并发清除阶段,清理删除掉标记阶段判断死亡的对象,由于不需要移动存活对象,所以这个阶段可以和用户线程一起执行。
在整个CMS的工作流程中,并发标记和并发清除是耗时最长的,在其他时候,垃圾收集器都是可以与用户线程一起工作的。所以从总体上来看,CMS收集器的内存回收过程是与用户线程一起并发执行的。
CMS的执行流程入下图所示:
image.png
由于CMS在并发清理阶段,用户线程是可以正常运行的,程序正常运行期间会产生新的垃圾对象。且这些新的垃圾对象时在标记之后产生的,因此CMS无法在当次收集时清理掉他们。只能留待下一次垃圾清理时清理。这一部分垃圾被称为“浮动垃圾”。
同样的,由于用户线程是正常运行的,那就需要预留够足够的空间,以便用户线程使用。也就是说CMS不能在老年代几乎被填满的时候,进行垃圾收集,必须留一部分空间供并发收集时的程序使用。在JDK5的默认设置中,CMS收集器当老年代使用了68%的空间后就被激活。这是一个保留的设置,当老年代增长不是太快时,可以适当调高参数-XX:CMSInitiatingOccupancyFraction的值来提高CMS的触发百分比,降低内存的回收频率,获取更好的性能。
到了JDK6,默认的百分比已经提高到了92%。但这又面临另一种风险:要是CMS运行期间预留的内存空间无法满足程序分配对象的需要,就会出现一次“并发失败(Concurrent Mode Failure)”,这时候虚拟机就会启动后背预案:冻结用户线程,临时采用Serial Old收集器来重新进行老年代的垃圾收集,但这样停顿时间会很长。因此参数-XX:CMSInitiatingOccupancyFraction设置的太高将会容易导致大量的并发失败产生,性能反而会降低。
CMS采用的是并发清理算法,这个算法有个最大的缺点:会产生大量的空间碎片。空间碎片过多时,将会给大对象分配带来很大麻烦,往往会出现,命名老年代有很多剩余空间,但是无法找到足够大的连续空间来分配当前对象,而不得不触发一次FULL GC。

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

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

相关文章

C++:重写和重载

重写(Override)和重载(Overload)是面向对象编程中常用的两个概念,它们虽然都涉及到方法的定义,但是在实现和使用上有着不同的特点。 重写(Override): 重写是指在子类中重…

【备战软考(嵌入式系统设计师)】07 - 计算机网络模型

七层模型 计算机网络中比较常见的有OSI七层模型和TCP/IP四层模型。 软考中主要考七层模型,但是实际中使用的还是四层模型比较多,我们主要是为了考试,那就主要讲讲七层模型。不过实际上四层模型就是将七层模型压缩了三层,本质上是…

深度学习中的注意力机制一(Pytorch 15)

一 简介 灵长类动物的视觉系统接受了大量的感官输入,这些感官输入远远超过了大脑能够完全处理的程度。然而, 并非所有刺激的影响都是相等的。意识的聚集和专注使灵长类动物能够在复杂的视觉环境中将注意力引向感 兴趣的物体,例如猎物和天敌。…

电子电器架构 --- 主机厂产线的两种刷写方法

电子电器架构 — 主机厂产线的两种刷写方法 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证…

DS:顺序表、单链表的相关OJ题训练(1)

欢迎各位来到 Harper.Lee 的学习小世界! 博主主页传送门:Harper.Lee的博客主页 想要一起进步的uu可以来后台找我交流哦! 在DS:单链表的实现 和 DS:顺序表的实现这两篇文章中,我详细介绍了顺序表和单链表的…

IDEA基于Maven构建项目

IDEA基于Maven构建项目 一、Maven简介 Apache Maven 是一个软件项目管理和理解工具。基于项目对象模型的概念(POM),Maven 可以从中心信息中管理项目的构建、报告和文档。 Apache Maven 可以用于构建和管理任何基于 Java 的项目。 下载地址…

【可实战】被测需求理解(需求文档是啥样的、从哪些角度进行需求评审、需求分析需要分析出哪些内容、如何提高需求分析能力)

产品人员会产出一个需求文档,然后组织一个需求的宣讲。测试人员的任务就是在需求宣讲当中,分析需求有没有存在一些问题,然后在需求宣讲结束之后通过分析需求文档,分析里面的测试点并预估一个排期。 一、需求文档是什么样的&#x…

视频教程下载:为 GPTs 商店构建 10 个 GPTs获得被动收入

欢迎来到 AI 驱动的内容创作新时代 - GPT 商店。这门综合课程是您成为定制和利用 GPT 模型解决多样化应用的专家的路线图。无论你是错过了应用商店革命的初始浪潮还是乘着它取得了成功,这都是你站在下一个重大数字飞跃前沿的机会。 课程模块: - 介绍 Ch…

Unity 性能优化之动态批处理(四)

提示:仅供参考,有误之处,麻烦大佬指出,不胜感激! 文章目录 前言一、动态合批是什么?二、使用动态批处理1.打开动态合批2.满足条件 三、检查动态合批是否成功五、动态合批弊端总结 前言 动态批处理是常用优…

libmodbus使用

安装可以看这个博客&#xff1a; https://blog.csdn.net/hanhui22/article/details/105786762 它的安装可以&#xff0c;但是编译测试看不太懂&#xff0c;我没跟着它的编译&#xff0c;完了后把/lib下的 放到开发板的/usr/lib下 编写代码: #include <stdio.h> #inclu…

UI组件库和内容文字的中英文切换

同时实现UI组件库(这里以ElementPlus为例)和内容文字的中英文切换 1. 安装vueI18n和element-plus pnpm i vue-i18n element-plus 2. 然后在项目中src目录下新建lang文件夹&#xff0c;里面新建en.ts和zh.ts还有index.ts index.ts import { createI18n } from vue-i18n impor…

jvm重要参数可视化和线上问题排查

jvm重要参数可视化和线上问题排查 目标jvm参数分类(了解)运行时数据区相关的&#xff08;jdk1.8&#xff09;处理 OOM 相关的垃圾回收器相关的GC 日志记录相关的意义,默认值,调优原则&#xff08;重要&#xff0c; 待拆分&#xff09; 排查 OOM 流程 和 常见原因参考文章 目标 …

c#数据库:1.c#创建并连接数据库

安装软件:SQL Server Management Studio Management Studio Visual Studio 2022 启动服务: 打开SQL Server Management Studio Management Studio ,连接到服务器(GUANZU是我的计算机名) 新建数据库,随便起个名字叫aq: c#代码: using System; using System.Collections.Gener…

深度学习:基于Keras,使用长短期记忆神经网络模型LSTM和RMSProp优化算法进行销售预测分析

前言 系列专栏&#xff1a;【机器学习&#xff1a;项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目&#xff0c;每个项目都处理一组不同的问题&#xff0c;包括监督和无监督学习、分类、回归和聚类&#xff0c;而且涉及创建深度学习模型、处理非…

[C++核心编程-02]----C++引用详解和使用方法分析

前言 在C中&#xff0c;引用是一个别名&#xff0c;它允许将一个已存在的变量或对象用不同的名称来访问。引用在定义时必须初始化&#xff0c;并且一旦初始化就不能再绑定其他对象&#xff0c;因此引用在声明时被初始化后就不能再改变引用对象。引用使用&符号进行声明。 引…

【C++STL详解(六)】--------list的模拟实现

目录 前言 一、接口总览 一、节点类的模拟实现 二、迭代器类的模拟实现 迭代器的目的 list迭代器为何要写成类&#xff1f; 迭代器类模板参数说明 模拟实现 1.构造函数 2.*运算符重载 3.->运算符重载 4.前置 5.后置 6.前置-- 7.后置-- 8.! 9. 三、list类的…

【Mac】graphpad prism for Mac(专业医学绘图工具) v10.2.3安装教程

软件介绍 GraphPad Prism for Mac是一款专业的科学数据分析和绘图软件&#xff0c;广泛用于生物医学和科学研究领域。它具有强大的统计分析功能&#xff0c;可以进行各种数据分析&#xff0c;包括描述性统计、生存分析、回归分析、方差分析等。同时&#xff0c;它还提供了丰富…

滑动验证码登陆测试编程示例

一、背景及原理 处理登录时的滑动验证码有两个难点&#xff0c;第一个是找到滑块需要移动的距离&#xff0c;第二个是模拟人手工拖动的轨迹。模拟轨迹在要求不是很严的情况下可以用先加速再减速拖动的方法&#xff0c;即路程的前半段加速度为正值&#xff0c;后半段为负值去模…

Go未用代码消除与可执行文件瘦身

在日常编写Go代码时&#xff0c;我们会编写很多包&#xff0c;也会在编写的包中引入了各种依赖包。在大型Go工程中&#xff0c;这些直接依赖和间接依赖的包数目可能会有几十个甚至上百个。依赖包有大有小&#xff0c;但通常我们不会使用到依赖包中的所有导出函数或类型方法。 这…

如何高速下载,百度 阿里 天翼 等网盘内的内容

如何高速下载&#xff0c;百度 阿里 天翼 等网盘内的内容&#x1f3c5; 前言教程下期更新预报&#x1f3c5; 前言 近段时间经常给大家分享各种视频教程&#xff0c;由于分享的资料是用迅雷网盘存的&#xff0c;但是绝大部分用户都是使用的某度&#xff0c;阿某的这些网盘&…