JVM -Xmx参数允许将JVM的最大堆大小设置为某个值。但是,有没有办法让这个价值变得有活力?换句话说,我想告诉JVM“看看,如果你需要它,只需继续从系统中取出RAM,直到系统出来。”
问题的两个部分原因:首先,有问题的应用程序可以使用非常广泛的ram,具体取决于用户正在做什么,因此概念性的min和max值相差很远。其次,JVM似乎在启动时保留虚拟内存的最大堆空间。这个特定的应用程序运行在各种各样的硬件上,因此选择“一刀切”的最大堆空间很难,因为它必须足够低才能在低端硬件上运行,但我们真的喜欢能够利用真正强劲的机器,如果它们可用的话。
但是,有没有办法让这个价值变得有活力?
从字面上看,没有。最大堆大小设置为JVM启动时间,无法增加。
实际上,您可以将最大堆大小设置为平台允许的最大大小,并让JVM根据需要扩展堆。这样做有明显的风险;即您的应用程序将使用所有内存并导致用户的计算机停止运行。但是这个风险隐含在你的问题中。
编辑
值得注意的是,有各种-XX...
GC调优选项,允许您调整JVM扩展堆的方式(最多)。
另一种可能性是将您的应用程序分成两部分。应用程序的第一部分完成了确定问题“大小”所需的所有准备工作。然后它计算出适当的最大堆大小,并在新的JVM中启动应用程序的第二部分内存。
它没有。它可能,也可能应该:
-Xmx90% // 90% of physical memory
但是,默认隐含的100%可能不是一个好主意。
用非GC语言编写的程序非常勤奋地管理它的内存,它会尽快修剪任何垃圾。允许它获取它请求的任何内存是有意义的,假设它负责迅速的垃圾处理。
GC语言是不同的。它只在必要时收集垃圾。只要有空间,它就不会在乎垃圾徘徊。如果它可以获得它想拥有的所有内存,它将获得计算机中的所有内存。
因此GC程序员不必再担心处理每一块垃圾了,但他仍然必须对可容忍的垃圾/活动对象比率有一个大概的了解,并用GC指示-Xmx。
基本上,你无法使用纯Java来适应各种用户的硬件:那就是一些shell /批处理脚本可以派上用场。
我在OS X和Linux上做到这一点:我有一个小的bash shell脚本,负责根据运行应用程序的硬件找到正确的JVM参数,然后调用JVM。
请注意,如果您要提供桌面Java应用程序,那么您可能希望使用类似izpack的东西来为您的用户提供安装程序:
我根本不知道Java Web Start是否可以用来提供不同的JVM参数,具体取决于用户的配置(可能不是,如果你计划提供一个专业的桌面应用程序,JWS真的很不错。)
有一个JDK增强建议(JEP)8204088
“动态最大内存限制”
这表明要引入CurrentMaxHeapSize:
为了动态限制提交的内存(即堆大小)可以增长的大小,引入了一个新的动态用户定义变量:CurrentMaxHeapSize。此变量(以字节为单位)限制了可以扩展堆的大小。它可以在启动时设置并在运行时更改。无论何时定义,它必须始终具有等于或低于MaxHeapSize的值(Xmx - 限制堆可以增长的启动时间选项)。与MaxHeapSize不同,CurrentMaxHeapSize可以在运行时动态更改。
预期的用法是使用非常保守的Xmx值设置JVM(显示对内存占用的影响非常小),然后使用CurrentMaxHeapSize动态限制控制堆的大小。
虽然没有迹象表明这个功能正在积极地工作,但它是相对较新的JEP(从2018年开始),所以我仍然会记住这一点。
公司Jelastic(jelastic.com)为G1垃圾收集器制作了JEP 8204088的工作原型:
请参阅http://mail.openjdk.java.net/pipermail/hotspot-gc-dev/2018-May/022077.html上的说明和OpenJDK http://cr.openjdk.java.net/~tschatzl/jelastic/cmx/的补丁列表