java 鼓励 JVM 进行 GC 而不是增长堆?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5355933/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 10:45:38  来源:igfitidea点击:

Encourage the JVM to GC rather than grow the heap?

javajvmheapjvm-hotspotjvm-arguments

提问by Electrons_Ahoy

(Note that when I say "JVM", I really mean "Hotspot", and I'm running the latest Java 1.6 update.)

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

Example situation:

示例情况:

My JVM is running with -Xmx set to 1gb. Currently, the heap has 500mb allocated, of which 450mb is used. The program needs to load another 200 mb on the heap. Currently, there is 300mb worth of "collectable" garbage in the heap (we'll assume it's all in the oldest generation.)

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

Under normal operation, the JVM will grow the heap to 700 mb or so, and garbage collect when it gets around to it.

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

What I would like in that situation is for the JVM to gc first, then allocate the new stuff, so that we end up with the heap size staying at 500mb, and the used heap at 350mb.

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

Is there a JVM parameter combo that does that?

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

回答by WhiteFang34

You could try specifying -XX:MinHeapFreeRatioand -XX:MaxHeapFreeRatioto control heap expansion and shrinking:

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

  • -XX:MinHeapFreeRatio- when the percentage of free space in a generation falls below this value the generation will be expanded to meet this percentage. Default is 40.
  • -XX:MaxHeapFreeRatio- when the percentage of free space in a generation exceeded this value the generation will shrink to meet this value. Default is 70.
  • -XX:MinHeapFreeRatio- 当一代中的可用空间百分比低于此值时,将扩展该代以满足此百分比。默认值为 40。
  • -XX:MaxHeapFreeRatio- 当一代中的可用空间百分比超过此值时,该代将收缩以达到此值。默认值为 70。

You might also want to experiment with concurrent GC by specifying -XX:+UseConcMarkSweepGC. Depending on your application it could keep the heap size lower at the cost of additional CPU cycles.

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

The JVM is otherwise going to use the memory you specify as available when it's optimal do to so. You could specify a lower amount like -Xmx768mto keep it contained and it might run fine, although you would increase your risk of running out of memory in a heavy load scenario. Really the only way to use less memory overall is to write code that uses less memory :)

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

回答by Aleksandr Dubinsky

There are four (actually, five) different garbage collectors in HotSpot, and your options are different for each one.

HotSpot 中有四种(实际上是五种)不同的垃圾收集器,每个垃圾收集器的选择都不同。

  • The serial collector has -XX:MinHeapFreeRatioand -XX:MaxHeapFreeRatio, which let you more or less directly control the behavior. I don't have much experience with the serial collector however.
  • The parallel collector (-XX:+UseParallelOldGC) has -XX:MaxGCPauseMillis=<millis>and -XX:GCTimeRatio=<N>. Setting a lower maximum pause time generally causes the collector to make the heap smaller. However, if the pause time is already small the heap won't become smaller. OTOH, if the max pause time is set too low, the application may spend all of its time collecting. Setting a lower gc time ratio also generally makes the heap smaller. You are telling the gc that you're willing to dedicate more CPU time to collection in return for a smaller heap. However, this is just a hint and may have no effect. In my opinion, the parallel collector is close to untunable for the purpose of minimizing the heap's size. This collector works better (it tunes itself) if you let it run for a while and the application's behavior stays constant.
  • The CMS collector (-XX:+UseConcMarkSweepGC) generally requires a larger heap to accomplish its main goal of low pause time, so I won't discuss it.
  • The new G1 collector (-XX:+UseG1GC) isn't as brain-dead as the older collectors. I find that it chooses a smaller heap size on its own. It has a lot of tuning options, although I've only begun to study them. -XX:InitiatingHeapOccupancyPercent, -XX:G1HeapWastePercent, -XX:G1ReservePercentand -XX:G1MaxNewSizePercentmay be of interest.
  • 串行收集器具有-XX:MinHeapFreeRatio-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可能是感兴趣的。

Take a look at the official documentationfor the garbage collectors as well as this list of flags.

查看垃圾收集器的官方文档以及此标志列表

回答by Hyman

You could as usually invoke the System.gc()method before allocating the additional 200MB of objects but this will just be a hint to the JVM that it can or can't follow and in anycase you won't know when this takes place.. as stated inside documentation it is a best-effort request.

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

By the way take into account that garbage collection is an heavy operation so if there's no specific need to do it, just don't try to force it.

顺便说一下,垃圾收集是一项繁重的操作,因此如果没有特别需要这样做,请不要尝试强制执行。

Just to know: if you set -Xmx1Gthen you are telling to the JVM that 1GB is the maximum space for the heap, and since you are specifying that, I don't see why it should try to keep it low if it knows that 1GB will be still ok (we're in the context of memory-managed languages). If you don't want the heap to increase that much just decrease the maximum value so that it will be forced to do GC before allocating new objects, otherwise why are you telling it to use 1GB?

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

回答by MeBigFatGuy