JVM — JDK11垃圾回收器 ZGC

这篇具有很好参考价值的文章主要介绍了JVM — JDK11垃圾回收器 ZGC。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. ZGC介绍

ZGC(The Z Garbage Collector)是 JDK 11 中推出的一款低延迟垃圾回收器,为实现以下几个目标而诞生的垃圾回收器,停顿时间不超过 10ms,停顿时间不会因堆变大而变长,支持 8MB~4TB 级别的堆(未来支持 16TB)

2. ZGC内存和原理

2.1 ZGC内存分布

ZGC 与传统的 CMS、G1 不同、它没有分代的概念,只有类似 G1 的 Region 概率;在划分内存的方式上,ZGC 与 G1 有着相似的地方,都舍弃了年轻代、老年代的划分方式,但是又与 G1 的形式不太一样,ZGC 是页为单位进行划分,一般分为三种页面:

  • 小型 Region(Small Region):容量固定为 2MB,用于放置小于 256KB 的小对象。
  • 中型 Region(Medium Region):容量固定为 32MB,用于放置大于 256KB 但是小于 4MB 的对象。
  • 大型 Region(Large Region):容量不固定,可以动态变化,但必须为 2MB 的整数倍,用于放置 4MB 或以上的大对象。每个大型 Region 中会存放一个大对象,这也预示着虽然名字叫 “大型 Region”,但它的实际容量完全有可能小于中型 Region,最小容量可低至 4MB。大型 Region 在 ZGC 的实现中是不会被重分配的(重分配是 ZGC 的一种处理动作,用于复制对象的收集器阶段)因为复制大对象的代价非常高。
    JVM — JDK11垃圾回收器 ZGC,JVM,jvm,数据库,大数据
2.2 ZGC 原理

全并发的 ZGC垃圾回收流程: 与 CMS 中的 ParNew 和 G1 类似,ZGC 也采用标记 - 复制算法,不过 ZGC 对该算法做了重大改进:ZGC 在标记、转移和重定位阶段几乎都是并发的,这是 ZGC 实现停顿时间小于 10ms 目标的最关键原因。

ZGC 垃圾回收周期如下图所示:
JVM — JDK11垃圾回收器 ZGC,JVM,jvm,数据库,大数据
ZGC 只有三个 STW 阶段:初始标记,再标记,初始转移
初始标记和初始转移分别都只需要扫描所有 GC Roots,其处理时间和 GC Roots 的数量成正比,一般情况耗时非常短;再标记阶段 STW 时间很短,最多 1ms,超过 1ms 则再次进入并发标记阶段。即,ZGC 几乎所有暂停都只依赖于 GC Roots 集合大小,停顿时间不会随着堆的大小或者活跃对象的大小而增加。与 ZGC 对比,G1 的转移阶段完全 STW 的,且停顿时间随存活对象的大小增加而增加。

3. ZGC技术特性

3.1 着色指针

着色指针(Colored Pointers)是 ZGC 的关键技术。ZGC 之前的垃圾回收器 JVM 将对象的 GC 信息记录在对象头 Mark Word 中,GC 进行标记的时候遍历 GC Roots 的对象然后对 Mark Word 的信息进行修改。而 ZGC 将 GC 信息记录在指针中,标记算法不再寻找 Mark Word 中的信息,只需要找到相应的指针信息即可。
在 64 位架构的计算机中(ZGC 只支持 64 位), 一个 Java 对象 64 位,其中低位的 42 位是对象地址,42-45 位用来做标记信息,四个状态分别是 Marked0、Marked1、Remapped、Finalizable,剩下的 18 位预留以后使用。
创建对象时,JVM 先在堆空间申请一个内存地址,同时利用 MMAP 函数将该内存地址分别映射到 Marked0、Marked1,Remapped 完成多视图映射。在同一时间这三个视图有且仅有一个生效,这是一种 “空间换时间” 的思想。
JVM — JDK11垃圾回收器 ZGC,JVM,jvm,数据库,大数据

3.2 读屏障

