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

JVM垃圾收集算法、对应收集器和选择建议

如果说垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。

到目前为止还没有最好的垃圾收集器出现,也没万能的垃圾收集器。实际使用中,根据具体应用场景选择合适的垃圾收集器。

1、垃圾收集算法

垃圾收集算法可以从高层次上归纳为四种主要类型:分代收集理论、标记-复制算法、标记-整理算法和标记-清除算法。

1.1、分代收集理论

大多对象在内存中只会存活很短的时间,JVM堆内存被分为新生代和老年代。新生代中又分为Eden区和两个Survivor区,新生代主要用于存放新建的对象,短期内未被回收的对象会晋升到老年代。

算法应用: JVM垃圾收集器的基础,所有垃圾收集器都基于这一理论实现。

1.2、标记-复制算法

标记-复制算法,将堆内存划分为两个相等的区域,将存活的对象从一个区域复制到另一个区域,回收未被复制的对象。

优点: 简单高效,尤其适用新生代,总是从空区域开始分配区域,不会产生内存碎片。

缺点: 需要两个相同大小的内存区域,导致内存利用率降低。

典型应用: Serial GC、Parallel GC和G1 GC的新生代部分。

1.3、标记-整理算法

标记-整理算法,首先标记所有的存活的对象,再将存活的对象向堆的一端移动,最后清理掉堆的另一端的空闲内存。

优点: 解决内存碎片问题,适合老年代内存管理。

缺点: 对象移动和引用更新会带来额外的开销。

典型应用: Serial GC,Parallel GC和G1 GC的老年代部分

1.4、标记-清除算法

标记-清除算法,先标记所有存活的对象,再清理未标记的对象。

优点: 实现简单,不需要额外的空间来移动对象。

缺点: 产生内存碎片。

典型应用: CMS GC的老年代部分。

2、垃圾收集器
2.1、新生代垃圾收集器

对象存活时间较短,大多数对象在创建后很快就会被回收,主要基于复制算法,该算法效率高、能快速回收短生命周期的对象。

Serial 收集器:

  • 使用单线程进行垃圾收集,适用于单处理器环境
  • 是最简单的收集器,使用 标记-复制算法 处理新生代
  • 垃圾收集时会 Stop-The-World(暂停所有用户线程)
  • 适合需要最小化内存管理开销的场景(如桌面应用程序)

ParNew 收集器:

  • Serial 收集器的多线程版本
  • 可以在多核环境下使用多线程进行垃圾收集
  • 常与 CMS 收集器配合使用来回收新生代

Parallel Scavenge 收集器:

  • 也叫做 “吞吐量优先” 收集器,适用于高吞吐量的场景
  • 通过多线程进行垃圾收集,使用 标记-复制算法
  • 强调在单位时间内完成尽可能多的任务
  • 适合后台服务器应用程序
2.2、老年代垃圾收集器

老年代的对象存活时间较长,存活率高,常用算法是标记-整理算法或标记-清除算法,主要针对内存碎片化问题进行优化。

Serial Old 收集器:

  • 使用 标记-整理算法
  • 是 Serial 收集器 在老年代的版本
  • 使用单线程,适用于单处理器环境

Parallel Old 收集器:

  • 使用 标记-整理算法
  • 是 Parallel Scavenge 收集器 的老年代版本
  • 支持多线程并发回收
  • 适合在多处理器环境下进行高吞吐量的垃圾回收

CMS(Concurrent Mark-Sweep)收集器:

追求低停顿,适合低延迟应用场景(如交互式应用程序)

CMS的工作过程【四个阶段】

① 初始标记: 暂停所有的其他线程(STW),记录下gc roots直接能引用的对象,速度很快。

② 并发标记: 从GC Roots的直接关联对象开始遍历整个对象图,过程耗时较长,但不需要停顿用户线程,可以与垃圾收集线程一起并发运行。

