G1 垃圾收集器

Heer Liu

G1 垃圾收集器是一种新型的垃圾收集器,专门针对大堆内存的应用程序进行优化,可以更好地处理大量对象的分配和释放,减少停顿时间,并帮助应用程序提高性能。G1 收集器是在 JDK 7 update 4 版本中首次推出的,在 Java 9 中正式成为默认的垃圾收集器。通过启动参数"-XX:+UseG1GC"来使用 G1 垃圾收集器。

区域划分

G1(Garbage-First)垃圾收集器,将 Java 堆内存划分为多个大小相等的区域(Region),并对这些区域进行垃圾回收。每个区域的大小通常是1MB到32MB之间,并且可以通过JVM参数 -XX:G1HeapRegionSize 进行调整,默认为 1M。

堆内存的区域划分

  • Eden 区:当新对象被创建时,它们会首先被分配到Eden区。Eden区是G1垃圾收集器的年轻代区域。默认情况下,Eden区的大小占整个Java堆内存的5%到10%。
  • 存活区(Survivor区):与 CMS 垃圾收集器类似,G1 垃圾收集器还使用了两个 Survivor 区,并且 Survivor 区的大小与 Eden 区的大小相等。当执行年轻代垃圾回收时,存活的对象会被移动到 Survivor 区。默认情况下,Survivo r区的大小占整个 Java 堆内存的5%到10%。
  • Old 区:存放长时间存活的对象。G1 垃圾收集器采用了“增量式整理”算法来避免 Full GC 带来的停顿时间过长。默认情况下,Old 区的大小占整个 Java 堆内存的60%到80%。
  • Humongous 区:专门用来存储大对象,如果一个对象的大小超过了一个区域的 50%,那么这个对象将直接被分配到 Humongous 区,而不是被分配到 Eden区或 Old 区。对于 Humongous 对象,G1 垃圾收集器将使用“复制”算法进行垃圾回收。

工作原理

G1 垃圾收集器采用“复制和标记整理”两种算法来回收内存,主要工作流程:

G1

  1. 初始标记阶段:在此阶段中,G1收集器会标记所有被根对象直接关联的对象,并记录它们的位置和状态。
  2. 并发标记阶段:在此阶段中,G1收集器会并发地处理堆中的对象,找出所有与标记对象直接或间接关联的对象,并标记它们。
  3. 最终标记阶段:在此阶段中,G1收集器会重新暂停应用程序,完成对并发标记过程中可能遗漏的标记的补充,以确保所有存活的对象都已被标记。
  4. 筛选阶段:在此阶段中,G1收集器会基于可回收的内存大小和回收时间预算来确定哪些区域需要被回收,并将这些区域加入回收集。
  5. 清理阶段:在此阶段中,G1收集器会清理回收集中的区域,并将其中的内存返回给Java虚拟机,使其可以再次使用。

总的来说,G1垃圾收集器通过将堆内存分成多个大小相等的区域,将大型堆的垃圾收集任务分成多个小的垃圾收集任务,从而避免了全局暂停,具有更高的可预测性和可控性。同时,G1垃圾收集器也可以根据应用程序产生的垃圾量自适应调整阶段时间,提高了垃圾回收的效率。

优缺点

优点

  1. 分代收集:G1垃圾收集器将堆内存分为多个大小相等的区域,并根据它们的特征来进行垃圾回收。这样可以避免全局暂停,提高了响应时间和吞吐量。(G1 收集器也引入了"混合模式"的回收策略,将Young GC和部分Full GC结合起来,从而达到更好的性能。
  2. 并发收集:在并发标记阶段,G1垃圾收集器可以与应用程序并发执行。这意味着应用程序可以在垃圾回收期间继续运行,减少了暂停时间,提高了系统的可用性。
  3. 可预测性:G1垃圾收集器会自动调整垃圾回收策略,以满足应用程序需要的响应时间和吞吐量。这使得应用程序的性能更加稳定和可预测。
  4. 空间利用率:G1垃圾收集器可以更好地利用堆空间,减少了碎片化问题,从而可以更有效地使用可用内存。

缺点

  1. 初始标记和最终标记仍需STW: 尽管 G1 收集器的大部分工作都是并发的,但在 JVM 执行初始标记和最终标记时仍需要暂停应用程序。这一点可能会导致应用程序在某些情况下出现停顿。
  2. 物理内存占用:G1收集器需要维护大量的数据结构来跟踪堆内存的使用情况,这会对物理内存造成一定的负担。
  3. 相比CMS,在GC过程中会占用更多的CPU时间。
  4. 长时间运行的应用可能会出现某些性能问题,因为G1垃圾收集器不能保证我们的操作不会访问已经被回收的对象(也就是说,它不能保证与CMS相同的延迟)。

使用建议

  1. 长期运行的应用程序:对于需要长时间运行的应用程序,使用G1垃圾收集器可以减少暂停时间并提高吞吐量。这是因为G1收集器可以将大型堆分成多个大小相等的区域,并且只回收那些空间最多的区域。
  2. 大型内存项目:由于G1收集器具有更好的内存利用率和更低的碎片化,因此适用于需要大量内存的项目。
  3. 多核处理器:G1收集器在多核处理器上的性能表现更佳。因为它可以以并发方式执行垃圾回收操作,从而使每个核处理器都可以同时处理GC操作和应用程序代码。
  4. 稳定的堆大小:G1收集器的优化需要稳定的堆大小才能发挥最大效益,建议将Xmx值设置为整个堆的90%到95%。
  5. 谨慎使用-XX:MaxGCPauseMillis参数:G1的目标是进行可控制、可预测的垃圾回收,而不是无限制地降低停顿时间。设置过低的 MaxGCPauseMillis 值会导致过多的垃圾回收操作和资源消耗,从而降低垃圾回收的效率和性能。
  6. 监控和调整:使用G1垃圾收集器需要监控应用程序的性能,并根据实际情况进行调整。可以通过JVM参数和工具来调整G1收集器的行为,以达到最佳性能。

结论

G1 垃圾收集器是一种新型的垃圾收集器,专门针对大堆内存的应用程序进行优化,可以更好地处理大量对象的分配和释放,减少停顿时间,并帮助应用程序提高性能。

  • 标题: G1 垃圾收集器
  • 作者: Heer Liu
  • 创建于: 2020-06-10 20:18:01
  • 链接: https://blog.heer.love/posts/bc8ac7bc/
  • 版权声明 : 本文章采用 CC BY-NC-SA 4.0 进行许可。
推荐阅读
CMS 垃圾回收器 CMS 垃圾回收器 JVM 垃圾回收算法 JVM 垃圾回收算法 JVM 安全点 JVM 安全点