注:JAVA自动垃圾收集器是把双刃剑,既带来了无数开发便利,也引入了不少StopTheWorld这样的性能问题。如何解决这些问题,且看ZGC!

1.简介

今天,应用程序同时为数千甚至数百万用户提供服务的情况并不少见。这些应用程序通常需要大量内存。但不得不小心的是,内存管理非常容易影响应用程序性能。

为了解决这个问题,Java 11引入了Z垃圾收集器(ZGC)作为垃圾收集器(GC)实现(2019.05.15注:当前这个功能为实验性)。

在本教程中,我们将看到ZGC如何设法在数TB的内存堆上保持低暂停时间。

2.主要概念

为了理解ZGC,我们需要了解背后的基本概念和术语内存管理和垃圾收集器。

2.1。内存管理

物理内存是我们的硬件提供的RAM。

操作系统(OS)为每个应用分配虚拟内存空间。

当然,我们将虚拟内存存储在物理内存中,操作系统负责维护两者之间的映射。此映射通常涉及硬件加速。

2.2。垃圾收集

当我们创建Java应用程序时,我们不必释放我们分配的内存,因为垃圾收集器会为我们执行此操作。综上所述,GC可以通过一系列的内存引用识别判断应用程序中的哪些对象可达,从而释放不可达的对象。

为实现这一目标,垃圾收集器有多个阶段。

2.3。 GC相属性

GC阶段可以具有不同的属性:

并行阶段:可以在多个GC线程上运行

串行阶段:单个线程上运行

Stop-the-world阶段:GC线程不能与应用程序代码同时运行

并发阶段:GC线程可以在后台运行,而应用程序可以完成它的工作

渐进式阶段:GC可以在完成所有工作之前终止,并在以后继续

请注意,所有上述技术都有其优点和缺点。例如,假设我们有一个可以与我们的应用程序同时运行的阶段。此阶段的串行实现需要1%的整体CPU性能并运行1000ms。相比之下,并行实现使用30%的CPU并在50ms内完成其工作。

在这个例子中,并行解决方案使用更多的CPU资源,因为它可能更复杂并且必须同步线程。对于CPU密集型应用程序(例如批处理作业)来说,这是一个问题,因为一旦CPU计算能力较低时导致无法进行有效的工作。

当然,这个例子的数字可能不是真实的。但是,显而易见所有应用程序都有自己的特性,因此它们有不同的GC要求。

3. ZGC Concepts

除了久经考验的GC技术之外,ZGC还引入了两个新概念:指针着色和Load barriers。

3.1。指针着色

指针表示虚拟内存中字节的位置。但是,我们不一定要使用指针的所有位来执行此操作 - 一些位可以表示指针的属性。这就是我们所说的指针着色。

使用32位,我们可以处理4千兆字节。由于现在配置的内存比这个更常见,我们显然不能使用这32位中的任何一个进行着色。因此,ZGC使用64位指针。这意味着ZGC仅适用于64位平台:

ZGC指针使用42位来表示地址本身。因此,ZGC指针可以处理4TB的内存空间。

最重要的是,我们有4位来存储指针状态:

终结bit - 只能通过终结器访问该对象

重映射bit - 引用指向对象的当前地址(请参阅重定位)

marked0和marked1bits - 用于标记对象可达性

我们还将这些位称为元数据位。在ZGC中,这些元数据位中只有一个是1。

3.2。 Multi-Mapping

Multi-mapping意味着我们将多个虚拟内存范围映射到物理内存。在ZGC中,这些范围仅在前面提到的元数据位中不同。

请注意指针着色解除引用更加昂贵因为我们必须屏蔽有用位来访问地址本身。然而,ZGC绕过这个成本,因为四个元数据位中只有一个是1。这样我们只有四个范围要映射,映射由操作系统处理。此外,我们只使用其中三个范围,因为我们从不想取消引用可终结指针:

3.3。Load Barriers

