JVM(四)HotSpot虚拟机垃圾回收器

HotSpot虚拟机垃圾回收器


HotSpot虚拟机提供有多种垃圾收集器,这些收集器大多适用于不同的分代内存中,并可以互相配合其他收集器使用。G1是目前最新最先进的垃圾收集器,在新生代和老年代都适用。

新生代垃圾收集器

Serial 收集器

serial收集器是HotSpot虚拟机client模式下默认的新生代收集器。采用复制算法,单线程,在执行垃圾收集任务时会中断用户代码的执行,可以和CMS、Serial Old两种老年代收集器配合使用。

ParNew 收集器

ParNew收集器可以看做是serial收集器的多线程版本,在进行垃圾收集时采用多线程任务,但同样需要暂停用户程序,适用于作为运行在server模式下的虚拟机的新生代收集器。

由于使用多线程垃圾收集,线程较多时,线程间的切换,线程创建与销毁同样需要消耗较大的CPU资源,因此应当使用-XX:ParallelGCThreads 参数来限制垃圾收集器的线程数,以达到最佳的性能。

Parallel Scavenge 收集器

Parallel Scavenge收集器也是一个采用复制算法的多线程新生代垃圾收集器,其与ParNew收集器的不同之处在于,前者的关注点在于达到一个可控的吞吐量,而其他收集器的关注点在于尽可能得缩短垃圾收集时的用户线程等待时间。

吞吐量即CPU用于运行用户代码的时间与总的CPU时间的比值,吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间)。

有三个参数和吞吐量相关:

  1. -XX:MaxGCPauseMilis
    此参数设置一个大于0的毫秒数值,收集器尽可能保证在此时间内完成垃圾收集。如果此值设置较大,用于垃圾收集时间可能会很长;如果设置过小,则垃圾收集发生就会变得频繁。所以要适当设置,以达到一个较高的吞吐量。
  2. -XX:GCTimeRatio
    这个参数值是一个大于0小于99的整数,表示垃圾收集收件占总的时间的比率,公式为:GC时间占比 = 1 / (1 + N)NGCTimeRatio 的值。
  3. -XX:UseAdaptiveSizePolicy
    这是一个开关参数,打开后JVM会根据当前系统的运行情况收集性能监控数据,动态调整相关参数以提供最合适的停顿时间或者最大吞吐量。

老年代垃圾收集器

Serial Old 收集器

Serial Old是Serial收集器的老年代版本, 用于Clicent 模式下,使用“标记-整理”算法。其一种用途是作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用。

Parallel Old 收集器

顾名思义,此收集器是 parallel scavenge 的老年代版本,使用多线程和“标记-整理”算法。

CMS 收集器

CMS(concurrent mark sweep) 收集器是一种以获取最短回收停顿时间为目标的收集器,采用“标记-清除”算法,收集过程分为四个阶段:

  1. 初始标记
    标记一下GC Root能直接关联到的对象。需要中断用户进程。
  2. 并发标记
    标记需要清理的对象,比较耗时,能与用户进程并发
  3. 重新标记
    标记在“并发标记”阶段因用户进程发生变化的对象。
  4. 并发清除
    清除标记的对象,比较耗时,能与用户进程并发

CMS收集器的缺点:

  1. 对CPU资源敏感。
    CMS默认的启动回收线程数为(CPU数量+3)/ 4 。当CPU数量在4以上时,CMS使用的CPU不少于 1/4 ;但是当CPU数量小于4时,CMS所占的CPU资源就比较多。
  2. 无法处理浮动垃圾
    浮动垃圾即出现在CMS标记过程中的垃圾,本次GC无法回收只能等到下次GC时再清理掉。因此CMS不能在老年代内存快满时才进行GC,否则没有足够的空间存放浮动垃圾,从而出现 Concurrent Mode Failure,在此时虚拟机将启动后备预案,使用 Serial Old 收集器进行老年代垃圾收集。而这样的话停顿时间就会变长。因此需要通过 -XX:CMSInitiatingOccupancyFranction 参数设置适当的CMS收集器启动阈值,当空间使用达到此阈值时启动CMS收集。
  3. 空间碎片
    由于CMS收集器采用“标记-清除”算法,不可避免的会产生空间碎片问题,因此CMS收集器提供了两个参数解决此问题:

    a. -XX:UseCMSCompactAtFullCollection 
        此参数用来在CMS收集器即将进行 Full GC 时进行内存碎片整理过程
    b. -XX:CMSFullGCsBeforeCompaction
        此参数设置在n次不压缩的Full GC后,来一次带压缩的Full GC

G1 收集器

G1是目前Sun公司最先进最新的收集器,其面向服务端,既可以用于新生代也可以用于老年代,其有下面几个特点:

  • 并行与并发
  • 分代收集
  • 空间整合
  • 可预测的停顿

G1收集器中仍然后分代概念,但是其实现和其他的收集器不同。G1将整个JAVA堆划分为多个大小相等的独立区域(Region),新生代和老年代都是一部分region的集合。

G1跟踪每个region的回收价值,并维护一个优先列表,每次GC时优先回收价值最大的region。

G1中每个region都有一个 remember set ,G1通过将引用类型数据的引用信息记录在其所在region的remember set中,避免了在内存回收时的全堆扫描并不会有遗漏。

G1运作分为以下步骤:

  1. 初始标记
  2. 并发标记
  3. 最终标记
  4. 筛选回收

其四个步骤作用于CMS收集器类似,区别在于除了并发标记外,其余三个G1步骤都需要停顿用户线程(实际上回收阶段可以与用户进程并发)。

猜你喜欢

转载自blog.csdn.net/wy11933/article/details/80209962