如果说垃圾回收算法是内存回收的方法论,垃圾回收器就是内存回收的实践者。
世上不存在“万能”的垃圾回收器,只能选择具体引用所合适的垃圾回收器。
七款经典垃圾回收器 新生代收集器 :Serial、 ParNew、 Parallel Scavenge;
老年代收集器 : Serial Old 、Paraller Old、 CMS;
整堆收集器 :G1;
垃圾回收器间组合关系
Serial垃圾回收器
单线程工作的垃圾回收器,他在进行垃圾回收时,必须暂停所有后台的工作线程,知道他的垃圾回收完成,在后台自动完成的,用户不可知,不可控情况下。
他是新生代垃圾回收器,默认采用复制算法
Serial old垃圾回收器
在老年代也有对应的Serial old 同样也是采用串行回收,算法采用标记整理
主要用于与新生代Serial、ParNew、Parallel Scavenge配合使用,作为老年代CMS收集器的后备垃圾回收器使用
缺点:
把用户正在工作的线程停掉,对用户来说是不能接受的。
优点: 在单核处理器或者是处理器核心数较小环境来说,Serial没有线程交互,专心垃圾回收自然可以获得最高的单线程收集效率。
适用场景:
在桌面应用和部分微服务应用场景,分配给虚拟机管理的内存一般不会很大,收集几十兆或者一二百兆的新生代延迟可以控制在十几毫秒,只要不发生频繁收集这个停顿点用户还是可以接受。
配置命令: 使用-XX:+UseSerialGC 老年代自动 Serial Old GC
ParNew收集器
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收集器(吞吐量优先)
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垃圾回收器
关注服务器的响应速度,希望停顿时间较短,给用户带来良好的体验,并发收集、低停顿。
工作原理
初始标记: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.面向服务端的垃圾回收器,主要配合大容量
优点
分代收集:他不要求整个年轻代、老年代都是连续的,也不坚持大小和固定数量。
兼顾年轻代和老年代的垃圾回收
空间整合:采用标记复制算法,整体上也可以看做标记压缩,俩种算法都可以避免内存碎片,有利于程序长时间运行。
可限制停顿时间模型