Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 新一代垃圾回收器 ZGC 收集器
文章目录
- 垃圾回收机制
- 垃圾收集器
- 垃圾收集器分类
- ZGC 收集器
- ZGC 的性能优势
- 复制算法
- 指针染色
- 读屏障
- ZGC 的工作过程
- Stop-The-World 暂停阶段
- 并发阶段
垃圾回收机制
垃圾回收(Garbage Collection,GC
),顾名思义就是释放垃圾占用的空间,当需要排查各种内存溢出问题、当垃圾收集成为系统达到更高并发的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。有效的使用可以使用的内存,对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收。
垃圾收集器
如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。Java 垃圾收集器(Garbage Collector, GC)是 Java 虚拟机(JVM)的一部分,它自动管理内存,回收不再使用的对象所占用的内存空间。这有助于防止内存泄漏,并且使得开发人员可以更专注于业务逻辑的编写而不是内存管理。
没有万能的垃圾收集器,只有根据具体应用场景选择适合自己的垃圾收集器。垃圾收集器是垃圾回收算法(如引用计数法、标记清除法、标记整理法、复制算法等)的具体实现。它的主要任务是识别并回收那些不再被程序使用的对象所占用的内存空间,从而避免内存泄漏和内存溢出的问题。
垃圾收集器分类
就目前来说,JVM 的垃圾收集器主要分为两大类:分代收集器和分区收集器,分代收集器的代表是 CMS
,分区收集器的代表是 G1
和 ZGC
JVM(Java虚拟机)垃圾回收机制 —— 垃圾收集器
JDK 默认垃圾收集器(使用 java -XX:+PrintCommandLineFlags -version
命令查看):
- JDK 8:
Parallel Scavenge
(新生代)+Parallel Old
(老年代) - JDK 9 ~ JDK20:
G1
ZGC 收集器
ZGC
(Z Garbage Collector) 是一种低延迟、可伸缩性强的垃圾回收器,是JVM 中的一项重要技术。ZGC的目标是 尽可能地减少垃圾回收对应用程序的停顿时间,并且可以处理大内存堆 。
它于Java 11版本中正式发布,适用于大内存低延迟服务的内存管理和回收,在 128G 的大堆下,最大停顿时间为 1.68 ms,停顿时间远胜于 G1
和 CMS
。
相关文章:新一代垃圾回收器ZGC的探索与实践 - 美团技术团队
通过下面的参数启动 ZGC:
$ java -XX:+UseZGC className
ZGC的设计原则是给予应用程序更多的时间来执行业务逻辑,以减少垃圾回收的停顿时间。它具有以下特点:
-
低停顿时间:ZGC 以毫秒为单位的短暂停顿时间作为目标,在控制在10ms以内。它通过并发的方式进行垃圾回收,减少对应用程序的影响。即使是大型堆内存,ZGC也能维持非常低的停顿时间。
-
可伸缩性:ZGC 的设计使其能够处理几个字节到数TB范围内的大型堆内存。它采用了柔性的并发策略,允许在并行、并发和单线程模式之间根据需要做出动态调整。
-
不需要设置-Xmx:与传统的垃圾回收器相比,ZGC不要求显式设置最大堆大小。ZGC可以自动按需调整堆的大小,并将内存释放给操作系统。
-
一致的性能:ZGC致力于提供一致的性能,无论是小型应用还是大型内存应用,都希望能够获得稳定的延迟和吞吐量。
ZGC 的性能优势
与 G1
和 CMS
类似,ZGC
也采用了复制算法
ZGC
在复制算法的基础上做了重大优化,ZGC 在标记、转移和重定位阶段几乎都是并发的,这是 ZGC
实现停顿时间小于 10ms 的关键所在。
-
ZGC
使用的是柔性并发(Colored Pointers) 的技术,通过将对象指针分成多个颜色(Colored)(指针染色技术),以实现并发的垃圾回收。 -
它在垃圾回收过程中会对引用关系进行处理,并且可以并发复制和重定向对象。同时,
ZGC
还采用了读屏障技术来保护并发操作中的数据一致性。
复制算法
复制算法主要包括以下 3 个阶段:
- 标记阶段:从 GC Roots 开始,分析对象可达性,标记出活跃对象。
-
对象转移阶段:把活跃对象复制到新的内存地址上。
-
重定位阶段:因为转移导致对象地址发生了变化,在重定位阶段,所有指向对象旧地址的引用都要调整到对象新的地址上。
标记阶段因为只标记 GC Roots
,耗时较短。但转移阶段和重定位阶段需要处理所有存活的对象,耗时较长,并且转移阶段是 STW
的,因此,G1 的性能瓶颈就主要在转移阶段。
指针染色
ZGC
在垃圾回收过程中会对引用关系进行处理,并且可以并发复制和重定向对象。同时,ZGC
还采用了读屏障技术来保护并发操作中的数据一致性。
在一个指针中,除了存储对象的实际地址外,还有额外的位被用来存储关于该对象的元数据信息。这些信息可能包括:
- 对象是否被移动了(即它是否在回收过程中被移动到了新的位置)。
- 对象的存活状态。
- 对象是否被锁定或有其他特殊状态。
通过在指针中嵌入这些信息,ZGC
在标记和转移阶段会更快,因为通过指针上的颜色就能区分出对象状态,不用额外做内存访问。
ZGC
仅支持64位系统,它把64位虚拟地址空间划分为多个子空间,如下图所示:
其中:
- 0-4TB 对应 Java 堆
- 4TB-8TB 被称为
M0 地址空间
- 8TB-12TB 被称为
M1 地址空间
- 12TB-16TB 预留未使用
- 16TB-20TB 被称为
Remapped 空间
。
当创建对象时,首先在堆空间申请一个虚拟地址,该虚拟地址并不会映射到真正的物理地址。同时,ZGC
会在 M0
、M1
、Remapped
空间中为该对象分别申请一个虚拟地址,且三个虚拟地址都映射到同一个物理地址。
下图是虚拟地址的空间划分:
三个空间在同一时间只有一个空间有效。ZGC
之所以设置这三个虚拟地址,是因为 ZGC
采用的是“空间换时间”的思想,去降低 GC
的停顿时间。与上述地址空间划分相对应,ZGC
实际仅使用64位地址空间的第0-41位,而第42-45位存储元数据,第47-63位固定为0。
由于仅用了第 0~43 位存储对象地址, 2 44 2^{44} 244 = 16TB,所以 ZGC 最大支持 16TB 的堆。而对象的存活信息,则存储在42-45位中,这与传统的垃圾回收并将对象存活信息放在对象头中完全不同。
读屏障
当程序尝试读取一个对象时,读屏障会触发以下操作:
-
检查指针染色:读屏障首先检查指向对象的指针的颜色信息。
-
处理移动的对象:如果指针表示对象已经被移动(例如,在垃圾回收过程中),读屏障将确保返回对象的新位置。
-
确保一致性:通过这种方式,ZGC 能够在并发移动对象时保持内存访问的一致性,从而减少对应用程序停顿的需要。
读屏障可能被 GC 线程和业务线程触发,并且只会在访问堆内对象时触发,访问的对象位于 GC Roots
时不会触发,这也是扫描 GC Roots
时需要 Stop The World
的原因。
下面是一个简化的示例代码,展示了读屏障的触发时机。
Object o = obj.FieldA // 从堆中读取引用,需要加入屏障
<Load barrier>
Object p = o // 无需加入屏障,因为不是从堆中读取引用
o.dosomething() // 无需加入屏障,因为不是从堆中读取引用
int i = obj.FieldB //无需加入屏障,因为不是对象引用
ZGC 的工作过程
ZGC 周期由三个 STW(Stop The World) 暂停和四个并发阶段组成:标记/重新映射(M/R)
、并发引用处理(RP)
、并发转移准备(EC)
和 并发转移(RE)
。
Stop-The-World 暂停阶段
-
标记开始(Mark Start)STW 暂停:这是 ZGC 的开始,进行 GC Roots 的初始标记。在这个短暂的停顿期间,ZGC 标记所有从 GC Root 直接可达的对象。
-
重新映射开始(Relocation Start)STW 暂停:在并发阶段之后,这个 STW 暂停是为了准备对象的重定位。在这个阶段,ZGC 选择将要清理的内存区域,并建立必要的数据结构以进行对象移动。
-
暂停结束(Pause End)STW 暂停:ZGC 结束。在这个短暂的停顿中,完成所有与该 GC 周期相关的最终清理工作。
并发阶段
-
并发标记/重新映射 (M/R) :这个阶段包括并发标记和并发重新映射。在并发标记中,ZGC 遍历对象图,标记所有可达的对象。然后,在并发重新映射中,ZGC 更新指向移动对象的所有引用。
-
并发引用处理 (RP) :在这个阶段,ZGC 处理各种引用类型(如软引用、弱引用、虚引用和幽灵引用)。这些引用的处理通常需要特殊的考虑,因为它们与对象的可达性和生命周期密切相关。
-
并发转移准备 (EC) :这是为对象转移做准备的阶段。ZGC 确定哪些内存区域将被清理,并准备相关的数据结构。
-
并发转移 (RE) :在这个阶段,ZGC 将存活的对象从旧位置移动到新位置。由于这一过程是并发执行的,因此应用程序可以在大多数垃圾回收工作进行时继续运行。
ZGC 的两个关键技术:指针染色和读屏障,不仅应用在并发转移阶段,还应用在并发标记阶段:将对象设置为已标记,传统的垃圾回收器需要进行一次内存访问,并将对象存活信息放在对象头中;而在 ZGC 中,只需要设置指针地址的第42-45位即可,并且因为是寄存器访问,所以速度比访问内存更快。
尽管ZGC在降低停顿时间方面表现出色,但与其他垃圾回收器相比,在某些特定场景或对于特定应用程序可能会有一些性能上的差异。因此,在选择垃圾回收器时需根据具体需求和应用程序特点进行评估和选择。
相关文章:

Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 新一代垃圾回收器 ZGC 收集器
文章目录 垃圾回收机制垃圾收集器垃圾收集器分类ZGC 收集器ZGC 的性能优势复制算法指针染色读屏障 ZGC 的工作过程Stop-The-World 暂停阶段并发阶段 垃圾回收机制 垃圾回收(Garbage Collection,GC),顾名思义就是释放垃圾占用的空…...

