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

【JVM】垃圾收集器详解

你将学到

1. Serial 收集器

2. ParNew 收集器

3. Parallel Scavenge 收集器

4. Serial Old 收集器

5. Parallel Old 收集器

6. CMS 收集器

7. G1 收集器


在 Java 中,垃圾回收(GC)是自动管理内存的一个重要机制。HotSpot JVM 提供了多种垃圾收集器,供开发者根据不同的应用场景进行选择。每种垃圾收集器都有其独特的实现原理、优缺点以及适用场景。在这篇博客中,我们将详细介绍 HotSpot JVM 中的 7 种垃圾收集器,帮助开发者更好地理解它们,并在不同的项目中做出最优的选择。 

 HotSpot 虚拟机中的7个垃圾收集器,图中有连线的说明是可以一起搭配使用的,下面针对每一个垃圾收集器,作单独的讲解。


1. Serial 收集器

Serial收集器是在进行垃圾收集时,必须暂停其他所有工作线程(Stop The World)。Stop The World并不是啥好事,因为它会导致用户线程停止工作,所以有些真实应用来说是无法接受的。

总结:

  • Serial 翻译为串行,也就是说它以串行的方式执行Serial 是新生代的垃圾收集器
  • 算法:复制算法
  • HotSpot 虚拟机运行在客户端模式下的默认新生代收集器

2. ParNew 收集器

ParNew垃圾收集器Parallel Garbage Collector 的一个变种,它专门用于 年轻代(Young Generation) 的垃圾回收,ParNew 的设计目的是提高 年轻代垃圾回收的吞吐量,通常通过 并行处理 来缩短回收时间,减少停顿时间。

总结:

  • 垃圾收集时是多线程并行的
  • ParNew是新生代的垃圾收集器
  • 使用的是复制算法
  • 在 CMS 收集器中,ParNew 用于年轻代垃圾回收,而老年代则由 CMS 来进行回收。ParNew 和 CMS 共同合作,减少了老年代的 Full GC 触发次数,并优化了停顿时间
  • 使用 -XX:ParallelGCThreads 参数来设置GC线程数

3. Parallel Scavenge 收集器

Parallel Scavenge 收集器,是 HotSpot JVM 中的一种 年轻代(Young Generation) 垃圾收集器。它专注于提高 吞吐量,通过并行化的方式来减少垃圾回收过程中的时间开销。Parallel Scavenge 是基于 复制算法(Copying Algorithm)实现的,并且通过多线程的方式来加速垃圾回收过程。这里的吞吐量指 CPU 用于运行用户代码的时间占总时间的比值。

吞吐量 = 运行用户代码的时间/(运行用户代码的时间+运行垃圾收集的时间)

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

总结

  • 吞吐量优先收集器
  • 新生代垃圾收集器
  • 算法:复制算法
  • 两个精确控制吞吐量的参数
    • 控制最大垃圾收集停顿时间:-XX:MaxGCPauseMilis。
    • 直接设置吞吐量大小:XX:GCTimeRatio。
  • GC 自适应的调节策略开关:开启开关,就不需要手动指定新生代的大小(-Xmm)、Eden 和 Survivor 区的比例、晋升老年代对象年龄等细节参数了。虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量。(XX:+UseAdaptiveSizePolicy)

4. Serial Old 收集器

erial Old 收集器 是 HotSpot JVM 中的一种 老年代(Old Generation) 垃圾收集器。它是 Serial Garbage Collector 的一个扩展版本,用于全堆垃圾回收时处理老年代的内存。Serial Old 的设计理念和 Serial GC 一致,主要特点是使用 单线程 执行垃圾回收任务,适用于资源受限或者对垃圾回收停顿时间不敏感的场景。

总结

  • 老年代收集器
  • 算法:标记-整理算法
  • gc时暂停所有用户线程
  • 主要作为客户端模式下的HotSpot虚拟机使用,另外也作为CMS收集器并发收集发生Concurrent Mode Failure时的后备预案使用

5. Parallel Old 收集器