读屏障主要是用来解决指针在并行转移的过程中出现的问题。ZGC 进行并行转移时,GC 线程与 Java 应用线程同时工作,当 Java 应用线程读取一个未完成转移的对象的时候就会出现指针无效的问题。为了解决这个问题 ZGC 使用了读屏障的技术,当出现上述情况的时候,Java 应用线程必须在读取对象之前先把对象转移。同时 ZGC 设置了触发条件,只有在应用线程从内存堆中加载对象引用的情况下才会触发读屏障。读屏障根据着色指针记录的 GC 信息判断对象是否被移动过,如果对象发生过移动就需要对指针的内存地址进行修复。读屏障的触发条件可参考以下代码:

Object object = obj.FieldA ; // 从堆中读取对象引用,需要加入读屏障

Object o = object ;          // 不需要加入读屏障,因为不是从堆中读取引用

object.doSomething ();        // 不需要加入读屏障,因为不是从堆中读取引用

int i = obj.FieldB;          // 不需要加入读屏障,因为不是对象引用

ZGC 中读屏障的代码作用:

GC 线程和应用线程是并发执行的,所以存在应用线程去 A 对象内部的引用所指向的对象 B 的时候,这个对象 B 正在被 GC 线程移动或者其他操作,加上读屏障之后,应用线程会去探测对象 B 是否被 GC 线程操作,然后等待操作完成再读取对象,确保数据的准确性。具体的探测和操作步骤如下:
JVM — JDK11垃圾回收器 ZGC,JVM,jvm,数据库,大数据

4 JVM参数解析

4.1 JVM参数使用

下面是一些通用 GC 参数和 ZGC 特有参数以及 ZGC 的一些诊断选型,来自官网:

JVM — JDK11垃圾回收器 ZGC,JVM,jvm,数据库,大数据
对比G1和ZGC JVM参数:

  • JKD8 G1 的启动参数:
-server -Xms1024m -Xmx1024m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+PrintReferenceGC
-XX:+ParallelRefProcEnabled
-XX:G1HeapRegionSize=16m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/apps/errorDump.hprof
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintHeapAtGC
-XX:+PrintGCApplicationConcurrentTime
-verbose:gc
-Xloggc:/opt/apps/logs/${app_name}-gc.log
  • JDK 9开始部分JVM参数已移除:
CMSDumpAtPromotionFailure
CMSPrintEdenSurvivorChunks
G1LogLevel
G1PrintHeapRegions
G1PrintRegionLivenessInfo
G1SummarizeConcMark
G1SummarizeRSetStats
G1TraceConcRefinement
G1TraceEagerReclaimHumongousObjects
G1TraceStringSymbolTableScrubbing
GCLogFileSize
NumberOfGCLogFiles
PrintAdaptiveSizePolicy
PrintClassHistogramAfterFullGC
PrintClassHistogramBeforeFullGC
PrintCMSInitiationStatistics
PrintCMSStatistics
PrintFLSCensus
PrintFLSStatistics
PrintGC
PrintGCApplicationConcurrentTime
PrintGCApplicationStoppedTime
PrintGCCause
PrintGCDateStamps
PrintGCDetails
PrintGCID
PrintGCTaskTimeStamps
PrintGCTimeStamps
PrintHeapAtGC
PrintHeapAtGCExtended
PrintJNIGCStalls
PrintOldPLAB
PrintParallelOldGCPhaseTimes
PrintPLAB
PrintPromotionFailure
PrintReferenceGC
PrintStringDeduplicationStatistics
PrintTaskqueue
PrintTenuringDistribution
PrintTerminationStats
PrintTLAB
TraceDynamicGCThreads
TraceMetadataHumongousAllocation
UseGCLogFileRotation
VerifySilently
-Xloggc
  • JAVA11 G1 启动参数如下:
-server -Xms1024m -Xmx1024m -Xss256k
-XX:+UseG1GC
-XX:MaxDirectMemorySize=256m
-XX:+UseCompressedOops 
-XX:+UseCompressedClassPointers
-XX:+SegmentedCodeCache 
-verbose:gc
-XX:+PrintCommandLineFlags
-XX:+ExplicitGCInvokesConcurrent
-Djava.security.egd=file:/dev/./urandom
-Xlog:gc*,safepoint:/data/log/${app_name}-gc.log:time,uptime:filecount=100,filesize=50M
  • JDK17 ZGC 的启动参数如下:
