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

发布于 2024-10-24 03:20:56 字数 345 浏览 8 评论 0原文

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

示例情况:

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

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

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

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

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

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.)

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

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.

Is there a JVM parameter combo that does that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

花辞树 2024-10-31 03:20:56

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

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

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

否则,JVM 将在最佳情况下使用您指定的可用内存。您可以指定一个较低的数量(例如 -Xmx768m)来控制它,并且它可能会正常运行,尽管您会增加在重负载情况下耗尽内存的风险。实际上,总体上使用更少内存的唯一方法是编写使用更少内存的代码:)

You could try specifying -XX:MinHeapFreeRatio and -XX:MaxHeapFreeRatio to control heap expansion and shrinking:

  • -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.

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.

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 -Xmx768m to 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 :)

用心笑 2024-10-31 03:20:56

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

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

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

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

查看 列表java 标志

Update Java 15 added two more collectors. Some of the relevant options in ZGC are:

  • -XX:+UseZGC enable ZGC
  • -XX:+ZProactive and -XX:+ZUncommit Both are enabled by default. ZGC will proactively try to both free garbage objects and to release the freed memory to the OS. The rest of the options tweak how aggressively it's done.
  • -XX:ZCollectionInterval=seconds How often the GC runs. Set to a few seconds to ensure that garbage is cleaned up as quickly as possible. (By default it's 0, ie no guarantee the GC will run.)
  • -XX:ZUncommitDelay=seconds Sets the amount of time (in seconds) that heap memory must have been unused before being uncommitted. By default, this option is set to 300 (5 minutes). Set a lower value to get back the memory more quickly
  • -XX:SoftMaxHeapSize The GC will fire more often whenever the application uses more memory than this limit. (This is probably the answer the OP is looking for.)
  • -XX:SoftRefLRUPolicyMSPerMB Not sure how often this option is relevant, but it controls how long some cached objects remain in memory.

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

  • The serial collector has -XX:MinHeapFreeRatio and -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:G1ReservePercent and -XX:G1MaxNewSizePercent may be of interest.

Take a look at the list of java flags.

萌辣 2024-10-31 03:20:56

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

顺便说一句,请考虑到垃圾收集是一项繁重的操作,因此如果没有特定需要执行此操作,请不要尝试强制执行。

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

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.

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 -Xmx1G then 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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文