105

我一直能够为在 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,Windows 可以识别大约 3.5GB。

4

13 回答 13

129

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

可以尝试在您的 JVM 进程中检查您的 DLL 绑定,并尝试将您的 DLL 重新设置为更紧凑的地址空间。不好玩,但如果你绝望...

或者,您可以只切换到 64 位 Windows 和 64 位 JVM。尽管其他人建议,虽然它会消耗更多的 RAM,但您将拥有更多连续的虚拟地址空间,并且连续分配 2GB 将是微不足道的。

于 2009-01-31T00:02:39.267 回答
51

这与连续内存有关。

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

我们需要一个连续的内存区域用于堆的原因是我们有一堆边数据结构,这些数据结构由从堆开始的(缩放的)偏移量索引。例如,我们使用“卡片标记数组”跟踪对象引用更新,该数组每 512 字节堆有一个字节。当我们在堆中存储一个引用时,我们必须在卡片标记数组中标记相应的字节。我们右移存储的目标地址并使用它来索引卡片标记数组。有趣的寻址算术游戏,你不能在 Java 中做,你必须(必须:-)在 C++ 中玩。

通常我们可以轻松获得适度的连续区域(在 Windohs 上最多约 1.5GB,在 Solaris 上最多约 3.8GB。YMMV。)。在 Windohs 上,问题主要是在 JVM 启动之前加载了一些库,从而破坏了地址空间。使用 /3GB 开关不会变基这些库,所以它们对我们来说仍然是一个问题。

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

于 2009-01-31T01:26:14.917 回答
20

Windows 的 Java 堆大小限制为:

  • 32 位 Java 上可能的最大堆大小: 1.8 GB
  • 32 位 Java 的推荐堆大小限制: 1.5 GB(或1.8 GB,带 /3GB 选项)

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

于 2009-01-31T01:56:39.190 回答
10

Oracle JRockit可以处理非连续堆,在 Windows 2003/XP 上使用 /3GB 开关可以拥有 2.85 GB 的 Java 堆大小。似乎碎片对 Java 堆的大小有相当大的影响。

于 2009-02-01T22:25:58.490 回答
6

JVM 需要连续内存,根据正在运行的其他内容、之前运行的内容以及 Windows 管理内存的方式,您最多可以获得 1.4GB 的连续内存。我认为 64 位 Windows 将允许更大的堆。

于 2008-10-05T04:26:43.780 回答
6

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

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

也许另一个JVM?你试过和谐吗?我认为他们计划允许非连续记忆。

于 2008-10-06T19:59:41.790 回答
3

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

更多测试:我能够在一台只有 768MB 物理 RAM(加上虚拟内存)的旧 Windows XP 机器上分配 1300MB。在我的 2GB RAM 机器上,我只能获得 1220MB。在其他各种公司机器(使用较旧的 Windows XP)上,我能够获得 1400MB。具有 1220MB 限制的机器是相当新的(刚从戴尔购买),所以它可能有更新(而且更臃肿)的 Windows 和 DLL(它运行的是 Window XP Pro 版本 2002 SP2)。

于 2008-10-05T23:48:23.060 回答
2

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

只是把它放在这里以防其他人收到上述错误消息而没有像提问者那样指定大量内存。

于 2011-04-07T02:38:34.230 回答
1

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

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

于 2008-10-05T05:09:02.603 回答
1

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

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

除了 heap 之外, 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 施加 4GB 限制?

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

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

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

于 2015-06-12T16:17:53.747 回答
0

这是增加分页大小的方法

  1. 右键我的电脑--->属性--->高级
  2. 在性能部分点击设置
  3. 单击高级选项卡
  4. 在虚拟内存部分,单击更改。它将显示您当前的分页大小。
  5. 选择可用硬盘空间的驱动器。
  6. 提供初始大小和最大大小...例如初始大小 0 MB 和最大大小 4000 MB。(根据您的需要)
于 2012-12-17T21:25:44.450 回答
0

**有很多方法可以改变堆大小,比如,

  1. 文件->设置->构建、执行、部署->编译器 在这里你会发现堆大小
  2. file->setting->build, exceution, deployment->compiler->andriod在这里你也会发现堆大小。如果您遇到同样的问题,您可以将其用于 andriod 项目。

对我有用的是

  1. 设置适当的 JAVA_HOME 路径,以防你更新了 java。

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

名称:_JAVA_OPTION 值:-Xmx750m

仅供参考:您可以在 Intellij help->edit custom VM option中找到默认 VMoption ,在此文件中您可以看到堆的最小和最大大小。**

于 2020-02-17T16:47:35.367 回答
-1

首先,当你有 4 GB 的 RAM 时使用页面文件是没有用的。Windows 不能访问超过 4GB(实际上是因为内存漏洞而减少了),因此不使用页面文件。

其次,地址空间一分为二,一半给内核,一半给用户态。如果您的应用程序需要更多 RAM,请使用 boot.ini 中的 /3GB 选项(确保 java.exe 被标记为“大地址感知”(谷歌了解更多信息)。

第三,我认为你不能分配完整的 2 GB 地址空间,因为 java 在内部浪费了一些内存(用于线程、JIT 编译器、VM 初始化等)。使用 /3GB 开关了解更多信息。

于 2009-02-02T23:03:48.197 回答