Windows XP上的Java最大内存


103

我一直能够为在32位Windows XP(Java 1.4、1.5和1.6)上运行的Java SE分配1400 MB的内存。

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,Windows可以识别约3.5GB。


至少以我的经验,您会注意到在32位Shell或64位Shell中运行应用程序的最大差异,尽管很少使用64位WindowsXP系统。
djangofan 2013年

Answers:


124

请记住,Windows具有虚拟内存管理功能,而JVM仅需要在其地址空间中连续的内存。因此,系统上运行的其他程序不一定会影响您的堆大小。将以您的方式获取的是被加载到您的地址空间中的DLL。不幸的是,Windows中的优化在链接过程中最大程度地减少了DLL的重定位,使您更有可能拥有零散的地址空间。除了常见的东西外,可能还会影响您地址空间的其他因素包括安全软件,CBT软件,间谍软件和其他形式的恶意软件。差异的可能原因是不同的安全补丁,C运行时版本等。设备驱动程序和其他内核位具有其自己的地址空间(4GB 32位空间中的其他2GB)。

可以尝试在JVM进程中进行DLL绑定,然后尝试将DLL的基础重新构建为更紧凑的地址空间。不好玩,但是如果你不顾一切...

另外,您可以只切换到64位Windows和64位JVM。不管别人怎么建议,同时将咀嚼更多的内存,您将有很多更连续虚拟地址空间,并分配2GB连续将是微不足道的。


5
使用进程资源管理器查看dll在内存中的加载位置。通常,一些更新的驱动程序会将其自身停留在地址空间的中间。使用REBASE命令,您可以轻松地将它们推开。但是请记住,该dll可能会再次更新并中断。
brianegge

2
我从未接受过此作为答案,但是stackoverflow将其标记为已回答。
Steve Kuo

@Christopher,是否可以在32位Windows XP上使用64位JVM?
Pacerier,2014年

@Pacerier抱歉,我错过了您的查询。AFAIK,这是不可能的。OS X对于使用32位内核的64位用户空间有一些技巧,但是我还没有听说过Windows可以使用这些技巧。
Christopher Smith

@ChristopherSmith,顺便说一句,您提到“ 系统上运行的其他程序不一定会影响堆大小 ”。如果是这样,我们如何解释这个结果:stackoverflow.com/questions/9303889/…
和平者

50

这与连续内存有关。

以下是我在网上找到的一些信息,之前有人问过这个信息,据说是来自“ VM神”:

之所以需要为堆使用连续的内存区域,是因为我们有一堆辅助数据结构,这些数据结构从堆开始处按(缩放的)偏移量进行索引。例如,我们使用“卡标记数组”跟踪对象引用更新,该“卡标记数组”每512字节堆有一个字节。当我们将引用存储在堆中时,我们必须在卡标记数组中标记相应的字节。我们右移商店的目标地址,并用它来索引卡标记阵列。解决(必须:-)在Java中不能用C ++玩的有趣的寻址算法游戏。

通常,我们不会遇到中等大小的连续区域(在Windohs上大约为1.5GB,在Solaris.YMMV上大约为3.8GB)。在Windohs上,问题主要是在JVM启动之前,有一些库被加载,从而破坏了地址空间。使用/ 3GB开关不会重新建立这些库的基准,因此它们仍然是我们的问题。

我们知道如何制作分块堆,但使用它们会产生一些开销。与32位JVM中更大的堆相比,我们对更快的存储管理的需求更多。如果您确实想要大堆,请切换到64位JVM。我们仍然需要连续的内存,但是进入64位地址空间要容易得多。


那很有趣。我总是问自己为什么要1500 MB,现在我明白了,谢谢!
TimBüthe2012年

3
很抱歉跟进一个古老的问题,但这是我到目前为止看到的最好的答案。但是,如果JVM无法获得最大堆大小,为什么它在启动时会失败?它不应该安静地争取到高于最小值的最佳尺寸吗?
Stroboskop 2014年

