跳转至

垃圾收集器(具体实现)

HotSpot虚拟机的垃圾收集器

  • 7中作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用。虚拟机所处的区域,则表示它是属于新生代收集器还是老年代收集器。重点分析CMS和G1这两款相对复杂的收集器
  • 不存在完美的收集器

1. Serial收集器

  1. 最基本历史最悠久的收集器
  2. 单线程,只使用一个CPU一条收集线程区完成垃圾收集工作,在进行垃圾收集的时,必须暂停其他所有的工作线程,直到它收集结束

2. ParNew收集器

  1. Serial收集器的多线程版本
  2. 目前只有它能与CMS收集器配合工作

3. Parallel Scavenge收集器

  1. 是一个新生代收集器,赋值算法,并行多线程收集器
  2. 目标:达到一个可控制的吞吐量(Throughput),吞吐量 = 运行用户代码时间/(运行用户代码时间 + 垃圾收集时间)
  3. 停顿时间越短越适合需要与用户交互的程序,良好的响应速度能提升用户体验,而高吞吐量则可以高效率地利用CPU时间,尽快完成程序的运算任务,主要适合后台运算而不需要太多交互的任务

4. Serial Old收集器

  1. Serial收集器的老年代版本,单线程收集器,使用“标记——整理”算法
  2. 主要意义也是在于给Client模式下的虚拟机使用。
  3. 在Server模式下,两大用途:
  4. 在JDK1.5以及之前的版本中与Parallel Scavenge收集器搭配使用
  5. 作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用

5. Parallel Old收集器

  1. Parallel Scavenge收集器的老年代版本,使用多线程和“标记——整理”
  2. 直到Parallel Old收集器出现后,“吞吐量优先”收集器终于有了比较名副其实的应用组合,在注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge 加 Parallel OLd收集器。

6. CMS收集器

  1. CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器
  2. 目前很大一部分的Java应用集中在互联网或者B/S系统的服务器上,这类应用尤其重视服务器的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。
  3. “标记——清除”算法
  4. 运作过程:
  5. 初始标记
  6. 并发标记
  7. 重新标记
  8. 并发清除 其中,初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing 的过程,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。
  9. 缺点:
  10. CMS资源对CPU资源非常敏感
  11. CMS收集器无法处理浮动垃圾(Floating Garbage),可能出现"Concurrent Mode Failure"失败而导致另一次Full GC的产生。
  12. “标记——清除”算法,收集结束的时候会有大量空间碎片产生。

7. G1收集器

  1. G1(Garbage-First)收集器是当今收集器技术发展的最前沿成果之一,早在JDK 1.7刚刚确立项目目标,Sun公司给出的JDK 1.7RoadMap里面,它就被视为JDK 1.7中HotSpot虚拟机的一个重要进化特征。
  2. 面向服务器端应用
  3. 与其它GC收集器相比,G1具有的特点:
  4. 并行与并发
  5. 分代收集
  6. 空间整合
  7. 可预测的停顿
  8. G1收集器的运作大致可划分为以下一个步骤:
  9. 初始标记
  10. 并发标记
  11. 最终标记
  12. 筛选回收

8. 理解GC日志

  1. 最前面的数字:代表了GC发生的时间,这个数字的含义是从Java虚拟机启动以来经过的秒数
  2. GC日志开头的"[GC"和"[Full GC"说明了这次垃圾收集的停顿类型,而不是用来区分新生代GC还是老年代GC的。如果有"Full",说明这次GC是发生了Stop-The-World的
  3. 接下来的"[DelNew"、"[Tenured"、"[Perm"表示GC发生的区域,这里显示的区域名称与使用的GC收集器是密切相关的,例如上面样例所使用的Serial收集器中的新生代名为"Default New Generation",所以显示的是"[DefNew"。如果是ParNew收集器,新生代名称就会变为"[ParNew",意为"Parallel New Generation"。如果采用Parallel Scavenge收集器,那它配套的新生代称为"PSYoungGen",老年代和永久代同理。
  4. 后面方括号内部的"3324K->152K(3712K)"含义是"GC前该内存区域已使用容量->GC后该内存区域已使用容量(该内存区域总容量)"。而在方括号之外的"3324K->152K(11904K)"表示"GC前Java堆已使用容量-> GC后Java堆已使用容量(Java堆总容量)"
  5. 再往后,"0.0025925 secs"表示该内存区域GC所使用的时间,单位是秒。

9. 垃圾收集器参数总结