当前位置: 首页 > 知识库问答 >
问题:

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

养俊驰
2023-03-14

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

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

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

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

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

我检查了两个系统中的空闲内存(使用< code>free命令),得到如下结果。

    < li>12GB机器:大约3GB可用空间。 < li>8GB机器:大约4GB可用空间。

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

共有3个答案

督飞鸣
2023-03-14

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

系统中的总虚拟内存(以 KB 为单位)可以通过以下方式找到:

ulimit-v

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

ulimit -v <new amount in KB>

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

申屠锦
2023-03-14

可用的内存是可用RAM加上交换空间的组合。它还取决于系统是否启用了过量使用——如果启用了过量使用,内核将允许程序分配比实际可用的更多的内存(在合理的限制内),因为程序分配的内存经常超过它们实际要使用的内存。

请注意,默认情况下启用了过度提交。要禁用它,请将2写入/proc/sys/vm/overcommit_memory。(奇怪的是,0的值并不意味着“没有过度提交”。)但是最好先阅读过度提交留档。

孟德曜
2023-03-14

我从JDK错误中找到了有趣的评论(JDK 9版本中的错误而不是8版本中的错误。它说错误在8. x版本中得到了修复,但没有告诉次要的构建号。

如果虚拟内存受到“ulimit-v”的限制,并且服务器有大量RAM,那么如果没有GC的额外命令行参数,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可以解决的问题。如果是这样,我们可以关闭这个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
 类似资料:
  • 问题内容: 我有两台linux机器(都是VM),一台有12GB内存,另一台有8GB内存。 我试图在两台机器上启动相同的Java程序,并且最大可能的最大堆大小(使用-Xmx标志)。以下是我得到的结果。 12GB机器:9460MB 8GB机器:4790MB 如果我指定的最大堆大小超出了限制,我将得到以下错误。 我检查了两个系统中的可用内存(使用命令),然后得到关注。 12GB机器:大约3GB可用空间。

  • 问题内容: 这是 不是 增加Java的堆的最大尺寸的虚拟机启动后。技术原因是什么?垃圾回收算法是否取决于要使用固定数量的内存?还是出于安全原因,通过消耗所有可用内存来防止Java应用程序从DOS的系统中移至其他应用程序? 问题答案: 最后我知道在Sun的JVM中,必须在连续的地址空间中分配整个堆。我想对于大堆值,很难在启动后将其添加到您的地址空间中,同时又要确保它保持连续。您可能需要在启动时获取它

  • 我正在尝试使用画布元素,但高度不能超过像素。如果我尝试使用像素,我会在IE11中得到。这在Chrome中工作正常。画布用于PDF生成,我真的没有时间将生成移动到服务器。 我在谷歌上搜索了一下,看起来大小可能会因平台和浏览器的不同而有所不同。 是浏览器分配的内存和内存设置决定了这一点吗? 编辑:我在这里找到了一些信息: 看起来我可以有两倍的尺寸。也许这只是为了IE9。

  • 有很多关于堆大小的帖子和站点,但是没有一个提到在调用JVM时如何找出我可以保留的最大可能堆大小。 任务是用最大可用堆大小xmx=max动态启动我的jvm(这里不需要讨论这个任务的对象!)。 我们可以考虑读取当前可用或空闲的内存,并将该大小用于xms和XMX。但这不起作用。 调用Java程序时: Java-XMS1536M-XMX1536M myApp 导致: 选择您选中的应用程序大约需要的堆。并在

  • 如果我逃跑 在铬33上,我得到 为什么?

  • 我正在调查EE应用程序上的性能问题,这些问题可能是由于垃圾收集器的优化程度不高造成的。 在查看在重载下收集的日志时,我偶然发现了以下发现: 按照这里的官方jstat留档,我们可以看到当前的旧代大小(OGC)已经达到了最大旧代大小(OGCMX)。然而,第一行告诉我们,“旧空间利用率占空间当前容量的百分比”(O)“仅”为88%。 我的问题是: 什么机制在jstat输出中将旧的生成限制设置为OGCMX?