-server -Xms1024m -Xmx1024m
#开启ZGC
-XX:+UseZGC 
#GC周期之间的最大间隔(单位秒)
-XX:ZCollectionInterval=120
#官方的解释是 ZGC 的分配尖峰容忍度,数值越大越早触发GC
-XX:ZAllocationSpikeTolerance=4
#关闭主动GC周期,在主动回收模式下,ZGC 会在系统空闲时自动执行垃圾回收,以减少垃圾回收在应用程序忙碌时所造成的影响。如果未指定此参数(默认情况),ZGC 会在需要时(即堆内存不足以满足分配请求时)执行垃圾回收。
-XX:-ZProactive 
#GC日志
-Xlog:safepoint=trace,classhisto*=trace,age*=info,gc*=info:file=/opt/logs/gc-%t.log:time,level,tid,tags:filesize=50M 
#发生OOM时dump内存日志
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/apps/errorDump.hprof

GC 日志中包含有关 GC 操作的详细信息,可以帮我们分析当前 GC 存在的问题。先来看一下上面 JVM 参数中关于 GC 日志的参数:

  • safepoint=trace:记录关于 safepoint 的 trace 级别日志。 Safepoint 是 JVM 中一个特殊的状态,它用于确保所有线程在特定操作(如垃圾回收、代码优化等)之前进入安全状态。

  • classhisto*=trace:记录与类的历史相关的 trace 级别日志。 age*=info:记录与对象年龄(在新生代中存在的时间)相关的 info 级别日志。

  • gc*=info:记录与垃圾回收相关的 info 级别日志。

  • file=/opt/logs/gc-% t.log:将日志写入到 /opt/logs/ 目录下的文件中,文件名为 gc-% t.log,其中 % t 是一个占位符,表示当前时间戳。

  • time,level,tid,tags:在每个日志记录中包含时间戳、日志级别、线程 ID 和标签。

  • filesize=50M:设置日志文件的大小限制为 50MB。当日志文件大小达到此限制时,JVM 将创建一个新的日志文件并继续记录。

更详细的 gc 日志配置可以参考:https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html#enable-logging-with-the-jvm-unified-logging-framework

4.2 STW 日志解析

其中我们重点关注的就是 GC 的 STW 情况,以下是一些关键字代表 GC STW 阶段

  • 最基本的 STW 三阶段,初始标记:日志中 Pause Mark Start,再标记:日志中 Pause Mark End,初始转移:日志中 Pause Relocate Start。
    JVM — JDK11垃圾回收器 ZGC,JVM,jvm,数据库,大数据

  • 内存分配阻塞:这一般是因为垃圾生产速度大于回收速度,垃圾来不及回收,垃圾将堆占满时,线程会阻塞等待 GC 完成,关键字是 Allocation Stall(被阻塞的线程名称)
    JVM — JDK11垃圾回收器 ZGC,JVM,jvm,数据库,大数据
    如果出现此类日志,可以尝试如下方法解决:

  • -XX:ZCollectionInterval 该配置含义:两个 GC 周期之间的最大间隔(单位秒)。默认情况下,此选项设置为 0(禁用),可以适当调小该配置,让 GC 周期缩短、提升垃圾回收速度,但这会提升应用 CPU 占用。

  • -XX:ZAllocationSpikeTolerance 官方的解释是 ZGC 的分配尖峰容忍度。其实就是数值越大,越早触发回收。可以适当调大该配置,更早触发回收,提升垃圾回收速度,但这会提升应用 CPU 占用。

  • 安全点:所有线程进入到安全点后才能进行 GC,ZGC 定期进入安全点判断是否需要 GC。先进入安全点的线程需要等待后进入安全点的线程直到所有线程挂起。日志关键字 safepoint … stopped

  • dump 线程、内存:比如 jstack、jmap 命令,一般是手动 dump 导致,日志关键字 HeapDumper

5 总结

ZGC 作为下一代垃圾回收器,性能非常优秀。ZGC 垃圾回收过程几乎全部是并发,实际 STW 停顿时间极短,不到 10ms。这得益于其采用的着色指针和读屏障技术。文章来源地址https://www.toymoban.com/news/detail-541231.html

