一次完整的GC流程

  1. 首先,任何新对象都分配到 eden 空间。两个幸存者空间开始时都是空的。
  2. 当 eden 空间填满时,将触发一个Minor GC(年轻代的垃圾回收,也称为Young GC),删除所有未引用的对象,大对象(需要大量连续内存空间的Java对象,如那种很长的字符串)直接进入老年代。
  3. 所有被引用的对象作为存活对象,将复制到第一个幸存者空间S0,并标记年龄为1,即经历过一次Minor GC。之后每经过一次Minor GC,年龄+1。GC分代年龄存储在对象头的Mark Word里。
  4. 当 eden 空间再次被填满时,会执行第二次Minor GC,将Eden和S0区中所有垃圾对象清除,并将存活对象复制到S1并年龄加1,此时S0变为空。
  5. 如此反复在S0和S1之间切换几次之后,还存活的年龄等于15的对象(JDK8默认15,JDK9默认7,-XX:InitialTenuringThreshold=7)在下一次Minor GC时将放到老年代中。
  6. 如果老年代内存不足够存储新对象,则会执行Full GC(清空整个新生代和老年代)。
  7. 当老年代满了时会触发Full

FullGC触发条件

  1. 调用System.gc():调用 System.gc() (用于请求 JVM 执行垃圾回收)时,JVM 会建议执行 Full GC(具体是否执行取决于垃圾回收器实现的System.gc()逻辑,例如Parallel GC、CMS等传统垃圾回收器该方法会Full GC,而G1、ZGC等现代回收器不会Full GC)。
  2. 空间分配担保失败:当对象从新生代晋升到老年代前,要检查老年代是否有足够空间容纳新对象,这叫做空间分配担保。如果空间不足,则空间分配担保失败,JVM会执行Full GC。
  3. 老年代满了:当老年代满了时会触发Full GC或者Major GC(老年代的垃圾回收,清理整个老年代空间)。具体是Full GC还是Major GC取决于用哪个垃圾回收器,传统垃圾回收器会Full GC,G1(优先使用Mixed GC,清空部分新生代和老年代)、ZGC(直接抛出内存溢出错误)等现代回收器会避免Full GC。
  4. 方法区满了:当方法区(Method Area)空间不足时,会触发Full GC
  5. 元空间不足时会进行扩容,当扩容到-xx:metaSpacesize参数指定值也会触发FullGC

youngGC(Minor GC):

对新生代垃圾回收。新建对象一般放在新生代的Eden区进行分配,如果Eden区没有足够的空间就会触发youngGC。youngGC出发频率很频繁,回收速度也很快

FullGC:

回收整个新生代、老年代、永久代无用对象。FullGC较YoungGC stw时间更长至少10倍以上。

 

Major GC/Old GC

老年代会在两种情况下触发 Old GC:一是开启分配担保机制,在Minor GC前,根据历次 Minor GC 后进入老年代的对象大于当前老年代内存大小,判断 Minor GC 有风险,则会触发 Old GC;二是 Minor GC 后剩余对象太多,老年代放不下了也会触发 Old GC。

posted on 2023-06-23 17:41  colorfulworld  阅读(97)  评论(0)    收藏  举报