当前位置: 首页 > news >正文

【JVM】7种经典的垃圾收集器

文章目录

  • 1. 垃圾收集器概述
  • 2. Serial 收集器
  • 3. ParNew 收集器
  • 4. Paraller Scavenge 收集器
  • 5. Serial Old收集器
  • 6. Parller Old收集器
  • 7. CMS 收集器
  • 8. Garbage First 收集器

本文参考:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)

1. 垃圾收集器概述

image-20230212113322170

图中所示七种垃圾收集器虽然算不上先进技术,但是它们在实践中足够成熟,基本上可以认为是现在未来两、三年内,能够在生产环境上放心使用的所有垃圾收集器了。

这七种垃圾收集器是作用于不同分代的,两个收集器之间若有连线,则说明它们可以搭配使用。垃圾收集器的位置则表示了属于新生代还是老年代收集器。

垃圾收集器根据发展实践可以分为:

  1. 串行
  2. 吞吐量优先
  3. 响应时间优先

2. Serial 收集器

Serial收集器是最基础、历史最悠久的收集器。它是用于新生代的垃圾收集器。

这个收集器是一个单线程工作的收集器,“单线程”不仅仅代表了这个收集器只会使用一个处理器或一个收集线程去进行垃圾收集工作,更重要的是,Serial 收集器在进行垃圾收集的时候必须暂停其他所有工作,直到收集工作完成。

也就是说在用户不可知、不可控的情况下,把用户的正常工作的线程全部停掉,这是一个不能接受的事情。

image-20230212114757514

即使 Serial 收集器是最早出现的垃圾收集器,但是如今HotSpot虚拟机运行在客户端模式下的默认新生代收集器依然是 Serial 收集器。

Serial 收集器的优点很简单,那就是简单高效,在内存资源受限的环境中,它是所有收集器里额外内存消耗最小的,对于单核处理器或核心数较小的处理器来说,Serial 收集器没有线程交互的开销,专心做垃圾收集因此保证了收集效率。


3. ParNew 收集器

ParNew 收集器实际上就是 Serail 收集器的多线程版本,除了同时使用多线程进行垃圾回收之外,其他的任何行为包括所有控制参数、收集算法等都与 Serail 收集器一样,并无太多创新之处

image-20230212115554893

并且除了Serial收集器外,目前只有ParNew收集器可以与CMS收集器配合工作。

CMS是一款在强交互应用中几乎可称为具有时代意义的垃圾收集器,它是真正意义上支持并发的垃圾收集器,首次实现了让垃圾收集器线程在用户线程同时工作,所以,CMS的出现巩固了ParNew的地位

ParNew 收集器在单核心处理器的环境绝对不必Serial收集器更好的效果,甚至存在线程交互的开销。
ParNew收集器通过超线程技术实现的伪双核处理器环境中都不能百分之百超越Serial。

不过随着处理器核心数量的增加,ParNew对于垃圾收集时的系统资源高效利用还是很有好处的,它默认开启的收集线程数和处理器核心线程数相同。


4. Paraller Scavenge 收集器

Paraller Scavenge 收集器是基于标记-复制算法实现的收集器,也是能够并行收集的多线程收集器。

该垃圾收集器常被称为“吞吐量优先收集器”

并行:并行描述的是多条垃圾收集器线程之间的关系,说明同一时间有多条这样的线程在协同工作,通常默认此时用户线程是处于等待状态

并发:并发描述的是垃圾收集器线程与用户线程之间的关系,说明同一时间垃圾收集器线程与用户线程都在运行。由于用户线程并未被冻结,所以程序仍然能响应服务请求,但由于垃圾收集器线程占用了一部分系统资源,此时应用程序的处理的吞吐量将受到一定影响。

Paraller Scavenge 收集器的特点是达到一个可控的吞吐量。

image-20230212133427488

