我使用-Xms256m
and -Xmx256m
JVM options将初始和最大Java堆大小设置为256MB。 GC日志(使用-XX:+PrintHeapAtGC
)表明堆大小为251904K
(246MB),即smaller than the minimum heap size, -Xms256m
(请参阅最后一行日志)。但是,这是因为the stated heap size is the available heap size,不包括the unavailable from space。
当我从空间内存中手动包含不可用的时,派生的堆大小为262656K
(256.5MB),略大于大于最大堆大小{{ 1}} (512KB):
-Xmx
为什么堆大小略大于最大堆大小[heap size] = [eden space size] + [from space size] + [to space size] + [OldGen size]
262656K = 66048K + 10752K + 10752K + 175104K
?
答案 0 :(得分:5)
首先它看起来很奇怪,但像往常一样没有魔法。找到答案的唯一方法是深入探讨openjdk sources。只需结帐并尝试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
here的逻辑。
尝试自己找到关于-XX:SurvivorRatio
的相同逻辑:)