我正在努力使用Java堆空间设置。 Windows上的默认Java是32位客户端,与操作系统版本无关(这是Oracle向所有用户推荐的)。它似乎默认将最大堆大小设置为256 MB,这对我来说太少了。
我使用自定义启动器来启动应用程序。我希望它在具有大量RAM的计算机上使用更多内存,并且在RAM较少的计算机上默认为-Xmx512m
。据我所知,唯一的方法是静态-Xmx
设置(必须在启动时设置)。
我的用户拥有8 GB RAM,64位Windows和32位Java 7. JVM可见的最大内存为4G(通过查询OperatingSystemMXBean
返回)。我理解为什么,没问题。
由于某些原因,我的应用程序无法使用-Xmx1300m
启动此用户,即使他有2.3G可用内存。他关闭了一些应用程序(拥有5G可用内存),但仍无法启动。报告给我的错误是:
error occured during init of vm
could not reserve enough space for object heap
发生了什么事?可能是因为32位JVM只能解决“第一”4G内存问题,并且必须在前4 GB内提供1300M块?
除了要求每个人安装64位Java(不太可能接受)之外,我该如何解决这个问题呢?
编辑:如果重要,它是一个胖胖的Swing客户端,而不是小程序。
答案 0 :(得分:2)
这不是内存问题,而是地址空间的问题。
在理论上可由32位进程寻址的4 GB(2 ^ 32)上,必须考虑到操作系统内核需要该地址空间的一部分(显然该进程无法触及)这一事实。
当您使用Java时,java
进程本身的地址空间会在堆,permgen,本机资源,JVM本身等之间进一步分割。
您使用的是64位操作系统。运行64位JVM。您的字节码(即所有罐子)将运行完全相同。没有理由使用32位JVM!
答案 1 :(得分:2)
正如其他人所提到的,这个特定用户的计算机很可能在32位地址空间中没有足够大的连续JVM空闲内存块。最大32位堆空间与系统有关(请注意,操作系统和确切的JVM版本都有所不同)但在Windows上通常大约为1100-1600 MB。例如,在我的64位Windows 7系统上,这些是我安装的特定32位JVM版本的最大-Xmx大小:
分配给进程的剩余内存由OS(或仿真器,对于64位主机上的32位进程),JVM本身以及JVM使用的其他结构使用。 p>
如果无法让客户端安装64位JVM,请将其与应用程序捆绑在一起。即使没有足够大的连续物理内存块,64位地址空间也会有一个大于1300 MB空闲的连续内存块。
如果您的软件是一个独立的应用程序,捆绑JVM是件小事。如果启动程序是applet,则可能必须让applet在启动应用程序之前检查已知位置的64位JVM(并在必要时下载)。
如果您的应用程序使用32位本机库,请确保您还可以获得这些本机库的64位版本。
你真的没有理由不能将JVM与你的应用程序捆绑在一起,但是你可能有一些32位的本机依赖项没有被移植到64位 - 在这种情况下,它赢了无论你是否捆绑了一个JVM,因为你仍然坚持使用32位。在这种情况下,您可以通过重复执行java -Xmx####m -version
并解析输出(当然####
是Xmx值)来使启动器执行二进制搜索以确定最大堆大小。找到最大Xmx后,可以使用该值启动程序。 (注意:稍微更安全的选择是简单地尝试运行程序并检查堆空间错误,在每次尝试启动程序失败后减少Xmx。)
如果收到类似以下内容之一的错误消息,则需要使用较小的Xmx值:
Java 7:
Error occurred during initialization of VM
Could not reserve enough space for object heap
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
Java 6:
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
Java 5:
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
但如果你得到类似下面的内容,你知道你已经找到了最大值,或者你可以尝试更大的Xmx值:
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) Client VM (build 23.21-b01, mixed mode)
答案 2 :(得分:1)
我同意以前的答案。只是几个额外的评论。是32位理论上可以访问4GB,但在Windows中,上半部分保留用于操作系统,下半部分用于所有应用程序。由于Windows将Java视为“用户”程序,而不是操作系统的一部分,因此您可以做的最好的是2GB。而在实践中,它远不如此。 1.2GB听起来不错。
但是,在32位模式下运行时,我实际上建议下降到1024M。如果你绝对最大化堆空间,你可能遇到一个更严重的问题,你用完“本机内存”。如果你从来没有经历过这个真正的享受 - 因为不是获得一个好的Java堆栈跟踪,整个JVM立即崩溃。
我同意其他人的意见,你需要咬紧牙关并增强应用程序以支持64位JVM。在我的例子中,我们有一个服务包装器,所以我们需要重新分配两个JVM,然后是一个32位服务包装器和一个64位服务包装器。然后,用户可以根据需要注册32位或64位版本。
答案 3 :(得分:1)
Windows XP仅限于1.2 - 1.4 GB的连续内存。即使您有64位JVM,32位仿真也与Windows XP的兼容性相同,即具有相同的限制。
如果要使用更多内存,请运行64位JVM。除非你有32位的DLL,否则有一些小小的理由不会。
答案 4 :(得分:0)
我工作的应用程序需要尽可能多的内存。通过试验和错误我发现在Windows下,我可以可靠地分配给32位JVM的大约1200 MB。它略有不同但我从未知道它低于此值。在运行OpenJVM的Linux下,我有时可以分配1300MB。这个限制的原因有很多,但是从我读到的内容中,停止JVM获取更大堆的主要问题之一就是要求堆是一个连续的内存块。
由于您使用的是64位计算机,运行64位操作系统,我强烈建议您只需切换到64位JVM。然后,您可以分配基本上无限量的内存。然而,我的实验表明,超过大约10GB的内存是一个收益递减的严重情况,因为JVM似乎没有很好地使用它并且性能受损。我相信Java 8可以更好地管理大量内存。