Parallel Scavenge 收集器提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis 参数以及直接设置吞吐量大小的-XX:GCTimeRatio 参数

  1. -XX:MaxGCPauseMillis:参数允许值是一个大于0的毫秒数,收集器会尽力保证内存回收花费时间不超过用户的设定值,**但是这个参数值不建议设置得更小一点,因为垃圾收集停顿时间是牺牲吞吐量和新生代空间为代价的。**系统把新生代调的小一点,垃圾收集速度肯定快一点,但是随之而来的就是频繁的垃圾收集,因此吞吐量也会下来。
  2. -XX:GCTimeRatio:值应该是一个大于0小于100的正数,也就是垃圾收集时间总时间的比率,相当于吞吐量的倒数。比如设置为19,那么就是允许的最大垃圾收集器占用的时间为5%(即1/(1+19));默认为99,允许的最大1%(1/(1+99))为垃圾收集时间

5. Serial Old收集器

Serial Old收集器是Serial收集器的老年代版本,同样也是一个单线程收集器,使用标记-整理算法

image-20230212135752822

如果在服务端模式下,它也可能有两种用途:一种是在JDK 5以及之前的版本中与 Parallel Scavenge 收集器搭配使用9,另外一种就是作为 CMS 收集器发生失败时的后备预案,在并发收集发生Concurrent Mode Failure 时使用。


6. Parller Old收集器

Parller Old收集器是Parller Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现。

image-20230212140005545

在Parller Old收集器没有出现之前,Parller Scavenge收集器只能和Serial Old收集器搭配使用,由于Serial Old收集器应用性能上的拖累,并不能是的Parller Scavenge收集器未必能发挥出最好的吞吐量最大化的效果。这组合甚至不如ParNew加CMS的组合来得优秀。

直到 Paraller old 收集器出现后,“吞吐量优先”收集器终于有了比较名副其实的搭配组合,在注重吞吐量或者处理器资源较为稀缺的场合,都可以优先考虑 Paraller Scavenge 加Paraller Old 收集器这个组合。


7. CMS 收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的 Java 应用集中在互联网网站或者基于浏览器的 B/S 系统的服务端上,这类应用通常都会较为关注服务的响应速度希望系统停顿时间尽可能短,以给用户带来良好的交互体验。

CMS收集器是基于标记-清除算法实现的。它的回收垃圾的步骤如下

  1. 初始标记

    1. 需要Stop The Word,仅仅标记从GC Roots的直接关联对象,速度很快
  2. 并发标记

    1. 从GC Roots的直接关联对象开始遍历整个对象图的过程,过程耗时但不需要停顿用户线程,可以与垃圾收集线程一起并发允许
  3. 重新标记

    1. 需要Stop The Word,为的是修正并发标记期间,因用户程序继续允许而导致标记产生变动的拿一些对象的标记记录。
    2. 停顿时间比初始标记时间常,但比并发标记时间短
  4. 并发清除

    1. 清除标记阶段判断已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以和用户进程同时运行的

image-20230212140536014

CMS的优点的优点有并发收集、低停顿。

不过CMS并没有达到完美,它有以下几个缺点

  1. CMS收集器对处理器资源非常敏感
  2. CMS无法处理浮动垃圾
    1. 由于并发标记和并发清除阶段,用户线程是继续运行的,程序在运行的时候自然会产生新的垃圾对象。
  3. 由于使用标记-清除算法实现,所以会导致空间碎片比较多。

8. Garbage First 收集器

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

G1收集器面向堆内存任何部分来组成回收集 (Collection Set,一般简称 CSet)进行回收,衡量标准不再是它属于哪个分代,而是哪块内存中存放的垃圾数量最多,回收收益最大,这就是 G1 收集器的 Mixed GC 模式。

G1开创的基于 Region 的堆内存布局是它能够实现这个目标的关键。虽然 G1 也仍是遵循分代收集理论设计的,但其堆内存的布局与其他收集器有非常明显的差异:G1 不再坚持固定大小以及固定数量的分代区域划分,而是把连续的 Java 堆划分为多个大小相等的独立区域(Region),每一个Region 都可以根据需要,扮演新生代的 Eden 空间、Survivor 空间或者老年代空间。收集器能够对扮演不同角色的 Region 采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获取很好的收集效果。

