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

时间:2009-09-16 18:44:52

标签: java jvm

问题不在于32位操作系统上的最大堆大小,因为32位操作系统的最大可寻址内存大小为4GB,并且JVM的最大堆大小取决于连续的可用内存量是多少保留

我更感兴趣的是知道在64位操作系统中运行的32位JVM的最大(理论上和实际可实现的)堆大小。基本上,我正在寻找类似于the figures in a related question on SO的答案。

至于为什么使用32位JVM而不是64位JVM,原因不是技术,而是行政/官僚 - 在生产环境中安装64位JVM可能为时已晚。 / p>

17 个答案:

答案 0 :(得分:85)

您可以询问Java Runtime:

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)");
    }
}

这将根据默认堆分配报告“Max Memory”。因此,您仍然需要使用-Xmx(在 HotSpot 上)。我发现在Windows 7 Enterprise 64位上运行,我的 32位 HotSpot JVM最多可以分配1577MiB:

[C:scratch]> java -Xmx1600M MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
[C:scratch]> java -Xmx1590M MaxMemory
Total Memory: 2031616 (1.9375 MiB)
Max Memory:   1654456320 (1577.8125 MiB)
Free Memory:  1840872 (1.75559234619 MiB)
[C:scratch]>

在同一操作系统上使用 64位 JVM,当然它要高得多(约3TiB)

[C:scratch]> java -Xmx3560G MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
[C:scratch]> java -Xmx3550G MaxMemory
Total Memory: 94240768 (89.875 MiB)
Max Memory:   3388252028928 (3184151.84297 MiB)
Free Memory:  93747752 (89.4048233032 MiB)
[C:scratch]>

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

  • 对于32位Windows:它将<2GB(Windows internals book表示用户进程为2G​​B)
  • 对于32位BSD / Linux:&lt; 3GB(来自魔鬼书)
  • 对于32位MacOS X:&lt; 4GB(来自Mac OS X internals本书)
  • 不确定32位Solaris,请尝试上面的代码告诉我们。

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

- 更新20110905 :我只想指出其他一些意见/细节:

  • 我运行的硬件是64位,安装了6GB的实际RAM。操作系统是Windows 7 Enterprise,64位
  • 可分配的实际Runtime.MaxMemory数量还取决于操作系统的工作集。我曾经运行过这个,同时我也运行了VirtualBox,发现我可以使用-Xmx1590M成功启动HotSpot JVM并且必须变小。这也意味着你可能会获得超过1590M的时间,具体取决于你当时的工作集大小(尽管由于Windows的设计,我仍然保持32位以下2GiB)

答案 1 :(得分:65)

32位JVM预计会有一大块内存并使用原始指针,因此不能使用超过4 Gb(因为这是32位限制,也适用于指针)。这包括Sun和 - 我很确定 - 也是IBM的实现。我不知道是否例如JRockit或其他人拥有32位实现的大内存选项。

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


编辑2014-05-15:Oracle FAQ:

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

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

答案 2 :(得分:16)

您未指定哪个操作系统。

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

我们将应用程序移植到Linux上,我们在64位硬件上运行32位JVM,并且很容易运行2.2GB的虚拟机。

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

答案 3 :(得分:14)

来自4.1.2 Heap Sizing

  

“对于32位进程模型,最大虚拟地址大小   进程通常为4 GB,但某些操作系统将此限制为   2 GB或3 GB。最大堆大小通常为-Xmx3800m(1600m)   2 GB限制),但实际限制取决于应用程序。   对于64位过程模型,最大值基本上是无限制的。“

在这里找到了一个非常好的答案:Java maximum memory on Windows XP

答案 4 :(得分:12)

我们最近有过这方面的经验。我们最近从Solaris(x86-64版本5.10)移植到Linux(RedHat x86-64),并且已经意识到我们在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)。

答案 5 :(得分:9)

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

