[HotSpot 虚拟机垃圾收集调优指南-JavaSE11-笔记]-7-Garbage-First 垃圾收集器简介G1

7-Garbage-First 垃圾收集器简介G1

7.1 Garbage-First 垃圾收集器简介

Garbage-First (G1) 垃圾收集器针对具有大量内存的多处理器机器。它试图以高概率满足垃圾收集暂停时间目标,同时在几乎不需要配置的情况下实现高吞吐量。G1 旨在使用当前目标应用程序和环境提供延迟吞吐量之间的最佳平衡,其功能包括:

  • 堆大小高达 10 GB 或更大,超过 50% 的 Java 堆被实时数据占用。
  • 随时间变化的对象分配和提升率。
  • 堆中有大量碎片。
  • 可预测的暂停时间目标不超过几百毫秒,避免长时间的垃圾收集暂停
  • G1 取代了并发标记扫描 (CMS) 收集器。它也是默认的收集器

G1 收集器实现了高性能,并尝试通过以下几节中描述的几种方式来满足暂停时间目标。

7.2 启用 G1

Garbage-First 垃圾收集器是默认收集器,因此通常您不必执行任何其他操作。 -XX:+UseG1GC您可以通过在命令行上 提供来显式启用它。

7.3 基本概念

G1 是一个分代的增量的并行的、主要是并发的stop-the-world疏散的垃圾收集器,它监控每个 stop-the-world 暂停中的暂停时间目标。与其他收集器类似,G1 将堆分成(虚拟)年轻代老年代。空间回收工作集中在最有效的年轻代偶尔在老一代进行空间回收

某些操作总是在 stop-the-world 暂停中执行以提高吞吐量。其他在应用程序停止时需要更多时间的操作(例如全局标记等全堆操作)与应用程序并行执行。为了使 stop-the-world 停顿时间短于空间回收,G1 逐步并行执行空间回收G1 通过跟踪有关先前应用程序行为垃圾收集暂停的信息构建相关成本模型,从而实现可预测性。它使用此信息来确定在暂停中完成的工作的大小。例如,G1 首先在最有效的区域回收空间(即大部分被垃圾填满的区域,因此得名)。

G1 主要通过使用疏散来回收空间:在选定的内存区域找到要收集的活动对象复制到新的内存区域,并在此过程中压缩它们疏散完成后,先前由活动对象占用的空间重新用于应用程序的分配

Garbage-First 收集器不是实时收集器。它试图在较长时间内以高概率达到设定的暂停时间目标,但对于给定的暂停并不总是绝对确定

7.4 堆布局

G1 将堆划分为一组大小相等的堆区域,每个区域都是连续的虚拟内存范围,如图 7-1 所示。区域内存分配内存回收单位。在任何给定时间,这些区域中的每一个都可以是空的(浅灰色),或者分配给特定的一代,无论是年轻的还是年老的。当内存请求进入时内存管理器会分发空闲区域。内存管理器将它们分配给一代,然后将它们作为空闲空间返回给应用程序,它可以自行分配到其中。
在这里插入图片描述

图 7-1 G1 垃圾收集器堆布局

G1垃圾收集器堆布局说明如下

  • 伊甸园区域(红色)
  • 幸存者区域(红色带有“S”)
  • 老区(浅蓝色)构成老年代
  • 跨越多个区域的对象,老年代区域可能是巨大的(带有“H”的浅蓝色)

年轻代包含伊甸园区域(红色)幸存者区域(红色带有“S”)。这些区域提供与其他收集器中的相应连续空间相同的功能,不同之处在于,在 G1 中,这些区域通常以非连续模式布局在内存中。老区(浅蓝色)构成老年代。对于跨越多个区域的对象,老年代区域可能是巨大的(带有“H”的浅蓝色)

应用程序总是分配到年轻代,即伊甸园区域,但直接分配为属于老年代的巨大对象除外。

