这不是重复,因为提到重复的帖子只告诉你为什么不使用System.gc(),而我确实知道,这不是我的问题。 < / p>
使用System.gc()或Runtime.getRuntime()。gc()不会总是执行垃圾收集,它只是请求它,它甚至可以被JVM忽略。
这背后有原因吗?它是&#34;随机&#34;?由于我不认为编程中存在随机存在,我很好奇它为什么有时不收集它,有时也会在不同的时间收集它。
答案 0 :(得分:8)
是。有一个很好的理由。
首先,您需要了解有关垃圾收集的一些事实:
那么你的问题:
使用System.gc()或Runtime.getRuntime()。gc()并不总是执行垃圾收集,它只是请求它,它甚至可以被JVM忽略。这背后有原因吗?
是。 主要是以防止天真的程序员在错误的时间调用gc()
可能导致的灾难性行为影响。
是“随机”吗?
不。这与随机性无关。
实际上,典型的JVM有一个命令行开关,用于确定是否忽略gc()
个调用。这允许用户/部署者/集成商/任何人减轻程序员做出的糟糕选择。
但请注意,它无法从Java代码中重写。这将使这个命令行切换失败的目的。
我很好奇为什么它有时不收集它,有时也会收集它。
JVM的正常行为是尝试在最有效的情况下运行垃圾收集器 。 JVM可以优化两种方式:
它可以优化以最大化收集器的吞吐量;即最小化用于收集的CPU时间
可以优化以最小化GC暂停的长度;即JVM在收集期间必须冻结所有应用程序线程的时间。
这很复杂。从外部观察者(谁/无法访问堆统计数据等)的角度来看,可能很难理解为什么GC在给定时间点运行。但肯定不是随机。
1 - GC算法的一个反直觉属性是收集成本(在大多数情况下)由跟踪非垃圾对象和移动内存以合并释放空间的成本所支配。因此,如果在没有太多垃圾收集的情况下调用GC,您将最终跟踪/移动大量非垃圾,实际上没什么好处。相比之下,JVM可以更好地了解何时是收集的好时机。首先,它知道在任何时间点每个池中剩余多少空间。
除了反直觉之外,随着堆变大,这种行为会变得更糟。因此,程序员可以编写以错误方式使用gc()
的代码,而不会注意到存在性能问题。当应用程序以生产工作负载/问题大小运行时,性能只会成为问题。将此与使用堆缓存内容和/或内存泄漏的效果相结合......