Java 为什么我能够在Windows和Solaris上将-Xmx设置为大于机器上物理和虚拟内存的值?

Java 为什么我能够在Windows和Solaris上将-Xmx设置为大于机器上物理和虚拟内存的值?,java,Java,在具有12GB RAM和33GB虚拟内存(每个任务管理器)的64位Windows机器上,我能够以不可能的-Xmx设置3.5TB运行Java(1.6.0_03-b05),但在35TB时失败。当它工作和失败时,背后的逻辑是什么?35TB的错误似乎意味着它试图在启动时保留空间。为什么它会对-Xmx(而不是-Xms)这样做 C:\temp>java-Xmx3500g ostest os.arch=amd64 13781729280字节RAM C:\temp>java-Xmx35000g ostest 初

在具有12GB RAM和33GB虚拟内存(每个任务管理器)的64位Windows机器上,我能够以不可能的-Xmx设置3.5TB运行Java(1.6.0_03-b05),但在35TB时失败。当它工作和失败时,背后的逻辑是什么?35TB的错误似乎意味着它试图在启动时保留空间。为什么它会对-Xmx(而不是-Xms)这样做

C:\temp>java-Xmx3500g ostest os.arch=amd64 13781729280字节RAM C:\temp>java-Xmx35000g ostest 初始化VM时出错 无法为对象堆保留足够的空间 无法创建Java虚拟机。 在Solaris(4GB内存,Java 1.5.0_16)上,我几乎放弃了在1 PB时设置Xmx的能力。我不理解它何时会在-Xmx设置上出错的逻辑

devsun1.mgo:/export/home/mgo> java -d64 -Xmx1000000g ostest os.arch=sparcv9 4294967296 Bytes RAM devsun1.mgo:/export/home/mgo>java-d64-xmx100000g ostest os.arch=sparcv9 4294967296字节RAM 根据Sun的java论坛(OP有16GB的物理内存)上的信息:

您可以指定-Xmx20g,但是如果您机器上所有进程所需的内存总量超过了您机器上的物理内存,那么您很可能会结束分页。有些应用程序可以在分页内存中运行,但JVM不是其中之一。您的代码可能运行正常,但是,例如,垃圾收集将非常缓慢

更新:我在谷歌上搜索得更远了一点,而且更准确地说,根据

使用64位虚拟机可以创建多大的堆?

在64位虚拟机上,您有64位 处理结果的可寻址性 在最大Java堆大小受限的情况下 仅通过物理内存的数量 并交换系统提供的空间。
另见


我不知道为什么可以启动堆大于45GB的JVM。这有点让人困惑

只是为了强化Pascal的答案——在windows中指定高最大内存大小时要非常小心。我在做一个服务器项目,它需要尽可能多的物理内存,但一旦超过了物理ram,糟糕的性能并不能很好地描述所发生的事情——挂起的机器可能会更好

发生的事情(至少这是我在检查日志和重新运行测试几天后对它的评估)是,Windows耗尽了ram,并要求所有应用释放它们所能释放的。当它询问Java时,Java启动GC。GC会接触所有内存(导致已调出的任何内容都被调入)。这进而导致windows内存不足。然后Windows会向所有应用程序发送一条消息,要求它们释放所能释放的。。。。(无限期重复)


实际上可能不是这样,但Java GC有时会触及非常旧的内存,这一事实使它与分页不兼容。

至少对于Windows的Sun 64位VM 1.6.0_17,ObjectStartArray::initialize将在VM启动时为堆的每个512字节分配1个字节。使用35TB堆启动VM将导致VM立即分配70GB,从而在您的系统上失败

Sun的32位VM(因此我认为64位VM)在计算最大堆时不考虑可用的物理内存,但仅受Windows和Linux上2GB可寻址内存或Solaris上4GB的限制,或者可能在启动时无法为管理区域分配足够的内存

仔细想想,对照可用物理内存检查max heap值的合理性没有多大意义。X GB的物理内存并不意味着X GB在需要时可供VM使用,它也可以被其他进程使用,因此VM需要一种方法来应对需要的堆比操作系统可用的堆还要多的情况。如果VM没有中断,那么如果无法从操作系统分配内存,就会抛出OutOfMemoryErrors,就像已经达到最大堆大小一样

devsun1.mgo:/export/home/mgo> java -d64 -Xmx1000000g ostest os.arch=sparcv9 4294967296 Bytes RAM