【问题标题】:Can the JVM max heap size be dynamic?JVM 最大堆大小可以是动态的吗?
【发布时间】:2011-03-29 04:57:12
【问题描述】:

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

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

【问题讨论】:

标签: java memory jvm


【解决方案1】:

有一个 JDK 增强提案 (JEP) 8204088

“动态最大内存限制”

建议引入CurrentMaxHeapSize

动态限制提交内存的大小(即堆 size) 可以增长,引入了一个新的动态用户定义变量: 当前最大堆大小。这个变量(以字节定义)限制了多大 堆可以扩展。它可以在启动时设置并在 运行。无论何时定义,它必须始终有一个值 等于或低于 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/

【讨论】:

    【解决方案2】:

    它没有。它可以,而且可能应该:

    -Xmx90%  // 90% of physical memory
    

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

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

    GC 语言是不同的。它仅在必要时收集垃圾。只要有空间,它就不会在意周围的垃圾。如果它能得到它想拥有的所有内存,它就会得到计算机中的所有内存。

    所以 GC 程序员不必再担心如何处理每一块垃圾,但他仍然需要对可容忍的垃圾/活动对象比率有一个大致的了解,并使用 -Xmx 来指示 GC。

    【讨论】:

    • 只是补充一点,这种限制不是 GC 语言固有的,只是 Java 选择的有问题的实现的结果
    • Microsoft Java 实现(回溯)没有-Xmx 概念,可以根据需要分配尽可能多的内存。
    • java 假设它是唯一运行的程序有点粗鲁,我不买 GC 是不同的。任何语言,无论是否是 GC,都没有理由简单地使用所有可用内存。觉得动态适应太难了?不如简单地运行一次 GC,检查有多少内存是“活动的”,然后当分配使用双倍内存时,再次运行 GC。问题解决了。
    【解决方案3】:

    但是,有没有办法使该值动态化?

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

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

    编辑

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

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

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

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

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

    【讨论】:

    • 我讨厌坟墓挖掘等等,但你能不能创建一个本机库,以一种完全 hacky 的方式,用 realloc 调整堆大小并设置适当的变量?
    • 这是不切实际的。首先,Java 堆没有分配到malloc'd 空间之外。如果你克服了这一点,你会遇到各种各样的并发症。如果您真的想要更改最大堆大小的能力,则需要修改 JVM / GC。这将是很多工作。
    【解决方案4】:

    基本上,您无法使用纯 Java 适应各种用户的硬件:这时一点点 shell/batch 脚本就可以派上用场了。

    我在 OS X 和 Linux 上就是这样做的:我有一个小的 bash shell 脚本,它负责根据运行应用程序的硬件找到正确的 JVM 参数,然后调用JVM。

    请注意,如果您提供的是桌面 Java 应用程序,那么您可能希望使用 izpack 之类的工具为您的用户提供安装程序:

    http://izpack.org

    我完全不知道是否可以使用 Java Web Start 来根据用户的配置提供不同的 JVM 参数(可能不会,而且如果您打算提供具有专业外观的桌面应用程序,那么 JWS 真的很糟糕)。

    【讨论】:

      猜你喜欢
      • 2010-11-08
      • 2013-01-01
      • 2019-12-23
      • 2011-01-07
      • 2012-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多