基于 K8S kubernetes 的常见日志收集方案
目录 1、日志对我们来说到底重不重要? 2、常见的日志收集方案 2.1 EFK 2.2 ELK Stack 2.3 ELKfilebeat 2.4 其他方案 2、elasticsearch组件介绍 3、filebeat组件介绍 3.1 filebeat和beat关系 3.2 filebeat是什么? 3.3 Filebeat工作原理 3.4 …...

Unity3D 小案例 像素贪吃蛇 02 蛇的觅食
Unity3D 小案例 像素贪吃蛇 第二期 蛇的觅食 像素贪吃蛇 食物生成 在场景中创建一个 2D 正方形,调整颜色,添加 Tag 并修改为 Food。 然后拖拽到 Assets 文件夹中变成预制体。 创建食物管理器 FoodManager.cs,添加单例,可以设置…...

【sgCreateCallAPIFunction】自定义小工具:敏捷开发→调用接口方法代码生成工具
<template><div :class"$options.name" class"sgDevTool"><sgHead /><div class"sg-container"><div class"sg-start"><div style"margin-bottom: 10px">调用接口方法定义列表</div…...

京东商品详情的 API 探秘与应用
在当今数字化的商业世界中,获取准确而详细的商品信息对于开发者、商家以及消费者都具有至关重要的意义。京东作为国内领先的电商平台之一,提供了丰富的商品资源和强大的 API 接口,让我们能够轻松获取京东商品的详情信息。本文将带你深入了解如…...

