Minor GC、Major GC和Full GC

113 阅读3分钟

在GC期间,所有用户线程都将被挂起,发生STW。~~~在收垃圾的时候,总不希望别人继续扔垃圾吧

JVM在进行GC的时候,并非每次都对上面三个内存区域(新生代、老年代、方法区)一起回收的,大部分的时候回收都是在新生代

针对Hotspot VM的实现,它里面的GC按照回收区域又分为2种类型:一种是部分收集(Partial GC)一种是整堆收集(Full GC)

  1. 部分收集(Partial GC):不是完整的收集整个Java堆的垃圾收集,其中又分为

    • 新生代收集(Minor GC / Young GC):只是在新生代(Eden\S0,S1)的垃圾收集

    • 老年代收集(Major GC / Old GC):只是对老年代的垃圾收集

      目前只有垃圾回收器CMS GC 会有单独收集老年代的行为

  2. 混合收集(Mixed GC):收集整个新生代和部分老年代的垃圾收集

    • 目前 只有垃圾回收器G1 GC 会有这种行为
  3. 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集

注意:某些情况下,Major GC和Full GC被认为是等价【说是等价不如说是混淆,所以面试时,当面试官提到Major GC,可以问清楚具体是Old GC还是Full GC,我们这里就将Major GC按照Old GC来介绍】

可能触发Minor GC的情况

  • 年轻代空间不足

    当年轻代空间不足的时候,就会触发Minor GC,这里的年轻代满指的是Eden区满,而不是S0或者S1满Survivor满不会触发Minor GC (但是每次Minor GC 会清理年轻代的内存,包括 Eden/S0/S1)

可能触发Major GC的情况

这里我们就按照Major GC是Old GC的情况来说的

  • 老年代空间不足

    当应用程序运行一段时间后,存活的对象会从新生代(Young Generation)被晋升到老年代。如果老年代的可用空间不足以容纳新晋升的对象,那么就会触发 Major GC。

例外如下

Parallel Scavenge(-XX:+UseParallelGC)下,默认是在要触发Major GC前先执行一次Minor GC,并且两次GC之间能让应用程序稍微运行一小下,以期降低Major GC的暂停时间(因为Minor GC会尽量清理了Minor 年轻代的死对象,减少了Major GC的工作量)。控制这个行为的VM参数是-XX:+ScavengeBeforeFullGC

可能触发Full GC的情况

  • 老年代空间不足

    当应用程序长时间运行并创建大量存活时间较长的对象时,老年代可能会被占满。此时,JVM将进行Full GC,以清理无用的对象并为新的对象分配空间。

  • 方法区空间不足

    如果方法区空间不足,可能也会触发Full GC。例如,在Hotspot虚拟机中,如果永久代或Metaspace【这两个取决于JDK版本】空间不足,JVM可能会触发Full GC

  • 显式调用System.gc()

    如果在代码中显式调用System.gc(),默认情况下JVM会进行Full GC。但实际上并不建议这么做,最好是由JVM自行决定何时进行GC