G1 垃圾回收暂停可以回收整个年轻代的空间,以及任何额外的老年代区域集在任何回收暂停。在暂停期间G1 将该集合集中的对象复制到堆中的一个或多个不同区域对象的目标区域取决于该对象的源区域整个年轻代被复制到幸存者或旧区域,而对象从旧区域复制到其他不同的旧区域使用老化

7.5 垃圾回收周期

在高层次上,G1 收集器在两个阶段之间交替

  • Young-only 阶段包含垃圾收集,这些垃圾收集会逐渐用老年代中的对象填满当前可用的内存。
  • 空间回收阶段是 G1 除了处理年轻代外,还逐步回收老年代中的空间。然后循环以仅年轻阶段重新开始。

图 7-2 给出了关于这个循环的概述,并举例说明了可能发生的垃圾收集暂停序列:
在这里插入图片描述

图 7-2 垃圾回收周期概览

“图 7-2 垃圾回收周期概览”说明
以下列表详细描述了 G1 垃圾收集周期的阶段、它们的暂停和阶段之间的转换:

  • Young-only 阶段:这个阶段从一些将对象提升到老年代的正常年轻集合开始。当老年代占用率达到某个阈值,即 Initiating Heap Occupancy 阈值时,young-only 阶段和空间回收阶段之间的转换开始。此时,G1 会安排一个 Concurrent Start young collection,而不是 Normal young collection。

    • 并发开始:这种类型的收集除了执行正常的年轻收集之外,还会开始标记过程。并发标记确定老年代区域中所有当前可到达(活动)的对象,以保留用于下一个空间回收阶段。在集合标记尚未完全完成时,可能会发生正常的年轻集合。标记结束时有两个特殊的停顿:Remark 和 Cleanup。

    • 重新标记: 此暂停完成标记本身,执行全局引用处理和类卸载,回收完全空的区域并清理内部数据结构。在 Remark 和 Cleanup G1 之间计算信息,以便稍后能够同时回收选定的老年代区域中的空闲空间,这将在 Cleanup 暂停中完成。

    • 清理: 这个暂停决定了空间回收阶段是否真的会紧随其后。如果随后是空间回收阶段,则 Young-only 阶段以单个 Prepare Mixed 年轻集合完成。

  • 空间回收阶段: 该阶段由多个混合收集组成,除了年轻代区域外,还疏散老年代区域集的活动对象。当 G1 确定疏散更多的老年代区域不会产生足够的可用空间值得努力时,空间回收阶段就结束了。

在空间回收之后,收集周期以另一个年轻阶段重新开始。作为备份,如果应用程序在收集活动信息时内存不足,G1 会像其他收集器一样执行就地STOP THE WORLD全堆压缩(Full GC)

7.6 垃圾优先内部

本节介绍垃圾优先 (G1) 垃圾收集器的一些重要细节。

确定启动堆占用
Initiating Heap Occupancy Percent (IHOP)(启动堆占用率)是触发 Initial Mark 收集的阈值,它被定义为老年代大小的百分比 。

默认情况下,G1 通过观察标记需要多长时间以及标记周期期间通常在老年代分配多少内存来自动确定最佳 IHOP。此功能称为自适应 IHOP。如果此功能处于活动状态,则该选项-XX:InitiatingHeapOccupancyPercent将初始值确定为当前老年代大小的百分比,只要没有足够的观察值来对 Initiating Heap Occupancy 阈值进行良好预测。使用选项关闭 G1 的这种行为-XX:-G1UseAdaptiveIHOP。在这种情况下, 的值-XX:InitiatingHeapOccupancyPercent总是决定这个阈值。

在内部,自适应 IHOP 尝试设置 Initiating Heap Occupancy,以便当老年代占用率达到当前最大老年代大小减去-XX:G1HeapReservePercent作为额外缓冲区的值时,空间回收阶段的第一次混合垃圾收集开始。

7.7 G1 标记

