JVM垃圾收集器(二)

news2025/1/25 9:14:01

目录

1、Serial

2、ParNew

3、Parallel Scavenge

4、Serial Old

5、Parallel Old

6、CMS

1、为什么需要两次“stop the world”

2、CMS的并发带来的问题

3、CMS的触发时机

4、CMS的缺陷

5、为什么CMS用清除算法

7、G1

1、Region

2、设计Region的意义

3、G1的三种模式

4、Mixed GC的运行过程

5、Card Table

6、三色标记法

7、STAB

8、G1的特点

8、JDK 默认垃圾收集器


规范中并未规定垃圾收集器如何实现,所以不同的虚拟机都提供了各种收集器,让用户根据需求组合使用。

HotSpot的各种收集器:

两个收集器之间存在连线,表示它们可以搭配使用。提供这么多种组合,还是因为每款收集器各有优劣,至今没有十全十美的收集器。

1、Serial

这是最基础的收集器,用于新生代,名字的意思是“串行”。

这是一个单线程工作的收集器,单线程指的是它只使用一条线程来进行垃圾收集。

标记-复制算法。

它的原理和流程比较简单,但由于停止线程这个动作是虚拟机主动发起的,用户线程不可知,突然就被停掉,不是很好。

后续垃圾收集器的一大目标,就是缩短用户线程的停顿时间,但始终没有办法不停顿。

 

2、ParNew

这是Serial的多线程并行版本,默认开启的收集线程数和cpu数量一样,可以同时使用多条线程进行并行的垃圾收集。

除了Serial外,只有ParNew能与CMS配合工作。CMS具有划时代意义,后来ParNew可以视为合并成了CMS的专用新生代收集器。

标记-复制算法。

3、Parallel Scavenge

也是针对新生代,支持多线程并行收集,特点是关注点不同。

  • CMS等收集器的关注点是,尽可能缩短垃圾回收时用户线程的停顿时间

  • 而Parallel Scavenge的关注点是,保证一个可控制的吞吐量,保证用户体验。

    (这里的吞吐量指的是,单位时间内(运行用户代码+进行垃圾收集),用户代码执行时间的占比)

由于关注吞吐量,所以Parallel Scavenge也被称为“吞吐量优先收集器”。        

适合注重吞吐量,或者处理器资源稀缺的场景。

标记-复制算法。

4、Serial Old

这是Serial的老年代版本,也是单线程的,使用标记-整理算法。

5、Parallel Old

这是Parallel Scavenge的老年代版本,支持多线程并发收集,使用标记-整理算法。

6、CMS

CMS(Concurrent Mark Sweep)是一种以达到“最短回收停顿时间”为目标的收集器。适合关注响应速度的服务器。

它比一般的标记-清除算法要复杂一些,分为以下4个阶段:

  • 初始标记:Stop The World,标记GC Roots能直接关联到的对象,比较快。
  • 并发标记:执行GC Roots跟踪标记过程,可以和用户线程并发执行,不需要暂停用户线程。
  • 重新标记:Stop The World,对标记期间产生的对象存活性的再次判断,修正对这些对象的标记,执行时间相对并发标记短。
  • 并发清除:清除对象,可以和用户线程并发执行。

CMS是清理老年代的

1、每阶段做的事情

初始标记

工作模式:JDK7之前单线程,JDK8之后多线程

目的:标记存活对象

包括两部分:

  • 标记老年代中GC Roots能直接关联到的对象
  • 标记新生代中还存活的,包含指向老年代的引用的对象,即额外考虑新生代对老年代的跨代引用

此阶段会stw,为了缩短停顿时间,可以开启初始标记并行化,-XX:+CMSParallelInitialMarkEnabled,同时调大并发标记的线程数,不过不要超过CPU的核数

并发标记

目的:顺着初始标记阶段标记出的存活对象,找出所有的存活对象

因为是和用户线程并发执行,所以期间可能发生这些动作:

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

对于这些对象,都需要重新标记当前的最新状态,否则就可能漏标存活对象。

为了提高重新标记的效率,避免重新扫描整个老年代,此阶段在发现上述行为后,会把该对象所在的card标记为脏卡,后续只需要扫描所有脏卡来处理。

因此,并发标记阶段完成后,老年代的所有存活对象并不会都被标记,还有一部分以脏卡的形式被记录,等待后续处理。

预清理阶段

目的:扫描所有脏卡,检查脏卡内所有对象的引用关系,标记存活对象

可终止的预处理

目的:这个阶段去尝试进行重新标记阶段的工作,因为重新标记阶段会stw,这样能减少一些停顿时间

