一个 JVM 参数引发的频繁 CMS GC( 三 )

看第二次 CMS GC 日志 , 有以下四个发现:

  1. 由日志 “CMS-initial-mark: 899032K(3354624K)” 可知 , 其实第一次 CMS GC 是已经回收了 OldGen , 而且释放了大量空间 , OldGen 的使用占比只有 899032 / 3354624 = 26.8% , 很奇怪为什么会进行 CMS GC?
  2. 由日志 “2019-03-28T20:05:24.213+0800: 3644476.680: [GC (CMS Initial Mark)” 可知 , 第二次 CMS GC 开始的具体时间是 20:05:24.213 , 上次 CMS GC 结束时间 20:05:22.211 相差 2s 。
  3. 由日志 “[GC (CMS Final Remark) 3644477.934: [ParNew: 649871K->649871K(1887488K), 0.0000289 secs]” 可知 , 第二次 CMS GC 日志中包含一次 Young GC , 毫无疑问是因为配置了-XX:+CMSScavengeBeforeRemark 参数导致的 。
  4. Young GC 后 eden、from、to 三个 space 的使用量都不是 0 的情况依然存在 , 只是 eden space 由使用比率 13% 增加到 33% 。 很奇怪 , 此时通过日志 “concurrent mark-sweep generation total 3354624K, used 899032K” 可知 , OldGen 空闲空间很大 , 为什么 Young GC 好像没起作用 。
Heap after GC invocations=18479 (full 732): par new generationtotal 1887488K, used 649871K [0x0000000673400000, 0x00000006f3400000, 0x00000006f3400000) eden space 1677824K,33% used [0x0000000673400000, 0x0000000695e4cfa0, 0x00000006d9a80000) from space 209664K,39% used [0x00000006e6740000, 0x00000006eb796e60, 0x00000006f3400000) tospace 209664K,95% used [0x00000006d9a80000, 0x00000006e5efae68, 0x00000006e6740000) concurrent mark-sweep generation total 3354624K, used 899032K [0x00000006f3400000, 0x00000007c0000000, 0x00000007c0000000) Metaspaceused 90199K, capacity 91456K, committed 91776K, reserved 1130496Kclass spaceused 9512K, capacity 9798K, committed 9856K, reserved 1048576K}第三次-第 N 次 CMS GC 日志
2019-03-28T20:05:34.478+0800: 3644486.945: [GC (CMS Initial Mark) [1 CMS-initial-mark: 573449K(3354624K)] 1247191K(5242112K), 0.5737527 secs] [Times: user=0.79 sys=0.00, real=0.57 secs]2019-03-28T20:05:35.052+0800: 3644487.519: Total time for which application threads were stopped: 0.5762441 seconds, Stopping threads took: 0.0001088 seconds2019-03-28T20:05:35.052+0800: 3644487.520: [CMS-concurrent-mark-start]............看第三次-第 N 次 CMS GC 日志 , 有三个发现:
  1. 由日志 “CMS-initial-mark: 573449K(3354624K)” 可知 , OldGen 的使用占比只有 573449 / 3354624= 17.1% , 很奇怪为什么会进行 CMS GC?
  2. 由日志 “2019-03-28T20:05:34.478+0800: 3644486.945: [GC (CMS Initial Mark)” 可知 , 第三次 CMS GC 的开始时间 20:05:34.478 与 第二次 CMS GC 结束时间 20:05:32.476 又相差 2s 。
  3. 由于配置了 -XX:+CMSScavengeBeforeRemark 参数 , CMS GC 过程中依然包含一次 Young GC 。
  4. Young GC 后 eden、from、to 三个 space 的使用量都不是 0 的情况依然存在 , 只是 eden space 由使用比率增长 。很奇怪 , OldGen 空闲空间很大 , 为什么 Young GC 好像没起作用?
根源定位通过日志分析 ,, 大家很容易发现三个问题:
每次 CMS GC 都是相隔 2s?这其实是 CMS background collector 的策略 , 每隔 CMSWaitDuration(默认为2000ms) 时间进行一次检测 , 若发现满足 CMS GC 触发条件 , 就进行一次 CMS background collector 。
第二次及后面的 CMS GC , OldGen 的使用占比情况都没有达到 80% , 很疑惑是什么导致了 CMS GC?通过上面的分析 , 其实只要知道是什么满足了 CMS GC 触发条件而导致了 CMS GC , 就能回答第二个问题 。


推荐阅读