堆大小大于-Xmx

Don*_*ero 2 java memory heap garbage-collection jvm

我使用-Xms256m-Xmx256mJVM选项将初始和最大Java堆大小设置为256MB .GC日志(使用-XX:+PrintHeapAtGC)表明堆大小为251904K(246MB),小于最小堆大小-Xms256m(参见最后一行日志).然而,这是因为所陈述的堆大小是可用的堆大小,不包括不可用 的空间.

当我手动包含空间内存中的不可用时,派生的堆大小为262656K(256.5MB),略大于最大堆大小-Xmx(512KB):

[heap size] = [eden space size] + [from space size] + [to space size] + [OldGen size]
  262656K   =       66048K      +       10752K      +     10752K      + 175104K
Run Code Online (Sandbox Code Playgroud)

为什么堆大小略大于最大堆大小-Xmx

qww*_*sad 5

首先它看起来很奇怪,但像往常一样没有魔力.找到答案的唯一方法是深入探讨openjdk来源.只是结帐并尝试grep:grep -r "Xmx" .

会有很多测试,但它们对我们来说并不感兴趣.两个文件可以帮助我们:/vm/runtime/arguments.cpp和/vm/memory/collectorPolicy.cpp

让我们来看看arguments.cpp:只有简单的参数解析,例如-Xmx256M它会像result = 256 * 1024 * 1024(我的一些内联).所以我们的问题没有答案.

但变量MaxHeapSize在这里初始化,所以我们可以尝试找到它.实际用法MaxHeapSize可以在我们的/vm/memory/collectorPolicy.cpp中找到(其中Xmx仅在注释中使用),其中所有堆生成大小都是由某些策略选择的.

如果我们跳过所有细节,我们会发现堆中的所有区域都应该对齐,区域的大小取决于比率参数.

生成比率的默认JVM参数是-XX:NewRatio=2(年轻的比率:旧的基因大小)和-XX:SurvivorRatio=8(伊甸园:幸存者的比率).但是堆大小并不总是被3,9或其他东西整除,所以应该有一些舍入.而且,正如我之前提到的,总会有一些对齐.

最后,答案是:这些尺寸是满足世代比率和对齐条件的唯一可能尺寸.这些值的总和等于Xmx参数值并不总是可能的.

如果您有兴趣的细节,你可以找到逻辑舍入-XX:NewRatio 这里的方法scale_by_NewRatio_aligned.试着找到关于-XX:SurvivorRatio你自己的相同逻辑:)