G1介绍


1.来源

本文主要翻译oracle官方文档: https://docs.oracle.com/javase/9/gctuning/garbage-first-garbage-collector.htm#JSGCT-GUID-ED3AB6D3-FD9B-4447-9EDF-983ED2F7A573

目录结构与官方文档类似。

首先补充一个堆内存中各个名词的概念:

(1)init  表示 Java 虚拟机在启动期间从操作系统请求用于内存管理的初始内存量(以字节为单位)。 Java 虚拟机可能会向操作系统请求额外的内存,也可能会随着时间的推移向系统释放内存。 init 的值可能未定义。

(2)used 表示当前使用的内存量(以字节为单位)。

(3)committed 表示保证可供 Java 虚拟机使用的内存量(以字节为单位)。提交的内存量可能会随时间变化(增加或减少)。 Java 虚拟机可能会向系统释放内存,并且导致commited内存可能小于 init。commited将始终大于或等于used。

(4)max 表示可用于内存管理的最大内存量(以字节为单位)。它的值可能是未定义的。如果已定义,最大内存量可能会随时间变化。如果定义了 max,则使用和提交的内存量将始终小于或等于 max。如果尝试增加已用内存,即使 used <= max 仍然为 true(例如,当系统虚拟内存不足时),则内存分配可能会失败。

Garbage-First 垃圾回收期简介

垃圾优先 (G1) 垃圾收集器设计针对具有大量内存的多内核机器。 它尽量保证在几乎不需要配置的情况下实现高吞吐量,并且试图以足够高的概率满足垃圾收集暂停时间的目标。

G1 旨在当前的目标应用程序和环境在延迟和吞吐量之间提供最佳平衡,其特性包括:

  • 堆大小高达 10 GB 或更大,其中超过 50% 的 Java 堆被实时数据占用。
  • 对象分配和晋升的速率可能随时间显着变化。
  • 堆中有大量碎片。
  • 不超过几百毫秒的可预测的暂停时间目标,避免长时间的垃圾收集暂停。

G1 替换了并发标记扫描 (CMS) 收集器。 它也是默认JAVA9 的收集器。

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

使用G1

在java 8 中如果想使用G1,需要显示的在启动命令中添加  -XX:+UseG1GC

基本概念

G1 是一个分代的、增量的、并行的、最大化并发的、stop-the-world 和 疏散型的垃圾收集器,它监视每个 stop-the-world 暂停中的暂停时间目标。 与其他收集器类似,G1 将堆分成(虚拟)年轻代和年老代。空间回收工作集中在回收最有效的年轻代上,偶尔在老年代进行空间回收。
某些操作总是在 stop-the-world 暂停中执行以提高吞吐量。其他需要耗费更多时间的操作(例如全局标记等全堆操作)与应用程序并发执行。为了使空间回收的stop-the-world暂停较短,G1 逐步并行地执行空间回收。 G1 通过跟踪有关先前应用程序行为和垃圾收集暂停的信息来构建相关回收成本的模型来实现可预测性。
G1使用此信息来确定在暂停中完成的工作的大小。例如,G1 首先回收效率最高的区域(即大部分被垃圾填满的区域,因此得名)中的空间。 G1 主要通过使用疏散来回收空间:在要收集的选定内存区域内找到的活动对象被复制到新的内存区域,并在此过程中压缩它们。疏散完成后,先前由活动对象占用的空间将重新用于应用程序分配。
G1收集器不是实时收集器。它试图在更长的时间内以高概率满足设定的暂停时间目标,但定不是绝对满足设定的暂停时间。
 

堆布局

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

 

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

应用程序总是分配到年轻代,即 eden 区域。而大对象会被直接分配为属于老年代。

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

 

垃圾回收周期

 

 

下面的列表详细描述了 G1 垃圾回收周期的各个阶段、它们的暂停以及各个阶段之间的转换:

*备注:  空间回收过程 space-reclamation phase (mixed gc过程中的一部分 )

Young-only 阶段:这个阶段从一些普通的年轻代开始,将对象提升到老年代。当老年代占用率达到某个阈值,即初始堆占用阈值(IHOP) 时,年轻代和空间回收阶段之间的过渡开始。此时,G1 调度的是 Concurrent Start 年轻收集而不是普通的年轻收集。

  • Concurrent Start :除了执行普通的年轻收集之外,这种类型的收集还会启动标记过程(marking process)。并发标记决定了老年代区域中所有当前可访问的(活动的)对象,以便为接下来的空间回收阶段保留。当集合标记还没有完全完成时,可能会发生正常的年轻集合。标记以两个特殊的stop-world结束:remark和cleanup。
  • Remark:此暂停完成标记本身,执行全局引用处理和类卸载,回收完全空的区域并清理内部数据结构。在 Remark 和 Cleanup 之间 G1 计算信息以便稍后能够同时回收选定的老年代区域中的空闲空间,这将在 Cleanup 暂停时完成。
  • CleanUp:这个暂停决定了空间回收阶段是否真的会随之而来。如果随后是空间回收阶段,则仅年轻阶段以单个 Prepare Mixed 年轻集合结束。

Space-reclamation phase:这个阶段由多个混合集合组成,除了年轻代区域外,还清除老年代区域集的活动对象。当 G1 确定 回收更多的老年代区域也不会产生足够的可用空间时,空间回收阶段结束。

空间回收后,收集周期从另一个仅年轻阶段重新开始。作为备份,如果应用程序在收集活动信息时内存不足,G1 会像其他收集器一样执行就地停止世界全堆垃圾回收(Full GC)

确定initial heap的设置

初始堆占用百分比 (IHOP) 是触发初始标记收集的阈值,它被定义为老年代大小的百分比。

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

使用选项-XX:-G1UseAdaptiveIHOP 关闭 G1 的这种行为。在这种情况下,-XX:InitiatingHeapOccupancyPercent 的值始终确定此阈值。

在内部,自适应 IHOP 尝试设置初始堆占用率,以便在老年代占用率处于当前最大老年代大小减去 -XX:G1HeapReservePercent 作为额外缓冲区时开始空间回收阶段的第一个混合垃圾收集.

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM