扫码关注微信公众号

回复“面试手册”,获取本站PDF版

回复“简历”,获取高质量简历模板

回复“加群”,加入程序员交流群

回复“电子书”,获取程序员类电子书

当前位置: Java > JVM高频面试题 > 19.垃圾收集器

垃圾回收算法是内存回收的方法论,垃圾收集器则是内存回收的具体实现。Java规范中并没有对垃圾收集器的实现有任何规范,所以不用的厂商、不同的版本的虚拟机提供的垃圾收集器是不同的,这里主要讨论的是HotSpot虚拟机所包含的虚拟机,按照年代划分如下:

垃圾收集器
垃圾收集器

其中新生代收集器有Serial、ParNew、Parallel,老年代收集器有CMS、Serial Old、Parallel Ol,G1则既可以在新生代收集,又能在老年代收集。两个垃圾收集器之间如果存在连线,则说明它们可以搭配使用。

那哪个收集器的性能最好呢,其实这里并不存在最好的收集器,只有在对应场景中最合适的垃圾收集器

Serial收集器

Serial收集器是最基本的收集器,并且是单线程的收集器,这里的单线程不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,在它进行垃圾收集时,必须暂停其他所有的线程工作,直到它收集结束。不难想象,这对很多应用来说都是难以接受的,如下图

 Serial收集器
Serial收集器

除了上面写到的缺点,Serial收集器也有着优于其他收集器的地方,简单而高效(与其他收集器的单线程相比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾回收自然可以获得最高的单线程的收集效率。

ParNew收集器

ParNew收集器是Serial收集器的多线程版本,除了使用多条线程进行垃圾回收外,其他地方与Serial一样,从下图中也可以看出,除了多了几个GC线程,和Serial收集器并没有什么区别

ParNew收集器
ParNew收集器

Parallel Scavenge收集器

Parallel Scavenge 是一个使用标记-复制算法的多线程收集器,看起来和ParNew很像,Parallel Scavenge收集器的关注点和与其他收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间(用户体验),而Parallel Scavenge收集器的关注点是达到一个可控制的吞吐量(提高CPU的效率),这里的吞吐量指的是CPU用于运行代码的时间和CPU总消耗时间的比值。

那更短的停顿时间和更高的吞吐量有什么好处呢?

停顿时间越短越适合需要与用户交互的程序,良好的响应速度可以提升用户体验。更高的吞吐量适合在后台运算而不需要太多交互的程序,高吞吐量可以提高CPU的利用率,尽快地完成程序的运算任务。

Serial Old收集器

Serial Old是Serial收集器的老年代版本,同样是单线程收集器,采用标记-整理算法,主要有两大用途:一是在JDK1.5以及之前的版本中与Parallel Scavenge收集器搭配使用,二是作为CMS收集器的后备预案。

Parallel Old收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,采用多线程和标记-整理算法。该收集器是在JDK1.6才开始提供的,因为当新生代选择了Parallel Scavenge收集器,老年代只能选择Serial Old(Parallel Scavenge无法与CMS搭配使用),这时Serial Old收集器会影响整体的吞吐量,所以提供了Parallel Old收集器和Parallel Scavenge搭配使用

CMS收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,采用标记-清除算法,其运作过程可以分为初始标记并发标记重新标记并发清除四个步骤。

  • 初始标记:暂停其他线程,标记GC Roots能直接关联的对象,速度很快
  • 并发标记:同时开启GC线程和用户线程,跟踪记录发生引用更新的地方
  • 重新标记:修正并发标记期间因用户线程继续运作而导致标记产生变动的那一部分对象的标记记录
  • 并发清除:GC线程对未标记的区域进行清除

上述四个步骤中,初始标记和重新标记两个步骤会“Stop The Word”,也就是会暂停用户线程,如下图

CMS收集器

这里解释下在垃圾收集器的语境中,并行和并发的概念:

  • 并行:指多条垃圾收集器线程并行工作,此时用户线程仍处于等待状态
  • 并发:指用户线程与垃圾收集线程同时执行(也可以交替执行)

CMS的优点是并发收集停顿时间短,缺点主要有以下三个:

  • CMS收集器对CPU资源非常敏感
  • CMS收集器无法处理浮动垃圾,浮动垃圾指在CMS并发清理阶段用户线程运行时不断产生的垃圾,CMS无法在当次集中收集处理它们,只能在下一次GC时清理
  • 所采用的标记-清除算法会导致收集结束时产生大量的空间碎片。

G1收集器

G1收集器是面向服务端应用的垃圾收集器,回收范围包括新生代和老年代,主要有以下特点:

  • 并行与并发:G1充分利用多CPU、多核环境下的硬件优势,使用多个CPU来缩短Stop The World停顿时间,部分其他收集器需要停顿Java线程执行的GC动作,G1收集器可以通过并发的方式让Java程序继续执行
  • 分代收集:分代概念在G1中依然保留,G1可以不需要其他收集器配合就能独自管理整个GC堆
  • 空间整合:G1从整体上看是基于标记-整理算法实现的,从局部上看是基于标记-复制算法实现的,这意味着G1运作期间不会产生内存碎片
  • 可预测的停顿:G1除了追求停顿外,还能建立可预测的停顿时间模型

G1收集器的运作步骤如下:

  • 初始标记
  • 并发标记
  • 最终标记
  • 筛选回收

看起来和CMS很像,如下图

G1收集器
G1收集器

点击面试手册,获取本站面试手册PDF完整版