1

我遇到了一个关于 outOfMemory 错误的奇怪问题。我写了一个应用程序,它在某些部分内存使用量很大。在我的笔记本电脑(linux,64bit,eclipse indigo,vmargs:xms:40,xmx:512,4gb物理内存)上,应用程序运行没有任何问题..在另一台电脑上(WinXP SP3,32bit,eclipse juno,vmargs:xms:40 , xmx:1024(!), 2gb 物理内存)应用程序终止并在标题中声明错误。两台机器都使用 oracle 的 java 7 jdk。这怎么可能,应用程序在另一台比我的笔记本电脑拥有更多堆空间的电脑上失败。我在我的笔记本电脑上开发了应用程序......但我认为这不应该是这个错误的原因,对吧?

4

2 回答 2

5

Hotspot Java 的 32 位和 64 位版本对于如何确定堆的默认最大大小有不同的策略。在 32 位 JVM 上,使用固定的默认堆大小。在 64 位 JVM 上,堆大小取决于系统上的物理内存量。

解决方案是使用java命令-Xmx选项显式设置最大堆大小。


在您的情况下,您已经在使用 -Xmx 参数,并且(显然)您在 32 位平台上使用了更大的值......并且 32 位版本首先死亡!我可以想到许多可能的解释(可能性越来越小):

  • 您的 32 位机器没有足够的交换空间,并且在尝试增加堆时无法满足 JVM 对更多内存的请求。

  • 您的应用程序正在计算有多少可用内存并相应地调整其行为......但在大内存情况下会出错。

  • 在这两种情况下,应用程序的输入存在一些差异,这就是导致问题的原因。

  • 该应用程序正在使用内存映射文件(或其他类似的文件),这些文件占用了很大一部分地址空间......减少了堆可用的地址空间。在 64 位机器上,您有许多 GB 的地址空间,但在 32 位 Windows XP 机器上,您的应用程序的地址空间将被操作系统和指令集/硬件架构限制在 ~2Gb。

(您对问题的更改描述无济于事......)


如果您从 Eclipse 启动应用程序,您可能会将 Eclipse JVM 使用的 -Xmx 设置与运行应用程序的 JVM 使用的 -Xmx 设置混淆。如果您没有在应用程序的启动器配置中明确设置 -Xmx 选项......它将使用默认堆大小!


回应您的评论:

但我必须实现一个应用程序,它将作为一个 jar 包含在另一个项目中,这是一个 Eclipse 插件。

对于 Eclipse 插件,JVM 大小由父 Eclipse 确定。你的插件在这件事上没有发言权。如果您的插件需要大量堆空间,则需要让用户手动调整 Eclipse 堆参数。

如果您从另一个 Eclipse 实例启动该 Eclipse 实例......我不确定应用程序启动器参数是否会产生任何影响。但这仅对开发插件的您(和其他人)很重要。

(对于可执行 JAR 文件,无法在 JAR 清单中指定堆大小。但还有其他选项 - 请参阅Can I set Java max heap size for running from a jar file?。

于 2012-08-06T09:29:35.590 回答
4

并非所有 OutOfMemoryErrors 都是相同的。您可以从中获取 OutOfMemoryError

  • 堆空间不足
  • GC太多。
  • 缺乏烫发
  • 堆栈空间不足(创建新线程)
  • 交换空间不足
  • 其他我已经忘记了。

您需要查看实际错误,我怀疑您的虚拟内存不足,因为您在 Windows XP 上总共只有大约 1.5 GB。

您可能会发现减小最大堆大小可以解决此问题,因为它会增加可用虚拟内存。


您需要检查您是否真的设置了您认为的最大值。在 64 位服务器 JVM 上,默认值可能很好(在这种情况下,您永远不需要设置它们)在 32 位客户端 JVM 上,默认值是公平的。

于 2012-08-06T09:32:40.620 回答