社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
阅读本文前需要了解的知识点:
特点: Serial收集器是最基本,发展例是最悠久的收集器。它是一个单线程收集器,即Serial收集器在工作时,必须暂停其他所有正在工作的线程,直到它的垃圾收集工作结束(即Stop The World)。Serial收集器到目前为止仍是虚拟机运行在Client模式下默认的垃圾收集器。下图为Serial/Serial Old收集器的运行过程。
优点: 简单高效。没有线程交互的开销,专注垃圾回收,可获得最高的单线程收集效率。
缺点: 收集工作进行时必须暂停其他所有正在工作的线程,会造成用户线程停顿。
适用场景: 运行在Client模式下的虚拟机(用户桌面)
特点:ParNew收集器相当于一个多线程版的Serial收集器,它除了能使用多线程进行垃圾回收,其余行为包括Serial收集器可用的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完全一样。
优点:可进行多线程收集,是除了Serial收集器之外唯一能与CMS收集器配合的新生代收集器。
缺点:ParNew收集器在单线程或CPU数量较少的情况下,由于存在线程交互的开销,效率并不能百分百保证完全超越Serial收集器。
适用场景:是运行在Server模式下的虚拟机的首选新生代收集器。
特点:Parallel Scavenge收集器也是一个新生代的、多线程的垃圾收集器,同样也是使用复制算法,特别之处在于它关注的重点目标是达到一个可控的吞吐量,因此又被称为“吞吐量优先收集器”。Parallel Scavenge 收集器可通过 -XX MaxPauseMills 和 -XX MaxTimeRadio两个参数来分别设置最大停顿时间和吞吐量。除此之外,Parallel Scavenge收集器还可以通过 -XX UseAdaptiveSizePolicy来开启收集器的自适应调节策略。
吞吐量:CPU用于运行用户代码的时间和CPU运行总消耗时间的比值,即吞吐量=运行用户代码的时间/(运行用户代码的时间+垃圾回收的时间),例如虚拟机总共运行了100分钟,其中一分钟用于垃圾回收,那么此时的吞吐量就是99%,高吞吐量可以高效率的利用CPU时间,使其尽快得完成运算任务,主要适合在后台运算而不需要太多交互的任务。
停顿时间:介绍 Serial 收集器的时候有提到过,回收器在进行垃圾回收都会或多或少的造成用户线程停顿,停顿的时间长度即为停顿时间。Parallel Scavenge收集器可设置停顿时间长短,但是要注意,这并不意味着会使系统的垃圾回收速度变得更快,它是以牺牲新生代的内存空间和吞吐量为代价的,由于内存空间缩小,新生代的垃圾回收就也变得更加频繁。就比如新生代原来是500M,每10秒进行一次垃圾回收,每次回收停顿100毫秒,设置MaxTimeMills 参数后,新生代变为300M,每5秒进行一次垃圾回收,每次回收停顿70毫秒,停顿时间的确是降低了,但是吞吐量也随之降低了。
自适应调节策略:不需要手动设定新生代大小(Xmm)、Eden区与Survivor区的比例(-XX SurvivorRatio)、晋升老年代对象年龄(-XX PretenureSizeThreshold)等细节参数,虚拟机会根据当前系统的运行情况收集性能监控信息,动态的调整这些参数以提供最大的吞吐量和最适合的停顿时间,自适应调节策略也是Parallel Scavenge收集器与ParNew收集器的一个重要区别。
特点: 和Serial收集器一样是单线程收集器,从名字就可以看出它是和Serial收集器配合使用的老年代收集器,它是基于“标记—整理”算法实现的。
优点: 高效
缺点: 单线程收集,用户停顿
适用场景: 主要给Client模式下的虚拟机使用。如果应用再Server段,则主要有两大用途:一是再JDK 1.5及其之前版本配合Parallel Scavenge收集器使用(因为Parallel Old收集器在JDK 1.6版本才出现),二是作为CMS收集器的后备预案,在Concurrent Mode Failure时使用(在CMS收集器讲解时会提到)。
特点: JDK 1.6版本才出现,多线程收集器,基于“标记整理”算法实现。未出现此收集器之前Parallel Scavenge收集器配合Serial Old收集器在服务端使用时无法充分利用服务器多CPU的处理能力,在老年代很大且硬件比较高级的情况下,Parallel Scavenge收集器配合Serial Old收集器这种组合甚至不一定有ParNew收集器加CMS收集器效率高。
适用场景: 配合Parallel Scavenge收集器使用,可用于注重吞吐量以及CPU资源敏感的场合。
特点: CMS收集器的主要目标是获取最短的回收停顿时间,它是基于“标记-清除”算法实现的。
它的运作主要分为以下 四个步骤:
优点: 停顿时间短,吞吐量大,并发收集
缺点:
(1)对CPU资源非常敏感。
虽然在并发阶段并不会导致用户线程停顿,但是因为垃圾回收线程占用了CPU资源从而会导致用户线程运行速度变慢,会使总的吞吐量降低。
(2)无法收集浮动垃圾。
在并发清除阶段,伴随着用户线程的进行,垃圾对象还会源源不断的产生,但由于这些垃圾对象产生在标记阶段之后,CMS无法在本次GC中收集它们,只能等到下一次GC再清除。
(3)容易产生大量内存碎片。
因为CMS回收器使用的是“标记—清除算法”,因此很容易产生大量的内存碎片。内存碎片过多,将会给大对象的内存分配带来麻烦,往往会出现老年代还有很大的空间剩余却因没有足够大的连续内存空间来分配对象而不得不提前触发一次Full GC。
说明: 在并发清除阶段,因为会有浮动垃圾的出现,因此CMS收集器的触发时机不会像其它老年代收集器一样到老年代几乎被填满以后才被触发,它必须给浮动垃圾预留空间。在JDK 1.5的默认设置下,CMS收集器在老年代使用了68%的内存空间时就会被激活,而到了JDK 1.6,CMS收集器的启动阈值已经达到92%,当然该参数可通过-XX CMSInitiatingOccupancyFraction的值来设置百分比,以达到更高的效率。当CMS收集器运行期间,预留空间的大小无法满足应用程序的需要时,就会出现一次“Concurren Mode Failure”失败,这时候虚拟机将启动后备预案:临时启用Serial Old收集器来进行老年代的垃圾回收,这样停顿时间就很长了。
适用场景: 互联网站或B/S系统的服务端(希望系统停顿时间短,响应速度快)
G1收集器是当今收集器技术发展的最前沿成果。它是一款面向服务器端的收集器,是为了取代CMS而设计的一款收集器。
特点:
G1收集器之所以能够建立可预测的停顿时间模型,就是因为它避免了在整个Java堆的全区域进行垃圾收集。G1跟踪每个Region中的垃圾堆积的价值大小(回收所获取空间的大小和回收所需要时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间(用户设定的收集时间)优先回收价值最大的Region区域。这种把Java堆划分区域以及具有优先级的区域回收方式,保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。
G1收集器的 运作步骤:
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!