JVM系统优化实践(24):ZGC(一)

您好,这里是「码农镖局」掘金小站,欢迎您来,欢迎您再来~


截止到目前,算上ZGC,Java一共有九种类型的GC,它们分别是:

1、Serial GC 串行/作用于新生代/复制算法/响应速度优先/适用于单CPU下的client模式

2、ParNew GC 并行/作用于新生代/复制算法/响应速度优先/多CPU的Server模式与CMS配合使用

3、Parallel GC 并行/作用于新生代/复制算法/吞吐量优先/适用于后台运算且不需要太多交互

4、Serial Old GC 串行/作用于老年代/标记-整理算法/响应速度优先/单CPU下的Client模式

5、Parallel Old GC 并行/作用于老年代/标记-整理算法/吞吐量优先/适用于后台运算且不需要太多交互

6、CMS GC 并行/作用于老年代/标记-清除算法/响应速度优先/适用于互联网或B/S业务

7、G1 GC 并行/新生或老年代/标记-整理算法+复制算法/响应速度优先/面向服务端应用

8、Epsilon GC A No-Op GC

9、The Z GC 并发/单代/标记-整理算法+复制算法/响应速度优先/面向大数据应用

ZGC之前,下面几种GC算法是Java的主流。

1、CMS GC(JDK1.4)

2、ParNew GC(JDK1.6)

3、G1 GC(JDK1.8)

而JDK11采用了全新的GC算法。官方的介绍说它是一个Scalable和Low-Latency的GC(可以在OpenJDK官网上查JEP333)。

ZGC野心极大,其诞生之初的目标就是:

1、支持TB级别的堆内存(最大4TB)

2、最大GC停顿时间不超过10ms,且不随着堆的大小而变化

3、GC停顿期间,吞吐量降低不超过15%

4、可伸缩、低延迟

不同于以往任何的那种修修补补式的GC,ZGC不是从过去GC算法优化来的,而是全新的,JDK11的ZGC只能运行在Linux64位操作系统中(JDK14可以运行于Windows和Mac系统)。

它采用单代模型,没有了年轻代、老年代的划分,也就没有了Minor GC和Major GC的区别。

1、Region Based GC,和G1类似,但有更加灵活的region size schema,这也正是能处理TB即堆内存的原因

2、Partial Compaction,和G1一样的部分压缩

3、Colored Object Pointer,染色对象指针,使用三色标记实现对象清理

4、Multi-Mapping,内存多重映射

5、使用Load Barrier(读屏障)技术修正GC扫描结果

6、Concurrent,ZGC几乎总是以并发的形式完成所有的工作

下面一个一个来说一下。

关于单代模型:

以前的GC模型之所以分代,是源于对象生命周期极短的假设。

实现分代模型非常麻烦,为了判断是年轻代还是老年代,G1通过Remembered Set记录Region对象之间的双向引用关系,这种跟踪跨代引用的任务特别繁重。所以ZGC的做法是控制停顿阶段做的事情不和堆中的对象产生直接关联,所有在堆上进行的扫描、分配、复制等操作都是并发的,通过扫描整个堆和染色指针技术,ZGC成功去除了Remembered Set。

关于Region区域:

和G1一样,都是基于内存Region设计的GC。但它和G1固定大小的Region不同,ZGC中每个Region大小分为3类:2MB、32MB、N×32MB这几种「规格」:

1、容量2MB的Small Page存放 < 256KB的小对象

2、容量32MB的Medium Page存放 >= 256KB 且 < 4MB的对象

3、容量N×32MB的Large Page存放 >= 4MB的大对象,每个Page只放一个对象

ZGC Region的核心亮点就是动态:动态地创建和销毁,动态地决定Region的大小。

Region区域看起来就想这样的:

关于部分压缩:

以前的ParallelOldGC、CMS,无论老年代有多大,都会进行整体压缩,从而Old区越大,导致停顿时间越长。而G1和ZGC是基于Region实现的,因此只会选择部分Region进行回收,这一点G1和ZGC是一样的。

关于染色指针:

ZGC的一个核心概念就是染色指针,这里是借用一个形象的说法,并非是真的给指针"染色",它是指在GC时标记哪些对象是可回收的,即GC Roots过程。传统HopSpot虚拟机的标记实现方案是直接将标记记录在对象头部信息上,再把标记信息记录在与对象相互独立的数据结构上,如G1的Remembered Set。而ZGC是直接把标记信息记录在引用对象的指针上,这是一种直接将少量的额外信息存储在指针上的技术。目前在64位的Linux系统中,高18位预留不能使用,剩余的46位最大可支持64TB的内存空间。

ZGC将46位中的高4位取出来,用于存储染色标识信息(Finalizable、Remapped、Marked1、Marked0),用剩余的42位地址来管理4TB内存空间。

1、Finalizable:表示对象是否只能通过finalize()方法访问,其他途径是访问不了的

2、Remapped:表示对象是否已被重新映射,即是否已指向新的地址

3、Marked1、Marked0:表示对象的三色标记状态,对象是否已被标记

之所以使用两个Marked0和Marked1标记,是因为每个GC周期开启时,会交换使用的标记位。


感谢您的大驾光临!欢迎骚扰,不胜荣幸~

相关推荐
吹晚风吧2 分钟前
什么是跨域?跨域怎么解决?跨域解决的是什么问题?
java·vue.js·js·cors
敲码图一乐12 分钟前
流量安全——基于Sentinel实现限流,熔断,降级
java·开发语言·数据库
0xMinos18 分钟前
Java 设计模式——单例模式
java·设计模式
zzywxc7871 小时前
AI赋能千行百业:金融、医疗、教育、制造业的落地实践与未来展望
java·人工智能·python·microsoft·金融·golang·prompt
一只学java的小汉堡1 小时前
Spring Boot 配置详解:从引导器到注解实战(初学者指南)
java·spring boot·后端
独自破碎E1 小时前
归并排序的递归和非递归实现
java·算法·排序算法
一叶飘零_sweeeet1 小时前
线程同步实战指南:从 bug 根源到锁优化的终极之路
java·线程·线程同步
失散131 小时前
分布式专题——25 深入理解网络通信和TCP、IP协议
java·分布式·网络协议·tcp/ip·架构
zz0723203 小时前
Java 集合体系 —— List 篇
java·list·集合体系
-雷阵雨-3 小时前
数据结构——LinkedList和链表
java·开发语言·数据结构·链表·intellij-idea