2015-02-08 207 views
2

我使用-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 unavailablefrom space堆大小大于-Xmx

当我手动包括从空间存储器不可用的,派生堆大小是262656K(256.5MB),这是比最大堆大小略微越大,-Xmx(由512KB):

[heap size] = [eden space size] + [from space size] + [to space size] + [OldGen size] 
    262656K =  66048K  +  10752K  +  10752K  + 175104K 

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

回答

5

首先它似乎很奇怪,但像往常一样没有魔法。找出答案的唯一方法是更深入:到openjdk sources。只是结帐,并尝试grep:grep -r "Xmx" .

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

让我们来看看arguments.cpp:只有简单的参数解析,对于-Xmx256M这将是类似result = 256 * 1024 * 1024(与我一些内联)。所以我们的问题没有答案。

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

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

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

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

如果您对细节感兴趣,可以在方法scale_by_NewRatio_aligned中找到四舍五入-XX:NewRatiohere的逻辑。 尝试自己找到关于-XX:SurvivorRatio的相同逻辑:)