我总是能够为在32位Windows XP(Java 1.4,1.5和1.6)上运行的Java SE分配1400兆字节.
java -Xmx1400m ...
今天我在使用Java 1.5_16和1.6.0_07的新Windows XP机器上尝试了相同的选项并得到错误:
Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine.
通过反复试验,我可以在这台机器上分配1200兆字节.
任何想法为什么一台机器将允许1400和另一台只有1200?
编辑:该机器有4GB的RAM,大约3.5GB,Windows可以识别.
请记住,Windows具有虚拟内存管理,而JVM只需要在其地址空间中连续的内存.因此,在系统上运行的其他程序不一定会影响您的堆大小.什么会妨碍你加载到你的地址空间的DLL.不幸的是,在链接期间最小化DLL重定位的Windows中的优化使得更有可能存在碎片化的地址空间.除了通常的东西之外,可能会切入你的地址空间的东西包括安全软件,CBT软件,间谍软件和其他形式的恶意软件.差异的可能原因是不同的安全补丁,C运行时版本等.设备驱动程序和其他内核位有自己的地址空间(4GB 32位空间的另外2GB).
您可以尝试在JVM进程中浏览DLL绑定,并尝试将DLL重新绑定到更紧凑的地址空间.不好玩,但如果你绝望了......
或者,您可以切换到64位Windows和64位JVM.不管别人怎么建议,同时将咀嚼更多的内存,您将有很多更连续虚拟地址空间,并分配2GB连续将是微不足道的.
这与连续的记忆有关.
以下是我在网上找到的一些信息,以前有人问过,据说来自"虚拟神":
我们需要堆的连续内存区域的原因是我们有一堆辅助数据结构,这些数据结构由堆起始处的(缩放)偏移量索引.例如,我们使用"卡标记数组"跟踪对象引用更新,每个512字节的堆有一个字节.当我们在堆中存储引用时,我们必须在卡片标记数组中标记相应的字节.我们右移商店的目的地地址并使用它来索引卡片标记数组.有趣的解决算术游戏,你不能用Java做(必须:-)在C++中玩.
通常我们在获得适度的连续区域方面没有问题(在Windohs上最高可达1.5GB,在Solaris上最高可达3.8GB.YMMV.).在Windohs上,问题主要是在JVM启动之前有一些库被加载,从而破坏了地址空间.使用/ 3GB开关不会重新定义这些库,因此它们仍然是我们的问题.
我们知道如何制作分块堆,但使用它们会有一些开销.与32位JVM中的大堆相比,我们对存储管理的要求更快.如果你真的想要大堆,请切换到64位JVM.我们仍然需要连续的内存,但是进入64位地址空间要容易得多.
Windows的Java堆大小限制是:
32位Java上最大可能的堆大小:1.8 GB
建议的 32位Java堆大小限制:1.5 GB(或1.8 GB/3GB选项)
这不会帮助您获得更大的Java堆,但现在您知道您不能超越这些值.
可以处理非连续堆的Oracle JRockit在Windows 2003/XP上使用/ 3GB开关可以具有2.85 GB的Java堆大小.看起来,碎片会对Java堆的大小产生很大的影响.
JVM需要连续的内存,并且根据正在运行的内容,以前运行的内容以及Windows如何管理内存,您可以获得高达1.4GB的连续内存.我认为64位Windows将允许更大的堆.
Sun的JVM需要连续的内存.因此,最大可用内存量由内存碎片决定.特别是当加载到某个预定义的基址时,驱动程序的dll会分散内存.因此,您的硬件及其驱动程序决定了您可以获得多少内存.
有两个来源与Sun工程师的声明:论坛 博客
也许另一个JVM?你尝试过Harmony吗?我认为他们计划允许非连续记忆.