我有两台linux机器(都是VM),一台有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版本中的错误而不是8中的错误。它表示错误已在8.x版本中修复,但未告知较小的内部版本号。


    // 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中解决的问题。如果是这样,我们可以关闭此错误。

    使用“UseConcMarkSweepGC”时,以上命令行不起作用。
    我试图添加MaxMetaspaceSize = 128m,但这没有帮助。
    我敢肯定有一个论点可以使它奏效,但我还没有找到。
    用有限的虚拟内存配置GC并不是非常用户友好。

    根据您的要求将参数更改为,然后尝试此操作。
    ulimit -S -v 4194304
    java -XX:MaxHeapSize=512m -XX:InitialHeapSize=512m -XX:CompressedClassSpaceSize=64m -XX:MaxMetaspaceSize=128m -XX:+UseConcMarkSweepGC -version
    

    07-27 20:00