21

(请注意,当我说“JVM”时,我的意思是“热点”,我正在运行最新的 Java 1.6 更新。)

示例情况:

我的 JVM 运行时 -Xmx 设置为 1gb。目前,堆分配了 500mb,其中 450mb 被使用。该程序需要在堆上再加载 200 mb。目前,堆中有 300mb 的“可收集”垃圾(我们假设它们都在最老的一代中。)

在正常操作下,JVM 会将堆增加到 700 mb 左右,并在到达时进行垃圾收集。

在这种情况下,我希望 JVM 先 gc,然后分配新的东西,这样我们最终的堆大小保持在 500mb,使用的堆大小保持在 350mb。

是否有一个 JVM 参数组合可以做到这一点?

4

4 回答 4

15

您可以尝试指定-XX:MinHeapFreeRatio-XX:MaxHeapFreeRatio控制堆扩展和收缩:

  • -XX:MinHeapFreeRatio- 当一代中的可用空间百分比低于此值时,一代将扩展以满足此百分比。默认值为 40。
  • -XX:MaxHeapFreeRatio- 当一代中可用空间的百分比超过此值时,一代将缩小以满足该值。默认值为 70。

您可能还想通过指定-XX:+UseConcMarkSweepGC. 根据您的应用程序,它可以以额外的 CPU 周期为代价来降低堆大小。

否则,JVM 将在最佳情况下使用您指定的可用内存。您可以指定一个较低的数量,例如-Xmx768m保持它包含在内,并且它可能运行良好,尽管您会增加在重负载情况下耗尽内存的风险。真正使用更少内存的唯一方法是编写使用更少内存的代码:)

于 2011-03-18T18:05:14.007 回答
12

更新Java 15 增加了两个收集器。中的一些相关选项ZGC是:

  • -XX:+UseZGC启用 ZGC
  • -XX:+ZProactive并且-XX:+ZUncommit两者都默认启用。ZGC 将主动尝试释放垃圾对象并将释放的内存释放给操作系统。其余选项调整完成的积极程度。
  • -XX:ZCollectionInterval=secondsGC 运行的频率。设置为几秒钟以确保尽快清理垃圾。(默认为 0,即不保证 GC 会运行。)
  • -XX:ZUncommitDelay=seconds设置堆内存在未提交之前必须未使用的时间量(以秒为单位)。默认情况下,此选项设置为 300(5 分钟)。设置较低的值可以更快地取回内存
  • -XX:SoftMaxHeapSize只要应用程序使用的内存超过此限制,GC 就会更频繁地触发。(这可能是 OP 正在寻找的答案。)
  • -XX:SoftRefLRUPolicyMSPerMB不确定此选项的相关频率,但它控制一些缓存对象在内存中的保留时间。

原始答案HotSpot 中有四个(实际上是五个)不同的垃圾收集器,每个选项的选项都不同。

  • 串行收集器具有-XX:MinHeapFreeRatioand -XX:MaxHeapFreeRatio,它可以让您或多或少地直接控制行为。但是,我对串行收集器没有太多经验。
  • 并行收集器 ( -XX:+UseParallelOldGC) 具有-XX:MaxGCPauseMillis=<millis>-XX:GCTimeRatio=<N>。设置较低的最大暂停时间通常会导致收集器使堆变小。但是,如果暂停时间已经很短,堆就不会变小。OTOH,如果最大暂停时间设置得太低,应用程序可能会将所有时间都花在收集上。设置较低的 gc 时间比率通常也会使堆更小。您告诉 gc 您愿意将更多的 CPU 时间用于收集以换取更小的堆。但是,这只是一个提示,可能没有任何效果。在我看来,为了最小化堆的大小,并行收集器几乎是不可调整的。如果您让它运行一段时间并且应用程序的行为保持不变,则此收集器会更好地工作(它会自行调整)。
  • CMS 收集器 ( -XX:+UseConcMarkSweepGC) 通常需要更大的堆来实现其低暂停时间的主要目标,因此我不会讨论它。
  • 新的 G1 收集器 ( -XX:+UseG1GC) 并不像旧的收集器那样脑残。我发现它自己选择了较小的堆大小。它有很多调整选项,虽然我才刚刚开始研究它们。-XX:InitiatingHeapOccupancyPercent, -XX:G1HeapWastePercent,-XX:G1ReservePercent并且-XX:G1MaxNewSizePercent可能感兴趣。

看看标志列表java

于 2015-01-30T09:57:09.883 回答
2

您通常可以在分配额外的 200MB 对象之前调用该System.gc()方法,但这只是对 JVM 的一个提示,它可以或不能遵循,并且无论如何您都不知道何时发生这种情况......如文档中所述这是一个尽力而为的请求。

顺便说一下,垃圾收集是一项繁重的操作,所以如果没有特别需要这样做,就不要试图强迫它。

只是要知道:如果您设置-Xmx1G然后您告诉 JVM 1GB 是堆的最大空间,并且由于您指定了这一点,我不明白为什么它应该尝试保持低如果它知道 1GB 将仍然可以(我们处于内存管理语言的上下文中)。如果您不希望堆增加那么多,只需减小最大值,以便在分配新对象之前强制执行 GC,否则为什么要告诉它使用 1GB?

于 2011-03-18T17:57:01.663 回答
1

我建议在这里看看:

http://www.petefreitag.com/articles/gctuning/

于 2011-03-19T06:28:57.023 回答