【问题标题】:Why can't the JVM ensure garbage collection为什么JVM不能保证垃圾回收
【发布时间】:2018-06-09 22:52:56
【问题描述】:

这不是重复的,因为提到重复的线程只会告诉你为什么不使用 System.gc(),虽然我知道,但这不是我的问题。

使用 System.gc() 或 Runtime.getRuntime().gc() 不会总是执行垃圾收集,它只是请求它,它甚至可以被 JVM 忽略。

这背后有什么原因吗?是“随机的”吗?由于我认为随机甚至在编程中存在,我很好奇为什么它有时不收集它,有时在不同的时间收集它。

【问题讨论】:

  • 我认为随机甚至不存在......” - 现在这很有趣。密码学依赖于它的存在;你是在暗示密码学不存在吗?附言当然不是随机的!
  • @BoristheSpider 密码学不是随机的,但你知道它会在什么时候执行吗?有规定吗?
  • @BoristheSpider 这取决于 OP 如何定义编程中的随机性。如果没有一些外部资源(即一些熵生成器),我会认为这个陈述是正确的。
  • @Turing85 我不认为这取决于我如何定义随机,而是我是否在随机和伪随机之间有所不同:P
  • 老实说,我不认为任何人都可以赢得关于随机性的讨论” - 真的不知道你的意思是什么,有一个正确和不正确的答案.我的观点是,在这种情况下使用“随机”是……没有帮助的。

标签: java garbage-collection


【解决方案1】:

是的。有一个很好的理由。


首先,您需要了解一些关于垃圾回收的一般知识:

  1. 运行垃圾收集器的成本很高。
  2. 在错误的时间(重复)运行垃圾收集器可能会导致灾难性的低效1
  3. 对于典型的应用程序来说,几乎不可能预测 GC 何时可以最有效地运行

所以对于你的问题:

使用 System.gc() 或 Runtime.getRuntime().gc() 不会总是执行垃圾收集,它只是请求它,它甚至可以被 JVM 忽略。这背后有什么原因吗?

是的。 主要是为了防止天真的程序员在错误的时间调用gc()可能导致的灾难性行为影响。

是“随机的”吗?

不。这与随机性无关。

实际上,典型的 JVM 有一个命令行开关,用于确定是否忽略 gc() 调用。这允许用户/部署者/集成者/任何人减轻程序员做出的错误选择。

但请注意,它不能被 Java 代码覆盖。这会破坏将其作为命令行开关的目的。

我很好奇为什么它有时不收集它,有时收集它,而且在不同的时间。

JVM 的正常行为是尝试在最有效的时候运行垃圾收集器。 JVM可以通过两种方式进行优化:

  • 它可以优化以最大化收集器的吞吐量;即尽量减少收集所花费的 CPU 时间

  • 可以优化以最小化GC暂停的长度;即 JVM 在收集期间必须冻结所有应用程序线程的时间。

这很复杂。从外部观察者的角度(谁/谁没有访问堆统计信息等)可能很难理解为什么 GC 在给定的时间点运行。但肯定不是随机


1 - GC 算法的反直觉特性之一是收集成本(在大多数情况下)主要由跟踪非垃圾对象和在内存中移动以合并释放空间的成本决定.因此,如果您在没有太多垃圾要收集的情况下调用 GC,那么您最终将跟踪/移动大量非垃圾而没有什么实际好处。相比之下,JVM 对何时是收集的好时机有更好的洞察力。首先,它知道在任何时间点每个池中剩余多少空间。

除了违反直觉之外,随着堆变大,这种行为会变得更糟。因此,程序员可能会以错误的方式编写使用gc() 的代码,而不会注意到存在性能问题。仅当应用程序以生产工作负载/问题大小运行时,性能才会成为问题。将其与使用堆缓存事物和/或内存泄漏的影响结合起来.....

【讨论】:

  • 好答案。我唯一的建议是,为了进一步解释您提到的复杂性,请添加一些关于如何有许多不同的垃圾收集器实现的信息。每个都采用不同的方法,并在不同的场景中表现出不同的行为。
  • @BasilBourque - 我认为没有必要在这里解释复杂性。 Oracle 垃圾收集文档比我做得更好。
  • 另一个例子是Epsilon 'garbage collector',它将被添加到 Java 11 中。它根本不执行任何垃圾收集。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-14
  • 1970-01-01
  • 2016-06-18
  • 1970-01-01
  • 2014-11-01
  • 2010-10-26
  • 1970-01-01
相关资源
最近更新 更多