调整 JVM 堆大小后解释 jstat 输出
最近尝试增加堆空间和新旧代大小的比率,我看到 jstat -gccapacity
的结果令人困惑,它显示的容量比我预期的要小得多。
JVM (1.5.0_16) 使用 -server -Xms2048m -Xmx2048m -XX:NewRatio=2
启动。它在 Solaris 5.10 amd64 主机上运行。大约有 10GB 的可用内存。因此,根据我的阅读,JVM 应该能够充分利用 2GB 的堆空间。
通过观察jstat -gcutil
,我观察到所有代都多次填充,导致垃圾收集。例如:
Timestamp S0 S1 E O P YGC YGCT FGC FGCT GCT
66150.4 0.00 51.09 56.95 90.33 54.85 6291 58.922 7 22.826 81.748
我本以为这会导致 JVM 将所有代扩展到其完整大小。然而,jstat -gccapacity
产生:
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
700416.0 700416.0 86016.0 1408.0 1408.0 39104.0 1398784.0 1398784.0 1398784.0 1398784.0 16384.0 65536.0 38912.0 38912.0 6338 7
后续运行显示 NGC/S0C/S1C/EC 值的变化:
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
700416.0 700416.0 86016.0 1472.0 1472.0 39104.0 1398784.0 1398784.0 1398784.0 1398784.0 16384.0 65536.0 38912.0 38912.0 6380 7
700416.0 700416.0 106496.0 1792.0 1856.0 97024.0 1398784.0 1398784.0 1398784.0 1398784.0 16384.0 65536.0 38912.0 38912.0 6433 7
700416.0 700416.0 106496.0 1792.0 1792.0 96064.0 1398784.0 1398784.0 1398784.0 1398784.0 16384.0 65536.0 38912.0 38912.0 6436 7
据我了解,容量数字是发电的总大小,利用率数字显示内的分配一代人。因此,上面的结果告诉我,新代的最小和最大容量组合均为 (NGCMN/MGCMX) 684MB,而旧代的最小和最大容量为 1,366MB (OGCMN/OGCMX)。让我困惑的是新一代的能力。所以我的问题是:
- 为什么 EC + S0C + S1C == NGC 不? (41,920 != 86016)
- 为什么 NGC 明显小于 NGCMN/MGCMX?
- 这是因为达到了最大堆大小(NGC+OGC+PGC 的大小为 1,488MB),如果是这样,什么会导致下限?我能找到的所有文档都说 Solaris 64 位 JVM 应该能够使用 4GB。
- 如果达到最大堆大小,为什么新一代的容量会发生变化(全部增加或全部减少),而老一代则没有改变来补偿)。
其他可能有用的 jstat 结果:
$ jstat -gcnew 20167
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
1536.0 1600.0 1300.3 0.0 13 15 1600.0 82880.0 30892.6 6482 60.540
$ jstat -gcnewcapacity 20167
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
700416.0 700416.0 106496.0 1472.0 233472.0 233472.0 1408.0 700288.0 81088.0 6489 7
$ jstat -gcold 20167
PC PU OC OU YGC FGC FGCT GCT
38912.0 21426.5 1398784.0 1375651.6 6503 7 22.826 83.627
$ jstat -gcoldcapacity 20167
OGCMN OGCMX OGC OC YGC FGC FGCT GCT
1398784.0 1398784.0 1398784.0 1398784.0 6517 7 22.826 83.779
$ jstat -gcpermcapacity 20167
PGCMN PGCMX PGC PC YGC FGC FGCT GCT
16384.0 65536.0 38912.0 38912.0 6531 7 22.826 83.925
Having recently attempted to increase the heap space and ratio of new to old gen size I'm seeing confusing results from jstat -gccapacity
which is showing much smaller capacities than I would expect.
The JVM (1.5.0_16) is started with -server -Xms2048m -Xmx2048m -XX:NewRatio=2
. It's running on a Solaris 5.10 amd64 host. With about 10GB of free memory. So from what I've read the JVM should be able to make use of the full 2GB of heap space.
Watching jstat -gcutil
I've observed all of the generations filling up several times causing garbage collections. E.g.:
Timestamp S0 S1 E O P YGC YGCT FGC FGCT GCT
66150.4 0.00 51.09 56.95 90.33 54.85 6291 58.922 7 22.826 81.748
Which I would have thought would cause the JVM to expand all the generations to their full size. However, jstat -gccapacity
produces:
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
700416.0 700416.0 86016.0 1408.0 1408.0 39104.0 1398784.0 1398784.0 1398784.0 1398784.0 16384.0 65536.0 38912.0 38912.0 6338 7
Subsequent runs show NGC/S0C/S1C/EC change in value:
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
700416.0 700416.0 86016.0 1472.0 1472.0 39104.0 1398784.0 1398784.0 1398784.0 1398784.0 16384.0 65536.0 38912.0 38912.0 6380 7
700416.0 700416.0 106496.0 1792.0 1856.0 97024.0 1398784.0 1398784.0 1398784.0 1398784.0 16384.0 65536.0 38912.0 38912.0 6433 7
700416.0 700416.0 106496.0 1792.0 1792.0 96064.0 1398784.0 1398784.0 1398784.0 1398784.0 16384.0 65536.0 38912.0 38912.0 6436 7
From what I understand, the capacity figures are the total size of the generation and the utilisation figures show allocations within the generation. So the above result is telling me that the combined new gen min and max capacities are both (NGCMN/MGCMX) 684MB and the old gen min and max are 1,366MB (OGCMN/OGCMX). What's confusing me is the capacities of the new generations. So my questions:
- Why doesn't EC + S0C + S1C == NGC? (41,920 != 86016)
- Why is NGC significantly smaller than NGCMN/MGCMX?
- Is this because the max heap size is being hit (which would put it at 1,488MB, from NGC+OGC+PGC), if so what would cause the lower limit? All the documentation I can find says a Solaris 64 bit JVM should be able to use 4GB.
- If the max heap size is being hit why do the new generations change in capacity (either all increasing or all decreasing) without the older generation changing to compensate).
Other potentially useful jstat results:
$ jstat -gcnew 20167
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
1536.0 1600.0 1300.3 0.0 13 15 1600.0 82880.0 30892.6 6482 60.540
$ jstat -gcnewcapacity 20167
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
700416.0 700416.0 106496.0 1472.0 233472.0 233472.0 1408.0 700288.0 81088.0 6489 7
$ jstat -gcold 20167
PC PU OC OU YGC FGC FGCT GCT
38912.0 21426.5 1398784.0 1375651.6 6503 7 22.826 83.627
$ jstat -gcoldcapacity 20167
OGCMN OGCMX OGC OC YGC FGC FGCT GCT
1398784.0 1398784.0 1398784.0 1398784.0 6517 7 22.826 83.779
$ jstat -gcpermcapacity 20167
PGCMN PGCMX PGC PC YGC FGC FGCT GCT
16384.0 65536.0 38912.0 38912.0 6531 7 22.826 83.925
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
事实证明,这是吞吐量收集器的故意行为:
使用 5.0 Java[tm] 虚拟机调整垃圾收集 > 5.2.2.2 调整生成大小
观察 JVM 处于峰值负载时的 GC 容量确实显示组合的年轻代当前容量等于最小/最大容量值。
It turns out that this is intentional behaviour by the throughput collector:
Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine > 5.2.2.2 Adjusting Generation Sizes
Observing the GC capacities while the JVM is under peak load does show the combined young gen current capacities to be equal to the min/max capacity values.