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

Vin*_*lds 104 java jvm

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

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

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

mik*_*ike 88

你可以问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)");
    }
}
Run Code Online (Sandbox Code Playgroud)

这将根据默认堆分配报告"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内部书籍说用户进程为2G​​B)
  • 对于32位BSD/Linux:<3GB(来自魔鬼书)
  • 对于32位MacOS X:<4GB(来自Mac OS X internals book)
  • 不确定32位Solaris,请尝试上面的代码并告诉我们.

对于64位主机操作系统,如果JVM是32位,它仍将依赖,最有可能如上所示.

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

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

  • 我喜欢你实际测试而不是猜测. (12认同)
  • 很好地发现了TGP1994.我认为,因为我已经指定了'M'和'G'倍数,所以大小(以字节为单位)无论如何都将成为1024字节的倍数.例如,1590M将被解析为1590*(1024*1024)= 1667235840字节(1628160KiB - 当然是1024的偶数倍). (4认同)
  • @djangofan是对的.该程序应除以1,048,576(1024*1024,或2 ^ 20),而不是104,856.但是,这只是一个展示的东西.从命令中可以看出,他只尝试将最大堆大小设置为1,590 MiB. (3认同)
  • 按照我之前的评论:[jdocs](http://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html)(至少用于windows)指定-Xmx和 - Xms参数必须给出一个1024的倍数...我不确定1590是否,所以我认为应该预期奇怪的结果. (3认同)

Tho*_*sen 66

期望具有单个大块内存并使用原始指针的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)

  • 不,因为签名而不是2GB.但是,4GB地址空间的一部分是为OS内核保留的.在Windows的普通消费者版本上,限制为2GB.在Linux和服务器版本的Windows(32位)上,每个进程的限制为3GB. (12认同)
  • 指针没有签名 - 说到负内存位置是没有意义的. (9认同)
  • @Jesper我想知道在64位操作系统上运行的32位JVM是否可以提供完整的4 GB地址空间? (3认同)

For*_*ner 16

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

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

我们将应用程序移植到Linux上,我们在64位硬件上运行32位JVM,并且运行起来非常容易.

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


dja*_*fan 14

4.1.2堆大小:

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

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


chi*_*nto 12

我们最近有过这方面的经验.我们最近从Solaris(x86-64版本5.10)移植到Linux(RedHat x86-64)并且已经意识到我们在Linux上的可用内存比用于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上启动.然后我们被支持告知了这一点.

Linux上的32位进程的最大可寻址地址空间为3gb(3072mb),而在Solaris上则为4gb(4096mb).


Lau*_*ves 9

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

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

  • 不完全的.由于32位地址空间不必与操作系统或硬件接口共享,因此64位机器中的JVM有更多空间. (8认同)
  • LG:我不同意你的原始答案.操作系统内核以及它映射的任何硬件和总线地址空间都会占用大量的地址空间,虽然这没有映射到用户程序,但它确实减少了操作系统自行设置后"剩余"的数量.这是一个相当大的4GB 32位空间.传统上,这意味着大约25%-75%的4GB用户进程无法使用.:-)内核黑客 (2认同)

小智 6

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

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

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

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

.