JVM工作原理与实战(二十七):堆的垃圾回收-G1垃圾回收器

简介: JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了G1垃圾回收器、G1垃圾回收器的回收方式、G1垃圾回收器执行流程、垃圾回收器的选择等内容。

一、垃圾回收器

垃圾回收器是Java虚拟机(JVM)中的重要组件,负责自动管理内存,回收不再使用的对象所占用的空间。了解垃圾回收器的种类、工作原理以及如何根据应用场景选择合适的垃圾回收器,对于提高应用程序的性能和稳定性至关重要。

垃圾回收器通过自动检测和回收不再被引用的对象,以释放内存空间,避免内存泄漏。为了实现这一目标,垃圾回收器采用了一系列算法来识别和回收无用对象。这些算法主要包括标记清除复制标记整理分代垃圾回收等。

垃圾回收器分为年轻代和老年代,它们各自负责不同生命周期的对象的回收。除了G1垃圾回收器外,其他垃圾回收器必须成对组合使用,以确保整个堆内存的有效管理。


二、G1垃圾回收器介绍

G1垃圾回收器(Garbage-First Garbage Collector)是JDK 9及之后版本的默认垃圾回收器。它的设计目标是将Parallel Scavenge和CMS两种垃圾回收器的优点相结合,以提供更好的性能表现。Parallel Scavenge关注吞吐量,允许用户设置最大暂停时间,但会减少年轻代可用空间的大小。相比之下,CMS关注暂停时间,但在吞吐量方面会有所下降。而G1垃圾回收器旨在解决这些问题,以实现更高效和可预测的垃圾回收性能。

G1垃圾回收器的设计特点:

  • 支持巨大的堆空间回收,并保证较高的吞吐量:通过将堆划分为多个相等的区域(Region),G1能够更有效地管理内存,并在回收过程中优先处理含有大量垃圾的对象区域。
  • 支持多CPU并行垃圾回收:G1采用并发收集方式,充分利用多核CPU的计算能力,提高垃圾回收的效率。这使得它在处理大规模数据和高负载应用程序时表现出色。
  • 允许用户设置最大暂停时间:通过调整相关参数,用户可以控制垃圾回收过程中的最大停顿时间,以满足应用程序的性能需求。

G1垃圾回收器采用了独特的内存管理策略,将整个堆内存划分为多个大小相等的区域,称为Region。这些Region不需要连续存储,提供了更大的灵活性。根据应用程序的需求,这些Region可以配置为Eden区(伊甸园区)、Survivor区(幸存者区)和Old区(老年代),以满足不同的回收需求。与之前的垃圾回收器相比,G1的出现改变了传统的内存管理方式。在G1之前,内存结构一般是连续的,而G1通过将堆内存划分为多个Region,打破了这种连续性。这种设计使得G1能够更好地适应现代计算机系统的内存布局和分配需求,提高了内存利用率和应用程序的性能。

image.gif

在G1垃圾回收器中,Region的大小是通过堆空间大小除以2048来计算得到的,也可以通过参数-XX:G1HeapRegionSize=来明确指定Region的大小。需要注意的是,Region size必须是2的指数幂,其取值范围是从1M到32M。

-XX:G1HeapRegionSize=

image.gif

G1垃圾回收器采用复制算法进行垃圾回收,该算法将活跃对象从一个内存区域复制到另一个内存区域,从而实现内存空间的回收。这种算法确保了内存碎片化最小化,提高了空间利用率和应用程序的性能。

G1垃圾回收器的优点:

  • 延迟可控性:对于较大的堆空间,如超过6G的堆,G1垃圾回收器能够保持较低的延迟,确保应用程序的响应性和性能。
  • 内存碎片最小化:G1通过复制算法进行垃圾回收,避免了内存碎片的产生,从而提高了内存的利用率和应用程序的性能。
  • 并发标记的SATB算法:G1使用高效的并发标记的SATB算法,该算法在标记阶段对应用程序的影响较小,确保了高吞吐量。
  • 多CPU并行处理:G1充分利用多核CPU的计算能力,通过并行处理提高垃圾回收的效率,特别是在处理大规模数据和高负载应用程序时。

G1垃圾回收器在吞吐量、延迟控制和内存管理方面具有显著优势。它适用于处理大规模数据和高负载应用程序的场景,尤其适用于对延迟敏感的应用程序和需要高效利用内存资源的应用。但是G1垃圾回收器在JDK 8之前还不够成熟,在JDK 8最新版本和JDK 9及更高版本中,建议默认使用G1作为垃圾回收器,可以使用-XX:+UseG1GC参数来启用G1垃圾回收器,JDK9之后默认不需要启用。

-XX:+UseG1GC

image.gif

三、G1垃圾回收器详解