此阶段最大持续时间为5秒,因为它期待这5秒内能发生一次young gc,清理新生代,进而减少下阶段扫描跨代引用的时间

重新标记

目的:完成对整个老年代的所有存活对象的标记,stw

用到三色标记里的增量更新算法做重新标记

调优:

这个阶段虽然目的是标记老年代,但是需要扫描整个堆,因为新生代可能存在对老年代的跨代引用。

为了以高效率,可以加入参数-XX:+CMSScavengeBeforeRemark,在重新标记之前进行一次young gc。

这样,只需要扫描较小的新生代,大大提高效率。

并发清理

1、为什么需要两次“stop the world”

在“初始标记”阶段,CMS会快速扫描一下能和GC Roots直接关联到的对象,之后就会解除暂停。

之后和用户线程并发执行,进行对象的可达性分析。

但是,在用户线程执行的过程中,引用关系很可能产生了变化,于是就再次stop the world,修改这些引用发生变化的对象的标记。

比如,一个对象在第一次被判断为了“死亡”,之后用户线程又重新与它建立了引用关系,那么第二次会将它修改为“存活”。

注意:未被“初始标记”阶段标记的对象,在“重新标记”阶段不会被标记为垃圾对象。

这个阶段的停顿时间一般会比初始阶段稍长一些,但远比并发标记的时间短。

由于整个过程中耗时最长的“并发标记”和“并发清除”过程,收集器线程都可以与用户线程一起工作。所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

优点:并发收集、低停顿

2、CMS的并发带来的问题

在并发阶段,它虽然不会导致用户线程停顿,但是占用了一部分CPU的运行资源,导致应用程序变慢了,降低总吞吐量。

CMS默认启动的回收线程数是(处理器核心数 + 3)/4。当处理器核心不足4个时,CMS对用户程序的影响较大。

3、CMS的触发时机

CMS收集器不能像其他收集器那样,等待老年代几乎满了才进行收集。这是因为CMS需要预留足够的内存给用户线程使用

默认的策略是,老年代使用了68%的空间后,就会开始回收。

  • 如果策略的阈值设置得较低,那么垃圾回收就会更频繁,影响性能
  • 如果策略的阈值设置得过高,如果CMS预留的内存无法满足程序分配新对象的需要,JVM就会启动应急预案:冻结用户线程的执行,临时启用Serial Old来重新对老年代进行垃圾回收,这样停顿时间就变得很长。

4、CMS的缺陷

  • CMS收集器对处理器资源非常敏感,因为虽然不会停止用户线程,但是会和用户线程一起竞争处理器资源,导致用户线程执行变慢
  • CMS无法处理“浮动垃圾”,可能导致这次GC没有产生足够的空间,不得不触发一次Full GC
  • CMS是基于标记-清除算法,会产生大量的空间碎片。如果影响到对象分配,就不得不触发一次Full GC来整理内存。
  • 如果在CMS运行过程中,用户线程突然产生了大量的垃圾,JVM就会紧急暂停用户线程,使用Serial Old来重新对老年代进行垃圾回收

什么是浮动垃圾

在“初始标记”第一次判断时,该对象不是垃圾。但到“重新标记”第二次判断的期间,这个对象变为了垃圾,那么本次垃圾回收就无法处理它,只能等到下一次GC时才有机会将它回收,这种对象就是浮动垃圾。

5、为什么CMS用清除算法

因为CMS考虑的是,尽量减少垃圾收集让用户线程停顿的时间,但是工作量无法减少,那么就考虑在某些阶段,让用户线程和垃圾收集并发执行。

正因如此,在用户线程正常执行时,CMS不能去擅自修改任何对象的地址,否则会导致用户线程无法定位到对象。

复制算法和整理算法都需要改变对象的内存地址,所以不适合。

 

7、G1

G1是一款面向服务器的高性能垃圾收集器,主要针对具有多核处理器和大内存的机器。

JDK 1.9时,G1作为了默认的垃圾收集器,同时CMS被标记为“不推荐使用”。

G1在以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征。

1、Region

G1堆内存的布局和其他收集器不同。

G1不再进行固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分成多个大小相等的独立区域(Region)

region 的大小是一致的,数值是在 1M 到 32M 字节之间的一个 2 的幂值数,JVM 会尽量划分 2048 个左右的 region。

每个Region都可以根据需要,扮演Eden、Survivor或者老年代空间。

G1可以对扮演不同角色的Region采用不同的收集策略,这样无论是新创建的对象,还是年龄较大的对象,都能获得很好的收集效果。

 

Region中还有一类特殊的Humongous区域,专门存储大对象。

