深入分析 Java ZGC
传统的垃圾回收
我们在开发 Java 程序时,并不需要显示释放内存,Java 的垃圾回收器会自动帮我们回收。GC 会自动监测对象引用,并释放不可达的对象。GC 需要监测堆内存中对象的状态,如果一个对象不可达,GC 就可以考虑回收这个对象。
CMS 与 G1 停顿时间瓶颈
在介绍 ZGC 之前,首先回顾一下 CMS 和 G1 的 GC 过程以及停顿时间的瓶颈。CMS 新生代的 Young GC、G1 和 ZGC 都基于标记-复制算法,但算法具体实现的不同就导致了巨大的性能差异。
标记-复制算法应用在 CMS 新生代(ParNew 是 CMS 默认的新生代垃圾回收器)和 G1 垃圾回收器中。标记-复制算法可以分为三个阶段:
- 标记阶段,即从 GC Roots 集合开始,标记活跃对象;
- 转移阶段,即把活跃对象复制到新的内存地址上;
- 重定位阶段,因为转移导致对象的地址发生了变化,在重定位阶段,所有指向对象旧地址的指针都要调整到对象新的地址上。
CMS 在 JDK11 已经被 G1 所取代,G1 GC 的详细算法可以参考文章:JVM G1GC 的算法与实现。
ZGC 概览
The Z Garbage Collector, also known as ZGC, is a scalable low latency garbage collector designed to meet the following goals:
- Sub-millisecond max pause times
- Pause times do not increase with the heap, live-set or root-set size
- Handle heaps ranging from a 8MB to 16TB in size
总结下来就是:
- 停顿时间不超过 10ms;
- 停顿时间不会随着堆的大小,或者活跃对象的大小而增加;
- 支持 8MB~4TB 级别的堆,未来支持 16TB。
ZGC was initially introduced as an experimental feature in JDK 11, and was declared Production Ready in JDK 15.
ZGC 的主要特点:
- Concurrent
- Region-based
- Compacting
- NUMA-aware
- Using colored pointers
- Using load barriers
At its core, ZGC is a concurrent garbage collector, meaning all heavy lifting work is done while Java threads continue to execute. This greatly limits the impact garbage collection will have on your application's response time.
This OpenJDK project is sponsored by the HotSpot Group.
ZGC 有一个“marking”的阶段,可以找到可达对象。GC 可以使用多种方法来存储对象的状态信息:比如创建一个 Map,key 是内存地址,value 是该地址上对象的状态信息。这种方法虽然简单,但是需要使用额外的内存来存储这些状态;同时维护这样的 Map 也是一个挑战。
ZGC 使用了一种完全不同的叫 着色指针(reference coloring) 方法:使用对象引用中的特定比特位来存储对象的状态。但是这种方法也有一个挑战,使用引用位来存储对象的元信息意味着多个引用可以指向同一个对象,因为对象位并不保存有关对象位置的任何信息。我们可以使用多重映射来解决此问题。
我们还希望解决内存碎片的问题。ZGC 使用 relocation 来解决这个问题。但是对于一个很大的堆来说,relocation 过程会非常慢。因为 ZGC 并不希望有很长的延时,ZGC 会将大多数的 relocation 过程与应用程序并行执行。但是这又引入了另一个问题。
比方说我们有了一个对象的引用,ZGC relocation 了这个对象,紧接着发生了线程的上下文切换,用户线程正在试图获取这个对象的旧内存地址。ZGC 使用 读屏障(load barriers) 来解决这个问题。load barrier 是线程从堆中获取一个对象引用时加入的一小段代码——比如我们需要访问一个对象的非原始类型的字段。
在 ZGC 中,load barrier 会检查引用元信息中的特定位,根据这些位的信息,ZGC 可能会在我们得到引用之前做一些处理,可能产生一个完全不同的引用,我们称这个过程为“重映射 remapping”。
深入 ZGC 原理
标记 Marking
ZGC 将标记分为 3 个阶段:
- stop-the-world 阶段。在这个阶段,我们寻找并标记根引用(root references)。根引用是堆中可达对象的起点,可以是局部变量或静态字段。这个阶段通常时间非常短,因为根引用的数量一般都非常小;
- concurrent 阶段。在这个阶段,我们从根引用开始遍历对象图,并标记每个到达的对象;
- stop-the-world 阶段。处理一些如弱引用的边缘情况。
此时我们就知道哪些对象是可达的。ZGC 使用 marked0 和 marked1 元数据位进行标记。
着色指针 Reference Coloring
一个引用就代表虚拟内存中一个字节的位置。我们并不需要使用引用的所有位来标识位置。在 32 位系统中,我们只能寻址 4GB 内存。由于现代计算机基本都有比这更多的内存,我们显然不能占用着 32 位中的任意一位。因此 ZGC 需要使用 64 位引用,这也就意味着 ZGC 仅适用于 64 位平台。
ZGC 引用使用 42 位来表示地址,引用可以寻址 4TB 的内存空间。最重要的是,我们有 4 位来存储引用的状态:
- finalizable 位:该对象只能通过终结器(finalizer)访问
- remap 位:引用是最新的,并指向对象的当前位置
- marked0 和 marked11 位:标记可达对象
我们称这些位为元数据位,ZGC 中这些位有且仅有一个位是 1。
Relocation
在 ZGC 中,Relocation 包括以下几个阶段:
- 并发阶段。查找需要重新定位的块,将它们加入 Relocation 候选集合。
- stop-the-world 阶段。重定位重定位集中的所有根引用并更新它们的引用。
- 并发节点。将重定位集中的所有剩余对象重定位,并将旧地址和新地址之间的映射存储在转发表中。
- 剩余引用的重写发生在下一个标记阶段。我们不需要两次遍历对象树。
重映射和读屏障 Remapping and Load Barriers
读屏障是 JVM 向应用代码插入一小段代码的技术。当应用线程从堆中读取对象引用时,就会执行这段代码。需要注意的是,仅“从堆中读取对象引用”才会触发这段代码。
读屏障示例:
Object o = obj.FieldA // 从堆中读取引用,需要加入屏障
<Load barrier>
Object p = o // 无需加入屏障,因为不是从堆中读取引用
o.dosomething() // 无需加入屏障,因为不是从堆中读取引用
int i = obj.FieldB //无需加入屏障,因为不是对象引用
ZGC 中读屏障的代码作用:在对象标记和转移过程中,用于确定对象的引用地址是否满足条件,并作出相应动作。
ZGC 并发处理演示
接下来详细介绍 ZGC 一次垃圾回收周期中地址视图的切换过程:
- 初始化:ZGC 初始化之后,整个内存空间的地址视图被设置为 Remapped。程序正常运行,在内存中分配对象,满足一定条件后垃圾回收启动,此时进入标记阶段。
- 并发标记阶段:第一次进入标记阶段时视图为 M0,如果对象被 GC 标记线程或者应用线程访问过,那么就将对象的地址视图从 Remapped 调整为 M0。所以,在标记阶段结束之后,对象的地址要么是 M0 视图,要么是 Remapped。如果对象的地址是 M0 视图,那么说明对象是活跃的;如果对象的地址是 Remapped 视图,说明对象是不活跃的。
- 并发转移阶段:标记结束后就进入转移阶段,此时地址视图再次被设置为 Remapped。如果对象被 GC 转移线程或者应用线程访问过,那么就将对象的地址视图从 M0 调整为 Remapped。
其实,在标记阶段存在两个地址视图 M0 和 M1,上面的过程显示只用了一个地址视图。之所以设计成两个,是为了区别前一次标记和当前标记。也即,第二次进入并发标记阶段后,地址视图调整为 M1,而非 M0。
着色指针和读屏障技术不仅应用在并发转移阶段,还应用在并发标记阶段:将对象设置为已标记,传统的垃圾回收器需要进行一次内存访问,并将对象存活信息放在对象头中;而在 ZGC 中,只需要设置指针地址的第 42~45 位即可,并且因为是寄存器访问,所以速度比访问内存更快。
支持平台
ZGC 性能对比
吞吐量对比
停顿时间对比
嗯,对比还是很明显的……
快速开始
通过下面的参数,能够启用 ZGC。
-XX:+UseZGC -Xmx<size> -Xlog:gc
如果想获取更多详细 log,可以使用下面的参数:
-XX:+UseZGC -Xmx<size> -Xlog:gc*
变更记录
JDK 17
- Dynamic Number of GC threads
- Reduced mark stack memory usage
- macOS/aarch64 support
- GarbageCollectorMXBeans for both pauses and cycles
- Fast JVM termination
JDK 16
- Concurrent Thread Stack Scanning (JEP 376)
- Support for in-place relocation
- Performance improvements (allocation/initialization of forwarding tables, etc)
JDK 15
- Production ready (JEP 377)
- Improved NUMA awareness
- Improved allocation concurrency
- Support for Class Data Sharing (CDS)
- Support for placing the heap on NVRAM
- Support for compressed class pointers
- Support for incremental uncommit
- Fixed support for transparent huge pages
- Additional JFR events
JDK 14
- macOS support (JEP 364)
- Windows support (JEP 365)
- Support for tiny/small heaps (down to 8M)
- Support for JFR leak profiler
- Support for limited and discontiguous address space
- Parallel pre-touch (when using -XX:+AlwaysPreTouch)
- Performance improvements (clone intrinsic, etc)
- Stability improvements
JDK 13
- Increased max heap size from 4TB to 16TB
- Support for uncommitting unused memory (JEP 351)
- Support for -XX:SoftMaxHeapSIze
- Support for the Linux/AArch64 platform
- Reduced Time-To-Safepoint
JDK 12
- Support for concurrent class unloading
- Further pause time reductions
JDK 11
- Initial version of ZGC
- Does not support class unloading (using -XX:+ClassUnloading has no effect)
FAQ
ZGC 中的“Z”表示什么?
ZGC 只是一个名字,Z 没有什么特殊含义。
发音是 "zed gee see" 还是 "zee gee see"?
没有规定,两者都可以。
GitHub 项目
Java 编程思想-最全思维导图-GitHub 下载链接,需要的小伙伴可以自取~
原创不易,希望大家转载时请先联系我,并标注原文链接。
参考资料
- https://www.baeldung.com/jvm-zgc-garbage-collector
- https://wiki.openjdk.java.net/display/zgc/Main#Main-JDK17
- 新一代垃圾回收器 ZGC 的探索与实践
- ZGC-FOSDEM-2018.pdf
- JVM G1GC 的算法与实现
深入分析 Java ZGC的更多相关文章
- 深入分析Java Web技术内幕(修订版)
阿里巴巴集团技术丛书 深入分析Java Web技术内幕(修订版)(阿里巴巴集团技术丛书.技术大牛范禹.玉伯.毕玄联合力荐!大型互联网公司开发应用实践!) 许令波 著 ISBN 978-7-121- ...
- 深入分析 Java 中的中文编码问题
登录 (或注册) 中文 IBM 技术主题 软件下载 社区 技术讲座 打印本页面 用电子邮件发送本页面 新浪微博 人人网 腾讯微博 搜狐微博 网易微博 Digg Facebook Twitter Del ...
- [转]深入分析 Java 中的中文编码问题
收益匪浅,所以转发至此 原文链接: http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 深入分析 Java 中的中文编码问题 编 ...
- 深入分析Java Web技术(2) IO
IO是当今Web面临的主要问题之一,可以说,大部分web应用的瓶颈都是IO的瓶颈. Java的IO类是java.io.它包含有80多个类,分为4大部分: 基于字节操作: InputStream,Out ...
- 深入分析Java Web技术(1)
BS网络模型的基本过程: 当我们在浏览器中输入"www.google.com"的时候,首先会请求DNS服务器对域名进行解析成都应的IP地址,然后根据这个IP地址在互联网上找到谷歌的 ...
- 深入分析 Java I/O 的工作机制--转载
Java 的 I/O 类库的基本架构 I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道.在当今这个数据大爆炸时代, ...
- 深入分析 Java I/O 的工作机制
I/O 问题可以说是当今互联网 Web 应用中所面临的主要问题之一,因为当前在这个海量数据时代,数据在网络中随处流动.这个流动的过程中都涉及到 I/O 问题,可以说大部分 Web 应用系统的瓶颈都是 ...
- Servlet工作原理解析 《深入分析java web 技术内幕》第九章
参考关于servblet的相关文章 侧重概况:https://blog.csdn.net/levycc/article/details/50728921 ibm的相关:https://www.ibm. ...
- 《深入分析Java Web技术内幕》读书笔记 - 第1章 深入Web请求过程
第1章 深入Web请求过程 1 1.1 B/S网络架构概述 2 基于统一的应用层协议HTTP来交互数据. 1.2 如何发起一个请求 4 HTTP连接本质是建立Socket连接.请求实现方式:工具包如H ...
随机推荐
- Veeam Backup & Replication 10.0.0.4461安装部署(包含补丁)
Veeam Backup & Replication 是一款数据保护软件,为VMware 和Hyper-V 虚拟机.物理与云环境提供了备份.复制与恢复选项.如有需要请去官方购买正版授权:htt ...
- 让textarea根据文本的长度自动调整它的高度
... <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR ...
- [atARC122F]Domination
如果一个红石头在另一个红石头的左下方(包括左和下),那么在后者的限制满足时,前者也一定满足,因此可以删去前者,再将其按照$rx_{i}$排序,即有$rx_{1}<rx_{2}<...< ...
- [bzoj3123]森林
首先对于询问操作可以使用可持久化线段树来维护,对于连边操作对于两颗树中选取较小的树暴力练到另一个点上,点数可以用并查集然后只修改根的点数即可. 1 #include<bits/stdc++.h& ...
- Anaconda 安装与卸载
Anaconda是一个免费开源的Python和R语言的发行版本,用于计算科学(数据科学.机器学习.大数据处理和预测分析),Anaconda致力于简化软件包管理系统和部署.Anaconda的包使用软件包 ...
- Go 类型强制转换
Go 类型强制转换 强制类型的语法格式:var a T = (T)(b),使用括号将类型和要转换的变量或表达式的值括起来 强制转换需要满足如下任一条件:(x是非常量类型的变量,T是要转换的类型) 1. ...
- Zabbix源码安装,使用service命令管理zabbix进程
1. 前期环境: Zabbix源代码解压包:/root/zabbix-3.0.27 Zabbix安装路径:/usr/local/zabbix-3.0.27 2. 复制启动脚本到 ...
- Excel—分组然后取每组中对应时间列值最大的或者最小的
1.MAX(IF(A:A=D2,B:B)) 输入函数公式后,按Ctrl+Shift+Enter键使函数公式成为数组函数公式. Ctrl+Shift+Enter: 按住Ctrl键不放,继续按Shift键 ...
- 45-Letter Combinations of a Phone Number
Letter Combinations of a Phone Number My Submissions QuestionEditorial Solution Total Accepted: 7855 ...
- javaSE高级篇3 — 网络编程 — 更新完毕
网络编程基础知识 先来思考两个问题( 在这里先不解决 ) 如何准确的找到一台 或 多台主机? 找到之后如何进行通讯? 网络编程中的几个要素 IP 和 端口号 网络通讯协议:TCP / UDP 最后一句 ...