ZGC深入解析

ZGC(Z Garbage Collector)是JDK 11中的低延迟垃圾收集器,支持10ms以内的停顿时间和TB级别的内存。它采用多重映射、读屏障和指针染色技术,实现并发处理。ZGC通过并发标记和转移阶段进行垃圾回收,并通过全局视图切换减少STW时间。在JDK16中,ZGC支持并发线程栈扫描,进一步降低了停顿时间。
摘要由CSDN通过智能技术生成

ZGC原理深入解析 主讲人:严镇涛

官网https://docs.oracle.com/en/java/javase/11/gctuning/z-garbage-collector1.html#GUID-A5A42691-095E-47BA-B6DC-FB4E5FAA43D0

ZGC(The Z Garbage Collector)是JDK 11中推出的一款追求极致低延迟的实验性质的垃圾收集器,不管是物理上还是逻辑上,在ZGC中已经不存在新老年代的概念了 借鉴pauseless GC 目标C4 GC

会分为一个个page,当进行GC操作时会对page进行压缩,因此没有碎片问题

在JDK11只能在64位的linux上使用,目前用得还比较少

个人认为用的少的原因:

  1. 用JDK8以上的就不多,够用了是关键
  2. 对于内存架构要求高
  3. 在JDK15之前处于实验阶段

(1)可以达到10ms以内的停顿时间要求,jdk15达到1ms

(2)支持TB级别的内存(支持8MB~4TB级别的堆,JDK15以后支持16TB)

(3)停顿时间不会随着堆的大小,或者活跃对象的大小而增加;堆内存变大后停顿时间还是在10ms以内

image.png

实际上:

ZGC诞生于JDK11,经过不断的完善,JDK15中的ZGC已经不再是实验性质的了。

从只支持Linux/x64,到现在支持多平台;从不支持指针压缩,到支持压缩类指针…

在JDK16,ZGC将支持并发线程栈扫描(Concurrent Thread Stack Scanning),根据SPECjbb2015测试结果,实现并发线程栈扫描之后,ZGC的STW时间又能降低一个数量级,停顿时间将进入毫秒时代。

SPECjbb: SPECjbb 是这几个字母的首字母组成的,Standard Performance Evaluation Corporation(spec公司),JAVA server Business Benchmark(java服务器业务测试工具)。

在SPECjbb 这个基准测试中,被测产品要运行JVM,模拟一家全球大型零售企业的各种终端销售点请求、在线购买、数据挖掘等日常业务,通过不断增加的业务量来测试系统能够处理的最大值,同时会测试随着业务量增加,系统响应时间的变化,以全面评估运行各项Java业务应用的服务器性能水平。

SPECjbb 模拟了三层客户/服务器模型结构:第一层是用户(客户端输入);第二层是商业应用逻辑;第三层是数据库。

image.png

ZGC三大核心技术

多重映射

为了能更好的理解ZGC的内存管理,我们先看一下这个例子:

你在你爸爸妈妈眼中是儿子,在你女朋友眼中是男朋友。在全世界人面前就是最帅的人。你还有一个名字,但名字也只是你的一个代号,并不是你本人。将这个关系画一张映射图表示:

image.png

在你爸爸的眼中,你就是儿子;
在你老婆的眼中,你就是老公;
在你同事的眼中,你就是同事;
假如你的名字是全世界唯一的,通过“你的名字”、“你爸爸的儿子”、“你老婆的老公”,“世界上最帅的人”最后定位到的都是你本人。

现在我们再来看看ZGC的内存管理。

ZGC为了能高效、灵活地管理内存,实现了两级内存管理:虚拟内存和物理内存,并且实现了物理内存和虚拟内存的映射关系。这和操作系统中虚拟地址和物理地址设计思路基本一致。

当应用程序创建对象时,首先在堆空间申请一个虚拟地址,ZGC同时会为该对象在Marked0、Marked1和Remapped三个视图空间分别申请一个虚拟地址,且这三个虚拟地址对应同一个物理地址。image.png

图中的Marked0、Marked1和Remapped三个视图是什么意思呢?

对照上面的例子,这三个视图分别对应的就是"你爸爸眼中",“你老婆的眼中”,“同事眼中”。

而三个视图里面的地址,都是虚拟地址,对应的是“你爸爸眼中的儿子”,“你老婆眼中的老公”…

最后,这些虚地址都能映射到同一个物理地址,这个物理地址对应上面例子中的“你本人”。

为什么这么设计呢?

这就是ZGC的高明之处,利用虚拟空间换时间,这三个空间的切换是由垃圾回收的不同阶段触发的,通过限定三个空间在同一时间点有且仅有一个空间有效高效的完成GC过程的并发操作,具体实现会在后面讲ZGC并发处理算法的部分再详细描述

读屏障

请各位注意,之前我们一直在聊写屏障,而这里聊到读屏障,很多同学就会把这个读屏障跟java内存模型的读屏障混淆。这里的读屏障实际上指的是一种手段,并且是一种类似于AOP的手段。

我们之前聊的写屏障是数据写入时候的屏障,而java内存屏障中的读屏障实际上也是类似的。

但是在ZGC中的读屏障,则是JVM向应用代码插入一小段代码的技术,当应用线程从堆中读取对象引用时,就会执行这段代码。他跟我们的java内存屏障中的读屏障根本就不是一个东西。他是在字节码层面或者编译代码层面给读操作增加一个额外的处理。一个类似与面向切面的处理。

并且ZGC的读屏障是只有从中读取对象引用,才需要加入读屏障

读屏障案例:

Object o = obj.FieldA      // 从堆中读取对象引用,需要加入读屏障
<load barrier needed here>

Object p = o               // 无需加入读屏障,因为不是从堆中读取引用
o.dosomething()            // 无需加入读屏障,因为不是从堆中读取引用
int i =  obj.FieldB        // 无需加入读屏障,因为不是对象引用

那么我加上这个读屏障有什么作用呢?

这里我们思考下:

由于GC线程和应用线程是并发执行的&#x

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值