平息兴奋的垃圾收集器

时间:2010-02-17 01:01:04

标签: java garbage-collection

我有一个与-Xmx2g非常愉快地运行的程序。随着-Xmx1g,它会停止。它永远不会出现内存异常 - 或者至少,我从来没有耐心等待足够长的时间。

这表明总足迹确实适合1克,但GC对可能耗尽空间感到担忧。

内存占用量是一些大而稳定的项目的组合,具有大量短暂的流量。

任何一个或多或少模糊的GC选项是否与这种情况相关?

4 个答案:

答案 0 :(得分:4)

您可以在JVM上设置许多选项,以便使用http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html进行垃圾回收。当一个应用程序由于GC而停止运行时,您通常会看到许多主要收集,这可能会在收集时阻止所有内容。您可以调整次要和主要收集参数,以查看是否可以有更频繁的次要收藏。

我建议使用VisualVM(JDK6附带,我相信更新7+)等工具来查看正在堆积的东西并分析对象图。另请参阅分析hprof文件的工具(How do I analyze a .hprof file?)。

答案 1 :(得分:3)

听起来你没有给JVM足够的堆。当然,工作集可能适合1Gbytes,但你仍然需要更多。要了解原因,请继续阅读。

让我们假设当垃圾收集器运行时,它会执行一定量的工作W1,该工作量与其扫描的非垃圾量成比例,以便识别垃圾和另一项工作量{{ 1}}与它找到的垃圾量成正比。 (事实上​​,它比这更复杂......但是让分析变得简单。)

假设您有一个堆1Gb堆,其中0.9Gb被可访问对象占用。每次GC运行时,它都可以回收最多0.1Gb的堆空间,这样做需要W2工作。回收的每字节工作量为W1 * 0.9Gb + W2 * 0.1Gb;即(W1 * 0.9Gb + W2 * 0.1Gb) / 0.1Gb

现在假设您有一个2Gb堆,其中0.9Gb被可访问对象占用。现在回收的每字节工作量为9 * W1 + W2(W1 * 0.9Gb + W2 * 1.1Gb) / 1.1Gb

如果比较这两个,您会发现与2Gb堆相比,GC在1Gb堆中回收的每字节大约W1 * 9/11 + W2个工作量大约W1 * 8

作为一般规则,运行堆越接近完整,垃圾收集器的效率就越低。课程是:

  • 将JVM配置为使用大量堆,

  • 配置JVM以在运行完整GC后,如果有少于(例如)25%的堆空闲时抛出OOM。

答案 2 :(得分:2)

在很多情况下,对于OOME来说,真的很长时间。这是因为,当GC开始努力工作时,它会停止程序中的所有活动。如果您通常每0.01秒的GC时间获得1秒的有用程序时间,在这些情况下,您可能会看到它完全相反 - 每1秒GC时间有效程序时间为0.01秒。按照这个速度,吃掉1 GB堆中最后512k可能需要花费很长的时间。

VisualVM及其VisualGC插件是你的朋友;当你处于这种状态时,他们的图表将显示出不同的模式。

答案 3 :(得分:0)

如果你不想做一些微调,你应该检查MinHeapFreeRatioMaxHeapFreeRatio参数以及其他所谓的Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning参数,这会导致“镇静剂效应”。