1.G1垃圾回收器的回收方式

G1垃圾回收器主要采用了两种垃圾回收方式:年轻代回收(Young GC)和混合回收(Mixed GC)。

年轻代回收(Young GC):主要针对Eden区和Survivor区中不再使用的对象进行回收。这个过程会导致应用程序线程暂停(Stop-The-World)。G1垃圾回收器提供了一种灵活的机制,允许开发人员通过参数-XX:MaxGCPauseMillis=n(默认值为200毫秒)来设定每次垃圾回收时的最大暂停时间。这个参数的设置有助于优化应用程序的性能,确保垃圾回收过程对应用程序的影响降至最低。

-XX:MaxGCPauseMillis=n

image.gif

混合回收(Mixed GC)

G1垃圾回收器的混合回收包括以下步骤:

  1. 初始标记(Initial Mark):这一步主要标记GC Roots引用的对象为存活。GC Roots是垃圾回收的起始点,通常是活跃的对象。
  2. 并发标记(Concurrent Mark):在这一阶段,垃圾回收器会并发地遍历堆中的对象图,将初始标记阶段标记为存活的对象引用的对象也标记为存活。
  3. 最终标记(Final Mark or Remark):此步骤会再次检查并标记在并发标记阶段可能被漏标的对象,确保所有存活的对象都被正确地标记。同时,任何不再关联的对象也会被标记。
  4. 并发清理(Cleanup):这一步骤将存活的对象复制到其他Region,确保没有内存碎片的产生。G1垃圾回收器通过这种方式优化内存使用,并提高后续的垃圾回收效率。

image.gif

G1垃圾回收器对老年代的清理策略是选择存活度最低的区域进行回收,这样可以高效地回收内存,这也是G1(Garbage first)名称的由来。在清理阶段,G1使用复制算法,确保内存碎片的最小化。这种混合回收策略允许G1在不影响应用程序性能的情况下有效地管理Java堆的内存。

案例(回收红色区域)

image.gif

FULL GC:当G1垃圾回收器在执行清理阶段时,如果发现没有足够的空闲Region来存放需要转移的对象,就会触发Full GC,它会暂停所有的用户线程并使用单线程执行标记整理算法进行内存整理。这种操作对应用程序的性能影响较大,因此应尽量避免。为了预防Full GC的发生,开发者应确保分配给应用程序的堆内存有适当的预留空间,避免堆内存过度使用。这样可以减少Full GC的发生频率,并提高应用程序的稳定性和性能。

2.G1垃圾回收器执行流程

年轻代回收:

  • 1.对象分配与判断:新创建的对象首先会被放置在Eden区。G1垃圾回收器通过监控年轻代的使用情况,当判断年轻代区域已满(超过60%容量)时,触发Young GC。
  • 2.存活对象标记:在执行Young GC时,G1首先会精确地标记出Eden和Survivor区域中的存活对象。
  • 3.对象复制与区域清空:根据预设的最大暂停时间和其他配置参数,G1选择某些区域,将存活对象复制到一个新的Survivor区(对象的年龄加1),并清空这些区域。


  • 4.性能记录与优化:在执行Young GC过程中,G1垃圾回收器会记录每次回收时每个Eden区和Survivor区的详细耗时数据。这些数据为下次回收提供了宝贵的参考,帮助G1更精确地计算出在给定的最大暂停时间内可以回收的Region数量。例如,如果配置的-XX:MaxGCPauseMillis为n(默认200),每个Region的回收耗时为40ms,那么在一次回收中,G1最多能处理4个Region。
  • 5.循环与移动:后续的Young GC过程与之前相似,Survivor区中的存活对象会被移动到另一个Survivor区。
  • 6.老年代与Humongous区:当某个对象的年龄达到预设阈值(默认15)或其大小超过一个Region的一半时,该对象会被移入老年代。这些老年代被称为Humongous区。例如,在堆内存为4G、每个Region为2M的环境中,任何超过1M的对象都会被放入Humongous区。如果对象过大,可能会跨越多个Region。


混合回收:

  • 7.触发条件与处理:随着时间的推移,老年代中会出现多个区域。当总堆占有率达到预设阈值(-XX:InitiatingHeapOccupancyPercent默认45%)时,G1会触发混合回收(Mixed GC)。这种回收会处理所有年轻代和部分老年代的对象以及大对象区。混合回收采用复制算法来完成,确保高效的内存回收。
-XX:InitiatingHeapOccupancyPercent

image.gif

3.垃圾回收器的选择