Parallel Old是Paralle Scavenge收集器的老年代版本,多线程并行收集。目前只能与新生代的Parallel Scavenge收集器搭配使用,可以说Parallel Old就是为Parallel Scavenge而生的。在这之前Parallel Scavenge收集器只能与老年代的Serial Old进行搭配,但是一个多线程,一个单线程,导致吞吐量并没有充分的提升,直到Parallel Old收集器出现。

总结:

  • Parallel Old为Parallel Scavenge而生,只能搭配Parallel Scavenge。
  • Parallel Old采用多线程
  • 算法:标记-整理
  • 在注重吞吐量以及处理器资源较为稀缺的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器这个组合
  • JDK 6时才开始提供

6. CMS 收集器

CMS(Concurrent Mark-Sweep) 收集器是 HotSpot JVM 提供的一种 低延迟 垃圾收集器,旨在减少垃圾回收过程中的停顿时间。它的主要目标是 最小化停顿时间,使得应用程序能够在垃圾回收的过程中尽可能保持运行状态,特别适用于对响应时间敏感的应用。

原理

CMS 收集器主要采用了 标记-清除(Mark-Sweep)算法,结合了并发执行来优化标记和清除阶段,减少了停顿时间。它的工作过程分为多个阶段:

  1. 初始标记(Initial Mark)

    • 初始标记阶段是 Stop-the-World 的,这意味着在这个阶段应用程序会暂停。该阶段会标记 GC Root 可达的对象。
    • 这个阶段会很快完成,因为只标记根对象的引用,不需要遍历整个堆。
  2. 并发标记(Concurrent Mark)

    • 在并发标记阶段,CMS 会并发地扫描整个堆,标记出所有存活的对象。
    • 这个阶段是 并发执行的,也就是说,在标记阶段,应用程序的线程可以继续运行,尽量减少停顿时间。
    • 但并发标记阶段的执行时间较长,且可能需要使用多个 CPU 核心来加速标记过程。
  3. 重新标记(Remark)

    • 在并发标记完成后,还需要进行 重新标记 阶段。这个阶段用于标记在并发标记过程中被修改的对象(即那些在并发标记过程中被修改了引用关系的对象)。此阶段也是 Stop-the-World 的,因此应用程序会暂停。
    • 重新标记是一个很短的阶段,主要用于修正并发标记阶段标记不全的问题。
  4. 并发清除(Concurrent Sweep)

    • 在并发清除阶段,CMS 会清理那些没有被标记为存活的垃圾对象。
    • 这个阶段是并发执行的,应用程序线程可以继续运行。

优点 并发收集,低停顿

不足

  • 吞吐量低:CMS追求用户线程停顿时间少,停顿时间少就只能与用户线程并发执行部分阶段,导致整个垃圾回收需要执行的整体时间会更长(停顿之后专心垃圾收集肯定是最快的),所以吞吐量会降低
  • 浮动垃圾问题:并发清除阶段,由于gc线程是与用户线程并发的,这个期间用户还会产生新的垃圾,所以一般会预留出一部分内存,不能等到老年代快满的时候才去收集,如果预留的内存不足以存放这部分浮动垃圾的话,就会出现Concurrent ModeFailure。出现这个错误之后,虚拟机将临时启用 Serial Old 来替代 CMS
  • 使用标记-清除算法:因为没有整理的过程,所以垃圾收集完之后,会有很多空间碎片,导致需要分配大块连续内存的时候,空间不足

7. G1 收集器

Garbage First(简称G1)收集器,意为垃圾优先,哪一块的垃圾最多就优先清理它。从名字就可以看出G1的一个特性,那就是G1能对不同区块的内存进行回收价值和成本排序,即价值越高成本越低的区块会被先回收。另外我们还能为G1设定性能指标,例如任意 1秒内暂停时间不超过 10 毫秒,G1会尽力去达成这个目标。

开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。JDK8 Update 40这个版本以后的G1收集器被Oracle官方称为“全功能的垃圾收集器”。JDK 9发布之 日,G1宣告取代Parallel Scavenge加Parallel Old组合,成为服务端模式下的默认垃圾收集器。

