Java堆空间与RAM

3

我在阅读一篇关于分析线程转储的文章后,有一个问题让我困扰。其中有一段提到,在32位JVM中逻辑最大堆大小为4GB。

这个链接指出,在32位Windows机器上,最大堆大小将约为1.4-1.6 GB。

我的问题是,假设我有大约8GB的RAM,如果我使用32位JVM,这是否意味着我只能利用其中的1.4-1.6 GB?64位JVM允许的最大大小是多少?

非常感谢您的帮助,因为我对此感到困惑。


1
32位机器的最大可寻址内存 = 2^32 = 4294967296 =~ 4 GB。您需要为操作系统、运行其他应用程序的页面等腾出空间。 - C.B.
1
是的,对于64位JVM来说,限制非常大,几乎可以视为无限(16 exbibytes)。 - Boris the Spider
可能重复的问题 https://dev59.com/Kmsz5IYBdhLWcg3wy689 。在某些系统上,约为1.5 GB的限制是真实存在的。对于64位的快速答案-大约是2^64,但操作系统可能会有限制。 - chro
4个回答

4
具体来说,针对Windows,原因是热点实现(Sun/Oracle JVM)和Windows DLL的结合。32位代码可以访问4GB虚拟地址空间(有扩展允许更多但我不会涉及)。在32位Windows上,这个虚拟地址空间的上2GB保留给操作系统使用(某些版本的操作系统接受/3GB标志作为引导参数,以允许3GB用户可访问空间)。此外,任何使用的库(*.dlls)都映射到该地址空间的部分。默认情况下,Windows基本*.dll文件在~1.6 GB标记处加载(根据操作系统版本和补丁级别略有不同)。最重要的是,Hotspot JVM仅支持分配单个连续的内存块用作堆空间。
所以,如果你试着在脑海中想象一下,你会发现你有一个自由空间约为2GB,而加载着大约1.6GB的“窗口”*.dlls。这就是该数字背后的逻辑。它还意味着即使你提供了/3GB标志,Sun/Oracle JVM也无法使用它。一些其他的VM更擅长处理碎片化堆-比如jrockit VM
你也可以尝试重新定位Windows dlls,使它们加载到更高的内存地址,并挤出更多可用的堆空间,但这个过程是脆弱的。
还要注意的是,很可能在特定机器上加载的驱动程序/应用程序(如反病毒软件)会将它们自己的*.dlls注入到Java进程中,而这些dlls可以加载到越来越低的内存地址,进一步缩小你可用的堆空间。
在64位的Windows版本中,可寻址限制为8-128TB,而物理限制目前为64TB。

非常感谢您提供如此详细的答案。感谢您抽出时间给我提供全面的回答。 - dinukadev
我给你点赞,这是一个非常好的答案。思路清晰,写得很好。 - duffymo

2

32位系统最大可以寻址4GB内存,即2的32次方。但由于还需要为操作系统腾出空间,因此在32位机器上JVM只能获得1.4-1.6GB内存。

64位系统最大可以寻址2的64次方大小的内存,即(2的32次方)的平方。可以看到,这是一个非常大的数字。


谢谢你的回答。非常有帮助。 - dinukadev

1
JVM和操作系统都使用分页内存管理系统,在32位操作系统中为我们获取4G虚拟内存。但是,如果您有8G的RAM,则必须使用64位版本的操作系统以获得最大的操作系统性能。

感谢您抽出时间回答。您的回答很有帮助。 - dinukadev

1
这取决于您的操作系统,32位版本的MacOS X和Linux有一定能力访问内核中超过4GB的空间,但仍限制进程为4GB。其他操作系统可能会更进一步限制进程内存,因为它们需要部分4GB用于自身。通常情况下,您希望避免将JVM交换到VM中,因此您需要了解系统有多少可用内存。

1
@dunukadev 请参考http://apple.stackexchange.com/questions/2498/why-can-mac-os-x-32-bit-access-all-4gb-of-memory-while-windows-32-bit-cant,了解更详细的MacOS X复杂的32位与64位模式解释。 - Michael Shopsin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接