G1 标记使用一种称为Snapshot-At-The-Beginning (SATB)(开始时的快照)的算法。它在初始标记暂停时拍摄堆的虚拟快照,此时在标记开始时处于活动状态的所有对象在标记的剩余时间内都被视为处于活动状态。这意味着在标记过程中变为静止(无法到达)的对象仍被视为活动对象,以回收空间(某些例外情况除外)。与其他收集器相比,这可能会导致一些额外的内存被错误地保留。但是,SATB 可能会在备注暂停期间提供更好的延迟。在该标记期间过于保守地考虑的存活对象将在下一次标记期间被回收。请参阅垃圾优先垃圾收集器调优 有关标记问题的更多信息的主题。

7.8 在非常紧张的堆情况下的行为

当应用程序保持大量内存以致疏散无法找到足够的空间复制到时,就会发生疏散失败。疏散失败意味着 G1 试图通过将任何已经移动的对象保留在其新位置,而不复制任何尚未移动的对象,仅调整对象之间的引用来完成当前的垃圾回收。疏散失败可能会产生一些额外的开销,但通常应该与其他年轻集合一样快。在疏散失败的垃圾收集之后,G1 将正常恢复应用程序,无需任何其他措施。G1 假设疏散失败发生在接近垃圾回收结束时;那是,

如果这个假设不成立,那么 G1 最终会安排一次 Full GC。这种类型的集合执行整个堆的就地压缩。这可能非常缓慢。

有关分配失败或 Full GC 在发出内存信号之前的问题的更多信息, 请参阅下一个博客调优篇。

7.9 巨大的对象

巨大的对象是大于或等于半个区域大小的对象。除非使用该选项 进行设置,否则当前区域大小根据G1 GC 的默认值部分中的默认值进行确定。-XX:G1HeapRegionSize

这些巨大的对象有时会以特殊方式处理

每个巨大的对象都被分配为老一代中的一系列连续区域。对象本身的起点始终位于该序列中第一个区域的起点。序列的最后一个区域中的任何剩余空间都将丢失用于分配,直到整个对象被回收。

一般来说,巨大的对象只能在清理暂停期间标记结束时回收,或者在完全 GC 期间如果它们变得无法访问。但是,对于原始类型数组(例如, bool各种整数和浮点值)的巨大对象有一个特殊规定。如果大量对象在任何类型的垃圾回收暂停时没有被许多对象引用,G1 有机会尝试回收巨大的对象。默认情况下启用此行为,但您可以使用选项禁用它-XX:G1EagerReclaimHumongousObjects

巨大对象的分配可能会导致垃圾收集暂停过早发生。G1 在每个巨大的对象分配时检查初始堆占用阈值,如果当前占用超过该阈值,则可能立即强制初始标记年轻收集。
巨大的对象从不移动,即使在 Full GC 期间也是如此。这可能会导致过早的缓慢 Full GC 或由于区域空间碎片而导致剩余大量可用空间的意外内存不足情况。

7.10 年轻一代的大小Young-Only Phase Generation Sizing

在young-only阶段,要收集的区域集(收集集)仅由年轻代区域组成。G1 总是在正常的年轻收集结束时为下一个 阶段调整年轻代的大小。这样,G1 可以满足使用 -XX:MaxGCPauseTimeMillis-XX:PauseTimeIntervalMillis基于对实际暂停时间的长期观察而设定的暂停时间目标。它考虑了类似规模的年轻一代回收需要多长时间。这包括诸如在收集过程中必须复制多少对象以及这些对象的相互连接程度等信息。

如果没有其他约束,则 G1 会在确定满足暂停时间的值-XX:G1NewSizePercent之间自适应调整年轻代的大小。 有关如何修复长时间停顿的更多信息, -XX:G1MaxNewSizePercent请参阅下一个博客调优篇 。

7.11 空间回收阶段分代的大小

在空间回收阶段G1 尝试在一次垃圾回收暂停中最大化在老年代回收的空间量。年轻代的大小设置为允许的最小值,通常由 确定-XX:G1NewSizePercent,并且添加任何用于回收空间的老年代区域,直到 G1 确定添加更多区域将超过暂停时间目标。在特定的垃圾回收暂停中,G1 按照回收效率、最高优先和剩余可用时间来获得最终回收集的顺序添加老年代区域。

