垃圾回收器

垃圾回收器

1.串行回收器

串行回收器是指使用单线程进行垃圾回收的回收器,每次回收只有一个线程,专注性和独占性有更好的性能表现,可以在新生代和老年代使用,所以可以分为新生代串行回收器和老年代串行回收器

1.1新生代串行回收器

特点:

单线程进行垃圾回收,独占式的垃圾回收。新生代串行回收器采用复制算法,实现简单,处理高兴,没有线程切换开销。在某些场景下超越并行回收器和并发回收器(比如单cpu等)

当串行回收器进行垃圾回收,java中的所有线程都会暂停,所以实时性要求高的应用场景,不能被接收

使用-XX:+UseSerialGC可以指定新生代串行回收器或者老年代串行回收器,当虚拟机在Client模式下,默认的垃圾回收器

1.2老年代串行回收器

特点:

老年代串行回收器使用的标记压缩算法,也是一个串行独占的垃圾回收器,由于老年代垃圾回收时间一般比新生代要长,所以停顿时间也可以比较长

-XX:+UseSerialGC:新生代和老年代都使用串行回收器

-XX:+UseParNewGC:新生代使用ParNew回收器,老年代都使用串行回收器

-XX:+UseParallelGC:新生代使用Parallel回收器,老年代都使用串行回收器

2.并行回收器

并行回收器在串行基础上做了改进,使用多个线程同时进行垃圾回收,对于并行能力较强的计算,可以有效缩短垃圾回收所需的实际时间

2.1新生代ParNew回收器

ParNew回收器是用于新生代垃圾回收,它只是简单地将串行回收器多线程化,回收策略,算法和参数和新生代串行回收器一样。ParNew也是一个独占式的回收器,所以应用程序会全部暂停,但是在并发能力较强的机器上,回收时间要短于串行回收器

-XX:+UseConcMarkSweepGC:新生代使用ParNew回收器,老年代使用CMS

-XX:ParallelGCThreads:ParNew回收器线程数量。

2.2新生代ParallelGC回收器

从表面上看和ParNew回收器一样,使用复制算法,多线程和独占式的收集器。它有一个很重要的特点就是关注系统的吞吐量。有两个重要的参数:

-XX:MaxGCPauseMills:设置最大垃圾回收的停顿时间

-XX:GCTimeRatio: 设置吞吐量的大小,默认值是99,就是1%(1/(1+99))的时间用于垃圾收集

-XX:UseAdaptiveSizePolicy 是一种自适应的GC调节策略,在这种模式下,新生代的大小,end和survivior的比例,晋升老年代的对象年龄参数都会自动调整已达到堆大小,吞吐量和停顿之间的平衡点。

注意:-XX:MaxGCPauseMills和-XX:GCTimeRatio是两个互相矛盾的参数。

2.3老年代ParallelOldGC回收器

老年代ParallelOldGC回收器也是多线程并发的收集器,关注吞吐量的一个回收器。用的是比较压缩算法,其余参数和ParallelGC回收器类似,一个用于新生代一个用于老年代。

3.CMS回收器

CMS是Concurrent Mark Sweep的缩写,意思是并发标记清除,它使用的标记清除算法,同时又是一个多线程并行回收的垃圾回收器。

回收步骤

  1. 初始标记:独占资源,标记跟对象
  2. 并发标记:标记所有对象
  3. 预清理:清理准备以及控制停顿时间
  4. 重新标记:独占资源,修正并发标记对象
  5. 并发清理:清理垃圾
  6. 并发重置

根据标记清除算法:初始标记,并发标记和重新标记都是标记清除的对象。并发清理则是正式回收垃圾对象,并发重置是在垃圾回收完成后,重新初始化cms数据结构和数据

主要参数

-XX:+UseConcMarkSweepGC 启用cms垃圾回收器

-XX:ConcMarkThreads 并发线程数

-XX:+CMSInitiatingOccupancyFraction 内存空间使用阈值,默认68%,达到阈值时会进行垃圾回收

-XX:+UseFullGCsBeforeCompaction:回收多少次后,进行内存压缩

-XX:+UseCMSCompactAtFullCollection 使CMS垃圾回收之后进行内存碎片整理,注意内存碎片整理不是并发的

4.G1回收器

G1回收器是从jdk7开始正式使用的回收器,回收还是分年轻代和老年代。但是它使用分区算法,其特点如下:

并行性: 垃圾回收期间,可以多个GC线程同时进行

并发性:程序和GC交替进行,所以不会完全阻塞程序

分代GC:G1依然是一个分代回收器,兼顾年轻代和老年代。

空间整理:在回收过程中会进行适当的空间移动,有效的复制对象,减少空间碎片

可预见性:由于分区的原因,可以选择部分区域进行回收,所以全局停顿可以得到很好的控制

注意:并行:程序会停顿,多线程同时进行,并发:程序和回收交替进行。

G1的回收过程可能有4个阶段:

新生代GC,并发标记周期,混合收集,可能会进行full GC

1.新生代GC

新生代GC是主要工作是回收eden区和survivor区,一旦eden区被占满,新生代GC就会启动。新生代GC只处理eden区和survivor区,回收之后所有eden区都应该被清空,survivor区清除一部分。还有一个变化就是年老代会增多

2.并发标记周期

并发标记周期可以分为以下步骤:

初始标记:标记从根节点可以直接到达的对象,它伴随着一次新生代GC,会产生停顿,应用程序在这个线程中会停顿

根区域扫描:这个可以跟应用程序一起运行

并发标记:查找整个堆的存活对象,并做好标记

重新标记:并发过程中程序依然进行,结果可能需要修正,重新标记,对上次结果进行补充,为了加快标记速度,会创建一个快照。

独占清理:这个阶段会引起停顿,它计算各个区域存活对象和GC回收比例进行排序,识别可供回收的区域。会标记可以混合回收区域,混合回收阶段会需要这些信息

并发清理阶段:识别并清理完全空闲区域,并发清理,不会引起停顿

3.混合回收:

在并发标记周期中会回收一部分对象,但是总体来说还是比例相当低。在并发标记周期中已经知道哪些可以区域可以混合回收,这个阶段就是对这些区域进行回收。会优先回收垃圾比例比较高的区域因为这些区域性价比比较高。它会回收年轻大和老年代区域。

4.必要时full GC

并发收集和应用程序交替运行,这样就不能避免在特别繁忙的场合出现回收过程中内存不足情况。当遇到这种情况G1就会进行full GC