到了这里,关于JVM — JDK11垃圾回收器 ZGC的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JVM之垃圾回收器

    垃圾回收常见面试题: 如何判断对象是否死亡。 简单的介绍一下强引用、软引用、弱引用、虚引用。虚引用与软引用和弱引用的区别、使用软引用能带来的好处 如何判断一个常量是废弃常量 如何判断一个类是无用的类 垃圾收集有哪些算法,各自的特点? HotSpot 为什么要分

    2024年02月14日
    浏览(39)
  • JVM基础(6)——JVM垃圾回收器简介

    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 学习必须往深处挖,挖的越深,基础越扎实! 阶段1、深入多线程 阶段2、深入多线程设计模式 阶段3、深入juc源码解析

    2024年01月23日
    浏览(39)
  • JVM常见的垃圾回收器(详细)

    1、Young为年轻代出发的垃圾回收器。 2、Old为老触发的垃圾回收器。 3、连线代表的是垃圾回收器的组合。CMS 和Serial Old连线代表CMS一旦不行了,Serial Old上场。 1、什么是STW? STW是Stop-The-World缩写: 是在垃圾回收算法执⾏过程当中,将JVM内存冻结丶应用程序停顿的⼀种状态。

    2024年02月08日
    浏览(33)
  • JVM垃圾回收器G1详解

    在我们应用程序所应对的业务越来越庞大、复杂,用户越来越多,没有GC就不能保证应用程序正常进行,而经常造成STW的GC又跟不上实际的需求,我们需要不断地尝试对GC进行优化。G1(Garbage-First)垃圾回收器是在Java7 update4之后引入的一个新的垃圾回收器,是当今收集器技术发

    2024年02月09日
    浏览(35)
  • JVM基础(8)——CMS垃圾回收器

    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 学习必须往深处挖,挖的越深,基础越扎实! 阶段1、深入多线程 阶段2、深入多线程设计模式 阶段3、深入juc源码解析

    2024年01月16日
    浏览(41)
  • Java虚拟机(JVM)、垃圾回收器

    JRE(Java Runtime Environment,运行环境) 所有的程序都要在JRE下才能够运行。包括JVM和Java核心类库和支持文件。 JDK(Java Development Kit,开发工具包) 用来编译、调试Java程序的开发工具包。包括Java工具(javac/java/jdb等)和Java基础的类库(java API )。 JVM(Java Virtual Machine,虚拟机) JRE的一部分,

    2024年02月12日
    浏览(47)
  • 说一下 JVM 有哪些垃圾回收器?

    如果说垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。下图展示了7种作用于不同分代的收集器,其中用于回收新生代的收集器包括Serial、ParNew、Parallel Scavenge,回收老年代的收集器包括SerialOld、Parallel Old、CMS,还有用于回收整个Java堆的G1收集器

    2024年02月22日
    浏览(40)
  • JVM的组件、自动垃圾回收的工作原理、分代垃圾回收过程、可用的垃圾回收器类型

    https://www.processon.com/diagraming/64c8aa11c07d99075d934311 https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html 年轻代是所有新对象被分配和老化的地方。当年轻代填满时,这会导致minor garbage collection,minor gc会回收掉很多的游离对象。游离的年轻代很快就被收集起来。一些幸存的

    2024年02月14日
    浏览(46)
  • java八股文面试[JVM]——垃圾回收器

    jvm结构总结   常见的垃圾回收器有哪些?     CMS(Concurrent Mark Sweep) 整堆收集器 : G1 由于整个过程中 耗时最长 的 并发标记 和 并发清除 过程中,收集器线程都可以与用户线程一起工作,所以 总体上来说 ,CMS收集器的内存回收过程是与用户线程一起并发地执行。老年代收

    2024年02月11日
    浏览(44)
  • 【jvm系列-10】深入理解jvm垃圾回收器的种类以及内部的执行原理

    JVM系列整体栏目 内容 链接地址 【一】初识虚拟机与java虚拟机 https://blog.csdn.net/zhenghuishengq/article/details/129544460 【二】jvm的类加载子系统以及jclasslib的基本使用 https://blog.csdn.net/zhenghuishengq/article/details/129610963 【三】运行时私有区域之虚拟机栈、程序计数器、本地方法栈 https

    2024年02月05日
    浏览(76)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包