为什么默认的Java最大堆大小是物理内存的1/4?

3

你链接的文档说明默认的最大堆大小为“物理内存的四分之一或1GB中较小的一个”。 - ernest_k
@RajThakur 我没有它的来源,但我听说过很多次,所以不是100%确定。 - talex
@talex 确实,我也没有找到任何有希望的信息。 - Raj Thakur
他们必须提供一些默认值,所以他们选择了“1/4”并进行了文档记录。为什么HashMap中的默认桶数是16或ArrayList中的默认桶数是10?同样的原因。 - Eugene
3
我记得曾经默认的堆大小是64MB,即使我们已经拥有多个GB的内存,这个设置仍然存在。新的默认设置的细节并不真正重要,任何东西都比那好... - Holger
显示剩余3条评论
1个回答

2
这可以追溯到JDK 5,它引入了JVM人体工程学。在此之前,JVM会为堆空间设置非常小的默认值。JDK 1.1的默认值为16Mb,JDK 1.2将其更改为默认情况下Xms为1Mb,Xmx为64Mb。在JDK 1.3中,Xms默认值增加到2Mb。
由于Java在服务器上越来越受欢迎,内存容量显着增加,Sun在JDK 5中引入了“服务器级”机器的概念。这是具有2个或多个物理处理器和2个或多个Gb内存的机器(如果我没记错,在JDK 5中,机器还不能运行Windows才算是服务器)。
在服务器级机器上,默认情况下设置以下参数:
  • 吞吐量垃圾收集器(即并行收集器)
  • 初始堆大小为物理内存的1/64,最高1Gbyte
  • 最大堆大小为物理内存的1/4,最高1Gbyte
  • 服务器运行时编译器
Ergonomics提供了两个命令行标志,允许用户为JVM设置性能目标;其想法是JVM通过修改其参数来内部计算如何实现此目标。最终目标是消除大量用于手动调整JVM性能的-XX标志。
这些参数包括:
-XX:MaxGCPauseMillis=nnn,它设置您希望GC在毫秒级别下的最大暂停时间。
-XX:GCTimeRatio=,它将垃圾收集时间与应用程序时间的比率设置为1 /(1 + nnn)。这被称为吞吐量目标。
您可以指定这些目标中的任意一个或两个。如果JVM成功实现这两个目标,则尝试减少正在使用的内存(占用空间目标)。
更多详细信息请参见此处:

https://www.oracle.com/technetwork/java/ergo5-140223.html


如果一个虚拟机运行一个Java Web服务器,它只能使用1/4的物理内存,有没有办法将-Xmx增加到1/2的物理内存? - sendreams
是的,您可以使用-Xms(初始大小)和-Xmx(最大大小标志)轻松更改用于堆的内存量。然而,并不建议使用超过机器物理内存的一半。 - Speakjava
一台机器有64GB内存,我已经更改了-xms=20g -xmx=30g,但最大堆大小始终为16g(使用jconsole连接到实例,它将显示最大堆大小参数),无法正常工作。 - sendreams
我刚试了一下,首先你需要-Xms20g -Xmx30g(不要加等号)。 使用jconsole,报告显示已分配的内存为20GB,但最大堆大小仅为28GB。如果我将mx增加到32g,则最大堆为30GB。我不知道为什么会显示这个。我不确定为什么你的系统没有显示正确的值。 - Speakjava

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