堆大小是 Java 应用程序的基本参数。它直接影响我们可以使用的内存量,并间接影响应用程序的性能。例如,压缩指针的使用情况、垃圾回收周期的数量和持续时间等。
在本教程中,我们将学习如何使用 –XX:MaxRAM 标志为堆大小计算提供更多优化机会。在容器内或不同主机上运行应用程序时,这一点尤其重要。
用于配置堆的标志可以一起工作,也可以相互覆盖。了解他们的关系对于更深入地了解他们的目的很重要。
控制堆大小的主要方法是 -Xmx 和 -Xms 标志,它们分别控制最大和初始大小。它是一个强大的工具,但不考虑机器或容器上的可用空间。假设我们在可用 RAM 从 4 GB 到 64 GB 不等的各种主机上运行应用程序。
如果没有 -Xmx,JVM 会自动为应用程序堆分配大约 25% 的可用 RAM。但是,通常,JVM 分配的初始堆大小取决于各种参数:系统架构、JVM 版本、平台等。
在某些情况下,此行为可能是不可取的。根据可用的 RAM,它可能会分配截然不同的堆。让我们检查一下 JVM 在具有 24 GB RAM 的机器上默认分配了多少:
$ java -XX:+PrintFlagsFinal -version |\
grep -e '\bMaxHeapSize\|\bMinHeapSize\|\bInitialHeapSize'
size_t InitialHeapSize = 402653184 {product} {ergonomic}
size_t MaxHeapSize = 6442450944 {product} {ergonomic}
size_t MinHeapSize = 8388608 {product} {ergonomic}
JVM 分配了大约 6 GB 或 25%,这对我们的应用程序来说可能太多了。将最大堆设置为特定值也可能会产生问题。如果我们使用 -Xmx4g,那么对于可用内存不足的主机,它可能会失败,而且,我们将无法获得我们可以拥有的额外内存:
$ java -XX:+PrintFlagsFinal -Xmx4g -version |\
grep -e '\bMaxHeapSize\|\bMinHeapSize\|\bInitialHeapSize'
size_t InitialHeapSize = 402653184 {product} {ergonomic}
size_t MaxHeapSize = 4294967296 {product} {command line}
size_t MinHeapSize = 8388608 {product} {ergonomic}
在某些情况下,可以通过使用脚本动态计算 -Xmx 来解决此问题。但是,它绕过了 JVM 启发式方法,而 JVM 启发式方法可能更精确地说明了应用程序需求。
标志 -XX:MaxRAM 旨在解决上述问题。首先,它可以防止 JVM 在具有大量 RAM 的系统上过度分配内存。我们可以将此标志视为 “运行应用程序,但假设你最多有 X 数量的 RAM”。
此外,-XX:MaxRAM 允许 JVM 对堆大小使用标准启发式方法。让我们回顾一下前面的示例,但使用 -XX:MaxRAM:
$ java -XX:+PrintFlagsFinal -XX:MaxRAM=6g -version |\
grep -e '\bMaxHeapSize\|\bMinHeapSize\|\bInitialHeapSize'
size_t InitialHeapSize = 100663296 {product} {ergonomic}
size_t MaxHeapSize = 1610612736 {product} {ergonomic}
size_t MinHeapSize = 8388608 {product} {ergonomic}
在这种情况下,JVM 会计算最大堆大小,但假设我们只有 6 GB 的 RAM。请注意,我们不应将 -Xmx 与 -XX:MaxRAM 一起使用。因为 -Xmx 更具体,所以它会覆盖 -XX:MaxRAM:
$ java -XX:+PrintFlagsFinal -XX:MaxRAM=6g -Xmx6g -version |\
grep -e '\bMaxHeapSize\|\bMinHeapSize\|\bInitialHeapSize'
size_t InitialHeapSize = 100663296 {product} {ergonomic}
size_t MaxHeapSize = 6442450944 {product} {command line}
size_t MinHeapSize = 8388608 {product} {ergonomic}
此标志可以提高资源利用率和堆分配。但是,我们仍然无法控制应该为堆分配多少 RAM。
现在我们处于控制之中,可以告诉 JVM 应该考虑多少 RAM。让我们定义分配堆的策略。-XX:MaxRAM 标志与 -XX:MaxRAMPercentage 和 -XX:MinRAMPercentage 配合得很好。它们提供了更大的灵活性,尤其是在容器化环境中。让我们尝试将它与 -XX:MaxRAM 一起使用,并将堆设置为可用 RAM 的 50%:
$ java -XX:+PrintFlagsFinal -XX:MaxRAM=6g -XX:MaxRAMPercentage=50 -version |\
grep -e '\bMaxHeapSize\|\bMinHeapSize\|\bInitialHeapSize'
size_t InitialHeapSize = 100663296 {product} {ergonomic}
size_t MaxHeapSize = 3221225472 {product} {ergonomic}
size_t MinHeapSize = 8388608 {product} {ergonomic}
关于 -XX:MinRAMPercentage 有一个常见的混淆。它的行为与 -Xms 不同。 虽然,可以合理地假设它设置了最小堆大小。我们来检查一下以下设置:
$ java -XX:+PrintFlagsFinal -XX:MaxRAM=16g -XX:MaxRAMPercentage=10 -XX:MinRAMPercentage=50 -version |\
grep -e '\bMaxHeapSize\|\bMinHeapSize\|\bInitialHeapSize'
size_t InitialHeapSize = 268435456 {product} {ergonomic}
size_t MaxHeapSize = 1719664640 {product} {ergonomic}
size_t MinHeapSize = 8388608 {product} {ergonomic}
我们同时设置了 -XX:MaxRAMPercentage 和 -XX:MinRAMPercentage,但很明显,只有 -XX:MaxRAMPercentage 在工作。我们将 16 GB RAM 的 10% 分配给堆。但是,如果我们将可用 RAM 减少到 200 MB,我们将得到不同的行为:
$ java -XX:+PrintFlagsFinal -XX:MaxRAM=200m -XX:MaxRAMPercentage=10 -XX:MinRAMPercentage=50 -version |\
grep -e '\bMaxHeapSize\|\bMinHeapSize\|\bInitialHeapSize'
size_t InitialHeapSize = 8388608 {product} {ergonomic}
size_t MaxHeapSize = 109051904 {product} {ergonomic}
size_t MinHeapSize = 8388608 {product} {ergonomic}
在这种情况下,堆大小由 -XX:MinRAMPercentage 控制。当可用 RAM 降至 200 MB 以下时,此标志将启动。现在,我们可以将堆增加到 75%:
$ java -XX:+PrintFlagsFinal -XX:MaxRAM=200m -XX:MaxRAMPercentage=10 -XX:MinRAMPercentage=75 -version |\
grep -e '\bMaxHeapSize\|\bMinHeapSize\|\bInitialHeapSize'
size_t InitialHeapSize = 8388608 {product} {ergonomic}
size_t MaxHeapSize = 134217728 {product} {ergonomic}
size_t MinHeapSize = 8388608 {product} {ergonomic}
如果我们继续对如此小的堆应用 -XX:MaxRAMPercentage,我们将获得 20 MB 的堆,这可能不够满足我们的目的。这就是为什么我们为小堆和大堆设置了不同的标志。-XX:MaxRAM 标志与它们一起工作得很好,并给了我们更多的控制权。
控制堆大小对于 Java 应用程序至关重要。分配更多内存不一定是好的;同时,分配不足的内存是不好的。
使用 -Xmx、-XX:MaxRAM、-XX:MaxRAMPercentage 和 -XX:MinRAMPercentage 可以帮助我们更好地优化应用程序并提高性能。
原文:Difference Between Xmx and MaxRAM JVM Parameters | Baeldung
https://blog.xqlee.com/article/2506082127127378.html