功能测试干了三年,快要废了。。。
8年前刚进入到IT行业,到现在学习软件测试的人越来越多,所以在这我想结合自己的一些看法给大家提一些建议。 最近聊到软件测试的行业内卷,越来越多的转行和大学生进入测试行业,导致软件测试已经饱和了,想要获得更好的待…...

【C++】多态的认识和理解
个人主页 文章目录 ⭐一、多态的概念🎄二、多态的定义及实现1.多态的构成2.实现多态的条件3.虚函数的概念4.虚函数的重写和覆盖5.析构函数的重写6.协变7.override和 final关键字8.重载、重写/覆盖、隐藏这三者的区别 🏠三、纯虚函数和抽象类的关系&#…...

linux-安全管理-用户认证
Linux 安全管理:用户认证 一、概述 用户认证是 Linux 安全管理的核心部分,确保系统能够识别并验证合法用户,同时阻止未经授权的访问。Linux 提供了多种用户认证机制,包括用户名和密码认证、基于密钥的认证、双因素认证ÿ…...

webpack5 构建优化方案看这篇就够了!【Node.js进阶】
无论在面试还是内部晋升,webpack 构建优化方案 一直都是非常重要的部分。 webpack5构建加持 一、项目完成目标二、搭建项目1. 安装koa、koa/router (如果已经配置可路过)2. 创建入口文件3. 安装构建依赖4. 在项目根目录添加 .babelrc 文件5. …...

