为 Java 开疆扩土的 ZGC 上

简介: 为 Java 开疆扩土的 ZGC 上


一、JVM

JVM 是虚拟机,能够识别字节码,就是 class 文件或者你打包的 jar 文件,运行在操作系统上。

JVM 帮我们实现了跨平台,你只需要编译一次(Compile once,Running everywhere),就可以在不同的操作系统上运行,并且效果是一致的。

在 Java 中你使用对象,使用内存,不用担心回收,只管 new 对象就行了,不用管垃圾的回收。因为 Java 当中是自动化的垃圾回收机制。JVM有专门的垃圾回收器,把垃圾回收这件事给干了。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

二、ZGC 出现的背景

简言之,ZGC 的出现就是为了解决传统垃圾回收 STW 时间长的问题。

2.1 STW 带来的问题

(1)安卓手机的卡顿问题:Google 主导的 Android 系统需要解决的一大问题就是显示卡顿问题,通过对 GC 算法的不断演进,停顿时间控制在几个ms 级别。所以这也是Android与苹果IOS系统竞争的一大利器。

(2)证券交易系统的实时性要求:证券交易系统主要就是买入、卖出,现在都是使用系统完成自动下单,如果因为STW时间过长,可能就会在错误的时间点买入卖出。

(3)大数据平台:集群性能问题。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

三、垃圾回收器的发展

传统的 GC,如 CMS、G1 的停顿时间也跟随着堆大小的增长而同步增加,即堆大小指数级增长时,停顿时间也会指数级增长。特别是当触发 Full GC 时,停顿可达分钟级别(百GB级别的堆)。

为满足当前应用对于超低停顿、并应对大堆和超大堆带来的挑战,伴随着 2018 年发布的 JDK 11,A Scalable Low-Latency Garbage Collector - ZGC 应运而生。

四、ZGC 的特点

  • 停顿时间不超过10ms(JDK16 已经达到不超过 1ms);
  • 停顿时间不会随着堆的大小,或者活跃对象的大小而增加;
  • 支持8MB~4TB级别的堆,JDK15 后已经可以支持 16TB。

五、ZGC 的内存布局

为了细粒度地控制内存的分配,和 G1 一样,ZGC 将内存划分成小的分区,在 ZGC 中称为页面(page)。ZGC中没有分代的概念。

ZGC中支持三种页面,分别为小页面、中页面和大页面。其中小页面指的是 2MB 的页面空间,中页面指 32MB 的页面空间,大页面指受操作系统控制的大页。

  • 当对象大小小于等于 256KB 时,对象分配在小页面。
  • 当对象大小在 256KB 和 4M 之间,对象分配在中页面。
  • 当对象大于 4M,对象分配在大页面。

ZGC 对于不同页面回收的策略也不同。简单地说,小页面优先回收,中页面和大页面则尽量不回收。

5.1 为什么这么设计?

标准大页(huge page)是 Linux Kernel 2.6 引入的,目的是通过使用大页内存来取代传统的 4KB 内存页面,以适应越来越大的系统内存,让操作系统可以支持现代硬件架构的大页面容量功能。

Huge pages 有两种格式大小:2MB 和 1GB , 2MB 页块大小适合用于 GB 大小的内存, 1GB 页块大小适合用于 TB 级别的内存;2MB 是默认的页大小。

所以ZGC这么设置也是为了适应现代硬件架构的发展,提升性能。

六、ZGC 的核心概念

6.1 指针着色技术

颜色指针可以说是 ZGC 的核心概念。因为它在指针中借了几个位出来做事情,所以它必须要求在 64 位的机器上才可以工作。并且因为要求 64 位的指针,也就不能支持压缩指针。

ZGC 中低 42 位表示使用中的堆空间。ZGC 借几位高位来做GC相关的事情(快速实现垃圾回收中的并发标记、转移和重定位等)。

七、ZGC 流程

7.1 一次 GC 流程

一次 GC 主要包括两个流程:标记(标记垃圾)和转移(对象的复制和移动)。

