Java的7种垃圾收集器,帮助我们更好的管理java gc提升性能避免OOM

Tooha1年前 ⋅ 1262 阅读

使用 C 和 C++ 等编程语言编写的应用程序要求您在不再需要时对内存中的对象进行销毁。 您的应用程序增长得越多,您忽略释放未使用对象的可能性就越大。 这会导致内存泄漏,最终系统内存被用完,并且在某些时候没有更多的内存可以分配。 这会导致应用程序因 OutOfMemoryError 而失败。 但在 Java 的情况下,垃圾收集 (GC) 在应用程序执行期间自动发生,因此它减轻了手动释放的任务和可能的内存泄漏。

垃圾收集不是一项单一的任务。 Java 虚拟机 (JVM) 有八种不同的垃圾收集,了解每种垃圾收集的目的和优势很有用。

1. Serial GC

仅使用单个线程的 GC 的原始实现。 当垃圾收集发生时,它会暂停应用程序(通常称为“stop the world”事件)。这适用于可以承受小暂停的应用程序。 垃圾收集占用空间小,因此这是嵌入式应用程序的首选 GC 类型。 这种垃圾收集样式可以在运行时启用:

java -XX:+UseSerialGC

2. Parallel GC

和 Serial GC 一样,这也使用了“stop the world”的方法。 这意味着当 GC 发生时,应用程序线程被暂停。 但是在这种情况下,有多个线程执行 GC 操作。 这种类型的 GC 适用于在多线程和多处理器环境中运行的中型到大型数据集的应用程序。

这是 JVM 中默认的 GC,也称为吞吐量收集器。 各种 GC 参数,如吞吐量、暂停时间、线程数和占用空间,可以使用合适的 JVM 标志进行调整:

  • 线程数:-XX:ParallelGCThreads=<N>
  • 暂停时间:-XX:MaxGCPauseMillis=<N>
  • 吞吐量(GC 花费的时间与实际应用程序执行相比):-XX:GCTimeRatio=<N>
  • 最大堆占用空间:-Xmx<N>
  • 可以显式启用并行 GC:java -XX:+UseParallelGC。 使用此选项,年轻代中的次要 GC 由多个线程完成,而老年代中的 GC 和压缩则由单个线程完成。

还有一个名为 Parallel Old GC 的 Parallel GC 版本,它为年轻代和老年代使用多个线程:

java -XX:+UseParallelOldGC

3. Concurrent Mark Sweep (CMS)

并发标记扫描 (CMS) 垃圾收集与应用程序一起运行。 它对次要和主要 GC 使用多个线程。 删除未使用的对象后,CMS GC 不会对活动对象进行压缩,因此暂停的时间比其他方法要短。 此 GC 与应用程序同时运行,这会减慢应用程序的响应时间。 这适用于暂停时间较短的应用程序。 此 GC 在 Java 8u 中已弃用,并从 14u 开始完全删除。 但是,如果您仍在使用具有它的 Java 版本,则可以通过以下方式启用它:

java -XX:+UseConcMarkSweepGC

在 CMS GC 的情况下,应用程序会暂停两次。 当它标记一个可直接到达的活动对象时,它首先暂停。 这个停顿被称为初始标记。 它在 CMS GC 阶段结束时第二次暂停,以说明在并发周期中丢失的对象,此时应用程序线程在 CMS GC 完成后更新对象。 这被称为备注阶段。

4. G1 (Garbage First) GC

垃圾优先 (G1) 旨在取代 CMS。 G1 GC 是并行的、并发的、增量压缩的,暂停时间短。 G1 使用与 CMS 不同的内存布局,将堆内存划分为大小相等的区域。 G1 触发具有多个线程的全局标记阶段。 标记阶段完成后,G1 知道哪个区域可能大部分为空,并首先选择该区域进行扫描/删除阶段。

在 G1 的情况下,超过一半区域大小的对象被认为是“巨大的对象”。 这些对象被放置在老年代,在一个适当地称为巨大区域的区域中。 要启用 G1:

java -XX:+UseG1GC

5. Epsilon GC

这个 GC 是在 11u 中引入的,是一个 no-op(什么都不做)GC。 Epsilon 只管理内存分配。 它不做任何实际的内存回收。 Epsilon 仅适用于您知道应用程序的确切内存占用,并且知道它是免费的垃圾收集。

java -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC

6. Shenandoah

Shenandoah 是在 JDK 12 中引入的,是一种 CPU 密集型 GC。 它执行压缩,删除未使用的对象,并立即向操作系统释放可用空间。 所有这些都与应用程序线程本身并行发生。 要启用雪兰多:

java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC

7. ZGC

ZGC 专为具有低延迟要求和使用大堆的应用程序而设计。 ZGC 允许 Java 应用程序在执行所有垃圾收集操作时继续运行。 ZGC 是在 JDK 11u 中引入的,并在 JDK 12 中进行了改进。从 JDK 15 开始,Shenandoah 和 ZGC 都已退出实验阶段。要启用 ZGC:

java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC

灵活的垃圾收集

Java 为内存管理提供了灵活性。 熟悉可用的不同方法很有用,这样您就可以选择最适合您正在开发或运行的应用程序的方法。

https://opensource.com/article/22/7/garbage-collection-java

Stop-The-World也叫作STW CMS + G1 = ZGC, ZGC才是java gc的未来 https://kstefanj.github.io/2021/11/24/gc-progress-8-17.html Java中9种常见的CMS GC问题分析与解决 https://tech.meituan.com/2020/11/12/java-9-cms-gc.html

全部评论: 0

    相关推荐