为什么JVM无法确保垃圾回收

时间:2018-06-09 22:52:56

标签: java garbage-collection

这不是重复,因为提到重复的帖子只告诉你为什么不使用System.gc(),而我确实知道,这不是我的问题。 < / p>

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

这背后有原因吗?它是&#34;随机&#34;?由于我不认为编程中存在随机存在,我很好奇它为什么有时不收集它,有时也会在不同的时间收集它。

1 个答案:

答案 0 :(得分:8)

是。有一个很好的理由。

首先,您需要了解有关垃圾收集的一些事实:

  1. 运行垃圾收集器非常昂贵。
  2. 在错误的时间(重复)运行垃圾收集器可能会造成灾难性的低效率 1
  3. 典型应用程序无法预测GC何时可以最有效地运行
  4. 那么你的问题:

      

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

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

      

    是“随机”吗?

    不。这与随机性无关。

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

    但请注意,它无法从Java代码中重写。这将使这个命令行切换失败的目的。

      

    我很好奇为什么它有时不收集它,有时也会收集它。

    JVM的正常行为是尝试在最有效的情况下运行垃圾收集器 。 JVM可以优化两种方式:

    • 它可以优化以最大化收集器的吞吐量;即最小化用于收集的CPU时间

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

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

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

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