如果一个对象超过Region容量的50%,它就会被存放在N个连续的Humongous Region中,G1的大多数行为都会把它当做老年代的一部分来看待。

由于堆内存被零散拆分了,所以需要维护一个空闲列表,来记录所有可用的region。

2、设计Region的意义

G1中依然存在新生代、老年代的概念,但它们不是连续的,而是一系列Region的动态集合。

G1能建立起可预测的停顿时间模型的基础,就是选择将Region作为单次回收的最小单元。

具体的做法是,它会根据各个Region里面的垃圾堆积的“价值”,维护一个优先级列表。价值包括两个方面:

  • 回收后能获得的空间大小
  • 回收所需的时间

每次垃圾回收时,根据用户指定的允许停顿时间,优先回收那些价值大的Region,保证了有限时间内的较高效率

相当于垃圾回收的思路转变了:

  • 之前是优先回收新生代,因为新生代往往能获得较大的内存,新生代回收完还不够才会去全堆收集
  • 现在是,优先回收那些回收价值大的内存,这是一个主动的行为,所以效率就比之前高很多,因为更有针对性。

3、G1的三种模式

Young GC

当所有eden region被耗尽无法申请内存时,就会触发一次young gc。会暂停用户线程,发起多个垃圾回收线程。

存活的对象会被拷贝到survivor region,或者晋升到old region中。被清理的region会被放入空闲列表中,等待下次被使用

Mixed GC

之前的所有垃圾收集器,都是要么针对新生代,要么针对老年代,要么针对整堆进行垃圾回收的。

当越来越多的对象晋升到old region中,达到设定的阈值后,就会触发一次Mixed GC,回收掉高价值的目标

Full GC

如果对象内存分配速度过快,mixed gc来不及回收,导致老年代被填满,就会触发一次full gc

G1的full gc算法就是单线程执行的serial old gc,会导致用户线程被长时间暂停,所以需要避免Full GC。

4、Mixed GC的运行过程

  • 初始标记:

    • stop the world,标记一下GC Roots能直接关联到的对象
    • 并且修改TAMS指针的值,让下一阶段的用户线程能正确在可用的空间分配新对象
  • 并发标记:从GC Roots出发,对堆中对象进行可达性分析。和用户线程一起并发执行(只有并发标记阶段能和用户线程并发执行)

  • 最终标记:stop the world,处理并发阶段结束后遗留的STAB记录

  • 筛选回收

    • 根据用户设定的时间停顿用户线程,因为涉及到对象地址的修改。
    • 对Region的价值进行排序,根据用户期望的停顿时间制定回收计划,构成回收集
    • 然后把决定回收的那一部分Region的存活对象复制到空的Region中,清理掉旧Region的全部空间。

5、Card Table

在传统垃圾回收中遇到的跨代引用问题,G1中也同样存在。

由于G1把整个堆拆成了很多个region,所以每个region的不同对象之间是有互相引用的依赖关系的,而且同代引用也会发生在不同region之间。

如果进行回收之前需要遍历所有region来做到准确的垃圾回收,效率极低。

G1也是采用了Remember Set记忆集的思路,做了一个Card Table。

卡表中存放了各个Region之间的引用关系,这样就可以只去扫描相关的Region,不需要全体扫描。

6、三色标记法

G1和CMS一样,在并发标记阶段使用了三色标记法:

 

漏标问题

正常的引用关系是:

  • 一个对象扫描完成,作为灰色节点
  • 扫描该对象的成员变量,也就是和它有引用关系的其他对象,扫描完成后,之前的对象变为黑色节点
  • 还没有被扫描的对象,作为白色节点
  • 如果在并发标记阶段,用户线程把灰色节点和白色节点之间的引用删除,此时扫描灰色节点的成员变量时就不会扫描到该白色节点,它会被视为垃圾
  • 但是白色节点和黑色节点产生了引用,那么这个引用是无法被现有的扫描方式所察觉的,就会造成本来存在引用关系的节点被漏标的问题。

CMS和G1如何解决漏标问题

产生漏标问题的条件有两个:

  • 黑色对象指向了白色对象 (关注引用的增加)
  • 灰色对象指向白色对象的引用消失 (关注引用的删除)

所以要解决漏标问题,打破两个条件之一即可。

  • CMS的做法是:
    • 并发标记过程中,使用“增量更新”机制,如果产生了新的引用,就把该黑色节点标记为灰色,之后还会重新扫描,获得最新的引用关系
    • 并发标记完成后,要回收的对象就不会再增加了
    • 并发标记完成后触发二次停顿,把这些重新建立引用关系的对象移出回收范围
    • 并发标记过程中产生的新垃圾不会被回收。
  • G1的做法是:
    • 会记录在并发标记阶段产生的新垃圾,然后在最终标记阶段,把这些垃圾也计入回收范围。
    • 当灰–>白消失时,要把这个 引用 推到GC的堆栈,保证白还能被GC扫描到。