Region 是 G1收集器的单位回收的最小单位,这样做可以有计划避免整个JAVA堆中进行全区域的垃圾收集。并且G1收集器会跟踪各个Region的价值大小,也就是回收所获得的空间大小以及回收所需要的时间的经验值,在后台形成一个优先队列,再根据用户设定的允许的停顿时间,优先处理那些回收价值大的Region,这样保证了G1收集器在有限的时间内获取尽可能高的收集效率。

image-20230212161608985

G1收集器的运作步骤

  1. 初始标记
    1. 仅仅只是标记一下GC Roots 能直接关联到的对象并且修改 TAMS 指针的值,让下一阶段用户线程并发运行时,能正确地在可用的 Region 中分配新对象。这个阶段需要停顿线程,但耗时很短,而且是借用进行Minor GC 的时候同步完成的,所以G1 收集器在这个阶段实际并没有额外的停顿。
  2. 并发标记
    1. 从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫描完成以后,还要重新处理 SATB 记录下的在并发时有引用变动的对象。
  3. 最终标记
    1. 对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的 SATB 记录。
  4. 筛选回收
    1. 负责更新 Region 的统计数据,对各个Region 的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个 Region 构成回收集,然后把决定回收的那一部分Region 的存活对象复制到空的 Region 中,再清理掉整个旧 Region 的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多条收集器线程并行完成的。

image-20230212162540809


相关文章:

【JVM】7种经典的垃圾收集器

文章目录1. 垃圾收集器概述2. Serial 收集器3. ParNew 收集器4. Paraller Scavenge 收集器5. Serial Old收集器6. Parller Old收集器7. CMS 收集器8. Garbage First 收集器本文参考:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版&#xff…...

2023/2/12总结

滑动窗口(1)滑动窗口是一种基于双指针的思想,两个指针指向的元素形成一个窗口。一般用于求取数组或字符串的某个子串、子序列、最长最短等最值或者求某个目标值时,并且该问题本身可以通过暴力解决。滑动窗口分为固定窗口和不定窗口…...

Linux之正则表达式

