Java:什么决定了linux机器中可能的最大最大堆大小

时间:2015-11-19 01:19:56

标签: java linux

我有两台Linux机器(都是虚拟机),一台有12GB内存,另一台有8GB内存。

我尝试在两台机器上启动相同的java程序,最大可能的最大堆大小(使用-Xmx标志)。以下是我得到的结果。

  • 12GB机器:9460MB
  • 8GB机器:4790MB

如果我指定超出上限的最大堆大小,我会得到以下错误。

Error occurred during initialization of VM
Could not allocate metaspace: 1073741824 bytes

我检查了两个系统中的可用内存(使用free命令),我得到了跟进。

  • 12GB机器:大约3GB免费。
  • 8GB机器:大约4GB免费。

我的问题是,是什么决定了java程序可以启动的最大最大堆大小,这不会导致上述错误? (当程序给出上述错误时,系统有足够的内存来分配1073741824个字节的内存)

3 个答案:

答案 0 :(得分:7)

我从JDK bug找到了有趣的评论(JDK 9版本中的错误,而不是8中的错误。它说错误是在8.x版本中修复的,但不会告诉小版本号。

  

如果虚拟内存受限于" ulimit -v",并且服务器有大量RAM,那么如果没有额外的命令行参数,JVM就无法启动。

// After "ulimit -v" The jvm does not start with default command line. 
$ ulimit -S -v 4194304
$ java -version
Error occurred during initialization of VM
Could not allocate metaspace: 1073741824 bytes

<强>注释:

问题似乎是我们必须指定MALLOC_ARENA_MAX。

如果我设置环境变量MALLOC_ARENA_MAX = 4,则jvm可以在没有任何额外参数的情况下启动。

我想这不是可以从jvm修复的东西。如果是这样,我们可以关闭这个错误。

使用&#34; UseConcMarkSweepGC&#34;那么上面的命令行不起作用。 我试图添加MaxMetaspaceSize = 128m,但它没有帮助。 我确信有一个论点可以让它发挥作用,但我还没找到。 使用有限的虚拟内存配置GC不是非常用户友好。

根据您的要求更改参数并尝试使用此参数。

ulimit -S -v 4194304 
java -XX:MaxHeapSize=512m -XX:InitialHeapSize=512m -XX:CompressedClassSpaceSize=64m -XX:MaxMetaspaceSize=128m -XX:+UseConcMarkSweepGC -version

答案 1 :(得分:1)

我使用ravindra提供的线索进行了一些实验,发现最大最大堆大小与系统中可用的总虚拟内存有直接关系。

系统中的虚拟内存总量(以KB为单位)可以找到:

ulimit-v

虚拟内存总量可以通过以下方式更改:

ulimit -v <new amount in KB>

可能的最大最大堆大小比虚拟内存少大约2GB。如果使用ulimit -v unlimited指定无限制的虚拟内存,则可以为最大堆大小指定任何大的值。

答案 2 :(得分:0)

您可用的内存是空闲RAM和交换空间的组合。它还取决于系统是否启用了overcommit - 如果是这样,内核将允许程序分配比实际可用内存更多的内存(在合理的限制范围内),因为程序通常分配的内容超过它们真正要使用的内存

请注意,默认情况下会启用overcommit。要将其停用,请将2写入/proc/sys/vm/overcommit_memory。 (奇怪的是,0的值并不意味着“没有过度使用”。)但是首先阅读过度使用的文档是个好主意。