为什么G1不使用增量更新机制

因为如果把黑色节点标记为灰色节点,之后还要二次查找,效率低。

G1保存了卡表,里面存放了各个Region之间的引用关系。

7、STAB

G1使用原始快照(STAB)算法来解决,Snapshot-At-The-Beginning。

具体做法是:

  • 在GC开始之前,创建一个对象快照。
  • 在并发标记时所有快照中当时的存活对象就认为是存活的,标记过程中新分配的对象也会被标记为存活对象,不会被回收。

要达到GC与用户线程并发运行,必须要解决回收过程中新对象的分配,所以G1为每一个Region区域设计了两个名为TAMS(Top at Mark Start)的指针,从Region区域划出一部分空间用于记录并发回收过程中的新对象。这样的对象认为它们是存活的,不纳入垃圾回收范围。

8、G1的特点

  • 并行与并发:G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPU(CPU 或者 CPU 核心)来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 java 程序继续执行。
  • 分代收集:虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但是还是保留了分代的概念。
  • 空间整合:与 CMS 的“标记--清理”算法不同,G1 从整体来看是基于“标记整理”算法实现的收集器,从局部(两个Region之间)上来看是基于“复制”算法实现的,所以不会产生内存碎片
  • 可预测的停顿:这是 G1 相对于 CMS 的另⼀个优势,降低停顿时间是 G1 和 CMS 共同 的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定允许的停顿时间。

8、JDK 默认垃圾收集器

jdk1.7 默认垃圾收集器:Parallel Scavenge(新生代)+Parallel Old(老年代)

jdk1.8 默认垃圾收集器:Parallel Scavenge(新生代)+Parallel Old(老年代)

jdk1.9 默认垃圾收集器:G1

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

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

相关文章

【C++】——类与对象(中)+日期类对象的实现

文章目录 1. 前言2. 类的6个默认成员函数3. 构造函数4. 析构函数5. 拷贝构造函数6. 运算符重载6.1 赋值运算符重载 7. const成员8. 取地址及const取地址操作符重载9. 日期类对象的完整实现9.1 头文件9.2 源文件9.3 测试代码 10. 结尾 1. 前言 今天我们来继续学习C类与对象&…

网安学习路线!史上最详细没有之一

我经常会看到这一类的问题: 学习XXX知识没效果;学习XXX技能没方向;学习XXX没办法入门; 给大家一个忠告,如果你完全没有基础的话,前期最好不要盲目去找资料学习,因为大部分人把资料收集好之后&…

医日健自助售药机

产品概述 医日健智能自助售药机整合了信息化管理技术 、远程监控管理技术 、自动化技术、人脸识别技术等多种先进技术 ,结合药品零售的特点 ,通过在医院、诊所、药店、便利店、社区等场所部署药品自助售药机 ,为用户提供自选购药服务&#x…

深度学习用于医学预后-第二课第三周1-3节-生存模型,生存函数

文章目录 生存模型生存函数有效生存函数 生存模型 本周,我们将讨论生存模式(survival model)。生存模型是一种特殊的模型我们关心事件发生的时间,比如从治疗到复发的时间,或者从诊断到死亡的时间 这是一个常见的问题…

GPT自动理解视频、法律顾问、大模型安全围栏

每天都要浏览大量AI相关新闻,是不是感到信息量爆炸,有效信息少,无从看起? 这么多新产品和新工具,到底哪些是真正是有价值的,哪些只是浮躁的热点? 想参与AI产品和工具的开发,但苦于…

READNE.md 语法

标题列表引用代码块链接图片分割线表格 1. 标题 #一级标题 ##二级标题 ###三级标题 ####四级标题 #####五级标题 ######六级标题 2. 列表 2.1 有序列表 直接在前面写数字序号: 1. a 2. bc 3. 1234 2.2 无序列表 有三种方式:""、"-&q…

操作系统--需要背的概念性知识

第一章 操作系统概述 操作系统的作用:1)控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配;2)提供给用户和其他软件方便的接口和环境;3)实现了对计算机资源…

(GPT3)Language Models are Few-Shot Learners论文阅读

论文地址:https://arxiv.org/pdf/2005.14165v4.pdf 摘要 最近的工作表明,通过对大量文本语料库进行预训练,然后对特定任务进行微调,许多 NLP 任务和基准测试取得了实质性进展。 虽然在体系结构中通常与任务无关,但此方…

