64位操作系统上的32位JVM的最大Java堆大小

问题不在于32位操作系统上的最大堆大小,因为32位操作系统的最大可寻址内存大小为4GB,而JVM的最大堆大小取决于可以保留多少连续的空闲内存。

我更感兴趣的是了解在64位操作系统中运行的32位JVM的最大(理论和实际可行)堆大小。 基本上,我正在寻找类似SO的相关问题中的数字的答案。

至于为什么使用32位JVM而不是64位JVM,原因不是技术性的,而是管理/官僚性 – 在生产环境中安装64位JVM可能太晚了。

希望有一大块内存并使用原始指针的32位JVM不能使用超过4 Gb(因为这是32位限制,也适用于指针)。 这包括Sun和 – 我非常肯定 – 也是IBM的实现。 我不知道JRockit或其他公司是否有32位实现的大内存选项。

如果您希望达到此限制,则应强烈考虑为您的生产环境启动并行跟踪验证64位JVM,以便在32位环境发生故障时做好准备。 否则,你将不得不在压力下工作,这是不好的。


编辑2014-05-15:Oracle常见问题解答:

32位JVM的最大理论堆栈限制是4G。 由于可用交换,内核地址空间使用,内存碎片和虚拟机开销等各种附加限制,实际上限制可能会低得多。 在大多数现代的32位Windows系统上,最大堆大小的范围从1.4G到1.6G。 在32位Solaris内核上,地址空间限制为2G。 在运行32位虚拟机的64位操作系统上,最大堆大小可能会更高,在许多Solaris系统上接近4G。

http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit

你可以问Java运行时:

public class MaxMemory { public static void main(String[] args) { Runtime rt = Runtime.getRuntime(); long totalMem = rt.totalMemory(); long maxMem = rt.maxMemory(); long freeMem = rt.freeMemory(); double megs = 1048576.0; System.out.println ("Total Memory: " + totalMem + " (" + (totalMem/megs) + " MiB)"); System.out.println ("Max Memory: " + maxMem + " (" + (maxMem/megs) + " MiB)"); System.out.println ("Free Memory: " + freeMem + " (" + (freeMem/megs) + " MiB)"); } } 

这将基于默认堆分配报告“最大内存”。 所以你仍然需要玩-Xmx (在HotSpot上 )。 我发现在Windows 7 Enterprise 64位上运行,我的32位 HotSpot JVM最多可以分配1577MiB:

 [C:scratch]> java -Xmx1600M MaxMemory
 VM初始化期间发生错误
无法为对象堆预留足够的空间
无法创建Java虚拟机。
 [C:scratch]> java -Xmx1590M MaxMemory
总内存:2031616(1.9375 MiB)
最大内存:1654456320(1577.8125 MiB)
免费内存:1840872(1.75559234619 MiB)
 [C:划痕]>

而在同一个OS上的64位 JVM当然要高得多(大约3TiB)

 [C:scratch]> java -Xmx3560G MaxMemory
 VM初始化期间发生错误
无法为对象堆预留足够的空间
 [C:scratch]> java -Xmx3550G MaxMemory
总内存:94240768(89.875 MiB)
最大内存:3388252028928(3184151.84297 MiB)
免费内存:93747752(89.4048233032 MiB)
 [C:划痕]>

正如其他人已经提到,这取决于操作系统。

  • 对于32位的Windows:这将是<2GB( Windows内部书说2GB的用户进程)
  • 对于32位的BSD / Linux:<3GB(来自魔鬼书)
  • 对于32位MacOS X:<4GB(来自Mac OS X内部的书)
  • 不确定关于32位Solaris,请尝试上面的代码,并让我们知道。

对于一个64位的主机操作系统,如果JVM是32位的,它仍然依赖,很可能像上面所说的那样。

– 更新20110905 :我只想指出一些其他的观察/细节:

  • 我运行的硬件是64位,安装了6GB的实际内存。 操作系统是Windows 7 Enterprise,64位
  • 可以分配的Runtime.MaxMemory的实际数量也取决于操作系统的工作集 。 我曾运行这个,而我也有VirtualBox运行,发现我无法成功启动与-Xmx1590M的HotSpot JVM,并不得-Xmx1590M小。 这也意味着,你可能会得到超过1590M,这取决于你当时的工作集规模(尽管我仍然保持它在32位的2GiB下,因为Windows的设计)

你不指定哪个操作系统。

