5

我们有一个需要大量堆空间的 java 程序 - 我们以(以及其他命令行参数)参数 -Xmx1500m 开始它,它指定最大堆空间为 1500 MB。在刚刚重新启动的 Windows XP 机器上启动此程序时,它将毫无问题地启动和运行。但是如果程序运行了几次,计算机已经启动了一段时间等,当它尝试启动时,我得到这个错误:

初始化虚拟机时出错
无法为对象堆保留足够的空间
无法创建Java虚拟机。

我怀疑Windows本身存在内存碎片,但我不知道如何证实这种怀疑。发生这种情况时,任务管理器和 sysinternals procexp 报告 2000MB 可用内存。我看过这个与内部碎片有关的问题

所以第一个问题是,我如何确认我的怀疑?第二个问题是,如果我的怀疑是正确的,有没有人知道解决这个问题的任何工具?我环顾四周,但除了定期重新启动机器之外,我没有发现任何有用的东西。

ps - 改变操作系统目前也不是一个可行的选择。

4

6 回答 6

2

除非您的页面文件空间不足,否则此问题不是计算机内存不足。虚拟内存的全部意义在于允许进程使用比物理可用更多的虚拟内存。

不知道 JVM 是如何处理堆的,很难说到底是什么问题,但常见的问题之一是您的进程中没有足够的连续可用地址空间来允许扩展堆. 为什么在机器运行一段时间后这会成为问题有点令人困惑。

我一直在工作中解决类似的问题。我发现使用 WinDBG 运行程序并使用“!address”和“!address -summary”命令对于追踪进程的虚拟地址空间为何变得碎片化非常有用。您也可以尝试在重新启动后运行程序并使用“!address”命令对地址空间进行拍照,然后在程序不再运行时执行相同操作。这可能会提示您解决问题。也许像加载额外的DLL这样简单的事情可能会导致问题。

于 2008-09-19T17:30:10.023 回答
2

同意 Torlack,这在很大程度上是因为其他 DLL 正在加载并进入某些位置,从而将您可以为 VM 获得的内存量分成一大块。

如果你有超过 3G 的内存来移动一些 Windows 的东西,你可以在 WinXP 上做一些工作,在这里查找 PAE:http: //www.microsoft.com/whdc/system/platform/server/PAE/ PAEdrv.mspx

如果您的 Java 应用程序确实需要超过 1.2G 的内存,您最好的选择是查看 64 位 Windows 或 linux 或 OSX。如果您在应用程序中使用任何类型的本机库,则必须将它们重新编译为 64 位,但这比尝试重新设置 dll 和东西以最大化您可以在 32 位窗口上获得的内存要容易得多.

另一种选择是将您的程序拆分为多个 VM,并让它们通过 RMI 或消息传递或其他方式相互通信。这样,每个 VM 都可以拥有您需要的一些内存子集。在不知道您的应用程序做什么的情况下,我不确定这是否会有所帮助,但是...

于 2008-09-19T17:38:02.610 回答
2

我怀疑问题是 Windows 内存碎片。StackOverflow 上还有另一个问题,称为Windows XP 上的 Java Maximum Memory,它提到使用 Process Explorer 查看 DLL 映射到内存的位置,然后通过重新设置 DLL 的基础来解决问题,以便以更紧凑的方式加载到内存中。

于 2009-05-19T13:55:35.663 回答
0

对该应用程序使用 Minimem ( http://minimem.kerkia.net/ ) 可能会解决您的问题。但是,我不确定这是您正在寻找的答案。我希望它有所帮助。

于 2008-09-19T17:19:40.720 回答
0

也许您应该考虑启动程序并保留内存,而不是在每次运行后结束 VM。寻找不同的 GC 选项并释放您的对象。

于 2008-09-19T17:20:19.363 回答
0

使用 Microsoft SysInternals 工具中的 vmmap 查看虚拟地址空间的碎片,并确定是什么破坏了空间

于 2011-10-11T09:54:49.240 回答