JVM G1垃圾收集器

G1(Garbage-First)垃圾收集器是JDK 9之后引入的一款全新的垃圾收集器。与其他垃圾收集器不同,G1垃圾收集器主要针对大堆内存进行优化,尤其是在具有数GB至数百GB内存的环境中表现出色。

G1垃圾收集器基于分代收集理论,将堆内存分成多个Region,每个Region可以作为Eden区、Survivor区或Old区。在G1中,垃圾收集器不是依赖于年轻代和老年代的划分,而是把整个堆划分为多个大小相等的区域,每个区域的大小通常为1MB到32MB,这些区域不再是连续的,而是通过指针链接起来的。

与其他分代垃圾收集器不同,G1的分代不是固定的,而是根据实时的堆内存使用情况进行调整,以达到最大化的垃圾收集效率。G1收集器的垃圾回收主要包括以下步骤:

初始标记(Initial Mark):标记所有根区域对象和老年代区域存活对象,这个阶段需要STW(Stop The World)。

并发标记(Concurrent Mark):标记所有存活的对象,包括根对象、老年代对象和跨Region引用的对象,这个阶段不需要STW,可以与应用程序同时运行。

最终标记(Final Mark):为标记的对象创建标记存活信息,并发标记阶段的标记信息也会被处理,这个阶段需要STW。

筛选回收(Live Data Counting and Evacuation):G1将各个Region按照存活对象占比从高到低排序,根据内存回收目标选取一部分Region,将这些Region中的存活对象复制到其他未被选择的Region,最后清理选中的Region,这个阶段是并发的。

  • 相对于其他的垃圾收集器,G1有以下特点:
  • 分代收集:G1收集器同样将堆内存分为新生代和老年代,但是它不会强制限定它们的大小,而是把整个堆划分为多个相等大小的区域,每个区域可能是新生代或老年代,这样更加灵活。
  • 并行和并发:G1收集器可以利用多个CPU核心并行处理,同时也使用了一些并发技术,如并发标记和并发清除,从而减少了STW的时间。
  • 分区回收:G1收集器在收集时会优先回收垃圾最多的区域,这样可以提高垃圾回收的效率,避免全局扫描,降低STW时间。
  • 空间整理:G1收集器会尽量将存活对象放在一起,避免内存碎片的产生。
  • G1收集器的工作流程大致如下:
  • 初始标记阶段(STW):首先会暂停所有的应用线程,标记所有的根对象,并标记所有根对象直接引用的对象,这一阶段速度较快。
  • 并发标记阶段:同时开始标记阶段,标记所有存活的对象,这个阶段会和应用程序并发执行。
  • 最终标记阶段(STW):在并发标记阶段结束时,G1会再次暂停应用线程,完成标记工作。
  • 筛选回收阶段:G1收集器会根据垃圾最多的区域作为优先回收区域,执行空间整理,将存活对象拷贝到空闲区域,然后清空被回收的区域。该阶段也是与应用程序并发执行的。

G1收集器的优缺点如下:

优点:

高效的垃圾回收:G1的设计目标是在满足GC暂停时间和吞吐量要求的情况下,尽可能高效地回收垃圾。通过分区、增量式回收、全局并行和全局并发等技术,G1在垃圾回收方面表现出色。

低延迟:G1采用分区的方式进行垃圾回收,可以控制每个分区的大小,以便在某些分区中暂停时间较短,尽量避免应用程序的长时间停顿。

能处理大内存:G1是为了应对堆内存占用较大的应用程序而设计的,它能够处理很大的堆内存,减少堆内存的碎片化,提高内存使用率。

可预测性:G1垃圾收集器的设计目标是实现可控的GC暂停时间,可以通过设置目标GC时间和暂停时间等参数来控制GC暂停的时间。

不需要连续的物理内存:与CMS等垃圾收集器不同,G1垃圾收集器不需要连续的物理内存,这意味着即使堆内存分散在不同的物理内存上,G1垃圾收集器也可以正常运行。

缺点:

JVM G1 垃圾收集器相较于其他垃圾收集器在性能方面有所提升,但也存在以下一些缺点:

碎片问题:G1 垃圾收集器的堆内存被划分成多个区域,其中包括了新生代和老年代。在并发标记和整理阶段,会对堆内存进行空间整合,但在堆内存空间的划分和回收过程中,仍然可能出现碎片问题,这可能导致某些大对象无法找到足够的连续内存空间而被拒绝。

暂停时间不可预测:G1 垃圾收集器虽然采用了增量垃圾收集、并发标记和整理等技术来减小暂停时间,但在 GC 执行过程中仍然存在全局停顿的情况。由于 G1 垃圾收集器使用了多个线程并发进行垃圾回收,因此在 GC 过程中可能会造成一些短暂的卡顿,而这些卡顿的时间是不可预测的。

对硬件资源要求高:由于 G1 垃圾收集器需要使用多个线程并行进行垃圾回收,因此需要更多的 CPU 和内存资源来支持。如果应用程序所在的服务器硬件配置较低,则可能会影响垃圾回收的效率和应用程序的性能。

配置参数繁多:G1 垃圾收集器需要配置多个参数来进行优化和调整,例如:最大停顿时间、分区大小、并发线程数等。这些参数的设置需要根据具体的应用场景和硬件环境来进行调整,配置不当可能会导致垃圾回收效率降低,或者出现其它问题。