在Windows下(对于我的应用程序 – 一个长期运行的风险管理应用程序),我们发现在Windows 32bit上我们可以超过1280MB。 我怀疑在64位下运行一个32位的JVM会有什么不同。

我们把应用程序移植到Linux上,我们在64位硬件上运行一个32位的JVM,并且有一个容量为2.2GB的虚拟机。

您可能遇到的最大问题是GC取决于您正在使用的内存。

从4.1.2堆大小 :

“对于32位进程模型,进程的最大虚拟地址大小通常是4 GB,尽管有些操作系统将其限制为2 GB或3 GB。对于2 GB的限制,最大堆大小通常为-Xmx3800m(1600 m) ),但实际的限制是依赖于应用程序的,对于64位的过程模型,最大限度是无限的。

在这里找到了一个相当不错的答案: Windows XP上的Java最大内存 。

我们最近有一些这方面的经验。 我们最近从Solaris(x86-64版本5.10)移植到Linux(RedHat x86-64),并意识到我们在Linux上的Linux 32位JVM进程的可用内存少于Solaris。

对于Solaris,这几乎是4GB(http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit)。;

我们使用-Xms2560m -Xmx2560m -XX:MaxPermSize = 512m -XX:PermSize = 512m运行我们的应用程序,在Solaris上过去几年没有问题。 试图将其移动到Linux,我们有启动时随机存储器内存错误的问题。 我们只能使它在-Xms2300 -Xmx2300上始终如一地启动。 然后我们通过支持被告知这一点。

Linux上的32位进程具有3GB(3072MB)的最大可寻址地址空间,而在Solaris上则是4GB(4096MB)。

64位操作系统上的32位JVM的限制与32位操作系统上的32位JVM的限制完全相同。 毕竟,32位JVM将运行在32位虚拟机(虚拟化意义上),因此它不会知道它在64位操作系统/机器上运行。

在64位操作系统和32位操作系统上运行32位JVM的一个好处是可以拥有更多的物理内存,因此会减少交换/分页的频率。 但是,只有当您有多个进程时才能充分实现这一优势。

至于为什么用一个32位的JVM而不是一个64位的,原因不是技术上的,而是管理上的/官僚的。

当我在为BEA工作时,我们发现平均应用程序实际上在64位JVM中运行速度较慢 ,然后在32位JVM中运行。 在某些情况下,性能降低幅度高达25%。 因此,除非您的应用程序确实需要所有额外的内存,否则您最好设置更多的32位服务器。

我记得,使用64位BEA专业服务人员的三个最常见的技术理由是:

  1. 该应用程序正在操纵多个大规模的图像,
  2. 应用程序正在进行大量的数据处理,
  3. 该应用程序有内存泄漏,客户是政府合同中的主要部分,他们不想花时间和追踪内存泄漏的费用。 (使用大量的内存堆将会增加MTBF,而主要的仍然会得到支付)

当前由Oracle拥有的JROCKIT JVM支持不连续的堆使用,因此当JVM在64位Windows操作系统上运行时,允许32位JVM访问超过3.8 GB的内存。 (在32位操作系统上运行时为2.8 GB)。

http://blogs.oracle.com/jrockit/entry/how_to_get_almost_3_gb_heap_on_windows

JVM可以自由下载(需要注册)

http://www.oracle.com/technetwork/middleware/jrockit/downloads/index.html

以下是Solaris和Linux 64位下的一些测试

具有32 GB RAM的Solaris 10 – SPARC – T5220机器(大约9 GB可用)

 $ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3750m MaxMemory Error occurred during initialization of VM Could not reserve space for ObjectStartArray $ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3700m MaxMemory Total Memory: 518520832 (494.5 MiB) Max Memory: 3451912192 (3292.0 MiB) Free Memory: 515815488 (491.91998291015625 MiB) Current PID is: 28274 Waiting for user to press Enter to finish ... $ java -version java version "1.6.0_30" Java(TM) SE Runtime Environment (build 1.6.0_30-b12) Java HotSpot(TM) Server VM (build 20.5-b03, mixed mode) $ which java /usr/bin/java $ file /usr/bin/java /usr/bin/java: ELF 32-bit MSB executable SPARC Version 1, dynamically linked, not stripped, no debugging information available $ prstat -p 28274 PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP 28274 user1 670M 32M sleep 59 0 0:00:00 0.0% java/35 

