为什么部分oldGen是在小gc之后收集的?

时间:2015-01-26 03:30:30

标签: java garbage-collection

这是我的GC选项:

 -Xms64G -Xmx64G -XX:NewSize=18G -XX:MaxNewSize=24G -XX:SurvivorRatio=4 -XX:PermSize=128M -XX:MaxPermSize=128M -XX:CMSFullGCsBeforeCompaction=1 -XX:MaxDirectMemorySize=512M -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=80 

和日志:

109.127: [GC109.127: [ParNew: 20971520K->4194304K(20971520K), 0.9867550 secs] 32497068K->16761687K(62914560K), 0.9868580 secs] [Times: user=17.50 sys=0.33, real=0.99 secs]
114.982: [GC114.982: [ParNew: 20971520K->4194304K(20971520K), 1.0146370 secs] 33538903K->17802909K(62914560K), 1.0147240 secs] [Times: user=17.14 sys=0.32, real=1.01 secs]
120.811: [GC120.811: [ParNew: 20971520K->4194304K(20971520K), 1.0029230 secs] 34580125K->18848154K(62914560K), 1.0030200 secs] [Times: user=17.08 sys=0.31, real=1.00 secs]

为什么ParNew之后会减少oldGen的使用? ParNew只用于年轻的Gen?

我的jvm是Java HotSpot(TM)64位服务器VM(版本24.60-b09,混合模式)

1 个答案:

答案 0 :(得分:1)

  

是ParNew仅用于年轻的Gen?

你是对的:ParNew只收集youngGen对象。

  

为什么在ParNew之后会减少oldGen的使用?

事实并非如此。

内部括号外的数字用于总堆(年轻+旧版)

[GC109.127: [ParNew: YoungGenBefore->YoungGenAfter(TotalYoungGen), 0.9867550 secs] TotalHeapBefore->TotalHeapAfter(TotalHeap), 0.9868580 secs] [Times: user=17.50 sys=0.33, real=0.99 secs]

实际上有些对象在你的场景中从youngGen移动到oldGen,这意味着oldGen实际上正在增长(乍一看看起来有点棘手)。

让我们以第一行为例:

109.127: [GC109.127: [ParNew: 20971520K->4194304K(20971520K), 0.9867550 secs] 32497068K->16761687K(62914560K), 0.9868580 secs] [Times: user=17.50 sys=0.33, real=0.99 secs]

我们看到20971520K-4194304K = 16777216K字节已从youngGen中删除。 从总使用的堆中删除这个字节数,我们得到32497068K-16777216K = 15719852K。

但是我们可以看到我们在总堆中还剩下16761687K,这比我们计算的15719852K还多。

这意味着由于ParNew GC,16761687K-15719852K = 1041835K从youngGen移动到oldGen,因此仍然存在于总堆内存中。

<强>参考文献:

以下是我的计算的一个很好的解释:link

以下是关于ParNew和oldGen和youngGen的一些简单解释:link