每次垃圾回收要占用的老年代区域的数量在下限是由要收集的潜在候选老年代区域(收集集候选区域)的数量除以由 确定的空间回收阶段的长度 -XX:G1MixedGCCountTarget。收集集候选区域都是占有率低于-XX:G1MixedGCLiveThresholdPercent阶段开始时的老年代区域。

当收集集候选区域中可回收的剩余空间量小于 设置的百分比时,该阶段结束 -XX:G1HeapWastePercent。

有关G1 将使用多少个老年代区域以及如何避免长时间混合收集暂停的更多信息, 请参阅下一个博客调优篇。

G1 GC 的默认设置
本主题概述了特定于 G1 的最重要默认值及其默认值。它们粗略地概述了使用 G1 的预期行为和资源使用情况,没有任何附加选项。

选项和默认值描述
-XX:MaxGCPauseMillis=200最大暂停时间的目标。
-XX:GCPauseTimeInterval= ergo最大暂停时间间隔的目标。默认情况下,G1 不设置任何目标,允许 G1 在极端情况下连续执行垃圾回收。
-XX:ParallelGCThreads= ergo垃圾收集暂停期间用于并行工作的最大线程数。这是从运行 VM 的计算机的可用线程数得出的,方法如下:如果进程可用的 CPU 线程数小于或等于 8,则使用该数。否则,将大于最终线程数的线程数增加八分之五。-XX:HeapSizePerGCThread在每次暂停开始时,使用的最大线程数进一步受到最大总堆大小的限制:G1 不会使用每个Java 堆容量 超过一个线程。
-XX:ConcGCThreads= ergo用于并发工作的最大线程数。默认情况下,此值-XX:ParallelGCThreads 除以 4。
-XX:+G1UseAdaptiveIHOP -XX:InitiatingHeapOccupancyPercent=45控制初始堆占用率的默认值表示该值的自适应确定已打开,并且在前几个收集周期中,G1 将使用 45% 的老年代占用率作为标记开始阈值。
-XX:G1HeapRegionSize=ergo基于初始和最大堆大小的堆区域大小集。因此该堆包含大约 2048 个堆区域。堆区域的大小可以在 1 到 32 MB 之间变化,并且必须是 2 的幂。
-XX:G1NewSizePercent=5 -XX:G1MaxNewSizePercent=60年轻代的总大小,在这两个值之间变化,作为当前使用的 Java 堆的百分比。
-XX:G1HeapWastePercent=5集合集合候选中允许的未回收空间百分比。如果候选集合中的可用空间低于此值,则 G1 停止空间回收阶段。
-XX:G1MixedGCCountTarget=8许多集合中空间回收阶段的预期长度。
-XX:G1MixedGCLiveThresholdPercent=85在此空间回收阶段不会收集活动对象占用率高于此百分比的老年代区域。

7.12 与其它垃圾收集器的比较

这是G1和其他收集器之间主要区别的总结:

  • Parallel GC只能作为一个整体来压缩和回收老年代的空间。G1 将这项工作逐步分布在多个更短的垃圾收集中。这大大缩短了暂停时间,但可能会降低吞吐量。
  • 与 CMS 类似,G1 并发执行部分老年代空间回收。但是,CMS 无法对老年代堆进行碎片整理,最终会遇到长时间的 Full GC。
  • G1 可能表现出比其他收集器更高的开销,由于其并发性而影响吞吐量。

由于它的工作方式,G1 有一些独特的机制来提高垃圾收集效率:

  • G1 可以在任何收集期间回收一些完全空的、大面积的老年代。这可以避免许多其他不必要的垃圾收集,无需太多努力即可释放大量空间。
  • G1 可以选择同时尝试对 Java 堆上的重复字符串进行重复数据删除。

从老年代回收空的大对象总是启用的。您可以使用选项禁用此功能-XX:-G1EagerReclaimHumongousObjects。默认情况下禁用字符串重复数据删除。您可以使用选项启用它 -XX:+G1EnableStringDeduplication。

技术咨询支持,可以扫描微信公众号进行回复咨询
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宋小生的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值