G1依然还是采用了分代设计,但是之前的一些垃圾收集器有很大差别,不会在为新生代,老年代等分配规定大小的区域,而是将整个堆分成一个个大小固定的Region区域每一个Region都可以是新生代,老年代,Eden空间,Survivor空间的角色。所以Region成为了垃圾收集的最小单元,每一次回收都会是Region的整数倍大小。

  • 初始标记:仅仅只是标记一下GC Roots能直接关联到的对象。(需要停顿)
  • 并发标记:从GC Roots开始进行可达性分析,完成对象图的扫描,判断存活对象和可回收对象。做后再处理下SATB记录的有引用变动的对象(无需停顿)
  • 最终标记:对用户线程做另一个短暂的停顿,用于处理并发阶段结束后仍遗留 下来的最后那少量的SATB记录。(需要停顿)
  • 筛选回收:统计各个Region的回收价值和成本并进行排序,根据用户所期望的停顿时间来制定回收计划,筛选任意多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧 Region的全部空间。(需要停顿) 

总结:

相关文章:

【JVM】垃圾收集器详解

你将学到 1. Serial 收集器 2. ParNew 收集器 3. Parallel Scavenge 收集器 4. Serial Old 收集器 5. Parallel Old 收集器 6. CMS 收集器 7. G1 收集器 在 Java 中,垃圾回收(GC)是自动管理内存的一个重要机制。HotSpot JVM 提供了多种…...

python创建一个httpServer网页上传文件到httpServer

一、代码 1.server.py import os from http.server import SimpleHTTPRequestHandler, HTTPServer import cgi # 自定义请求处理类 class MyRequestHandler(SimpleHTTPRequestHandler):# 处理GET请求def do_GET(self):if self.path /:# 响应200状态码self.send_response(2…...

【Maui】提示消息的扩展

文章目录 前言一、问题描述二、解决方案三、软件开发(源码)3.1 消息扩展库3.2 消息提示框使用3.3 错误消息提示使用3.4 问题选择框使用 四、项目展示 前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移…...

租车骑绿岛

租车骑绿岛 真题目录: 点击去查看 E 卷 100分题型 题目描述 部门组织绿岛骑行团建活动。租用公共双人自行车,每辆自行车最多坐两人,最大载重M。给出部门每个人的体重,请问最多需要租用多少双人自行车。 输入描述 第一行两个数字m、n&…...

Pytorch - YOLOv11自定义资料训练

►前言 本篇将讲解目前最新推出的YOLOv11搭配Roboflow进行自定义资料标注训练流程,透过Colab上进行实作说明,使大家能够容易的了解YOLOv11的使用。 ►YOLO框架下载与导入 ►Roboflow的资料收集与标注 进行自定义资料集建置与上传 透过Roboflow工具进行…...

微服务与docker

准备工作 在课前资料中给大家提供了黑马商城项目的资料,我们需要先导入这个单体项目。不过需要注意的是,本篇及后续的微服务学习都是基于Centos7系统下的Docker部署,因此你必须做好一些准备: Centos7的环境及一个好用的SSH客户端装好Docker会使用Docker如果是学习过上面Doc…...

1.23 消息队列

使用消息队列&#xff0c;实现两个终端相互聊天 程序代码&#xff1a; w1.c #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h&g…...

【华为路由的arp配置】

华为路由的arp配置 ARP&#xff1a;IP地址与MAC地址的映射。 R1: g0/0/0:10.1.1.254/24 g0/0/1:10.1.2.254/24 PC1: 10.1.1.1/16 PC2: 10.1.1.2/16 PC3: 10.1.2.3/16 动态ARP 查看PC1的arp表&#xff0c;可以看到&#xff0c;列表为空。 查看R1的arp表 在PC3上ping命令测…...

绘制决策树的尝试1

代码复制 import pydotplus 复制 - 这一行代码用于导入pydotplus模块&#xff0c;这是一个用来在Python中创建图形的工具。2. python from IPython.display import Image 这一行代码用于从IPython显示模块中导入Image类&#xff0c;它允许我们在Jupyter笔记本中显示图像。…...

概率论里的特征函数,如何用卷积定理去理解

