这里讨论JDK 1.7 Update 14之后的HotSpot虚拟机,包含的虚拟机如下图所示(存在连线的表示可以搭配使用):
这里写图片描述
1、Serial收集器(单线程)
这里写图片描述-
最基本、发展历史最悠久,在JDK 1.3之前是新生代收集的唯一选择;
-
是一个单线程(只会使用一个收集线程,且必须暂停所有工作线程)的收集器,采用的是复制算法;
-
现在依然是虚拟机运行在Client模式下的默认新生代收集器,主要就是因为它简单而高效(没有线程交互的开销);
2、ParNew收集器(多线程)
这里写图片描述-
其实就是Serial收集器的多线程版本,采用的也是复制算法;
-
ParNew收集器在单CPU环境中绝对不会有比Serial收集器更好的效果;
-
是许多运行在Server模式下虚拟机首选的新生代收集器,重要原因就是除了Serial收集器外,只有它能与CMS收集器配合工作;
3、CMS收集器
这里写图片描述-
是一种以获取最短回收停顿时间为目标的收集器,特别适合互联网站或者B/S的服务端;
-
它是基于 标记-清除 算法实现的,主要包括4个步骤:
- 初始标记(STW,只是初始标记一下GC Roots能直接关联到的对象,速度很快);
- 并发标记(非STW,执行GC RootsTracing,耗时比较长);
- 重新标记(STW,修正并发标记期间因用户程序继续导致变动的那一部分对象标记);
- 并发清除(非STW,耗时较长);
-
还有3个明显的缺点:
- CMS收集器对CPU非常敏感(占用部分线程及CPU资源,影响总吞吐量);
- 无法处理浮动垃圾(默认达到92%就触发垃圾回收);
- 大量内存碎片产生(可以通过参数启动压缩);
4、G1收集器
这里写图片描述- 一款面向服务端应用的垃圾收集器,后续会替换掉CMS垃圾收集器。
- 将堆分为大小相等的独立区域,避免全区域的垃圾收集;新生代和老年代不再物理隔离,只是部分Region的集合;
- G1跟踪各个Region垃圾堆积的价值大小,在后台维护一个优先列表,根据允许的收集时间优先回收价值最大的Region;
- Region之间的对象引用以及其他收集器中的新生代与老年代之间的对象引用,采用Remembered Set来避免全堆扫描;
特点:
并行与并发(充分利用多核多CPU缩短STW时间);
分代收集(独立管理整个Java堆,但针对不同年龄的对象采取不同的策略);
空间整合(局部看是基于复制算法,从整体来看是基于标记-整理算法,都不会产生内存碎片);
可预测的停顿(可以明确指定在一个长度为M毫秒的时间片内垃圾收集不会超过N毫秒);
G1垃圾回收分为几个步骤:
-
初始标记(标记一下GC Roots能直接关联的对象并修改TAMS值,需要STW但耗时很短)
-
并发标记(从GC Root从堆中对象进行可达性分析找存活的对象,耗时较长但可以与用户线程并发执行)
-
最终标记(为了修正并发标记期间产生变动的那一部分标记记录,这一期间的变化记录在Remembered
Set Log里,然后合并到Remembered Set里,该阶段需要STW但是可并行执行) -
筛选回收(对各个Region回收价值排序,根据用户期望的GC停顿时间制定回收计划来回收);
网友评论