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

f0brbegy  于 2022-11-23  发布在  其他
关注(0)|答案(4)|浏览(113)

(Note当我说“JVM”时,我实际上是指“热点”,而且我正在运行最新的Java1.6更新。)
示例情况:
我的JVM在运行时将-Xmx设置为1gb。当前,堆分配了500 mb,其中450 mb已被使用。程序需要在堆上再加载200 mb。当前,堆中有300 mb的“可收集”垃圾(我们假设它们都在最老的代中)。
在正常操作下,JVM会将堆增长到700 mb左右,并在到达时进行垃圾收集。
在这种情况下,我希望JVM先gc,然后分配新的东西,这样我们最终的堆大小保持在500 mb,使用的堆大小为350 mb。
是否有JVM参数组合可以实现这一点?

bz4sfanl

bz4sfanl1#

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

  • -XX:MinHeapFreeRatio-当层代中的可用空间百分比福尔斯此值时,将扩展层代以满足此百分比。默认值为40。
  • -XX:MaxHeapFreeRatio-当层代中的可用空间百分比超过此值时,层代将收缩以满足此值。默认值为70。

您可能还想通过指定-XX:+UseConcMarkSweepGC来试验并发GC。根据您的应用程序,它可以以额外的CPU周期为代价来保持堆大小较低。
JVM会在最佳情况下使用您指定的可用内存。您可以指定一个较低的内存量(如-Xmx768m)来控制它,它可能会运行良好,但在重负载情况下会增加内存不足的风险。实际上,使用更少内存的唯一方法是编写使用更少内存的代码:)

cl25kdpy

cl25kdpy2#

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

  • -XX:+UseZGC使能ZGC
  • -XX:+ZProactive-XX:+ZUncommit都是默认启用的。ZGC将主动尝试释放垃圾对象并将释放的内存释放给操作系统。其余选项调整其执行的积极程度。
  • -XX:ZCollectionInterval=seconds GC运行的频率。设置为几秒以确保垃圾尽可能快地被清除。(默认值为0,即不能保证GC会运行。)
  • -XX:ZUncommitDelay=seconds设置在取消提交之前堆内存必须处于未使用状态的时间(秒)。默认情况下,此选项设置为300(5分钟)。设置较低的值可更快地收回内存
  • -XX:SoftMaxHeapSize每当应用程序使用的内存超过此限制时,GC将更频繁地触发。(这可能是OP正在寻找的答案。)
  • -XX:SoftRefLRUPolicyMSPerMB不确定此选项的相关频率,但它控制某些缓存对象在内存中保留的时间。
    原始答案HotSpot中有四个(实际上是五个)不同的垃圾收集器,您可以为每个垃圾收集器选择不同的选项。
  • 串行采集器有-XX:MinHeapFreeRatio-XX:MaxHeapFreeRatio,这让你或多或少地直接控制行为。
  • 该并联收集器(-XX:+UseParallelOldGC)有-XX:MaxGCPauseMillis=<millis>-XX:GCTimeRatio=<N>。设置较短的最大暂停时间通常会导致收集器缩小堆。但是,如果暂停时间已经很短,堆不会变小。OTOH,如果最大暂停时间设置得太短,应用程序可能会将所有时间都花在收集上。设置较低的gc时间比率通常也会使堆变小。您是在告诉gc您“We“我们愿意用更多的CPU时间来收集,以换取更小的堆。然而,这只是一个提示,可能没有任何效果。在我看来,为了最小化堆的大小,并行收集器几乎是不可调的。如果您让它运行一段时间,并且应用程序的行为保持不变,则它会自动调整。
  • CMS收集器(-XX:+UseConcMarkSweepGC)通常需要一个更大的堆来实现其低暂停时间的主要目标,因此我将不讨论它。
  • 新的G1收集器(-XX:+UseG1GC)不像旧的收集器那样愚蠢。我发现它会自己选择一个较小的堆大小。它有很多调整选项,尽管我才开始研究它们。-XX:InitiatingHeapOccupancyPercent-XX:G1HeapWastePercent-XX:G1ReservePercent-XX:G1MaxNewSizePercent可能会感兴趣。

看一看list of java flags

hc2pp10m

hc2pp10m3#

您可以像通常一样在分配额外的200MB对象之前调用System.gc()方法,但这只是对JVM的一个提示,它可以或不可以遵循,而且在任何情况下,您都不知道何时会发生这种情况。正如文档中所述,这是一个尽力而为的请求。
顺便说一下,考虑到垃圾收集是一个繁重的操作,所以如果没有特定的需要这样做,只是不要试图强迫它。
才知道:如果您设置-Xmx1G,那么您将告诉JVM 1GB是堆的最大空间,由于您指定了该值,我不明白为什么它应该尝试保持低,如果它知道1GB将仍然可以(我们是在内存管理语言的环境中)。如果您不'I don“我不希望堆增加那么多,只要降低最大值,这样它就可以在分配新对象之前强制执行GC,否则为什么要告诉它使用1GB?

相关问题