java - 为什么JVM不能保证垃圾回收

标签 java garbage-collection

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

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

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

最佳答案

是的。这是有充分理由的。

<小时/>

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

  1. 运行垃圾收集器的成本很高。
  2. 在错误的时间(重复)运行垃圾收集器可能会造成灾难性的低效1
  3. 典型应用程序几乎不可能预测 GC 何时可以最有效运行。
<小时/>

对于你的问题:

Using System.gc() or Runtime.getRuntime().gc() won't always execute garbage collection, it just requests it and it can even be ignored by the JVM. Is there a reason behind this?

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

Is it "random"?

不。这与随机性无关。

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

但请注意,它不能从 Java 代码中覆盖。这将违背使其成为命令行开关的目的。

I'm curious why it sometimes doesn't collect it, and sometimes does and also at different times.

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

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

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

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

<小时/>

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

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

关于java - 为什么JVM不能保证垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50779195/

相关文章:

java - 对象引用何时会被垃圾回收?

java - 以编程方式进行完整的线程转储(GC 线程、JNI 等...)

java - 从特定单词后开始读取文件

java - 我可以使用 Java 小程序违反同源策略吗?

java - Hybris 实体未找到异常

java - 在数据更改时刷新 Jframe

java - 添加 GeoFence jar 库后 GeoServe 崩溃

java - 有多少对象有资格进行垃圾回收?

.net - Funq和处理子容器

multithreading - 当 Async 值被垃圾收集时会发生什么?