何时收集垃圾

时间:2009-07-18 12:10:21

标签: java garbage-collection findbugs

我有一段代码在内存中加载了一个非常大的图像。因此,调用

似乎是合理的
System.gc();

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

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

  

...强制垃圾收集;   非常可疑,除了在   基准代码

它继续详细说明:

  

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

     

过去,人们的情况   已明确调用垃圾   例程中的收集器如close或   敲定方法导致了巨大的影响   性能黑洞。垃圾   收集可能很昂贵。任何   强迫数百或者数百万的情况   成千上万的垃圾收集   让机器爬行。

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

8 个答案:

答案 0 :(得分:9)

通常GC比你聪明,所以最好让它在运行时决定时运行。如果运行时需要内存,它将运行GC本身

答案 1 :(得分:9)

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

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

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

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

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

答案 2 :(得分:1)

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

在这种情况下,您应该做的是对代码进行概要分析。运行几次,看看你得到了什么样的结果。

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

确保尽可能早地使用大型物体。即将变量设置为null和/或让它们超出范围。这有帮助!

答案 6 :(得分:1)

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

答案 7 :(得分:0)

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

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

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