【问题标题】:What conditions would prevent the JVM from running a FULL Garbage Collection?什么条件会阻止 JVM 运行 FULL Garbage Collection?
【发布时间】:2010-08-13 15:34:46
【问题描述】:

当 CPU 处于 5% 到 8% 负载时,哪些情况会阻止 JVM 运行 FULL Garbage Collection?

我看到一个持续的浅 GC 周期,但无法调整 JVM 以运行 FULL GC。

哪里可以找到JVM说“我忙得跑不动”的条件。

【问题讨论】:

  • JVM 可能会简单地认为“我现在没有需要运行 GC。”
  • 我认为您需要翻转您的问题 - 为什么应该垃圾收集器现在运行?您是否遇到内存不足异常?
  • 您不太可能在这里找到解释:人们开始喜欢在 Java 中无法轻松控制 GC 的事实。所以因为你不能轻易强制一个完整的 GC,所以她会说这是一个“好事”[TM]。不要质疑为什么:Java 之神决定它是这样的,所以它是“好事”[TM]。不,如果您确实真的想强制执行 GC,请看这里:stackoverflow.com/questions/2178296/…(没有对 OP 的实际答案,但问题本身包含提示和链接到 REALLY 强制它。

标签: java garbage-collection jvm


【解决方案1】:

当我学习 SCJP 认证时,很多重点都放在了

“你不能做任何事情来强制 GC 在任何给定时间运行,您可以 只是给它提示”

拥有一个自动 GC 的整个想法正是不必担心它如何或何时运行来为您清理空闲内存。所以,没有办法真正改变 GC 实际运行的时间或方式……你必须重新实现一个 JVM 才能做你想做的事。

其中涉及的因素太多了,可能还有其他更优雅的解决方案。

【讨论】:

  • +1。即使明确告诉 GC 运行也不能保证它会在 Java 中运行。
  • +1 - 更简洁优雅地表达了我试图表达的观点。
【解决方案2】:

这完全取决于您在特定 JDK 中使用的垃圾收集器算法。关于垃圾收集,您可以保证的所有内容是,如果 JVM 抛出 OutOfMemoryError,垃圾收集器会尽最大努力收集 每个 无法访问/无法访问的对象。即使System.gc() 也不保证任何事情,无操作是完全合法的实现。

因此,鉴于此,我不知道您的问题是否有分量。如果您确实认为需要调整垃圾收集器,那么发布您所看到的问题以及导致认为 GC 性能差是问题的分析数据会有所帮助。

除此之外,垃圾收集器应该被视为一个黑盒子。它的实现背后的逻辑非常复杂,而且很有可能它比你更清楚在任何给定时间它应该做什么。 100 次中有 99 次尝试强制垃圾收集器以特定方式运行会降低性能,而不是提高性能。

【讨论】:

  • 如果程序故意抛出OutOfMemoryException,会有影响吗?当然,在某些时候,同样的异常也必须被捕获以防止它停止程序......
  • @FrustratedWithFormsDesigner:不,OutOfMemoryException 与 GC 无关(直接)。如果 GC 运行但您有内存泄漏(即:内存中的对象,GC 不会收集,因为您仍在引用它们),您将获得 OOME。再次运行 GC 有什么好处?已经跑了! OOME 是程序员必须处理的事情,而不是 GC。
  • @FrustratedWithFormsDesigner - 正如布赖恩所说,这不会达到预期的效果。我的意思只是当 JVM 由于无法分配所需的内存而“合法地”抛出此错误时 - 我将更正我的答案以相应地传达这一点。
【解决方案3】:

并不是说它运行起来很忙,而是它根本不需要额外的内存。

【讨论】:

  • 让我解释更多...

    我没有收到 OOM 错误。我所拥有的是一个创建大量对象的应用程序,并且在运行 FULL GC 之前使用了 70% 到 97% 的内存。 Shallow GC 不会回收这些内存,但是一旦运行 FULL GC,使用的内存会回到 40% 左右,然后再次开始攀升。

    SO:为什么 FULL GC 不会像 -XX:CMSInitiatingOccupancyFraction=50 所说的那样以 50% 的已用内存运行,而只能以如此高的水平运行?

    这是因为JVM 很忙?

    不是因为对象正在被使用,而是因为一旦被使用了
  • 当前设置:----------------- -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing -XX:CMSIncrementalDutyCycleMin=0 - XX:CMSIncrementalDutyCycle=10 -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -XX:MaxGCPauseMillis=250 -XX:MaxGCMinorPauseMillis=100 -XX:SurvivorRatio=128 -XX:MaxTenuringThreshold=0 -XX:CMSInitiatingOccupancyFraction=50 -XX:NewSize= 256m -XX:MaxNewSize=256m -XX:PermSize=160m -XX:MaxPermSize=160m
  • 我知道我无法强制 GC 运行。但我想知道如果已用内存超过 90% 以上,JVM 为什么认为它不应该运行?一定有什么正当理由。
  • 作为一种解决方法,我创建了一个简单的应用程序来检查使用的内存。如果是 >50% 则发出 System.gc() 只是要求 JVM 运行 GC,而不是强制它。这将已用内存保持在 50% 和 60% 已用内存之间,并且不会达到警报阈值点。但是,我不想要这个长期的。
  • @Mick Knutson:您的设置毫无意义。您正在指定在我看来与 UseConcMarkSweepGC 和 UseParNewGC 不兼容的设置,并且您还在设置 CMSIncrementalMode, which will cause CMSInitiatingOccupancyFraction to be ignored。也许this article on the available GC choices 可以帮助你澄清事情。
猜你喜欢
  • 1970-01-01
  • 2017-06-06
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 2023-03-31
  • 1970-01-01
  • 2014-04-20
  • 1970-01-01
相关资源
最近更新 更多