64位OS上32位JVM的最大Java堆大小

Maximum Java heap size of a 32-bit JVM on a 64-bit OS

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

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

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


您可以询问Java Runtime:

1
2
3
4
5
6
7
8
9
10
11
12
13
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上)。我发现我的32位HotSpot JVM在Windows 7 Enterprise 64位上运行,最多可以分配1577MiB:

1
2
3
4
5
6
7
8
9
[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)

1
2
3
4
5
6
7
8
[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内部书籍对用户进程说2GB)
  • 对于32位BSD / Linux:<3GB(来自Devil Book)
  • 对于32位MacOS X:<4GB(来自Mac OS X内部手册)
  • 不确定32位Solaris,请尝试上面的代码并告知我们。

对于64位主机操作系统,如果JVM是32位,则它仍将依赖,最有可能像上面演示的那样。

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

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


期望只有一个大块内存并使用原始指针的32位JVM不能使用超过4 Gb(因为32位限制也适用于指针)。这包括Sun以及-我很确定-还包括IBM的实现。我不知道是否JRockit或其他产品在其32位实现中具有较大的内存选项。

如果您希望达到此极限,则应强烈考虑为您的生产环境启动一个并行轨道,以验证64位JVM,以便在32位环境崩溃时做好准备。否则,您将不得不在压力下进行这项工作,这绝非好事。

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

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)


您没有指定哪个操作系统。

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

我们将应用程序移植到Linux,并且我们在64位硬件上运行32位JVM,并且拥有一个非常容易运行的2.2GB VM。

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


从4.1.2堆大小调整:

"For a 32-bit process model, the maximum virtual address size of the
process is typically 4 GB, though some operating systems limit this to
2 GB or 3 GB. The maximum heap size is typically -Xmx3800m (1600m) for
2 GB limits), though the actual limitation is application dependent.
For 64-bit process models, the maximum is essentially unlimited."

在这里找到了一个很好的答案:Windows XP上的Java最大内存。


我们最近对此有了一些经验。我们最近已经从Solaris(x86-64版本5.10)移植到Linux(RedHat x86-64),并且意识到与Solaris相比,Linux上可用于32位JVM进程的内存更少。

对于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上启动。然后我们得到了支持的建议。

A 32 bit process on Linux has a
maximum addressable address space of
3gb (3072mb) whereas on Solaris it is
the full 4gb (4096mb).


在64位操作系统上的32位JVM的限制将与在32位OS上的32位JVM的限制完全相同。毕竟,32位JVM将在32位虚拟机(从虚拟化的角度来看)中运行,因此它不会知道它在64位OS /计算机上运行。

与32位OS相比,在64位OS和32位OS上运行32位JVM的一个优点是可以拥有更多的物理内存,因此交换/分页的频率降低。但是,只有在您具有多个流程时,才能真正完全实现此优势。


As to why a 32-bit JVM is used instead of a 64-bit one, the reason is not technical but rather administrative/bureaucratic ...

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

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

  • 该应用程序正在处理多个海量图像,
  • 该应用程序正在进行大量运算,
  • 该应用程序存在内存泄漏,客户是最主要的
    政府合同,他们不想花时间和时间
    跟踪内存泄漏的开销。 (使用大量内存
    堆会增加MTBF,并且素数仍会得到回报)

  • Oracle当前拥有的JROCKIT JVM支持不连续的堆使用,因此,当JVM在64位Windows OS上运行时,允许32位JVM访问超过3.8 GB的内存。 (在32位OS上运行时为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位环境下进行的一些测试

    Solaris 10-SPARC-T5220计算机,具有32 GB RAM(大约有9 GB可用空间)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    $ 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(约3 GB可用空间*)的VMWare VM

    3 GB的可用RAM并不是真的。 ZFS缓存使用了大量的RAM,但是我没有root访问权限来检查到底有多少

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    $ 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可用空间)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    $ 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的同一台机器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    $ 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。我想他们现在正在调整JVM的性能,以更好地处理巨型堆。

    很难确切知道您可以做的更好。我想您的32位情况可以通过实验轻松当然,要进行抽象预测是很困难的,因为要考虑很多因素,特别是因为32位主机上可用的虚拟空间非常有限。堆确实需要存在于连续的虚拟内存中,因此地址空间的碎片dll和OS内核对地址空间的内部使用将确定可能的分配范围。

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

    加载DLL取决于JVM的实现和版本。加载OS内核取决于很多事情,包括发行版,硬件以及自上次重启以来到目前为止已映射了多少东西,谁知道...

    综上所述

    我敢打赌,您在32位域中获得1-2 GB,在64位域中获得约3 GB,因此总体提高了约2倍。


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


    我遇到了与Android Investor for Android Blocks Editor使用的JVM同样的问题。它将堆最大设置为925m。这还不够,但是我不能将其设置为超过1200m,具体取决于机器上的各种随机因素。

    我从Firefox下载了Nightly,这是Beta 64位浏览器,也是JAVA 7 64位版本。

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

    我在具有24GB RAM的计算机上运行Win 7 64位Ultimate。


    这很麻烦,但是您可以获得3gb的堆。

    http://www.microsofttranslator.com/bv.aspx?from=&to=en&a=http://forall.ru-board.com/egor23/online/FAQ/Virtual_Memory/Limits_Virtual_Memory.html


    我曾尝试在32位Linux机器上将堆大小设置为2200M,并且JVM运行良好。当我将其设置为2300M时,JVM没有启动。


    这里是热点32位JVM的另一点:
    本机堆容量= 4 Gig – Java堆– PermGen;

    由于Java Heap和本机Heap处于竞争之中,因此对于32位JVM来说,它尤其棘手。的
    Java堆越大,本机堆越小。尝试为32位VM设置大型堆
    例如,根据您的应用程序占用量,.2.5 GB +会增加发生本机OutOfMemoryError的风险,
    线程数等


    理论上的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.