esp32-C2 对接火山引擎实现智能语音(一)
目录 一、火山引擎大模型简介 1)火山引擎网址: 2)首先需要先注册火山引擎账号 3)语音识别——即语音转为文本 一句话识别 流式语音识别 录音文件识别标准版 录音文件识别极速版 4)语音合成——文本转音频 一、火山引擎大模型简介 火山引擎的智能语音技术,基于业界先…...

【MySQL-初级】mysql基础操作(账户、数据库、表的增删查改)
概述 数据备份与恢复 数据库备份:在cmd下 root用户:sudo mysqldump -u root -p Test > Test.sql普通用户:mysqldump -u zzz -p db_name > db_name.sql 数据库恢复 先创建一个空的数据库在cmd下:sudo mysql -u root -p d…...

centos bash脚本一键运行安装go环境
复制到install_go.sh直接bash install_go.sh运行就完了 echo ----------安装go环境 wget https://go.dev/dl/go1.21.13.linux-amd64.tar.gz tar -zxvf go1.21.13.linux-amd64.tar.gzmkdir /srv cp -r go /srv/echo "PATH$PATH:/srv/go/bin ">> ~/.bashrc echo…...

vue2制作高复用页面
记录一下页面搭建记录,利用vue2组件化开发的思想。这个页面适合于大部分信息管理系统~。模板固定,每次使用,直接修改表单表格参数,api接口等。 以上图页面为例,一个基础数据信息页面可以分为,分类ÿ…...

Feed流系统重构:架构篇
重构对我而言,最大的乐趣在于解决问题。我曾参与一个C#彩票算奖系统的重构,那时系统常因超时引发用户投诉。接手任务时,我既激动又紧张,连续两天几乎废寝忘食地编码。结果令人振奋,算奖时间从一小时大幅缩短至十分钟。…...

Android 后台服务之Persistent 属性
在 Android 开发中,有时我们需要后台服务持续运行,以保持应用的某些功能。例如,音乐播放器需要在后台播放音乐,或者健康应用需要持续跟踪用户的运动数据。后台服务是 Android 中的一种组件,它不与用户界面交互,能够在后台执行长时间运行的任务。由于 Android 系统的资源管…...

STM32+ESP01连接到机智云
机智云,全球领先的智能硬件软件自助开发及物联网(iot)云服务平台。机智云平台为开发者提供了自助式智能硬件开发工具与开放的云端服务。通过傻瓜化的自助工具、完善的SDK与API服务能力最大限度降低了物联网硬件开发的技术门槛,降低开发者的研发成本,提升…...

电脑实时监控软件有哪些?七个电脑屏幕监控软件任你选择
电脑实时监控软件种类繁多,每款软件都有其独特的功能和适用场景。 以下是七个备受推荐的电脑屏幕监控软件,供您选择: 1.安企神: 功能:它是一款国内领先的企业级电脑监控解决方案, 提供实时屏幕监控、 文…...

信奥学习规划(CSP-J/S)
CSP-J组学习路线规划 CSP-S组学习规划...

