鼓励JVM加入GC而不是增加堆?

Ele*_*hoy 19 java heap jvm jvm-hotspot jvm-arguments

(注意,当我说"JVM"时,我的意思是"Hotspot",我正在运行最新的Java 1.6更新.)

示例情况:

我的JVM在-Xmx设置为1gb的情况下运行.目前,堆已经分配了500mb,其中使用了450mb.该程序需要在堆上加载另外200 MB.目前,堆中有300mb的"可收集"垃圾(我们假设它们都是最老一代的.)

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

在这种情况下我想要的是JVM首先gc,然后分配新的东西,这样我们最终的堆大小保持在500mb,而使用的堆在350mb.

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

Whi*_*g34 13

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

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

您可能还想通过指定来试验并发GC -XX:+UseConcMarkSweepGC.根据您的应用程序,它可以使堆大小更低,但需要额外的CPU周期.

否则JVM将使用您指定的内存,因为它是最佳的.你可以指定一个较低的数量,-Xmx768m以保持它包含,它可能运行正常,但你会增加在重负载情况下内存不足的风险.真的是整体使用更少内存的唯一方法是编写使用更少内存的代码:)


Ale*_*sky 10

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

  • 串行收集器具有-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可能会感兴趣的.

看一下垃圾收集器的官方文档以及这个标志列表.


Jac*_*ack 2

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

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

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