概率论里的特征函数&#xff0c;如何用卷积定理去理解_哔哩哔哩_bilibili...

Spring 是如何解决循环依赖问题

Spring 框架通过 三级缓存 机制来解决循环依赖问题。循环依赖是指两个或多个 Bean 相互依赖&#xff0c;形成一个闭环&#xff0c;例如 Bean A 依赖 Bean B&#xff0c;而 Bean B 又依赖 Bean A。Spring 通过提前暴露未完全初始化的 Bean 来解决这个问题。 以下是 Spring 解决…...

Linux 目录操作详解

Linux目录操作详解 1. 获取当前工作目录1.1 getcwd()1.2 get_current_dir_name() 2. 切换工作目录2.1 chdir() 3. 创建和删除目录3.1 mkdir()3.2 rmdir() 4. 获取目录中的文件列表4.1 opendir() 打开目录4.2 readdir() 读取目录内容4.3 closedir() 关闭目录 5. dirent 结构体6.…...

Elasticsearch的经典面试题及详细解答

以下是一些Elasticsearch的经典面试题及详细解答&#xff1a; 一、基础概念与原理 什么是Elasticsearch&#xff1f; 回答&#xff1a; Elasticsearch是一个基于Lucene的分布式搜索引擎&#xff0c;提供了RESTful API&#xff0c;支持多租户能力。它能够快速、近实时地存储、搜…...

Linux-arm(1)ATF启动流程

Linux-arm(1)ATF启动流量 Author&#xff1a;Once Day Date&#xff1a;2025年1月22日 漫漫长路有人对你微笑过嘛… 全系列文章可查看专栏: Linux实践记录_Once_day的博客-CSDN博客 参考文档&#xff1a; ARM Trusted Firmware分析——启动、PSCI、OP-TEE接口 Arnold Lu 博…...

C#编程:List.ForEach与foreach循环的深度对比

在C#中&#xff0c;List<T>.ForEach 方法和传统的 foreach 循环都用于遍历列表中的元素并对每个元素执行操作&#xff0c;但它们之间有一些关键的区别。 List<T>.ForEach 方法 方法签名&#xff1a;public void ForEach(Action<T> action)类型&#xff1a;…...

C语言文件操作:标准库与系统调用实践

目录 1、C语言标准库文件操作 1.1.题目要求&#xff1a; 1.2.函数讲解&#xff1a; fopen 函数原型 参数 常用的打开模式 返回值 fwrite函数 函数原型 参数 返回值 注意事项 fseek函数 函数原型 参数 返回值 fread函数 函数原型 参数 返回值 fclose 函数…...

代码随想录 栈与队列 test 7

347. 前 K 个高频元素 - 力扣&#xff08;LeetCode&#xff09; 首先想到哈希&#xff0c;用key来存元素&#xff0c;value来存出现次数&#xff0c;最后进行排序&#xff0c;时间复杂度约为o(nlogn)。由于只需求前k个&#xff0c;因此可以进行优化&#xff0c;利用堆来维护这…...

C语言练习(21)

有一行电文&#xff0c;已按下面规律译成密码&#xff1a; A→Za→Z B→Yb→y C→Xc→X 即第1个字母变成第26个字母&#xff0c;第2个字母变成第25个字母&#xff0c;第i个字母变成第&#xff08;26-i十1&#xff09;个字母。非字母字符不变。假如已知道密码是Umtorhs&…...

智能手机“混战”2025:谁将倒下而谁又将突围?

【潮汐商业评论原创】 “去年做手机比较艰难&#xff0c;几乎每个品牌都在调价、压货&#xff0c;像华为这种以前都不给我们分货的厂商&#xff0c;也开始成为我的主要库存。不过今年开头比较好&#xff0c;20号国补一开始&#xff0c;店里的人流和手机销量就明显涨了不少&…...

计算机图形学:实验一 OpenGL基本绘制

1.OpenGL的环境配置&#xff1a; 集成开发环境Visual Studio Community 2019的安装&#xff1a; 在Windows一栏选择使用C的桌面开发&#xff1b;再转到“单个组件”界面&#xff0c;在“编译器、生成工具和运行时”一栏选择用于“Windows的C CMake工具”&#xff1b;然后转到…...

