在GC期间,所有用户线程都将被挂起,发生STW
。~~~在收垃圾的时候,总不希望别人继续扔垃圾吧
JVM在进行GC的时候,并非每次都对上面三个内存区域(新生代、老年代、方法区)一起回收的,大部分的时候回收都是在新生代
针对Hotspot VM的实现,它里面的GC按照回收区域又分为2种类型:一种是部分收集(Partial GC)一种是整堆收集(Full GC)
-
部分收集(Partial GC):不是完整的收集整个Java堆的垃圾收集,其中又分为
-
新生代收集(Minor GC / Young GC):只是在新生代(Eden\S0,S1)的垃圾收集
-
老年代收集(Major GC / Old GC):只是对老年代的垃圾收集
目前只有垃圾回收器
CMS GC
会有单独收集老年代的行为
-
-
混合收集(Mixed GC):收集整个新生代和部分老年代的垃圾收集
- 目前 只有垃圾回收器
G1 GC
会有这种行为
- 目前 只有垃圾回收器
-
整堆收集(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