正则表达式是组成“操作”的基本语法,而这些“操作”是应用于Sed和Awk必备的能力。因此只有了解了正则表达式,才能学好Sed和Awk。正则表达式分为基础正则表达式(Regular Expression)与扩展正则表达式(Extended Regular…...

前端高频面试题-HTML和CSS篇(一)

💻 前端高频面试题-HTML和CSS篇(一) 🏠专栏:前端面试题 👀个人主页:繁星学编程🍁 🧑个人简介:一个不断提高自我的平凡人🚀 🔊分享方向…...

Redis 专题总结

1. 什么是Redis ? 处理:内容缓存,主要用于处理大量数据的高访问负载。Redis是一款高性能的NOSQL系列的非关系型数据库,NoSQL(NoSQL Not Only SQL),意即“不仅仅是SQL”,是一项全新的数据库理念&#xff0…...

【Python百日进阶-Web开发-Vue3】Day515 - Vue+ts后台项目2:登录页面

文章目录 一、创建登录路由1.1 安装 Vue VSCode Snippets插件1.2 处理路径引用的红色波浪线1.3 入口文件 main.ts1.4 主组件 App.vue1.5 路由文件 router/index.ts1.6 首页组件 views/HomeView.vue1.7 登录组件 views/LoginView.vue二、实现登录页面的表单展示2.1 element-plus…...

【博客620】prometheus如何优化远程读写的性能

prometheus如何优化远程读写的性能 场景 为了解决prometheus本地存储带来的单点问题,我们一般在高可用监控架构中会使用远程存储,并通过配置prometheus的remote_write和remote_read来对接 远程写优化:remote_write 远程写的原理&#xff1a…...

redis可视工具AnotherRedisDesktopManager的使用

redis可视工具AnotherRedisDesktopManager的使用 简介 Another Redis DeskTop Manager 是一个开源项目,提供了以可视化的方式管理 Redis 的功能,可供免费下载安装,也可以在此基础上进行二次开发,主要特点有: 支持 W…...

【idea】idea生产类注释和方法注释

网上有很多类似的文章,但是我在按照他们的文章设置后,出现了一些问题,因此我这边在解决了问题后,总结一篇文章,发出来给大家借鉴一下。在此先说明一下idea的版本,是2020.1.3 设置动态模板,File…...

jenkins +docker+python接口自动化之jenkins容器安装python3(二)

jenkins dockerpython接口自动化之jenkins容器安装python3(二) 目录:导读 前提是在docker下已经配置好jenkins容器了,是将python安装在jenkins容器下的 1、先看你的jenkins是否安装好 2、以root权限进入jenkins容器&#xff1…...

go 命令行工具整理

这里会整理可能会使用到的命令行参数,比如 go build、go run,诸如此类。了解这些内容对我们工作会有什么帮助吗?更多的时候,是能让我们理解代码编译的意图,或者,给我们一种排查问题的手段。 比方说&#x…...

RuntimeError: CUDA out of memory

今天在训练模型的时候突然报了显存不够的问题,然后分析了一下,找到了解决的办法,这里记录一下,方便以后查阅。 注:以下的解决方案是在模型测试而不是模型训练时出现这个报错的! RuntimeError: CUDA out of…...

Kubernetes1.25中Redis集群部署实例

1、概述我们知道在 Kubernetes 容器编排平台中, 我们可以非常方便的进行应用的扩容缩, 同时也能非常方便的进行业务的迭代,本章主要讲解在Kubernetes1.25搭建Redis单实例和Redis集群主从同步的环境流程步骤, 如果是高频访问重要的线上业务我们最好是部署在物理机器上…...

C++11实现计算机网络中的TCP/IP连接(Windows端)

目录引言1、TCP2、IP2.1 IP路由器3、TCP/IP4、TCP/IP协议C11实现参考文献引言 TCP/IP 指传输控制协议/网际协议(Transmission Control Protocol / Internet Protocol)。[1] 在TCP/IP协议簇中主要包含以下内容: TCP (传输控制协议) - 应用程序…...

Spring框架自定义实现IOC基础功能/IDEA如何手动实现IOC功能

继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库Java设计模式克隆下载学习使用! 7.4 自定义Spring IOC 创建新模块,结构如图![[Pasted image 20230210173222.png]] 7.4.1 定义bean相关POJO类 7.4.1.1 定义propertyValue类 /** …...

pip离线安装windows版torch

文章目录前言conda创建虚拟环境安装torchtorch官网在线安装离线手动安装测试是否安装成功后记前言 学习的时候遇到几个机器学习相关的项目,由于不同的项目之间用到的依赖库不太一样,于是想利用conda为不同的项目创建不同的环境方便管理和运行&#xff0…...

Redis核心知识点

Redis核心知识点Redis核心知识点大全五种数据类型redis整合SpringBoot序列化问题渐进式扫描慢查询缓存相关问题数据库和缓存谁先更新缓存穿透缓存雪崩缓存击穿实际应用超卖问题分布式锁全局唯一ID充当消息队列Feed流附近商户签到HyperLogLog实现UV统计持久化RDBAOF持久化小结事…...

14. 最长公共前缀

14. 最长公共前缀 一、题目描述: 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 “”。 示例 1: 输入:strs [“flower”,“flow”,“flight”] 输出:“fl” 示例 2: …...

SignalR注册成Windows后台服务,并实现web前端断线重连

注意下文里面的 SignalR 不是 Core 版本,而是 Framework 下的 本文使用的方式是把 SignalR 写在控制台项目里,再用 Topshelf 注册成 Windows 服务 这样做有两点好处 传统 Window 服务项目调试时需要“附加到进程”,开发体验比较差&#xf…...

【前端笔试题二】从一个指定数组中,每次随机取一个数,且不能与上次取数相同,即避免相邻取数重复

前言 本篇文章记录下我在笔试过程中遇到的真实题目,供大家参考。 1、题目 系统给定一个数组,需要我们编写一个函数,该函数每次调用,随机从该数组中获取一个数,且不能与上一次的取数相同。 2、思路解析 数组已经有了…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

深度学习习题2

1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

数据结构:递归的种类(Types of Recursion)

目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...