【Linux取经之路】编译器gcc/g++的使用 调试器gdb的使用
目录 背景知识 编译器gcc/g的安装 编译器gcc/g的使用 调试器gdb的使用 cgdb 条件断点 背景知识 子曰:“温故而知新”。在谈gcc/g的使用之前,我们先来复习编译的4个阶段,也算是为下面的内容做一些铺垫,请看思维导图。 编译…...

自动化流程机器人(RPA)
自动化流程机器人(RPA)正逐渐成为企业提高效率和降低成本的强有力工具。 一、RPA的概念 自动化流程机器人(Robotic Process Automation,简称RPA)是一种利用软件机器人(Robot)模拟和执行复杂任务…...

Unity persistentDataPath使用案例
Unity persistentDataPath使用案例 一、Application.persistentDataPath 1、概念 persistentDataPath:此属性用于返回一个持久化数据存储目录的路径,可以在此路径下存储一些持久化的数据文件;是一个可读写的目录;此文件夹在Edi…...

Android 测试手册
1. 介绍 Android 测试是确保应用程序质量的重要步骤。它包括不同类型的测试,用于验证应用程序的功能、性能、安全性和用户体验。这个手册将指导你了解和实施 Android 测试的主要方法和工具。 2. 测试类型 2.1 单元测试 目的:验证单个组件(…...

各大平台统遭入侵??区块链市场遭攻击损失近3亿!
今年,全球发生多起骇人听闻的勒索入侵软件攻击事件,黑客组织利用各种手段和技术,不断试图突破网络安全防线,窃取敏感信息、破坏系统运行,甚至进行勒索和敲诈,使得网络安全问题日益凸显其重要性和紧迫性。 S…...

Java泛型(“代码模板”,一套代码套用各种类型)
1.什么是泛型 a.定义 i.如果不用泛型定义,在使用ArrayList时需要为每个class编写特定类型代码。 ii.泛型就是定义一种模板,既实现了编写一次,万能匹配,又通过编译器保证了类型安全。 iii.编写模板代码来适应任意…...

速响低代码平台:升级营销管理系统,开启高效无忧新体验!
当前日新月异的商业环境,企业面临着前所未有的挑战与机遇。随着市场竞争的日益加剧和企业业务的不断拓展,传统的营销方式和管理手段逐渐显露出其局限性,难以适应快速变化的市场需求。 数据收集难:传统的营销管理缺乏对客户数据的收…...

Gitlab升级14.0.12-->14.3.6遇到的gitlab-ctl reconfigure错误
问题描述 在按照官方文档升级路线11.0.2>17.2.2的过程中,升级14.0.12–》14.3.6时遇到一个错误: Running handlers: There was an error running gitlab-ctl reconfigure:rails_migration[gitlab-rails] (gitlab::database_migrations line 51) had…...

JDBC导图
思维歹徒 一、使用步骤 二、SQL注入 三、数据库查询(查询) 四、数据库写入(增删改) 五、Date日期对象处理 六、连接池使用 创建连接是从连接池拿,释放连接是放回连接池 七、事务和批次插入 八、Apache Commons DBUtil…...

飞思实验室与中飞院联合开发教学课程,校企联袂共绘教育蓝图
近日,飞思实验室与中国民用航空飞行学院(以下简称“中飞院”) 航空电子电气学院合作,共同开发《无人智能视觉导航控制技术》、《多旋翼无人飞行器集群系统》实验课程。这一举措旨在深化校企融合,学校通过引入企业带来的…...

Telephony Call
1、Telephony 架构 Telephony整体架构和Android架构一样的,包括APP层,框架层,HAL层,内核层。 其中HAL层不同平台实现方式不同,其中MTK SPRD 平台使用AT通道的方式实现,高通使用QMI方式实现。 2、通话业务介绍 APP包括Dialer.apk、TeleService.apk、Tele…...

Python--TCP/UDP通信
文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 一.客户端与服务端通信原理 1. 服务器端 服务器端的主要任务是监听来自客户端的连接请求,并与之建立连接,然后接收和发送数据。 创建套接字:首先࿰…...