ZGC简介

掘金 · · 2715 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

ZGC简介

JDK14

2020年3月份,JDK14发布,可能我们大部分小伙伴的生产环境还停留在JDK8。目前LTS版本的JDLK主要是7,8,以及11。其他版本的支持周期都比较短,一般不建议在生产环境中使用的,不过这不影响我们了解最新的JDK的一些特性,这些可能是后面Java语言的发展方向。这次JDK14就带来了非常多的新特性,主要如下:

  • Pattern Matching for instanceof (Preview)
  • Packaging Tool (Incubator)
  • NUMA-Aware Memory Allocation for G1 垃圾收集中分层,冷对象移出,需要硬件层面的支持。
  • JFR Event Streaming
  • Non-Volatile Mapped Byte Buffers
  • Helpful NullPointerExceptions。这个非常有用,方便程序猿们定义空指针异常。
  • Records (Preview)
  • Switch Expressions (Standard)
  • Deprecate the Solaris and SPARC Ports
  • Remove the Concurrent Mark Sweep (CMS) Garbage Collector。 移除了CMS。
  • ZGC on macOS。 ZGC支持Mac
  • ZGC on Windows。 ZGC支持windows
  • Deprecate the ParallelScavenge + SerialOld GC Combination
  • Remove the Pack200 Tools and API
  • Text Blocks (Second Preview)
  • Foreign-Memory Access API (Incubator)

可以看到jdk14带来的新特性还是比较多的。其中有些是Preview和Incubator,暂时还不是很成熟,令我比较惊讶的是JDK14居然会移除CMS垃圾收集器,反而重点增强了ZGC。ZGC还是第一次见到,它到底是什么,有什么魔力能获得JDK如此大的支持。下面就和大家一起了解一下ZGC。

ZGC是什么

  1. ZGC是一个低延迟高并发的垃圾收集器。与传统的CMS以及G1不同,ZGC基本上在所有的地方并发执行。只在初始Marking的时候需要STW,而这部分实际是花费时间并不多。其设计目标是支持TB级内存容量,暂停时间小于10ms,对整个系统的吞吐率的影响小于15%。

基本原理

ZGC能够实现以上目标主要依靠两种技术,Colored Pointer以及Load Barrier。

Colored Pointer 着色指针

ZGC主要是利用指针的64位来表示Finalizable、Remapped、Marked1、Marked0(因此智能支持64位平台,无法在32位机器中运行)。其中的42位是用来存储对象的,因此能够支持最多4TB的内存管理,中间四位就是着色指针,剩下的位数留待以后扩展。

Load Barrier 读屏障

Load Barrier是内存屏障的一种,内存屏障硬件层的概念,不同的硬件平台实现内存屏障的方式是不一样的。JVM通常会屏蔽这些差异,提供统一的内存屏障指令。内存屏障主要有两个作用

  • 阻止屏障两侧的指令重排序/
  • 强制将缓冲区的脏数据写回主内存,让缓存中响应的数据失效。

在指令前插入Load Barrier,可以让高速缓存中的数据失效,强制从新从主内存加载数据;

通过在指针上坐标记,访问指针的时候加入Load Barrier,如果对象被GC移动,指针的颜色就会发生变化,Load Barrier会将指针地址更新为有效地址再返回。因此永远只会有单个对象读取时有概率被减速,不存在为保持应用与GC一致直接STW。

回收流程

大的流程上看分为两个阶段:标记以及重定位。

标记

标记也分为三个阶段:

  1. STW:GC roots被标记为Live对象,通过GC roots可以访问堆上其他对象。不能通过GC roots访问的对象为垃圾对象,由于一般情况下GC roots比较小,因此标记步骤非常快。标记完成之后应用程序开始执行。
  2. 第二阶段并发变了对象图,并标记所有可以访问的对象。读屏障针使用掩码测试所有已加载的引用,该掩码确定它们是否已标记或尚未标记,如果尚未标记引用,则将其添加到队列以进行标记。
  3. 最终时间很短的STW,处理一些边缘情况。

重定位

重定位涉及移动活动对象以释放堆内存。

  1. root移动:ZGC也将内存分为多个页面,需要注意的是每个页面的大小是不同的(有点类似go的垃圾收集)。并发选择一组需要重定位活动对象的页面,出现一个STW,zgc定位改集合中的root对象,并将他们的引用映射到新位置。

  2. 并发重定位:GC线程遍历重定位集并重新定位其包含的页中所有对象。

  1. GC线程最终将对重定位中涉及到的所有对象重定位。

小结

zgc中碰到的几乎所有暂停都只依赖gc roots的大小。而不是实时堆的大小,这对目前或者以后的大内存的Java应用非常友好。这也是它性能很好的原因。与很多传统的收集器不同,ZGC也不区分新生代和老生带,这对性能调优也是一个好消息。另外附录2有一个非常好的图实例来介绍ZGC的收集过程,感兴趣的同学可以看一下。

使用

使用和调优是另外一个话题,目前工作中没有看到使用场景,想自己动手尝鲜的同学推荐一篇文章。

ZGC完全指南

引用

JDK14新特性

CMS,G1和ZGC

本文来自:掘金

感谢作者:掘金

查看原文:ZGC简介

2715 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传