这是我在企业软件开发生涯中多次遇到的问题。 我不得不每隔一段时间就提供有关配置特定新环境的建议。
而且,很多时候,手头的问题与“我应该使用32位或64位JVM”有关。 老实说,一开始我只是掷硬币。 而不是给出合理的答案。 (对不起,兄弟!)但是到目前为止,我已经对此进行了更多的了解,并希望与您分享。 第一站–越多越好。 对? 所以–当64> 32时,这很容易 答:如果可能,请始终选择64位? 好吧,抱着你的马。 64位体系结构的缺点是相同的数据结构会消耗更多的内存。 多很多。 我们的测量表明,根据JVM版本和操作系统版本以及硬件体系结构,最终使用的堆比32位多使用30-50%。 较大的堆还可能导致较长的GC暂停,从而影响应用程序延迟-在4.5GB的堆上运行完整的GC肯定比在3GB的堆上花费更长的时间。 因此,仅仅因为64比32大就跳到64位潮流上是不正确的。
但是……您什么时候才想要使用64位JVM? 在大多数情况下,原因是堆大。 在不同的体系结构上,您很快就会遇到32位体系结构上最大堆大小的限制。 下面说明了不同平台上的这些限制:
操作系统 | 最大堆 | 笔记 |
---|---|---|
的Linux | 2GB | 在特定的内核上有3GB的空间,例如hugemem |
视窗 | 1.5GB | 带有“ / 3GB”启动标志和通过/ LARGEADDRESSAWARE开关编译的JRE的最大3GB) |
Mac OS X | 3.8GB | 警报-找不到古老的Mac,因此未经我测试 |
现在怎么这么糟? 毕竟,我敢打赌,您已经看到32位计算机在16G + RAM上运行并且运行良好。 JVM在Windows上分配的内存不足此16G的10%怎么了?
主要原因–地址空间。 理论上,在32位系统中,每个进程最多可以分配4GB的内存。 在Windows上打破这一点的是如何处理进程地址空间。 Windows将进程地址空间减少一半。 其中一半保留给内核(用户进程无法使用),另一半保留给用户。 盒子中有多少RAM无关紧要,一个32位进程只能使用2GB RAM。 更糟糕的是,该地址空间必须是连续的,因此在实践中,Windows机顶盒通常只剩下1.5-1.8GB的堆空间。
您可以使用32位窗口来减少内核空间并增加用户空间,这是一个技巧。 您可以在boot.ini中使用/ 3GB参数。 但是,要实际利用此机会,必须使用/ LARGEADDRESSAWARE开关来编译/链接JVM。
不幸的是,至少对于Hotspot JVM并非如此。 直到最新的JDK 1.7版本,才使用此选项编译JVM。 如果您在2006年后版本的jRockit上运行,则更加幸运。 在这种情况下,您可以享受高达2.8-2.9GB的堆大小。
那么–我们可以得出结论,如果您的应用程序需要超过2-3GB的内存,那么您应该始终在64位上运行吗? 也许。 但是您也必须意识到这些威胁。 我们已经介绍了罪魁祸首–增加了堆消耗,并延长了GC暂停时间。 让我们在这里分析原因。
问题1:在64位上需要30-50%的更多堆
为什么这样? 主要是由于64位体系结构中的内存布局。 首先–在64位JVM上,对象标头是12个字节。 其次,对象引用可以是4个字节,也可以是8个字节,具体取决于JVM标志和堆的大小。 与32位标头上的8个字节和引用标本上的4个字节相比,这无疑增加了一些开销。 您还可以深入研究我们的较早文章之一,以获取有关计算对象的内存消耗的更多信息。
问题2:较长的垃圾收集暂停时间
建立更多的堆意味着GC在清除未使用的对象时还有更多工作要做。 在现实生活中,这意味着在构建大于12-16GB的堆时,您必须格外小心。 无需进行微调和测量,您就可以轻松引入几分钟的完整GC暂停时间。 在延迟不是很关键并且您可以优化吞吐量的应用程序中,这可能没问题,但是在大多数情况下,这可能会成为热门。
那么,当我需要更大的堆并且不希望引入由64位体系结构引起的开销时,该怎么办? 在我们较早的博客文章中 ,我们介绍了几种技巧–您可以通过堆分区,GC调整,在不同的JVM上构建或在堆外分配内存来摆脱困境。
最后,让我们重申一下,您应该始终了解选择64位JVM的后果。 但不要害怕此选项。
参考: 应该使用32位还是64位JVM? 从我们的JCG合作伙伴 Vladimir Sor在Plumbr Blog博客上获得。
翻译自: https://www.javacodegeeks.com/2012/12/should-i-use-a-32-or-a-64-bit-jvm.html