垃圾收集器(上)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_31156277/article/details/79951819

垃圾收集器(上)

描述: java虚拟机规范并未对垃圾收集器的具体实现做规范,所以不同厂商、不同版本虚拟机实现不一致;但一般都会提供参数能够进行垃圾回收器之间的组合。


前言

注: 基于JDK1.7Update14之后的HotSpot虚拟机
HotSpot虚拟机的垃圾收集器
新生代收集器:Serial、ParNew、Parallel Scavenge;

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

G1 收集器

上图展示了7种收集器,白色区域为新生代收集器,灰色区域为老年代收集器。如果两个收集器之间存在连线,就说明它们可以搭配使用。

任何虚拟机都需要集合具体环境、场景等进行合理选择,只有最合适的


1. Serial收集器

Serial收集器是一个新生代收集器单线程收集器,使用复制算法单线程,指不仅仅只会使用一个CPU或者一条收集线程去完成垃圾收集,更重要的是它在进行垃圾收集时,必须暂停其他所有线程的工作

如图展示: 在安全点需要暂停所有用户线程,(Stop The World

Serial收集器是虚拟机运行在Client模式下的默认新生代收集器。其优点:简单而高效(与其他收集器的单线程比),对于限定单个CPU的环境来说,Serial收集器减少了线程交互的开销。 所以运行在Client模式下的虚拟机来说是一个不错的选择。

总结:

描述项 具体细节
特点描述 针对新生代,复制算法、单线程收集,进行垃圾收集时,必须暂停所有工作线程,直到完成(Stop the world)
应用场景 虚拟机运行在Client模式下的默认新生代收集器
优点 简单高效(与其他收集器的单线程相比)
缺点 JVM在后台自动发起和自动完成的,把用户正常的工作线程全部停掉,即GC停顿 会带给用户不良的体验

2. ParNew 收集器

ParNew收集器其实就是serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为与Serial收集器一样;实现上,也共用了相当多的代码。
 ParNew 收集器

虽然与Serial收集器只是在收集垃圾时采用多线程外,没有其他太多的变化。但是它确实许多运行在Service模式下虚拟机中首选的新生代收集器,其中一个与性能无关的原因就是除了Serial收集器外,目前只有ParNew收集器能与CMS收集器配合工作。

ParNew 收集器也是使用 -XX:+UseConcMarkSeepGC选项后的默认新生代收集器,也可以使用-XX:UseParNewGC选项来强制指定;

默认开启的垃圾收集器线程数就是CPU数量,可通过-XX:parallelGCThreads参数来限制收集器线程数

Serial收集器 VS ParNew收集器:
单CPU,ParNew 不会比Serial收集效果更好,但是随着CPU的数量增加。ParNew则在GC时对系统资源有效利用更好

参数小节:

"-XX:+UseConcMarkSweepGC":指定使用CMS后,会默认使用ParNew作为新生代收集器;

"-XX:+UseParNewGC":强制指定使用ParNew;    

"-XX:ParallelGCThreads":指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相同;

总结:

描述项 具体细节
特点描述 除了垃圾收集采用多线程外,其余的行为、特点和Serial收集器一样
应用场景 在Server模式下,ParNew收集器是一个非常重要的收集器,因为除Serial外,目前只有它能与CMS收集器配合工作
优点 随着CPU数量增加,在GC时对资源利用更好

3. Parallel Scavenge收集器

Parallel Old收集器
Parallel Scavenge收集器也是一个新生代收集器,它也是使用复制算法的收集器,又是并行多线程收集器。parallel Scavenge收集器的特点是它的关注点与其他收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而parallel Scavenge收集器的目标则是达到一个可控制的吞吐量吞吐量= 程序运行时间/(程序运行时间 + 垃圾收集时间),虚拟机总共运行了100分钟。其中垃圾收集花掉1分钟,那吞吐量就是99%。

短停顿时间适合和用户交互的程序,良好的响应速度能提升用户体验。高吞吐量适合高效利用CPU,主要用于后台运算不需要太多交互

参数介绍:
Parallel Scavenge收集器提供两个参数用于精确控制吞吐量; 一个GC自适应参数:

参数 描述
-XX:MaxGCPauseMillis 控制最大垃圾收集停顿时间,是一个大于0的毫秒数
-XX:GCTimeRatio 设置垃圾收集时间占总时间的比率,0
-XX:UseAdaptiveSizePolicy 当这个参数打开之后,就不需要手工指定新生代的大小、Eden与Survivor区的比例、晋升老年代对象年龄等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种调节方式称为GC自适应的调节策略(GC Ergonomics)

  • MaxGCPauseMillis 允许的值是一个大于 0 的毫秒数,收集器将尽可能保证回收花费的时间不超过这个设定值,
    但是并不是将这个值设置的稍小一点,就能使系统的垃圾回收速度变的更快,
    原因是GC停顿时间缩短是以牺牲吞吐量和新生代空间来换取的。
    MaxGCPauseMillis 参数设置小,系统吧新生代调小,虽然收集一次时间变短,但是也会导致垃圾收集发生更加频繁。
  • 选项-XX:GCTimeRatio=19,设置了垃圾收集时间占总时间的5%–1/(1+19)
  • UseAdaptiveSizePolicy 可以做为Paralle Scavenge 与 ParNew的区别

总结:

描述项 具体细节
特点描述 也称为吞吐量收集器(Throughput Collector),新生代收集器;采用复制算法;多线程收集
应用场景 高吞吐量为目标,即减少垃圾收集时间,让用户代码获得更长的运行时间;
当应用程序运行在具有多个CPU上,对暂停时间没有特别高的要求时,即程序主要在后台进行计算,而不需要与用户进行太多交互
GC自适应的调节策略 JVM会根据当前系统运行情况收集性能监控信息,动态调整这些参数,以提供最合适的停顿时间或最大的吞吐量

4. Serial Old 收集器

Serial Old是 Serial收集器的老年代版本

描述项 具体细节
特点描述 Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法
应用场景 Serial Old收集器的主要意义也是在于给Client模式下的虚拟机使用

两大用途:

  • 一种用途是在JDK 1.5以及之前的版本中与Parallel Scavenge收集器搭配使用
  • 另一种用途就是作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用

5. Parallel Old收集器


Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程“标记-整理”算法。
JDK 1.6才开始提供的

Parallel Old收集器

由于之前有一个Parallel Scavenge新生代收集器,,但是却无老年代收集器与之完美结合,只能采用Serial Old老年代收集器,但是由于Serial Old收集器在服务端应用性能上低下(无法充分利用多CPU资源),其吞吐量反而不一定有PreNew+CMS组合给力

直到Parallel Old(1.6)收集器出现后,“吞吐量优先”收集器终于有了比较名副其实的应用组合。

应用场景:注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器

设置参数: “-XX:+UseParallelOldGC”:指定使用Parallel Old收集器;

总结:

描述项 具体细节
特点描述 是Parallel Scavenge收集器的老年代版本,它同样是一个多线程收集器,使用标记-整理算法
应用场景 注重吞吐量以及CPU资源敏感的场景,用Parallel ScavengeParallel Old组合

后记:

  • 介绍了三种新生代收集器,都采用复制算法(Copying);两个老年代,都采用标记整理(Mark-Compact)
  • CMS 和 G1 再单独一节重点讲解。

参考:

  1. 《深入理解java虚拟机》–周志明
  2. Java虚拟机垃圾回收(三) 7种垃圾收集器:主要特点 应用场景 设置参数 基本运行原理
  3. HotSpot垃圾收集器
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页