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字节的内存)


    我从JDK bug(JDK 9版本中的bug,而不是8版本)中发现了有趣的评论。它说bug在8.x版本中得到了修复,但并没有告诉次要的内部版本号。

    如果虚拟内存被限制为“ulimit -v”,并且服务器有很多RAM,那么JVM无法在没有向GC提供额外命令行参数的情况下启动。

    // 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修复的东西。 如果是的话,我们可以关闭这个bug。

    当使用“UseConcMarkSweepGC”时,上面的命令行不起作用。 我试图添加MaxMetaspaceSize = 128m,但它没有帮助。 我确信有一个论据可以使它工作,但我还没有找到一个。 使用有限的虚拟内存配置GC并不是很方便用户。

    根据您的要求更改参数并尝试这一个。

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

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

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

    ulimit-v
    

    总虚拟内存可以改变:

    ulimit -v <new amount in KB>
    

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


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

    请注意,overcommit默认情况下处于启用状态。 要禁用它,请将2写入/proc/sys/vm/overcommit_memory 。 (奇怪的是, 0的值并不意味着“不过量使用”)。但是,首先阅读过量使用文档是一个好主意。

    链接地址: http://www.djcxy.com/p/82899.html

    上一篇: Java: what determines the maximum max heap size possible in a linux machine

    下一篇: Java JVM max heap size reservable upfront