③ 重新标记: 主要处理漏标问题,停顿时间比初始标记阶段稍长,但比并发标记阶段短,主要用到三色标记里的增量更新算法

④ 并发清理: 开启用户线程,同时GC线程开始对未标记的区域做清扫,如果有新增对象会被标记为黑色不做任何处理。

CMS的优点: 大部分工作可以在用户线程运行时并发进行,减少垃圾收集时的停顿时间。

CMS的缺点: 产生内存碎片,有时需要额外的 Full GC 整理碎片。

2.3、新生代和老年代的统一收集器

同时管理新生代和老年代,旨在提供更加统一的垃圾回收体验。

G1(Garbage First)收集器:

  • JDK 1.7 中引入,目标是替代 CMS 收集器
  • 主要用于低停顿的场景,同时具备处理大堆内存的能力
  • 将堆划分为多个大小相等的区域,不再区分严格的新生代和老年代
  • 优先处理那些收集回报较高的区域
  • 结合标记-复制和标记-整理算法,解决CMS内存碎片问题
  • 具备并发回收能力,在应用程序运行时尽量减少停顿时间
  • SATB (Snapshot-At-The-Beginning)技术,用于实现并发标记的准确性

SATB 实现原理

  • 在并发标记阶段开始时,记录下堆中对象引用的一个快照(Snapshot)
  • 通过这个快照,垃圾收集器可以保证在标记过程中
  • 即使引用发生变化,也能正确识别出哪些对象是存活的

SATB 步骤

① 初始快照: 记录堆中所有对象的引用状态

② 引用更新: 在并发标记过程中,应用程序可能会更新对象的引用

③ 标记对象: 按照快照记录的状态,标记所有从 GC Roots 可达的对象

④ 结束标记: 所有标记的对象和新增引用对象,都被视为存活对象

SATB 优势

① 准确性: 在快照时存活的对象能会被正确标记为存活对象

② 性能: 仅在引用更新时需要记录旧引用,对应用程序的性能影响较小

③ 避免浮动垃圾: 有效减少因并发标记过程中的引用变化而导致的浮动垃圾

ZGC(Z Garbage Collector):

JDK 11 中引入,超低延迟,能够在很短的停顿时间内管理非常大的堆,停顿时间:一般小于 10ms,堆:高达 16 TB。

使用染色指针(Colored Pointers)和 读屏障(Read Barriers),实现了几乎完全的并发垃圾回收。核心目标是避免长时间的垃圾回收停顿,适用于需要大内存且要求极低延迟的应用场景。

ZGC 存在问题:

  • 最大的问题是浮动垃圾
  • ZGC的停顿时间在10ms以下,但执行时间大于这个值
  • 期间创建的新对象,难进入当次GC,这些就是浮动垃圾

ZGC 浮动垃圾的解决方案: 增大堆的容量

ZGC 4种触发时机:

① 定时触发: 默认为不使用,可通过ZCollectionInterval参数配置

② 预热触发: 最多三次,在堆内存达到10%、20%、30%时触发,主要是统计GC时间,为其他GC机制使用。

③ 分配速率: 基于正态分布统计,计算内存99.9%可能的最大分配速率,内存将要耗尽之前触发GC。

④ 主动触发: 默认开启,配置参数ZProactive

Shenandoah 收集器:

Red Hat 推出,低停顿的垃圾收集器,和 ZGC 类似,追求在大堆内存场景下实现低于 10ms 的 GC 停顿时间。

2.4、如何选择垃圾收集器建议
  • 优先调整堆的大小让服务器自己来选择
  • 如果内存小于100M,使用串行收集器
  • 如果是单核,且没有停顿时间要求,串行或JVM自己选择
  • 如果响应时间最重要,且不能超过1秒,使用并发收集器
  • 4G以下可以用parallel,4-8G可以用ParNew+CMS
  • 8G以上可以用G1,几百G以上用ZGC
  • JDK 1.8默认使用 Parallel(年轻代和老年代都是)
