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
基本概念
堆布局

年轻代包含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 作为额外缓冲区时开始空间回收阶段的第一个混合垃圾收集.