在64位操作系统上运行32位JVM与在32位操作系统上运行的一个优点是,您可以拥有更多的物理内存,因此会更频繁地遇到交换/分页。但是,当您有多个进程时,这个优势才能真正实现。

答案 6 :(得分:6)

  

至于为什么使用32位JVM而不是64位JVM,原因不是技术性的,而是行政/官僚......

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

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

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

答案 7 :(得分:4)

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

答案 8 :(得分:4)

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

Solaris 10 - SPARC - T5220计算机,具有32 GB RAM(并且大约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
BTW:显然Java并没有为启动分配太多的实际内存。每个实例似乎只需要大约100 MB(我开始10)

Solaris 10 - x86 - 具有8 GB RAM(大约3 GB可用*)的VMWare VM

3 GB的可用RAM并不是真的。 ZFS缓存使用了大量的RAM,但是我没有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 VM(使用大约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

答案 9 :(得分:3)

应该好多了

对于在64位主机上运行的32位JVM,我想象堆剩下的将是JVM之后可用的任何未分段的虚拟空间,它自己的DLL,以及任何OS 32位兼容性的东西已装载。作为一个疯狂的猜测,我认为3GB应该是可能的,但这要好多少取决于你在32位主机领域做得多好。

此外,即使您可以创建一个巨大的3GB堆,您可能也不想这样做,因为这会导致GC暂停变得潜在的麻烦。有些人只是运行更多的JVM来使用额外的内存而不是一个巨大的内存。我想他们正在调整JVM,以便更好地处理巨型堆。

要确切知道自己能做得多好,有点难。我想你的32位情况可以通过实验轻松确定。抽象地预测很难,因为很多因素都会影响它,特别是因为32位主机上可用的虚拟空间相当受限制。堆确实需要存在于连续的虚拟内存中,因此地址空间的碎片为操作系统内核对地址空间的dll和内部使用将决定可能的分配范围。

操作系统将使用一些地址空间来映射硬件设备,并使用它自己的动态分配。虽然此内存未映射到java进程地址空间,但OS内核无法同时访问它和您的地址空间,因此它将限制任何程序虚拟空间的大小。

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

总结

我敢打赌你在32位中获得1-2 GB,在64位中获得大约3 GB,因此总体上有大约 2x

答案 10 :(得分:2)

在Solaris上,自Solaris 2.5以来,限制大约为3.5 GB。 (大约10年前)

答案 11 :(得分:1)

我遇到了与App Inventor for Android Blocks Editor使用的JVM相同的问题。它将堆设置为最大925m。这还不够,但根据我机器上的各种随机因素,我无法设置超过1200米。

我从Firefox下载了Nightly,测试版64位浏览器,以及64位版本的JAVA 7.

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

我在一台24GB RAM的机器上运行Win 7 64位Ultimate。

答案 12 :(得分:0)

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

答案 13 :(得分:0)

答案 14 :(得分:0)

热点32位JVM还有一点: - 本机堆容量= 4 Gig - Java Heap - PermGen;

由于Java堆和本机堆正在竞争中,因此对于32位JVM来说尤其棘手。该 Java堆越大,本机堆越小。尝试为32位VM设置大堆 例如.2.5 GB +会增加原生OutOfMemoryError的风险,具体取决于您的应用程序占用空间, 线程数等。

答案 15 :(得分:0)

该限制还来自以下事实:对于32 bit VM,如果要所有heap4GB本身必须从地址0开始。

考虑一下,如果您想通过以下方式引用某些内容:

0000....0001

即:具有此特定位表示形式的引用,这意味着您正在尝试从堆访问第一个内存。为此,堆必须从地址零开始。但这永远不会发生,它从零开始偏移一些。

    | ....               .... {heap_start .... heap_end} ... |
 --> (this can't be referenced) <--

因为堆永远不会从OS中的地址零开始,所以32位引用中从来没有使用过很多位,因此可以引用的堆较低。

答案 16 :(得分:-1)

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

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

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.