顺便说一句:Java显然并没有分配太多的实际内存的启动。 似乎每个实例开始只有约100 MB(我开始10)

Solaris 10 – x86 – 8 GB RAM的VMWare VM(大约3 GB免费*)

3 GB的可用RAM并不是真的。 ZFS缓存使用的内存很大,但我没有root权限来检查确切的数量

 $ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3650m MaxMemory Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine. $ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3600m MaxMemory Total Memory: 516423680 (492.5 MiB) Max Memory: 3355443200 (3200.0 MiB) Free Memory: 513718336 (489.91998291015625 MiB) Current PID is: 26841 Waiting for user to press Enter to finish ... $ java -version java version "1.6.0_41" Java(TM) SE Runtime Environment (build 1.6.0_41-b02) Java HotSpot(TM) Server VM (build 20.14-b01, mixed mode) $ which java /usr/bin/java $ file /usr/bin/java /usr/bin/java: ELF 32-bit LSB executable 80386 Version 1 [FPU], dynamically linked, not stripped, no debugging information available $ prstat -p 26841 PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP 26841 user1 665M 22M sleep 59 0 0:00:00 0.0% java/12 

RedHat 5.5 – x86 – 4 GB RAM的VMWare虚拟机(使用大约3.8 GB – 缓冲区为200 MB,高速缓存为3.1 GB,大约3 GB免费)

 $ alias java='$HOME/jre/jre1.6.0_34/bin/java' $ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3500m MaxMemory Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine. $ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3450m MaxMemory Total Memory: 514523136 (490.6875 MiB) Max Memory: 3215654912 (3066.6875 MiB) Free Memory: 511838768 (488.1274871826172 MiB) Current PID is: 21879 Waiting for user to press Enter to finish ... $ java -version java version "1.6.0_34" Java(TM) SE Runtime Environment (build 1.6.0_34-b04) Java HotSpot(TM) Server VM (build 20.9-b04, mixed mode) $ file $HOME/jre/jre1.6.0_34/bin/java /home/user1/jre/jre1.6.0_34/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped $ cat /proc/21879/status | grep ^Vm VmPeak: 3882796 kB VmSize: 3882796 kB VmLck: 0 kB VmHWM: 12520 kB VmRSS: 12520 kB VmData: 3867424 kB VmStk: 88 kB VmExe: 40 kB VmLib: 14804 kB VmPTE: 96 kB 

同一台机器使用JRE 7

 $ alias java='$HOME/jre/jre1.7.0_21/bin/java' $ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3500m MaxMemory 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 -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3450m MaxMemory Total Memory: 514523136 (490.6875 MiB) Max Memory: 3215654912 (3066.6875 MiB) Free Memory: 511838672 (488.1273956298828 MiB) Current PID is: 23026 Waiting for user to press Enter to finish ... $ java -version java version "1.7.0_21" Java(TM) SE Runtime Environment (build 1.7.0_21-b11) Java HotSpot(TM) Server VM (build 23.21-b01, mixed mode) $ file $HOME/jre/jre1.7.0_21/bin/java /home/user1/jre/jre1.7.0_21/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped $ cat /proc/23026/status | grep ^Vm VmPeak: 4040288 kB VmSize: 4040288 kB VmLck: 0 kB VmHWM: 13468 kB VmRSS: 13468 kB VmData: 4024800 kB VmStk: 88 kB VmExe: 4 kB VmLib: 10044 kB VmPTE: 112 kB 

应该会好很多

对于在64位主机上运行的32位JVM,我想象一下剩下的堆是什么,在JVM之后有没有片段化的虚拟空间,它是它自己的DLL,以及任何OS 32位兼容性的东西已经加载。 作为一个疯狂的猜测,我认为3GB应该是可能的,但是这要取决于你在32位主机域中的表现如何。

另外,即使你可以创建一个巨大的3GB的堆,你也可能不想,因为这会导致GC暂停,从而变得非常麻烦。 有些人只是运行更多的JVM来使用额外的内存,而不是一个巨大的内存。 我想他们现在正在调整JVM以更好地与巨大的堆一起工作。

要知道你能做多少事情有点难。 我想你的32位的情况可以很容易地通过实验确定。 抽象地进行预测是很困难的,因为很多事情都要考虑在内,特别是因为32位主机上可用的虚拟空间相当有限。堆必须存在于连续的虚拟内存中,因此地址空间碎片化操作系统内核的地址空间的内部使用将决定可能的分配范围。

