JVM中Xmx 和 MaxRAM 参数区别详解

编程教程 > Java > Spring (43) 2025-06-09 12:16:39

1. 概述

 

堆大小是 Java 应用程序的基本参数。它直接影响我们可以使用的内存量,并间接影响应用程序的性能。例如,压缩指针的使用情况、垃圾回收周期的数量和持续时间等。

在本教程中,我们将学习如何使用 –XX:MaxRAM 标志为堆大小计算提供更多优化机会。在容器内或不同主机上运行应用程序时,这一点尤其重要。

2. 堆大小计算

 

用于配置堆的标志可以一起工作,也可以相互覆盖。了解他们的关系对于更深入地了解他们的目的很重要。

2.1. 使用 -Xmx

 

控制堆大小的主要方法是 -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 启发式方法可能更精确地说明了应用程序需求。

2.2. 使用 -XX:MaxRAM

 

标志 -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。

2.3. 使用 -XX:MaxRAMPercentage-XX:MinRAMPercentage

 

现在我们处于控制之中,可以告诉 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 标志与它们一起工作得很好,并给了我们更多的控制权。

3. 总结

 

控制堆大小对于 Java 应用程序至关重要。分配更多内存不一定是好的;同时,分配不足的内存是不好的。

使用 -Xmx、-XX:MaxRAM、-XX:MaxRAMPercentage -XX:MinRAMPercentage 可以帮助我们更好地优化应用程序并提高性能。


 

原文:Difference Between Xmx and MaxRAM JVM Parameters | Baeldung


评论
User Image
提示:请评论与当前内容相关的回复,广告、推广或无关内容将被删除。

相关文章
1. 概述 堆大小是 Java 应用程序的基本参数。它直接影响我们可以使用的内存量,并间接影响应用程序的性能。例如,压缩指针的使用情况、垃圾回收周期的数量和持续
常用JVM内存设置以及调优JVM内存简介JVM占用的内存称为堆(heap),他被分成三个区:1&gtl;年轻(young,又称为new)2&gtl;老(tenred,又称为ol
JVM调优总结篇(一),这里主要搬运了csdn大神得总结。收藏以后可能会用到
了解JDK、JRE 和 JVM 之间的差异
找到Java项目进程PID首先执行 jps 命令找到相应 java 进程的 pid:jps1 springBootMain 导出 jvm 内存堆栈快照hprof
当开发人员谈论Java应用程序及其开发环境时,JDK,JRE和JVM是非常常见的词汇。让我们来看看这些词之间的差异。
本文针对Java虚拟机对程序性能影响,通过设置不同的Java虚拟机参数来提升程序的性能。首先从Java虚拟机各个性能方面来进行监控,找出Java虚拟机中可能对程序性能影响较大的,然后先通过小实验...
Java基础JVM中堆和栈理解,收集各大网站各大牛人的语录,在Java中,内存主要分为两种,一种是栈(stack)内存,另一种就是堆内存(heap)(某些情况下说的堆栈内存是指栈内存)。
如果是直接部署的 nexus, 需要修改 $install-dir/bin/nexus.vmoptions 文件 ,添加参数-Xms128m -Xmx512m -XX:MaxDirectMe...
tomcat 8 Linux参数调优,通过Java启动命令参数调整来实现jvm内存调优
环境准备minikube 安装,参考minikube k8s 安装详细教程spring boot demo项目一个spring boot项目 maven 主要依赖 <depe...
Spring 5 入门实战Say Hello,本博客主要讲解spring 5最基础的容器入门实战。
Spring Boot 2.0 Redis整合,通过spring boot 2.0整合Redis作为spring缓存框架的实现。
spring boot webflux client实战,webclient是spring webflux的一个小组件。对于Java的http通讯来说,webclient是非常简单易用的。
Spring MVC 5 接受对象集合参数实战,在之前,我一直以为http传输的参数是KEY-VALUE键值对的方式和文件流的形式。直到最近遇到新需求才知道还有一种RAW的数据类型。通过这种原生...