JVM 最大堆大小可以是动态的吗?

2022-09-01 17:43:10

JVM -Xmx 参数允许将 JVM 的最大堆大小设置为某个值。但是,有没有办法使这种价值动态化?换句话说,我想告诉JVM“看,如果你需要它,只要继续从系统中获取RAM,直到系统出来。

问这个问题的两部分原因:首先,有问题的应用程序可以使用非常广泛的RAM,具体取决于用户正在做什么,因此概念上的最小值和最大值相距甚远。其次,JVM 似乎在引导时从虚拟内存中保留了最大堆空间。这个特定的应用程序在各种各样的硬件上运行,因此选择“一刀切”的最大堆空间是很困难的,因为它必须足够低才能在低端硬件上运行,但是如果它们可用,我们真的希望能够利用非常强大的机器。


答案 1

但是,有没有办法使这种价值动态化?

从字面上看,没有。最大堆大小是在 JVM 启动时设置的,不能增加。

在实践中,您可以将最大堆大小设置为平台允许的最大大小,并让 JVM 根据需要增长堆。这样做有明显的风险;即,您的应用程序将使用所有内存并导致用户的机器停止运行。但这种风险隐含在你的问题中。

编辑

值得注意的是,有各种GC调优选项允许您调整JVM扩展堆的方式(直到最大值)。-XX...

另一种可能性是将应用程序拆分为 2 个部分。应用程序的第一部分完成确定问题“大小”所需的所有准备工作。然后,它计算出适当的最大堆大小,并在新的 JVM 中启动应用程序内存不足的第二部分。

  • 这仅在应用程序可以按上述方式合理地分区时才有效。

  • 仅当可以计算问题大小时,这才有效。在某些情况下,计算问题大小等同于计算结果。

  • 目前尚不清楚您是否可以获得比仅让堆增长到最大大小更好的整体性能。


答案 2

事实并非如此。它可以,而且可能应该:

-Xmx90%  // 90% of physical memory

但是,默认的隐式 100% 可能不是一个好主意。

用非GC语言编写的程序非常努力地管理其内存,它将尽快修剪任何垃圾。允许它获取它请求的任何内存是有意义的,假设它负责及时的垃圾处理。

GC语言是不同的。它仅在必要时收集垃圾。只要有空间,它就不在乎垃圾徘徊。如果它可以获得它想要拥有的所有内存,它将获得计算机中的所有内存。

因此,GC程序员不必再担心处理每一块垃圾,但他仍然必须对可容忍的垃圾/实时对象比率有一个大致的了解,并使用-Xmx指导GC。