操作系统将使用一些地址空间来映射硬件设备和它自己的动态分配。 虽然这个内存没有映射到java进程地址空间,但OS内核不能同时访问它和你的地址空间,所以它会限制任何程序虚拟空间的大小。

加载DLL的依赖于JVM的实现和发布。 加载操作系统的内核取决于很多东西,发行版本,硬件,自从上次重启以来已经映射了多少东西,谁知道呢…

综上所述

我敢打赌,你在32位地盘上得到了1-2GB,在64位上得到了大约3,所以总体上提高了约2倍。

在Solaris上,从Solaris 2.5开始,限制大约为3.5 GB。 (大约10年前)

我遇到与App Inventor for Android块编辑器使用的JVM相同的问题。 它设置堆在925m最大。 这是不够的,但我不能设置超过1200米,取决于我的机器上的各种随机因素。

我下载了Nightly,来自Firefox的beta 64位浏览器,以及JAVA 7 64位版本。

我还没有找到新的堆栈限制,但是我打开了一个JVM,堆大小为5900米 。 没问题!

我在24GB内存的机器上运行Win 7 64 bit Ultimate。

我已经尝试在32位Linux机器上将堆大小设置为2200M,JVM工作正常。 当我将其设置为2300M时,JVM没有启动。

在这里还有一个关于热点的32位JVM: – 本地堆容量= 4 Gig – Java堆 – PermGen;

对于32位JVM,由于Java Heap和本地堆在竞争中,它可能会变得特别棘手。 Java堆越大,本地堆越小。 试图为32位虚拟机设置一个大堆,比如2.5 GB +,这会增加原生OutOfMemoryError的风险,具体取决于应用程序的占用空间,线程数量等。

理论4GB,但在实践中(对于IBM JVM):

Win 2k8 64,IBM Websphere Application Server 8.5.5 32bit

C:\IBM\WebSphere\AppServer\bin>managesdk.bat -listAvailable -verbose CWSDK1003I: Доступные SDK: CWSDK1005I: Имя SDK: 1.6_32 - com.ibm.websphere.sdk.version.1.6_32=1.6 - com.ibm.websphere.sdk.bits.1.6_32=32 - com.ibm.websphere.sdk.location.1.6_32=${WAS_INSTALL_ROOT}/java - com.ibm.websphere.sdk.platform.1.6_32=windows - com.ibm.websphere.sdk.architecture.1.6_32=x86_32 - com.ibm.websphere.sdk.nativeLibPath.1.6_32=${WAS_INSTALL_ROOT}/lib/native/win /x86_32/ CWSDK1001I: Задача managesdk выполнена успешно. C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2036 MaxMemory JVMJ9GC017E -Xmx слишком мала, должна быть не меньше 1 M байт JVMJ9VM015W Ошибка инициализации для библиотеки j9gc26(2): Не удалось инициализи ровать Could not create the Java virtual machine. C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2047M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 2146435072 (2047.0 MiB) Free Memory: 3064536 (2.9225692749023438 MiB) C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2048M MaxMemory JVMJ9VM015W Ошибка инициализации для библиотеки j9gc26(2): Не удалось создать эк земпляр кучи; запрошено 2G Could not create the Java virtual machine.

RHEL 6.4 64,IBM Websphere Application Server 8.5.5 32位

[bin]./java -Xmx3791M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 3975151616 (3791.0 MiB) Free Memory: 3232992 (3.083221435546875 MiB) [root@nagios1p bin]# ./java -Xmx3793M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 3977248768 (3793.0 MiB) Free Memory: 3232992 (3.083221435546875 MiB) [bin]# /opt/IBM/WebSphere/AppServer/bin/managesdk.sh -listAvailable -verbose CWSDK1003I: Available SDKs : CWSDK1005I: SDK name: 1.6_32 - com.ibm.websphere.sdk.version.1.6_32=1.6 - com.ibm.websphere.sdk.bits.1.6_32=32 - com.ibm.websphere.sdk.location.1.6_32=${WAS_INSTALL_ROOT}/java - com.ibm.websphere.sdk.platform.1.6_32=linux - com.ibm.websphere.sdk.architecture.1.6_32=x86_32 -com.ibm.websphere.sdk.nativeLibPath.1.6_32=${WAS_INSTALL_ROOT}/lib/native/linux/x86_32/ CWSDK1001I: Successfully performed the requested managesdk task.