【问题标题】:Full GC is not kicking in for G1 GC in Java 11. What could be the reasons?Java 11 中的 G1 GC 没有启动 Full GC。可能是什么原因?
【发布时间】:2021-11-21 13:03:47
【问题描述】:

JVM 参数如下: -Xms20g -Xmx20g -XX:MaxGCPauseMillis=10000 -XX:G1ReservePercent=30 -Duser.timezone=UTC

日志中唯一的东西是

  • Pause Young(正常)(G1 撤离暂停)

    暂停备注

    Pause Young(准备混合)(G1 撤离暂停)

    Pause Young(混合)(G1 疏散暂停)

    Pause Young(并发启动)

....

但没有像 Full GC 那样。一次也没有。

内存使用率超过 65%。

在什么级别的内存消耗下,我们可以期待 Full GC?

【问题讨论】:

  • 开发者在尽可能避免Full GC方面花费了很多精力。为什么你对他们的成功不满意?你想解决什么问题?
  • 差距在于我的理解是/应该尽可能避免 Full GC。我试图理解 GC 日志,但可以看到一个完整的 GC 引用,这让我很好奇。谢谢

标签: java garbage-collection garbage g1gc


【解决方案1】:

当您的对象寿命长(即从年轻代提升到老代)时,将触发一次完整的 GC。然后只有在内存压力需要的时候才会触发。

因此,您需要将大量对象存储在像 HashMap 这样的长寿命结构中。 巨大的 HashMap。然后让它久坐,然后尝试分配大对象。

另外,大多数 GC 算法都尽量避免 Full GC。所以使用像 ConcurrentMarkAndSweep 这样的旧算法可能更容易触发。用 G1 收集器实现它在理论上是可能的,但并不容易。

对于 G1 收集器,分配许多在集合中存活的对象,然后尝试分配非常大的对象可能会触发它。但这并不容易。

我曾在野外看到它们堆积如山。使用 16 GB 以上的 RAM 可能比使用小堆更容易重现(我看到您使用的是 20 GB,这很好)。

【讨论】:

  • 当我们说“长寿”时,我们在谈论什么时间?
  • 它必须在多个收藏中存活下来。年轻代将经典地使用复制收集器,而老一代(如果您有 ConcurrentMarkAndSweep 集)将使用标记和扫描算法。因此,为了模拟这一点,我会让它运行一段时间,同时它会不断地添加/删除东西。你希望一些数据能够在集合中幸存下来,并使其进入内存的旧部分。
  • ConcurrentMarkAndSweep ??我们这里有 G1。标记和扫描的概念在 G1 GC 中是否仍然适用?
  • 由于您使用 G1 收集器执行此操作,我认为您可以通过分配巨大的对象来强制执行此操作。但幸运的是,G1 就是为了避免这种情况而构建的。
  • 我没有注意到您使用的是 G1。对于 G1,这将非常困难。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 2015-08-01
  • 2018-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多