Load barriers是一段运行代码(当线程从堆中载入引用时) - 例如,当我们访问对象的non-primitive字段时。

在ZGC中,load barriers检查引用的元数据位。根据这些位,ZGC可能会在获得引用前执行一些处理。因此,它可能产生完全不同的引用。

3.4。标记

标记是垃圾收集器确定对象是否可达的过程。不可达对象被认为是需要回收的对象。 ZGC将标记分为三个阶段:

第一阶段是Stop-the-world阶段。在这个阶段,我们寻找根引用并标记它们。根引用是到达堆中对象的起点例如,局部变量或静态字段。由于根引用的数量通常较小,因此该阶段很短。

下一阶段是并发阶段。在这个阶段,我们遍历对象图,从根引用开始。我们标记我们到达的每个对象。此外,当Load Barriers检测到未标记的引用时,也会标记它。

最后阶段也是stop-the-world阶段,用于处理一些边缘问题,比如弱引用。

此时,我们知道哪些对象是可达的。

ZGC使用marked0和marked1用于标记的元数据位。

3.5。重定位

当我们必须为新对象分配内存时,我们可以遵循两种策略。

首先,我们可以扫描内存中的可用空间,该空间足以容纳我们的对象。扫描内存是一项昂贵的操作。此外,内存将被分段,因为对象之间会有间隙。如果我们想要最小化这些差距,它会使用更多的处理能力。

另一个策略是经常将碎片存储区中的对象重定位到更紧凑格式的空闲区域。为了更有效,我们将内存空间分成块。我们重新定位块中的所有对象或不重定位。这样,内存分配会更快,因为我们知道内存中有整个空块。

在ZGC,重定位也包括三个阶段。

并发阶段:查找我们要重定位的块并将它们放入重定位集中。

Stop-the-world阶段:重定位重定位集中的所有根引用并更新其引用。

并发阶段:重定位重定位集中的所有剩余对象,并在转发表中存储旧地址和新地址之间的映射。

3.6。重新映射

请注意,在重定位阶段,我们没有重写对重定位对象的所有引用。因此,使用这些引用,我们将无法访问我们想要的对象。更糟糕的是,我们可能会访问垃圾。

ZGC使用load barriers来解决这个问题。Load barriers使用称为重新映射的技术来修复指向重定位对象的引用。

下图显示了重映射的工作原理:

4.如何启用ZGC?

运行我们的应用程序时,我们可以使用以下命令行选项启用ZGC:

-XX:+UnlockExperimentalVMOptions -XX:+UseZGC

请注意,由于ZGC是一个实验性GC,因此需要一些时间才能获得官方支持。

5.结论

在本文中,我们看到ZGC打算以较低的应用程序暂停时间支持超大堆内存GC管理。

为了实现这一目标,它使用了包括彩色64位指针,Load barriers,重定位和重新映射在内的技术。

参考资料