二分查找题目:快照数组

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;快照数组 出处&#xff1a;1146. 快照数组 难度 7 级 题目描述 要求 实现支持下列接口的快照数组&#xff1a; SnapshotArray(int length) \textt…...

深度学习|表示学习|卷积神经网络|参数共享是什么?|07

如是我闻&#xff1a; Parameter Sharing&#xff08;参数共享&#xff09;是卷积神经网络&#xff08;CNN&#xff09;的一个重要特性&#xff0c;帮助它高效地处理数据。参数共享的本质就是参数“本来也没有变过”。换句话说&#xff0c;在卷积层中&#xff0c;卷积核的参数&…...

基于相机内参推导的透视投影矩阵

基于相机内参推导透视投影矩阵&#xff08;splatam&#xff09;&#xff1a; M c a m [ 2 ⋅ f x w 0.0 ( w − 2 ⋅ c x ) w 0.0 0.0 2 ⋅ f y h ( h − 2 ⋅ c y ) h 0.0 0 0 f a r n e a r n e a r − f a r 2 f a r ⋅ n e a r n e a r − f a r 0.0 0.0 − 1.0 0.0 ] M_…...

浅析Dubbo 原理:架构、通信与调用流程

一、Dubbo 简介 Dubbo 是阿里巴巴开源的高性能、轻量级的 Java RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;框架&#xff0c;旨在实现不同服务之间的远程通信和调用。在分布式系统中&#xff0c;不同服务可能部署在不同的服务器上&#xff0c;D…...

03垃圾回收篇(D3_垃圾收集器的选择及相关参数)

目录 学习前言 一、收集器的选择 二、GC日志参数 三、垃圾收集相关的常用参数 四、内存分配与回收策略 1. 对象优先在Eden分配 2. 大对象直接进入老年代 3. 长期存活的对象将进入老年代 4. 动态对象年龄判定 5. 空间分配担保 学习前言 本章主要学习垃圾收集器的选择及…...

一、引论,《组合数学(第4版)》卢开澄 卢华明

零、前言 发现自己数数题做的很烂&#xff0c;重新学一遍组合数学吧。 参考卢开澄 卢华明 编著的《组合数学(第4版)》&#xff0c;只打算学前四章。 通过几个经典问题来了解组合数学所研究的内容。 一、幻方问题 据说大禹治水之前&#xff0c;河里冒出来一只乌龟&#xff0c…...

Vue3+TS 实现批量拖拽文件夹上传图片组件封装

1、html 代码&#xff1a; 代码中的表格引入了 vxe-table 插件 <Tag /> 是自己封装的说明组件 表格列表这块我使用了插槽来增加扩展性&#xff0c;可根据自己需求&#xff0c;在组件外部做调整 <template><div class"dragUpload"><el-dialo…...

二叉树的所有路径(力扣257)

因为题目要求路径是从上到下的&#xff0c;所以最好采用前序遍历。这样可以保证按从上到下的顺序将节点的值存入一个路径数组中。另外&#xff0c;此题还有一个难点就是如何求得所有路径。为了解决这个问题&#xff0c;我们需要用到回溯。回溯和递归不分家&#xff0c;每递归一…...

Python OrderedDict 实现 Least Recently used(LRU)缓存

OrderedDict 实现 Least Recently used&#xff08;LRU&#xff09;缓存 引言正文 引言 LRU 缓存是一种缓存替换策略&#xff0c;当缓存空间不足时&#xff0c;会移除最久未使用的数据以腾出空间存放新的数据。LRU 缓存的特点&#xff1a; 有限容量&#xff1a;缓存拥有固定的…...

LabVIEW项目中的工控机与普通电脑选择

工控机&#xff08;Industrial PC&#xff09;与普通电脑在硬件设计、性能要求、稳定性、环境适应性等方面存在显著差异。了解这些区别对于在LabVIEW项目中选择合适的硬件至关重要。下面将详细分析这两种设备的主要差异&#xff0c;并为LabVIEW项目中的选择提供指导。 ​ 硬件设…...