7.2 根可达性算法

来判定对象是否存活的。这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的。

作为GC Roots的对象主要包括下面 4 种:

  • 虚拟机栈(栈帧中的本地变量表) :各个线程调用方法堆栈中使用到的参数、局部变量、临时变量等
  • 方法区中类静态变量 :Java 类的引用类型静态变量
  • 方法区中常量 :比如字符串常量池里的引用
  • 本地方法栈中 JNI 指针 :(即一般说的 Native 方法)

7.3 初始标记和并发标记

  • 初始标记 :从根集合(GC Roots)出发,找出根集合直接引用的活跃对象(根对象)
  • 并发标记 :根据初始标记找到的根对象,使用深度优先遍历对象的成员变量进行标记

7.4 并发标记算法

区分相邻两次GC中的标记:M0(mark-0)、M1(mark-1)。

(1)初始阶段

在 ZGC 初始化之后,此时地址视图为 Remapped,程序正常运行,在内存中分配对象,满足一定条件后垃圾回收启动。如下图所示:

(2)初始标记

这个阶段需要暂停(STW),初始标记只需要扫描所有 GC Roots,其处理时间和 GC Roots 的数量成正比,停顿时间不会随着堆的大小或者活跃对象的大小而增加。经过初始标记之后,直接引用 A 的指针变成了绿色。

(3)并发标记

这个阶段不需要暂停(没有 STW),扫描剩余的所有对象,这个处理时间比较长,所以走并发,业务线程与 GC 线程同时运行。但是这个阶段会产生漏标问题。经过并发标记之后,B 和 C 的指针都变成了绿色。

(4)再标记

这个阶段需要暂停(没有 STW),主要处理漏标对象,通过 SATB(原始快照)算法解决(G1 中的解决漏标的方案)。最后蓝色指针指向的对象就是垃圾。

相关文章
|
1月前
|
存储 Java 测试技术
Java 21革命性升级:探索分代ZGC的性能奇迹
Java 21革命性升级:探索分代ZGC的性能奇迹
62 0
|
算法 Java
为 Java 开疆扩土的 ZGC 下
为 Java 开疆扩土的 ZGC 下
|
Java 容器
Java(JDK)13新特性之ZGC Uncommit Unused Memory
Java(JDK)13新特性之ZGC Uncommit Unused Memory
136 0
|
存储 自然语言处理 算法
Java最前沿技术——ZGC
Java最前沿技术——ZGC
564 0
|
算法 Oracle 前端开发
牛逼!全网最全代表Java未来的ZGC深度剖析
JAVA程序最爽的地方是它的GC机制,开发人员不需要关注内存申请和回收问题。同时,JAVA程序最头疼的地方也是它的GC机制,因为掌握JVM和GC调优是一件非常困难的事情。在ParallelOldGC、CMS、G1之后,JDK11带来的全新的「ZGC」为我们解决了什么问题?Oracle官方介绍它是一个Scalable、Low Latency的垃圾回收器。所以它的目的是「降第停顿时间」,由此会导致吞吐量会有所降低。吞吐量降低问题不大,横向扩展几台服务器就能解决问题了啦。在全面介绍ZGC介绍,先统计一下大家线上环境在用什么垃圾回收器:
牛逼!全网最全代表Java未来的ZGC深度剖析
|
算法 Java 测试技术
Java 12 与Java 13 新特性预览:Switch表达式、GC新垃圾回收算法、低延时GC、ZGC改进等
Java 12 与Java 13 新特性预览:Switch表达式、GC新垃圾回收算法、低延时GC、ZGC改进、文本块等
8247 0
|
1天前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
7 1
|
1天前
|
缓存 监控 安全
深入理解Java中的线程池和并发编程
深入理解Java中的线程池和并发编程
|
1天前
|
设计模式 安全 Java
如何在Java中实现线程安全的单例模式
如何在Java中实现线程安全的单例模式
|
1天前
|
缓存 安全 Java
如何使用Java实现高效的多线程编程
如何使用Java实现高效的多线程编程