我们有一个java程序需要大量的堆空间 – 我们用(其他的命令行参数)参数-Xmx1500m来启动它,它指定了1500MB的最大堆空间。 在刚刚重新启动的Windows XP盒子上启动该程序时,它将启动并运行,没有问题。 但是如果程序运行了几次,计算机已经启动了一段时间等,当它试图启动时,我得到这个错误:
VM初始化期间发生错误 无法为对象堆预留足够的空间 无法创buildJava虚拟机。
我怀疑Windows本身正在遭受内存碎片化,但是我不知道如何确认这个怀疑。 在发生这种情况时,任务pipe理器和sysinternals procexp报告2000MB空闲内存。 我曾经看过这个与内部分裂有关的问题
所以第一个问题是,我如何确认我的怀疑? 第二个问题是,如果我的怀疑是正确的,有没有人知道任何工具来解决这个问题? 我已经环顾了很多地方,但除了定期重启机器之外,我还没有发现任何有用的东西。
ps – 改变操作系统目前也不是一个可行的select。
同意Torlack,很多这是因为其他DLL正在加载和进入某些地方,打破了一个大块可以获得的虚拟机的内存量。
你可以在WinXP上做一些工作,如果你有超过3G的内存来移动一些窗口的东西,请在这里查看PAE: http : //www.microsoft.com/whdc/system/platform/server/PAE/ PAEdrv.mspx
你最好打赌,如果你真的需要超过1.2G的内存为您的Java应用程序,是看64位窗口或Linux或OSX。 如果你在你的应用程序中使用任何类型的本地库,你将不得不重新编译它们的64位,但它会比试图重新组织和东西,以最大限度地提高你在32位窗口上获得的内存。
另一个选择是将程序分成多个虚拟机,并通过RMI或消息传递等方式与其他虚拟机进行通信。 这样每个虚拟机都可以拥有一些你需要的内存子集。 不知道你的应用程序做什么,我不知道这将有助于任何方式,虽然…
除非您的页面文件空间不足,否则此问题不是计算机内存不足。 虚拟内存的重点是允许进程使用比物理上可用的更多的虚拟内存。
不知道JVM如何处理堆,要确切地说明问题是什么有些困难,但是常见的问题之一是在进程中没有足够的连续可用地址空间来允许堆被扩展。 为什么在机器运行一段时间之后这会是一个问题,这有点令人困惑。
我一直在研究类似的问题。 我发现使用WinDBG运行程序并使用“!address”和“!address -summary”命令在追踪为什么进程的虚拟地址空间已经变得碎片化方面是非常宝贵的。 您也可以尝试重新启动后运行程序,并使用“!address”命令拍摄地址空间的图片,然后在程序不再运行时执行相同的操作。 这可能会让你知道这个问题。 也许简单的一个额外的DLL加载可能会导致问题。
我怀疑问题是Windows内存碎片。 还有一个关于Windows XP的 StackOverflow叫做Java Maximum Memory的问题 ,它提到了使用Process Explorer来查看DLL映射到内存的位置,然后通过重定义DLL来解决问题,以便以更紧凑的方式加载到内存中。
使用Minimem( http://minimem.kerkia.net/ )该应用程序可能会解决您的问题。 不过,我不确定这是你正在寻找的答案。 我希望它有帮助。
也许你应该考虑启动程序并保留内存,而不是在每次运行后结束虚拟机。 寻找不同的GC选项并释放你的对象。
使用Microsoft的SysInternals工具中的vmmap来查看虚拟地址空间的碎片,并确定什么是空间分割