java垃圾收集器zgc,ZGC简介:可扩展的低延时JVM垃圾收集器相关推荐

  1. SLIK: 高扩展、低延时的键值存储索引实现(RAMCloud)

    http://www.wzxue.com/slik-ramcloud/ SLIK: 高扩展.低延时的键值存储索引实现(RAMCloud) 2014 年 06 月 01 日 写评论 作者 麦子迈 RAM ...

  2. 【java虚拟机系列】JVM类加载器与ClassNotFoundException和NoClassDefFoundError

    在我们日常的项目开发中,会经常碰到ClassNotFoundException和NoClassDefFoundError这两种异常,对于经验足够的工程师而言,可能很轻松的就可以解决,但是却不一定明白为 ...

  3. 一个超乎想象的垃圾收集器:ZGC

    来源:占小狼的博客 Z Garbage Collector,即ZGC,是一个可伸缩的.低延迟的垃圾收集器,主要为了满足如下目标进行设计: 停顿时间不会超过10ms 停顿时间不会随着堆的增大而增大(不管 ...

  4. JVM垃圾收集器详解 CMS、G1、Shenandoah、ZGC

    上一篇我们讲解了一些垃圾回收的理论和一些基础的算法和思想,这一篇主要是jvm从古至今垃圾收集器的实现. 各垃圾回收器 注:有连线的代表他们可以互相配合使用. Serial和Serial Old收集器 ...

  5. 异常处理第一讲(SEH),筛选器异常,以及__asm的扩展,寄存器注入简介

    异常处理第一讲(SEH),筛选器异常,以及__asm的扩展,寄存器注入简介 参考文章: (1)异常处理第一讲(SEH),筛选器异常,以及__asm的扩展,寄存器注入简介 (2)https://www. ...

  6. JVM 垃圾收集器 学习笔记(《深入理解java虚拟机》之六 垃圾收集)

    目录 新生代收集器 Serial收集器 ParNew收集器 Parallel Scavenge收集器 老年代收集器 Serial Old收集器 Parallel Old收集器 CMS收集器 Remov ...

  7. 面试题:JVM垃圾收集器

    GC的性能指标 吞吐量:运行用户代码的时间占总运行时间的比例. 暂停时间:执行垃圾收集时,程序工作线程被暂停的时间. 内存占用:Java堆区所占的内存大小. 高吞吐量较好因为这会让应用程序的用户感觉应 ...

  8. 详述JVM垃圾收集器(二)常见的垃圾收集器

    一.Serial GC与Serial Old GC收集器 Serial收集器   Serial垃圾收集器可以说是最基础的.历史最悠久的垃圾收集器.在JDK1.3.1之前可以说是虚拟机新生代唯一的选择. ...

  9. JVM——垃圾收集器

    垃圾收集器与内存分配策略 一.概述 垃圾收集(Garbage Collection,简称GC),这项技术并不是Java语言的伴生产物,早在java语言出来之前,就已经有语言开始使用动态分配内存和垃圾回 ...

最新文章

  1. 安装惠普笔记本XP三种方法
  2. android优雅私有方法注释,带有注释参数的私有方法的Android java.lang.VerifyError
  3. OpenCV2:应用篇 三维重建
  4. selenium框架安装及webdriver安装
  5. nodejs+supertest+mocha 接口测试环境搭建
  6. mysql mariadb的VC客户端遇到的问题
  7. Linux Kernel Git国内镜像源
  8. 合成简单的声音波形(一)
  9. 易语言超文本ctrl c,易语言超文本浏览框处理键盘消息源码
  10. 笔记内容:非线性控制理论
  11. eclipse j2me 连接 KEmulator模拟器
  12. Ubuntu12.04 64位 无法运行32位程序 吉林大学校园网客户端Drcom DrClient
  13. AMD显卡怎么提高帧数?AMD显卡提高fps的方法
  14. 企业邮箱申请流程有哪些?公司邮箱的优势有哪些?
  15. 微信小程序超过屏幕高度后显示底部图标
  16. Cesium加载GLB和GLTF模型文件踩坑实录
  17. mysql mybatis 不等于号写法
  18. Linux设置组密码
  19. Xshell配色美化
  20. 360加固android app反编译,apk360加固脱壳

热门文章

  1. flannel 实战与源码分析(五)
  2. dnf 跨服 服务器 位置,《DNF》怎么跨区组队交易 2017最新跨区分布图
  3. team网卡配置_如何通过网卡Team增强服务器网络连接可靠性
  4. 小米退出鸿蒙,鸿蒙系统正式发布,魅族带头支持,小米还在观望
  5. 【微信小程序】组件的生命周期及自定义组件
  6. 微信小程序图片 height: auto 不生效问题
  7. Auto.js 分享信息到 QQ 微信
  8. 任务之间的同步与通信
  9. 基于S7-300 PLC和组态王配料饲料加工控制系统
  10. Java发送会议邮件 时区_【上海校区】基于JavaMail的日历(会议)邮件发送实现