我有两台linux机器(都是vm),一台内存为12GB,另一台内存为8GB。
我尝试在两台机器上启动相同的java程序,最大堆大小是可能的(使用-Xmx标志)。以下是我得到的结果。
如果指定的最大堆大小超出了上述限制,则会低于错误值。
Error occurred during initialization of VM
Could not allocate metaspace: 1073741824 bytes
我检查了两个系统中的可用内存(使用free
命令),得到了以下结果。
我的问题是,什么决定了java程序可以启动的最大堆大小,这不会导致上述错误?(当程序出现上述错误时,系统有足够的内存来分配1073741824
字节的内存)
可用内存是可用RAM加交换空间的组合。这还取决于系统是否启用了overcommit如果启用了,内核将允许程序分配比实际可用的内存更多的内存(在合理的限制内),因为程序通常分配的内存比实际使用的内存多。
请注意,默认情况下会启用overcommit。要禁用它,请将
2
写入/proc/sys/vm/overcommit_memory
。(奇怪的是,值0
并不意味着“没有overcommit”。)但是最好先阅读overcommit文档。我发现了来自JDK bug(JDK 9版本中的bug,而不是8版本中的bug)的有趣注释。它说这个错误在8.x版本中已经修复,但是没有告诉小的内部版本号。
评论:
问题似乎是我们必须指定MALLOC_ARENA_MAX
如果我设置环境变量MALLOC_ARENA_MAX=4,那么jvm可以在没有任何额外参数的情况下启动。
我想这不是可以从jvm修复的。如果可以的话,我们可以关闭这个漏洞。
使用“UseConcMarkSweepGC”时,上面的命令行不起作用。 我试图添加MaxMetaspaceSize=128m,但没有帮助。 我确信有一个论点能使它起作用,但我还没有找到一个。 用有限的虚拟内存配置GC不太方便用户。
根据需要将参数更改为,然后尝试此操作。
我用ravindra给出的线索做了一些实验,发现最大堆大小与系统中可用的虚拟内存总量有直接关系。
系统中的虚拟内存总量(以KB为单位)可以使用:
总虚拟内存可以更改为:
最大堆大小可能比虚拟内存小大约2GB。如果使用
ulimit -v unlimited
指定无限虚拟内存,则可以为最大堆大小指定任何大值。相关问题 更多 >
编程相关推荐