JVM(Java Virtual Machine)经典垃圾回收器

124 阅读6分钟
如果说垃圾回收算法是内存回收的方法论,垃圾回收器就是内存回收的实践者。

世上不存在“万能”的垃圾回收器,只能选择具体引用所合适的垃圾回收器。

七款经典垃圾回收器 新生代收集器 :Serial、 ParNew、 Parallel Scavenge;

老年代收集器 : Serial Old 、Paraller Old、 CMS;

整堆收集器 :G1;

垃圾回收器间组合关系

image.png

Serial垃圾回收器

image.png

    单线程工作的垃圾回收器,他在进行垃圾回收时,必须暂停所有后台的工作线程,知道他的垃圾回收完成,在后台自动完成的,用户不可知,不可控情况下。
    他是新生代垃圾回收器,默认采用复制算法        

Serial old垃圾回收器

    在老年代也有对应的Serial old 同样也是采用串行回收,算法采用标记整理
    主要用于与新生代Serial、ParNew、Parallel Scavenge配合使用,作为老年代CMS收集器的后备垃圾回收器使用

缺点:

把用户正在工作的线程停掉,对用户来说是不能接受的。

优点: 在单核处理器或者是处理器核心数较小环境来说,Serial没有线程交互,专心垃圾回收自然可以获得最高的单线程收集效率。

适用场景:

    在桌面应用和部分微服务应用场景,分配给虚拟机管理的内存一般不会很大,收集几十兆或者一二百兆的新生代延迟可以控制在十几毫秒,只要不发生频繁收集这个停顿点用户还是可以接受。
    

配置命令: 使用-XX:+UseSerialGC 老年代自动 Serial Old GC

ParNew收集器

image.png

 1.ParNew收集器实质上是Serial收集器的多线程并行版本,除了并行回收外,其他和Serial 没有任何区别
2.新生代同样采用标记复制算法 同样也有 stop-the-word机制
3.是很多jvm运行在Service模式下的新生代默认垃圾回收器
4.老年代可以和Serial old,CMS配合使用
5.jdk8以后被移除

优点

对于新生代,回收次数频繁,实用并行比较高效
对于老年代,回收次数少,使用串行更节约资源

Serial和ParNew对比

在核心cpu环境下ParNew要比Serial更高效一些
在单核心cpu环境下Serial要比ParNew更高效一些

ParNew参数设置

-XX:+/-UseParNewGC -XX:ParallelGCThreads参数来限制垃圾收集的线程数

Parallel Scavenge收集器和Parallel Scavenge old收集器(吞吐量优先)

image.png

1.和ParNew一样都是回收新生代的,使用标记复制算法、并行回收、“Stop-the-word”性能差别不大。
2.Parallel Scavenge目标为达到可控制的吞吐量,吞吐量优先 。
3.自适应调节策略(根据垃圾回收情况,进行一个监控,动态调整内存分配)也是和ParNew的一个区别
4.Parallel Scavenge old主要采用标记压缩算法,同样也基于并行回收和“Stop-the-word”机制
5.Parallel old 收集器用来替代老年代的Serial Old收集器
6.jdk8默认搭配的垃圾收集器

应用场景:

  主要适合在后台运算不需要太多交互任务。因此常见的服务器中使用

Parallel Scavenge配置参数

  -XX:+/-UseParallelGC 指定年轻代Parallel
  -XX:+/-UseParallelGC 指定老年代Parallel
  -XX:ParallelGCThreads参数来限制垃圾收集的线程数
  -XX:MaxGCPauseMillis 设置垃圾回收最大停顿时间
  -XX:GCTimeRatio 垃圾回收时间占总时间比例
 

GMS垃圾回收器

关注服务器的响应速度,希望停顿时间较短,给用户带来良好的体验,并发收集、低停顿。

工作原理 image.png

  初始标记:stop-the-word  耗时很短 仅仅只是标记一下 GCRoots能直接关联到的对象,速度很快。
  
  并发标记:用户线程和垃圾回收线程共同执行 
  并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象图的过程,耗时较长不需要停顿用户线程,并发运行

  重新标记:stop-the-word  :检查是否有存活对象漏标记

  并发清理:并发执行 清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。
  

CMS特点

最耗时的并发标记和并发清理都不需要暂停工作,所以整体回收效率是低停顿的
垃圾回收过程中,还需要保证有足够线程可用空间,当堆内存到一定阈值后,便开始垃圾回收。
运行期间内存如果无法满足程序需要,会临时启动Serial old进行回收,这样停顿时间就更长一点。

CMS缺点

   采用标记清除算法,会产生内存碎片。
   在并发标记阶段如果产生垃圾cms将无法对这些对象进行标记,导致这些垃圾无法回收
   

问题

 为什么不用标记压缩算法:因为在并发清理阶段压缩整理是需要移动对象内存地址,这时候多个用户线程还再并发执行中。

设定参数

    -XX:+UseConcMarkSweepGC  指定垃圾回收器
    -XX:CMSInitiatingOccupancyFraction设定内存回收使用率的阀值
    -XX:+UseCMS-CompactAtFullCollection用于指定在FULLGC完成后堆内存进行压缩整理
    -XX:CMSFullGCsBefore-Compaction 执行多少次FullGC后对内存空间进行整理
    -XX:ParallelCMSThreads设置CMS线程数量。
    

G1垃圾回收器(全功能收集器)

所对应的业务越来越大,用户越来越多,没有垃圾回收就无法保证一个用户程序正产运行,经常造成stw跟不上实际需求。硬件水平的不断提升,也有助于垃圾回收提升性能。

特征

    1.全区域垃圾回收器
    2.并行回收器,把堆内存划分为好多个区域(Region)。使用不同的Region表示不同的区域,Eden 幸存区,老年代等。
    3。根据堆中垃圾价值大小(收集时间,空间大小),根据允许的收集时间,收集价值最大的区域。侧重点在于回收垃圾最大量的区间,垃圾优先。
    5.面向服务端的垃圾回收器,主要配合大容量
    

优点

 分代收集:他不要求整个年轻代、老年代都是连续的,也不坚持大小和固定数量。
 兼顾年轻代和老年代的垃圾回收
 空间整合:采用标记复制算法,整体上也可以看做标记压缩,俩种算法都可以避免内存碎片,有利于程序长时间运行。
 可限制停顿时间模型