1.垃圾回收器的分类
处理范围划分:
新生代垃圾回收器:serial、parNew、parallel scavenge;
老年代垃圾回收器:serial Old、parallel Old、CMS;
整堆收集器:G1、ZGC;
2.Serial GC
Serial是单线程的串行垃圾回收器,主要采用标记-复制算法 进行垃圾回收。
单线程地好处就是减少上下文切换,减少系统资源的于但这种方式的缺点也很明显,在GC的过程中,必须暂停其他所有的工作线程,直至Serial收集器收集结束为止(Stop The World)。若GC不是频繁发生,这种方法会很不错,否则会影响程序的执行性能。
3.serial old
Serial Old是Serial的老年代版本,也是个单线程收集器,适用于老年代,使用的是标记-整理算法优缺点基本和Serial差不多,二者主要是回收算法不一样。
4.parNew
ParNew其实就是Serial的多线程版本,在参数、回收算法上,和Serial是完全一样的,所以他也是采用标记-复制算法 进行垃圾回收的。
ParNew在垃圾回收的时候,同样会STW,但是因为它是多线程并行进行垃圾回收的,所以通常情况下时间会比Serial短一些。
5.Parallel Scavenge
Parallel Scavenge 也是一个新生代的垃圾回收器,和ParNew一样,他也是多线程并行执行的,同样采用的也是 标记-复制算法。与ParNew最大的不同是,Parallel Scavenge 关注的是垃圾回收的吞吐量(吞吐量=代码运行时间/(代码运行时间+垃圾收集时间),以吞吐量优先。
因为Parallel Scavenge收集器的高吞吐量可以最高效率的利用CPU时间,尽快的完成程序的运算任务等,所以他主要适合在后台运算,比如一些定时任务的执行。
6.Parallel Old
Parallel是Parallel Scavenge的老年代版本,同样是一个关注吞吐量的并行垃圾收集器,他采用的是标记-整理算法算法进行垃圾回收的。
7.CMS
CMS,Concurrent Mark Sweep,同样是老年代的收集器。他也是一个并发执行的垃圾收集器,他和Parallel最大的区别是他更加关注垃圾回收的停顿时间,通过他的名字Concurrent Mark Sweep就可以知道,他采用的是耗时更短的标记-清除算法。
2)并发标记:从初始标记阶段标记的对象出发,遍历整个对象图,标记所有可达的对象。在此阶段,GC线程与应用线程同时运行,不需要STW。
3)预清理:这一阶段也是并发执行的,目的是在实际清理前,处理并发标记阶段结束后和重新标记阶段开始前这段时间内发生的变化。目的是减少重新标记阶段的工作量。
4)重新标记:这一阶段是为了修正并发标记期间因应用线程继续运行而产生的更改。这是另一个需要STW的阶段。
5)并发清理:在此阶段,GC线程清除不可达的对象,并回收它们占用的内存空间。这个阶段与应用线程并发执行,不需要STW。
缺点:
1)无法处理浮动垃圾,在最后一步并发清除过程中,用户线程执行也会产生垃圾,但这部分垃圾是在标记之后,所以只能等到下一次gc的时候清理掉。
2)cms使用的标记清除算法,会产生大量的垃圾碎片
8.G1
G1,Garbage First,是CMS的改进版,解决了CMS内存碎片、更多的内存空间等问题。总之,G1是一个先进的垃圾收集器,它可以提高系统的吞吐量,降低停顿的频率,并且可以有效管理大型堆。在JDK9之后,G1成为了默认的垃圾回收器。它开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。
G1开创的基于Region的堆内存布局是它能够实现这个目标的关键。虽然G1也仍是遵循分代收集理论设计的,但其堆内存的布局与其他收集器有非常明显的差异:G1不再坚持固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。收集器能够对扮演不同角色的Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获取很好的收集效果。