JVM基础系列:垃圾回收的几种类型
在了解JVM的垃圾回收的过程中,经常会遇到这些术语,例如:Minor GC、Young GC、Old GC、Full GC、Stop-The-World等。这些GC的术语代表什么,之间的区别又是什么,通过这一篇希望可以加深印象。
Minor GC
从年轻代空间回收内存称为Minor GC,有时候也成为Young GC,对于minor gc,需要知道的一些点:
- 当JVM无法为一个新的对象分配空间时会触发Minor GC,比如当Eden区满了,所以Eden区越小,越频繁执行Minor GC。
- 当年轻代中Eden区分配满的时候,年轻代中的部分对象会晋升到老年代,所以Minor GC 后老年代占用量通常有所升高。
- 所有的minor gc 都会触发STW,停止用户线程,对于大部分应用来说,停顿导致的延迟可以忽略不计得,因为大部分Eden区的对象都会被认为是垃圾,不会被复制到Survivor区或者老年代空间,这样复制清除的时间就少了。
Major GC
从老年代空间回收内存被称为Major GC,有时候称之为Old GC。
许多Major GC 是由 Minor GC 触发的,所以很多情况下将这两种GC 分离是不太可能的。
分配对象内存时发现内存不够,触发Minor GC。Minor GC 会将对象转移到老年代中,如果此时老年代空间不够,那么触发Major GC。因此才会说,许多Major GC 是由 Minor GC 引起的。
Full GC
Full GC 是清理整个堆空间--包括年轻代、老年代和永久代或者说元空间(如果有的话)的全局范围的GC,Full GC 不等于 Major GC,也不等于 Minor GC + Major GC,发生Full GC 需要看是使用了什么样的垃圾回收器组合,才能解释是什么样的垃圾回收。
Major GC通常是跟full GC是等价的,收集整个GC堆。但因为HotSpot VM发展了这么多年,外界对各种名词的解读已经完全混乱了,当有人说“major GC”的时候一定要问清楚他想要指的是上面的full GC还是old gen。
Minor GC、Full GC触发时机
Minor GC 的触发和回收相对来说简单很多,年轻代采用的回收算法是复制算法,系统自动触发的机制只有一个就是Eden区没有足够的空间分配给新创建的对象。
PS:只有Eden区,对于Surivior区,是存放Minor GC后存活的对象,并不用于分配给新对象。
Full GC 触发条件复杂一点
- 老年代空间不足,例如:大对象不停的直接进入老年代,最终造成空间不足。
- 方法区空间不足。
- Minor GC 引发 Full GC,这个情况比较复杂,重点讲下。
引发条件主要是由于年轻代对象在经历Minor GC 过后,部分存活对象或全部存活对象会进入老年代,从而触发Full GC,其实是JVM老年代空间担保机制
在发生Minor GC 之前,JVM会检查老年代最大可用连续空间是否打于新生代所有对象的总空间,这是在1.6之前,之所有是所有对象,是因为计算全部对象总和,相对来说资源消耗小,而且快。
情况1:老年代剩余连续空间>新生代对象总空间>历次晋升到老年代的对象的平均大小,这样Minor GC可以确保安全,直接Minor GC。
情况2:历次晋升到老年代的对象的平均大小<老年代剩余连续空间<新生代对象总空间,这种需要分情况,主要是看是否设置了HandlePromotionFailure (是否允许担保失败)参数,JDK1.6之后该参数已废弃,但是这个机制仍在,执行Minor GC,
Minor gc之前,发现老年代的可用连续内存空间小于年轻代的全部对象,如果这个时候发生MinorGC,年轻代的全部对象有可能全部进入老年代,老年代空间不足会发生Full GC,因此JVM在Minor GC之前会先参考HandlePromotionFailure 是否设置值,如果设置了,那会继续检查老年代最大可用内存是否大于历次晋升到老年代对象的平均大小,如果大于,那就冒险尝试一次Minor GC,尽管这次Minor GC 是有风险;如果小于,或者没有设置HandlePromotionFailure 值,那就会直接Full GC (因为HotSpot的JVM,除了CMS的 并发回收之外,其他能收集老年的GC,都会同时收集整个堆,包括年轻代,所以不需要额外再执行一次Minor GC),下面这张图显示了HandlePromotionFailure 担保机制的流程:
Stop-The-World
Stop-The-World,中文一般翻译为全世界暂停,是指在进行垃圾回收时因为标记或清理的需要,必须让所有执行任务的线程停止执行任务,从而让垃圾回收线程回收垃圾的时间间隔。
在Stop-The-World这段时间里,所有非垃圾回收线程无法工作,都暂停下来。只有等到垃圾回收线程工作完成才可以继续工作。可以看出,Stop-The-World时间的长短将关系到应用程序的响应时间,因此在GC过程中,STW的时间是非常重要的一个指标。