何时收集垃圾

我有一段代码在内存中加载了一个非常大的图像。 所以打电话似乎是合理的

System.gc(); 

在加载图像之前。 据我所知,它没有任何问题。

昨天我决定使用一个名为FindBugs的非常有用的软件来扫描你的代码并报告可能导致错误或通常不建议策略的问题。 问题是我提到的这段代码被报道了。 描述如下:

…强制垃圾收集; 除了在基准测试代码中,这是非常可疑的

它继续详细说明:

代码显式调用垃圾收集。 除了在基准测试中的特定用途外,这是非常可疑的。

在过去,人们在诸如close或finalize方法之类的例程中明确调用垃圾收集器的情况导致了巨大的性能黑洞。 垃圾收集可能很昂贵。 强制数百或数千个垃圾收集的任何情况都会导致计算机爬行。

所以我的问题是: 在这种情况下以编程方式调用垃圾收集器是不是可行的? 我的代码只调用一次,它所使用的方法很少使用。 如果调用它不行,那么在进行内存密集型操作之前需要尽可能多的内存并且需要释放尽可能多的内存之前,应该怎么办呢?

您是否通过System.gc()获得了任何性能改进? 我不这么认为,因为在加载图像之前你可能没有很多需要收集的对象。

通常现代垃圾收集者在运行时知道最佳,所以你不应该强制收集,除非你有一个非常好的理由。 (例如该插件建议的基准测试应用程序)

btw:调用System.gc()建议VM执行“完整”或“大”集合,这意味着很快就会停止所有线程。 否则它可能只会产生“小”垃圾收集,而不会停止所有线程。

使用-verbose:gc运行程序以查看收集的字节数。

这里还有很多关于垃圾收集的技术信息: http : //java.sun.com/developer/technicalArticles/Programming/GCPortal/

通常情况下,GC比您更聪明,因此最好让它在运行时决定时运行。 如果运行时需要内存,它将运行GC本身

调用垃圾收集器很好,你不会从中获得任何“问题”。 但是,我怀疑它会显着提升性能,除非该调用还涉及对分配的数据进行碎片整理。 我不知道。

在这种情况下你应该做的是描述代码。 运行几次,看看你得到了什么样的结果。

通常,您不应该干扰垃圾收集器。 如果在加载图像之前需要释放一些内存,那么垃圾收集器会为您完成。

无论如何,如果你只做一次,它可能不会大大影响你的表现。 在循环中完成的事情要重要得多。

你已经得到了很多好的建议,我将不再重申。

如果您确实遇到GC问题,例如您的应用程序暂停一秒钟,请执行以下操作:1。检查没有任何对System.gc()的调用; 2.查看配置gc的各种选项。 周围有很多人,他们更有帮助,然后强迫gc。

确保尽可能早地gc’ed大对象。 即将变量设置为null和/或让它们超出范围。 这有帮助!

如果内存分配失败,则启动GC循环并再次尝试分配。

一般来说,没有。 调用System.gc()是不合适的。 但是,我遇到过一些有意义的案例。

在我写的软件中,有一个内置的性能跟踪层。 它主要在自动化测试期间使用,但可以在现场用于诊断目的。 在测试之间或特定运行之后,我们将调用System.gc几次,然后记录仍然存在的内存。 它为我们提供了基本的内存占用基准,用于观察内存消耗趋势线随着时间的推移。 虽然这可以通过一些外部JVM接口来完成,但是更容易实现,并且不需要确切的数字。

在一个更老的系统上,我们可以拥有超过72个独立的JVM(是的,72,在构建时有充分的理由)。 在该系统中,让堆在所有72个JVM上自由浮动可能会产生一些过多的(超出物理内存)总内存消耗。 在重度数据练习之间调用System.gc()来尝试保持JVM接近平均值以防止堆增长(限制堆可能是另一个方向,但是它需要实现者为每个站点配置更多和更加了解发动机罩下发生的事情以使其正确并且不会使系统在负载下失效)。