3、我的公众号

敬请关注我的公众号:大象只为你,持续更新技术知识…

相关文章:

JVM垃圾收集算法、对应收集器和选择建议

如果说垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。 到目前为止还没有最好的垃圾收集器出现,也没万能的垃圾收集器。实际使用中,根据具体应用场景选择合适的垃圾收集器。 1、垃圾收集算法 垃圾收集算法可以从高…...

如何在算家云搭建Aatrox-Bert-VITS2(音频生成)

一、模型介绍 ‌ Aatrox - Bert -VITS2 模型是一种基于深度学习的语音合成系统,结合了 BERT 的预训练能力和 VITS2 的微调技术,旨在实现高质量的个性化语音合成。 二、模型搭建流程 1. 创建容器实例 进入算家云的“应用社区”,点击搜索找到…...

ceph灾备之cephfs snapshot mirror和rsync对比

背景 最近要做ceph集群之间的灾备功能,主要讨论文件存储,因为ceph集群容量越来越大,接入的业务也越来越多,一旦出现故障,恢复时间都是小时级(根据经验每年都会出现几次这种事故),对于核心业务无法接受&…...

【工具分享】Plutocrypt勒索病毒解密工具

前言 Plutocrypt勒索软件首次出现在2021年,作为CryptoJoker勒索软件的变种。该恶意软件通过钓鱼邮件和恶意链接传播,主要针对个人和小型企业用户。Plutocrypt使用了.NET框架开发,并依赖AES-256和RSA-4096的加密算法来加密受害者的文件。与Cr…...

IDEA启动提示Downloading pre-built shared indexes

Download pre-built shared indexes Reduce the indexing time and CPU load with pre-built JDK shared indexes 翻译: 下载预构建的共享索引 使用预构建的JDK共享索引减少索引时间和CPU负载. 使用预构建的JDK共享索引可以显著减少索引构建时间和CPU负载&#xf…...

[HCTF 2018]WarmUp 1--详细解析

打开靶机&#xff0c;进入界面&#xff1a; 信息搜集 当前界面没有任何有用信息。 想到查看页面源代码。右键–查看页面源代码 看到hint&#xff1a;<!--source.php--> 进入/source.php页面&#xff0c;看到页面源代码&#xff1a; <?phphighlight_file(__FILE_…...

软考教材重点内容 信息安全工程师 第1章 网络信息安全概述

第 1 章 网络信息安全概述 1.1.1 网络信息安全相关概念 狭义上的网络信息安全特指网络信息系统的各组成要素符合安全属性的要求&#xff0c;即机密性、完整性、可用性、抗抵赖性、可控性。 广义上的网络信息安全是涉及国家安全、城市安全、经济安全、社会安全、生产安全、人身安…...

TOSHIBA 74VHC00FT COMS汽车、工业企业的选择

74VHC00FT 是一种四路双输入 NAND 门&#xff0c;属于 CMOS 系列数字集成电路。它采用东芝先进的硅栅 C2MOS 技术设计&#xff0c;能够实现类似于双极性肖特基 TTL 逻辑电路的高速运行&#xff0c;同时保持 CMOS 器件的低功耗。这种独特的结合使其非常适合需要高性能和低功耗的…...

【Android】使用productFlavors构建多个变体

项目需求 在一个设备上安装两个一样的程序app 需求解决 我们知道每一个app都有一个包名的&#xff0c;如果一个app在Android设备上安装之后&#xff0c;再安装这个app的话会进行覆盖安装&#xff0c;因为他们两个的包名是一样的&#xff0c;默认是一个app。 但是我们现在需…...

ubuntu 22.04 防火墙 ufw

Ubuntu&#xff08;22.04&#xff09;云主机SSH安全加固 https://blog.csdn.net/qq_44846097/article/details/141098092 ubuntu22.04防火墙策略 https://blog.csdn.net/sunyuhua_keyboard/article/details/139493464 Ubuntu 22.04 防火墙设置和开放端口命令 https://blog.c…...