19

Windows的Java堆大小限制为:

  • 32位Java上的最大可能堆大小:1.8 GB
  • 在32位Java上建议的堆大小限制:1.5 GB(或带/ 3GB选项的1.8 GB

这并不能帮助您获得更大的Java堆,但是现在您知道您无法超越这些值。


10

可以处理非连续堆的Oracle JRockit在带有/ 3GB开关的Windows 2003 / XP上可以具有2.85 GB的Java堆大小。碎片似乎对Java堆的大小有很大影响。


6

JVM需要连续内存,并且取决于其他正在运行的内容,之前正在运行的内容以及Windows如何管理内存,您可能能够获得高达1.4GB的连续内存。我认为64位Windows将允许更大的堆。


2
我认为现代操作系统模拟了连续的内存。从80486开始,x86体系结构支持分页,从而可以轻松地重新安排物理内存。
Mnementh,2009年

3
Mnemeth:首先,WINAPI中有一个特定的API(AllocateUserPhysicalPages),用于数据库和VM等高级工具,最好通过Windows自己管理内存。二,寻呼是一个80386保护模式功能,而不是80486
塔马斯Czinege

6

Sun的JVM需要连续的内存。因此,可用内存的最大量取决于内存碎片。特别是,驱动程序的dll在加载到某些预定义的基地址时,往往会使内存碎片化。因此,您的硬件及其驱动程序决定了您可以获得多少内存。

两个来自Sun工程师的声明的来源:论坛 博客

也许另一个JVM?您尝试过和谐吗?我认为他们计划允许非连续存储。


但是我能够在只有1GB RAM(加上虚拟内存)的机器上分配1300MB。我的2GB RAM计算机(也带有虚拟内存)只能分配1200MB。
史蒂夫郭

和谐死了不是吗?
Pacerier 2014年

是的:“ Apache Harmony自2011年11月16日起在Apache软件基金会退休。”
bobbel 2014年

3

我认为这与以下响应所提示的Windows配置方式有关: Java -Xmx Option

进行更多测试:我能够在只有768MB物理RAM(加上虚拟内存)的旧Windows XP计算机上分配1300MB。在我的2GB RAM机器上,我只能获得1220MB。在其他各种公司计算机(使用较旧的Windows XP)上,我可以获得1400MB。限制为1220MB的机器是非常新的机器(仅从Dell购买),因此它可能具有较新的(并且更肿的)Windows和DLL(它正在运行Windows XP Pro 2002 SP2版)。


它也可能受您的虚拟内存设置的影响。
skaffman

我测试过的所有机器的虚拟内存至少是物理RAM的两倍。
史蒂夫郭

请注意,您真的永远不想真正将虚拟内存与Java一起使用,因为GC性能将变得非常差。内存量取决于已加载的dll并将内存碎片化。
kohlerm

2

从(有限内存)virtuozzo VPS运行Java程序时出现此错误消息。我没有指定任何内存参数,但发现我必须显式设置一个值,因为默认值一定太大。例如-Xmx32m(显然需要根据您运行的程序进行调整)。

只是将其放在此处,以防其他人收到上述错误消息而没有像发问者那样指定大量内存。


1

如果分配一个巨大的块,sun的JDK / JRE需要连续的内存量。

操作系统和初始应用程序倾向于在加载过程中分配点点滴滴,这会分割可用的RAM。如果连续块不可用,则SUN JDK无法使用它。Bea的JRockit(被Oracle收购)可以分块分配内存。


1

每个人似乎都在回答有关连续内存的问题,但忽略了一个更紧迫的问题。

即使分配了100%连续的内存,在32位Windows操作系统上,您也无法拥有2 GiB堆大小(默认情况下为*)。这是因为32位Windows进程不能处理超过2 GiB的空间。

除了堆外, Java进程还将包含perm gen(Java 8之前的版本),每个线程的堆栈大小,JVM /库的开销(随着每次构建而增加)。

此外,JVM标志及其默认值在版本之间会发生变化。只需运行以下命令,您就会知道一些:

 java -XX:+PrintFlagsFinal

许多选项会影响到堆内外的内存划分。留下或多或少的2 GiB可供您玩...

重用的部分这个答案矿(约Tomcat的,但适用于任何Java进程):

Windows操作系统将32位进程的内存分配限制为总共2 GiB(默认情况下)。

[您将只能]分配大约1.5 GiB堆空间,因为还有其他内存分配给该进程(JVM /库开销,perm gen空间等)。

为什么32位Windows施加2 GB的进程地址空间限制,而64位Windows施加4 GB的限制?

其他现代操作系统[cough Linux]允许32位进程使用4 GiB可寻址空间的全部(或大部分)。

也就是说,可以配置64位Windows操作系统以将32位进程的限制增加到4 GiB(32位为3 GiB):

http://msdn.microsoft.com/zh-CN/library/windows/desktop/aa366778(v=vs.85).aspx


1
该答案仅说明了为什么他可能只能分配2 GB,而不是为什么他只能在一台计算机上分配1.4 GB,而在另一台计算机上只能分配1.2 GB的原因。他没有达到此处所述的1.5 GB,2 GB或4 GB限制。
vapcguy

1
关于JVM标志的段落以某种方式解释了为什么内存在各个版本之间可能会有所不同。另外,请注意我关于堆设置如何始终占总进程大小的一部分(很大)的观点-因此低于该设置的设置仍可能会达到2 GiB 进程限制-另一设置可能会受到连续内存分配的限制。
迈克尔(Michael

或者他正在执行的1.4 GB分配的1.5 GB限制。现在变得更有意义-感谢您的澄清。
vapcguy

0

这是增加分页大小的方法

  1. 右键单击我的电脑--->属性--->高级
  2. 在效果部分中,点击设置
  3. 单击高级选项卡
  4. 在“虚拟内存”部分中,单击“更改”。它将显示您当前的页面大小。
  5. 选择具有可用硬盘空间的驱动器。
  6. 提供初始大小和最大大小...例如初始大小0 MB和最大大小4000 MB。(根据您的要求)

0

**有多种更改堆大小的方法,例如,

  1. 文件->设置->构建,执行,部署->编译器 ,您将在其中找到堆大小
  2. 文件->设置->生成,执行,部署->编译器-> andriod在这里,您还将找到堆大小。如果您遇到相同的问题,可以将其用于andriod项目。

对我有用的是

  1. 设置适当的适当的JAVA_HOME路径,以防您的Java被更新。

  2. 创建新的系统变量计算机->属性->高级设置- >创建新的系统变量

名称:_JAVA_OPTION值:-Xmx750m

仅供参考:您可以在Intellij 帮助->编辑自定义VM选项中找到默认VMoption ,在此文件中,您可以看到堆的最小和最大大小。**


-1

首先,当您有4 GB的RAM时使用页面文件是没有用的。Windows不能访问超过4GB的内存(实际上是由于内存不足而访问的内存较少),因此不使用页面文件。

其次,地址空间分为2个部分,一半用于内核,一半用于用户模式。如果您的应用程序需要更多RAM,请在boot.ini中使用/ 3GB选项(确保java.exe被标记为“支持大地址”)(有关更多信息,请参见Google)。

第三,我认为您无法分配全部2 GB的地址空间,因为Java在内部浪费了一些内存(用于线程,JIT编译器,VM初始化等)。使用/ 3GB开关更多。


1
页面文件不能用于4GB或RAM的想法是错误的。如果没有页面文件,则操作系统无法从物理RAM中驱逐未使用的过程数据(未使用服务的堆栈空间等),从而减少了可用于实际工作的RAM数量。具有页面文件可以释放RAM。
没人在2009年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.