FullGC

1. FullGC 是什么?

Full GC(Full Garbage Collection,全垃圾收集)是 Java 虚拟机(JVM)执行的一种垃圾收集过程,它会对整个堆内存进行垃圾收集,包括年轻代(Young Generation)和老年代(Old Generation),以及永久代(PermGen)或元空间(Metaspace)。

  • Minor GC:仅针对年轻代(Eden 和 Survivor 空间)进行垃圾收集。
  • Major GC:主要针对老年代进行垃圾收集,有时也被称为 Old GC。
  • Full GC:针对整个堆内存(包括年轻代、老年代和元空间)进行垃圾收集。

由于 Full GC 对应用性能影响较大,通常建议在调优 JVM 性能时,尽量减少 Full GC 的发生频率,通过适当的参数调整和垃圾收集器的选择来优化内存管理。

2. 触发条件

1. 调用System.gc()方法

  • 此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full GC的频率
  • 调优建议:能不使用此方法就别使用,让虚拟机自己去管理它的内存

2. 方法区空间不足

  • 方法区存放的为一些class的信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,方法区可能会被占满,从而执行Full GC。
  • 元空间的初始阈值设置太小,垃圾收集器调整元空间的大小需要Full GC。比如初始值是21M,full gc后,释放了20M,只剩1M,那么垃圾收集器就会将该值调成2M;相反,如果释放了1M,还剩20M,下次就会调整到40M,这个过程会多次触发full GC.
  • 一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大。
  • 调优建议:对于8G物理内存的机器来说,一般我会将这两个值都设置为256M。常见的问题:项目jar包只有1G,但是启动了好久,就可能是因为由于元空间设置的太小,一直在触发full GC。

3. Minor GC 之后仍然没有足够的空间容纳新的对象时。

4. 元空间(Metaspace)达到指定的最大值时。

3. 老年代空间不足

对象转入老年代的场景有:

  • 大对象直接进入老年代:为了避免为大对象GC时,多次在survivor上来回复制而降低效率。

    • 调优建议:
      • 尽量避免写大对象,
      • 结合你自己系统看下有没有什么大对象 生成,预估下大对象的大小,设置XX:PretenureSizeThreshold的值,一般来说设置为1M就差不多了,很少有超过1M的大对象,这些对象一般就是你系统初始 化分配的缓存对象,比如大的缓存List,Map之类的对象。
  • 长期存活的对象进入老年代:默认是经历了15次minor GC ,CMS是6次。

    • 调优建议:
      • 调整Eden和survivor的比例,默认时8:1:1,避免Eden区域过小,导致频繁minor GC,增大系统消耗
      • 如果我们可以确定大多数对象都是很快会被回收的,可以将该值调小,比如大多数对象都是3次左右就可以被回收,我们可以设置成5,如果超过了5,就说明剩下的应该是一些类似java bean 这种,会长期存活的对象,我们就没必要,让他再待在survivor占用空间了,提前让他们进入老年代。
  • 对象动态年龄判断:survivor区域里,对象年龄从小到大排序,当累加到某个年龄时,占用 survivor区域 的50%,就会把这个年龄大的对象都晋升到老年代。 如果系统中朝生夕死的对象比较多,

    • 调优建议:
      • 如果系统中朝生夕死的对象比较多,可以考虑将年轻代参数调大一些,这样对应survivor区域就会对应变大,减少对象因为触发了这个机制,进入到老年代,从而触发Full GC。一般情况,新生代默认是堆大小的1/3
      • 避免Survivor设置过小,导致对象从 eden 直接到达老年代,从而触发Full GC
  • 老年代空间分配担保机制。

    在发生 Minor GC 之前,虚拟机先检查老年代最大可用的连续空间是否大于新生代所有对象总空间。

    • 大于 -> minor GC
    • 小于 ->查看是否开启了空间担保机制
      • 没开启就直接触发full GC,
      • 开启了,就会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次 Minor GC;如果小于,会触发full gc。

3. 优化和调整

过于频繁的 Full GC 可能会导致性能问题,因此需要通过调整堆内存的大小、垃圾收集器的选择以及其他 JVM 参数(如 -XX:MaxMetaspaceSize-Xms-Xmx 等)来优化和减少 Full GC 的发生频率。


FullGC
http://example.com/FullGC/
作者
Panyurou
发布于
2024年6月13日
许可协议