4月份公司测试部门来了个卷王之王,让人奔溃...

前段时间公司新来了个同事,听说大学是学的广告专业,因为喜欢IT行业就找了个培训班,后来在一家小公司干了三年,现在跳槽来我们公司。来了之后把现有项目的性能优化了一遍,服务器缩减一半,性能反而提升4倍&am…

【AI面试】Anchor based 、 Anchor free 和 no anchor 的辨析

深度学习的目标检测算法,通常会在输入图像中采样大量的区域,然后判断这些区域中是否包含我们感兴趣的目标,并调整(回归)区域边界,从而更准确地预测目标的真实边界框(ground-truth bounding box&…

【高数+复变函数】傅里叶积分

文章目录 【高数复变函数】傅里叶积分2. 傅里叶积分2.1 复数形式积分公式2.2 三角形式 上一节: 【高数复变函数】傅里叶级数 【高数复变函数】傅里叶积分 2. 傅里叶积分 在上一节中,我们知道了傅里叶级数的基本知识,其中,周期为…

【MATLAB第31期】基于MATLAB的降维/全局敏感性分析/特征排序/数据处理回归问题MATLAB代码实现(持续更新)

【MATLAB第31期】基于MATLAB的降维/全局敏感性分析/特征排序/数据处理回归问题MATLAB代码实现(持续更新) 本文敏感性分析主要分析回归问题,下期分析分类问题(fisher、rf、arf、nca等)。 一、降维方法(回归) 常见的降…

【动态规划】0-1背包问题

概述 0-1背包问题是一种经典的动态规划问题,它的基本形式是:有一个背包,容量为 C C C,有 n n n 个物品 i i i,每个物品 i i i 的重量为 w i w_i wi​,价值为 v i v_i vi​。现在要从这 n n n 个物品…

id选择器和class选择器

id选择器 id选择器用来选取带有给定id属性的元素。语法:#id例如: html <div id"container">...</div>css #container {color: blue; }id选择器的一些特征: 1. id选择器以#号开头,后跟元素的id属性值。 2. id选择器只能选取带有给定id属性的元素。 3.…

在 Windows 上安装 kubectl

一、前言 个人主页: ζ小菜鸡大家好我是ζ小菜鸡&#xff0c;让我们一起学习在 Windows 上安装 kubectl。如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连) 二、 kubectl是什么 kubectl是Kubernetes集群的命令行工具&#xff0c;通过kubectl能够对集群本身进行管理&#xf…

一篇文章学会高级IO

文章目录 理解IO的本质认识五种IO模型阻塞式IO非阻塞式IO信号驱动式IO多路转接式IO异步式IO 高级IO的理解以及意义多路转接式IO的深入学习select模型select函数详解封装网络套接字&#xff1a;Sock.hppselectServer.cc(服务器文件)运行结果小结 poll模型poll函数详解Sock.hpppo…

Reed-Muller序列

Reed-Muller函数的由来 我们知道对于连续信号&#xff0c;时间和频率是对偶域(duality)&#xff0c;其中正弦函数是时移的特征函数&#xff08;where sinusoids are eigenfunctions of time shifts&#xff09;。而在汉明空间(Hamming space)中&#xff0c;there are discrete…

牛客网面试必刷:BM19 寻找峰值

牛客网面试必刷&#xff1a;BM19 寻找峰值 前言一、解法1&#xff1a;暴力依次搜索二、解法2&#xff1a;二分搜索 前言 给定一个长度为n的数组nums&#xff0c;请你找到峰值并返回其索引。数组可能包含多个峰值&#xff0c;在这种情况下&#xff0c;返回任何一个所在位置即可…

数据库基础篇 -- 1

目录 数据库基础 1.1&#xff1a;什么是数据库 1.2&#xff1a;常见数据库 1.3&#xff1a;数据库的基本使用 1.4&#xff1a;mysql的架构 1.5&#xff1a;sql分类 1.6&#xff1a;存储引擎 数据库基础 1.1&#xff1a;什么是数据库 数据库是指存储和管理结构化数据的…

解决频繁操作svn导致提交文件失败svn: E155015,亲测成功

我是因为频繁在本地删除创建重复的包和.java文件&#xff0c;以至于在提交至svn的时候会出现我之前删除的包和.java文件&#xff0c;所以我致力于将其删除干净&#xff0c;频繁的在本地删除、去svn删除…以至于再后来本地项目中和svn中都没有但是还是svn: E155015&#xff0c;查…