0%

gc_when

最近又陷入到了 jvm 这个深渊中,大多数地方都只是说了说 gc 的算法以及内存的结构等等,倒是很少看到关于何时进行 GC 有详细的说明,又说eden区不够分配新对象就minor gc ,old gen 不够分配新对象就full gc。也有说这个东西是无法预测的。

不过根据 RednaxelaFX 的知乎回答,大概理解了一些。

GC 的分类其实是这样:

  • Partial GC:并不收集整个GC堆的模式

    • Young GC:只收集young gen的GC

    • Old GC:只收集old gen的GC。只有CMS的concurrent collection是这个模式

    • Mixed GC:收集整个young gen以及部分old gen的GC。只有G1有这个模式

  • Full GC:收集整个堆,包括young gen、old gen、perm gen(如果存在的话)等所有部分的模式。

Major GC通常是跟full GC是等价的,收集整个GC堆。但因为HotSpot VM发展了这么多年,外界对各种名词的解读已经完全混乱了,当有人说“major GC”的时候一定要问清楚他想要指的是上面的full GC还是old GC。

关于GC的时机是这样触发:

  • young gc :也就是常说的 minor gc,会在 young gen 的 eden 区满了触发,也就是剩余空间不足以加载新对象时
  • full gc :
    • serial GC:
      1. 在 serial GC 实现中,在触发一次 young gc 之前,会根据历史GC统计数据,计算之前平均每次 young gc 晋升到 old gen 的对象大小,当 old gen 剩余空间比这个平均值小时,会进行一次 full gc 。(此时会取消这次 young gc,因为除了 CMS 的并发GC,大多数的 full gc 包含了对 young gen 以及其他的堆空间的 gc。)
      2. 在 perm gen 没有足够空间时
      3. 执行 System.gc()时,根据资料这个命令是建议JVM执行GC,而不是一定会执行。
      4. heap dump带GC。
    • Parallel Scavenge 框架下,执行full GC 之前会触发一次 young GC,以让程序在两次GC之间可以运行一下下,减少 full GC 的暂停时间,减少了 full GC的工作量。
    • 并发GC:以CMS为例子,定时检查 old gen 的使用量,超过了一定比例就进行一次 CMS GC。可以根据-XX:CMSInitiatingOccupancyFraction 设置比例,以及设置-XX:+UseCMSInitiatingOccupancyOnly设置仅超过比例GC,不然可能会在低于这个比例时也进行GC。