对于JDK 8及更早版本:

  • ParNew + CMS:这个组合关注垃圾回收时的暂停时间。ParNew作为年轻代回收器,而CMS用于老年代回收。这种组合适合对暂停时间有严格要求的场景。
  • Parallel Scavenge + Parallel Old:这个组合主要关注吞吐量。Parallel Scavenge用于年轻代,Parallel Old用于老年代。这种组合适合对吞吐量有较高要求的场景。
  • G1(JDK 8之前不建议):尽管G1在JDK 8之前并不推荐使用,但在JDK 8及更早版本中,如果堆大小较大并且关注暂停时间,可以考虑使用G1。

对于JDK 9及更高版本:

  • G1:随着G1的日趋成熟,从JDK 9开始,G1已成为默认的垃圾回收器。因此,建议在生产环境中使用G1,以充分利用其性能和功能。

总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了G1垃圾回收器、G1垃圾回收器的回收方式、G1垃圾回收器执行流程、垃圾回收器的选择等内容,希望对大家有所帮助。

相关文章
|
5月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
495 55
|
5月前
|
缓存 算法 Java
JVM深入原理(八)(一):垃圾回收
弱引用-作用:JVM中使用WeakReference对象来实现软引用,一般在ThreadLocal中,当进行垃圾回收时,被弱引用对象引用的对象就直接被回收.软引用-作用:JVM中使用SoftReference对象来实现软引用,一般在缓存中使用,当程序内存不足时,被引用的对象就会被回收.强引用-作用:可达性算法描述的根对象引用普通对象的引用,指的就是强引用,只要有这层关系存在,被引用的对象就会不被垃圾回收。引用计数法-缺点:如果两个对象循环引用,而又没有其他的对象来引用它们,这样就造成垃圾堆积。
157 0
|
5月前
|
算法 Java 对象存储
JVM深入原理(八)(二):垃圾回收
Java垃圾回收过程会通过单独的GC线程来完成,但是不管使用哪一种GC算法,都会有部分阶段需要停止所有的用户线程。这个过程被称之为StopTheWorld简称STW,如果STW时间过长则会影响用户的使用。一般来说,堆内存越大,最大STW就越长,想减少最大STW,就会减少吞吐量,不同的GC算法适用于不同的场景。分代回收算法将整个堆中的区域划分为新生代和老年代。--超过新生代大小的大对象会直接晋升到老年代。
111 0
|
7月前
|
存储 算法 Java
G1原理—5.G1垃圾回收过程之Mixed GC
本文介绍了G1的Mixed GC垃圾回收过程,包括并发标记算法详解、三色标记法如何解决错标漏标问题、SATB如何解决错标漏标问题、Mixed GC的过程、选择CollectSet的算法
G1原理—5.G1垃圾回收过程之Mixed GC
|
7月前
|
存储 算法 Java
G1原理—6.G1垃圾回收过程之Full GC
本文详细探讨了G1垃圾回收器对Full GC(FGC)的优化处理,涵盖FGC的前置处理、整体流程及并行化改进。重点分析了传统FGC串行化的局限性以及G1通过Region分区和RSet机制实现并行标记的优势,包括任务窃取提升效率、跨分区压缩以生成空闲Region等技术细节。此外,文章还介绍了G1的新特性——字符串去重优化,通过判断char数组一致性减少重复字符串占用内存,从而提升内存使用效率。总结部分全面回顾了G1在FGC中的各项优化措施及其带来的性能改善。
G1原理—6.G1垃圾回收过程之Full GC
|
7月前
|
存储 算法 Java
G1原理—4.G1垃圾回收的过程之Young GC
本文详细解析了G1垃圾回收器中YGC(Young Generation Collection)的完整流程,包括并行与串行处理阶段。内容涵盖YGC相关参数设置、YGC与Mixed GC及FGC的关系、新生代垃圾回收的具体步骤(如标记存活对象、复制到Survivor区、动态调整Region数量等),以及并行阶段的多线程操作和串行阶段的关键任务(如处理软引用、整理卡表、重构RSet)。
G1原理—4.G1垃圾回收的过程之Young GC
|
10月前
|
算法 网络协议 Java
【JVM】——GC垃圾回收机制(图解通俗易懂)
GC垃圾回收,标识出垃圾(计数机制、可达性分析)内存释放机制(标记清除、复制算法、标记整理、分代回收)
|
12月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
585 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
监控 算法 Java
深入理解Java中的垃圾回收机制(GC)
本文将探讨Java的自动内存管理核心——垃圾回收机制。通过详细解析标记-清除算法、复制算法和标记-整理算法等常用垃圾回收算法,以及CMS、G1等常见垃圾回收器,帮助读者更好地理解Java应用的性能优化和内存管理。同时,探讨分代收集、分区收集等策略在实际项目中的应用。结语部分总结了垃圾回收机制在Java开发中的重要性,并展望了未来可能的发展。
373 27
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。