MySQL压缩版安装详细图解

1.下载 mysql压缩包版本和msi版的安装方法不一样&#xff0c;下面的是压缩包版本的安装详细图解&#xff1a; 总地址下载地址&#xff1a;MySQL :: Download MySQL Community Server MySQL :: Download MySQL Community Server (Archived Versions) 压缩版下载MySQL :: Dow…...

elementui中的新增弹窗在新增数据成功后再新增 发现数据无法清除解决方法

elementui中的新增弹窗在新增数据成功后再新增 发现数据无法清除解决方法 试过网上其他方法&#xff0c;发现表单清空数据还是有问题&#xff0c;索性用下面方法解决: // 给弹框里面添加 v-ifvisible测试无问题&#xff0c;暂时先这样解决&#xff0c;如果有其他方法&#x…...

软件开发项目管理:实现目标的实用指南

由于软件项目多数是复杂且难以预测的&#xff0c;对软件开发生命周期的深入了解、合适的框架以及强大的工作管理平台是必不可少的。项目管理系统在软件开发中通常以监督为首要任务&#xff0c;但优秀的项目计划、管理框架和软件工具可以使整个团队受益。 软件开发项目管理的主要…...

Jenkins面试整理-如何在 Jenkins 中进行并行构建?

在 Jenkins 中,并行构建 是通过并行执行多个任务来提高构建效率的常见方法。并行构建特别适用于需要执行多个独立步骤的工作流,如并行测试、构建不同平台上的软件或并行执行多个阶段。Jenkins 提供了两种方式来配置并行构建:Declarative Pipeline 和 Scripted Pipeline。下面…...

DPDK(F-Stack) 实现UDP通信

因刚开始学习DPDK&#xff0c;在学习过程中了解到需使用用户态协议栈&#xff0c;在网上找到F-Stack的相关介绍&#xff0c;但是缺乏DPDK的相关知识&#xff0c;导致使用F-Stack 时UDP数据无法收到 一文了解dpdk rte_ring无锁队列F-Stack实现UDP服务端、客户端&#xff0c;并进…...

基于ExtendSim的库存与订购实验

说明&#xff1a; 库存和订购实验室是一个单部件模拟模型&#xff0c;旨在测试从组件需求站点到组件分发站点的订购策略&#xff0c;以及 在组件分销现场的生产区域内。最佳解决方案允许为需求站点提供高服务级别&#xff0c;同时最大限度地降低总库存水平。 该模型演示了分层模…...

操作系统个人八股文总结

1.进程和线程的区别 进程和线程的定义 进程&#xff1a; 进程是一个运行中的程序实例&#xff0c;是资源分配的基本单位。每个进程都有自己的地址空间、数据、堆栈以及其他辅助数据。线程&#xff1a; 线程是进程中的一个执行单元&#xff0c;是CPU调度的基本单位。一个进程可…...

scala set训练

Set实训内容&#xff1a; 1.创建一个可变Set&#xff0c;用于存储图书馆中的书籍信息&#xff08;假设书籍信息用字符串表示&#xff09;&#xff0c;初始化为包含几本你喜欢的书籍 2.添加两本新的书籍到图书馆集合中&#xff0c;使用操作符 3.删除一本图书馆集合中的书籍&…...

【d63】【Java】【力扣】141.训练计划III

思路 使用递归实现 出口 &#xff0c;遇到null 每一层要做&#xff1a;把下层放进去&#xff0c;把本层放下去 代码 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { …...

【Linux】- 权限(2)

接上一篇文章&#xff0c;继续介绍linux权限的相关知识。https://blog.csdn.net/hffh123/article/details/143432940?spm1001.2014.3001.5501j 目录 一、chown&#xff1a;修改文件的拥有者 二、chgrp&#xff1a;修改文件所属组 三、关于other的介绍 四、文件类型 1、分类…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...