背景介绍:7种垃圾收集器作用于不同的分代,如果两个收集器之间存在连续,就说明他们可以搭配使用。
从JDK1.3到现在,从Serial收集器-》Parallel收集器-》CMS-》G1,用户线程停顿时间不断缩短,但仍然无法完全消除
收集器 | 串行/并行/并发 | 新生代/老年代 | 收集算法 | 目标 | 适用场景 | 备注 |
---|---|---|---|---|---|---|
Serial | 串行 | 新生代 | 复制算法 | 响应速度优先 | 单CPU环境下的Client模式 | |
Serial Old | 串行 | 老年代 | 标记-整理算法 | 响应速度优先 | 单CPU环境下的Client模式、CMS的后备预案 | Serial收集器的老年代版本 |
ParNew | 并行 | 新生代 | 复制算法 | 响应速度优先 | 多CPU环境时在Server模式下与CMS配合 | Serial收集器的多线程版本 |
Parallel Scavenge | 并行 | 老年代 | 复制算法 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 | 类似于ParNew收集器,有自己的特点 |
Parallel Old | 并行 | 老年代 | 标记-整理算法 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 | Parallel Scavenge收集器的老年代版本 |
CMS | 并发 | 老年代 | 标记-清除算法 | 响应速度优先 | 集中在互联网站或者B/S系统服务端的Java应用 | |
G1 | 并发 | 新生代、老年代 | 标记-清除算法、复制算法 | 响应速度优先 | 面向服务端应用,将来替代CMS |
-
1、Serial收集器:串行/单线程收集器,使用一条垃圾收集线程去完成垃圾收集,而且它在进行垃圾收集的时候会暂停其他所有的工作线程直到收集结束。其新生代使用复制算法,老年代使用标记-整理算法。
-
缺点是要暂停所有的线程,优点是简单而高效没有线程交互的开销。
-
Serial 收集器对于运⾏在Client模式下的虚拟机来说是个不错的选择,HotSpot在Client模式下的默认
-
"-XX:+UseSerialGC":添加该参数来显式的使用Serial垃圾收集器。
-
2、ParNew收集器可看作Serial收集器的多线程版本,使用多线程进行垃圾收集,其余行为和Serial一样。
它是许多运⾏在Server模式下的虚拟机的⾸要选择,除了Serial收集器外,只有它能与CMS收集器(真正意义上的并发收集器,后⾯会介绍到)配合⼯作。 新⽣代采⽤复制算法,⽼年代采⽤标记-整理算法
-
并发:多个垃圾收集线程一起工作,用户线程等待
-
并行:用户线程和垃圾收集线程一起工作
-
"-XX:+UseConcMarkSweepGC":指定使用CMS后,会默认使用ParNew作为新生代收集器。 "-XX:+UseParNewGC":强制指定使用ParNew。 "-XX:ParallelGCThreads":指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相同。
-
-
3、Parallel Scavenge收集器类似于ParNew收集器,特别之处如下:
-
Parallel Scavenge收集器的关注点是吞吐量/高效率利用CPU。// CMS等关注的是用户线程的停顿时间/用户体验
-
吞吐量就是CPU中运行用户代码的时间比总消耗时间,Parallel Scavenge收集器提供了很多参数供⽤户找到最合适的停顿时间或最⼤吞吐量。
-
//Parallel Scavenge收集器提供了两个参数来用于精确控制吞吐量,一是控制最大垃圾收集停顿时间的 -XX:MaxGCPauseMillis参数,二是控制吞吐量大小的 -XX:GCTimeRatio参数; "-XX:MaxGCPauseMillis":参数允许的值是一个大于0的毫秒数,收集器将尽可能的保证内存垃圾回收花费的时间不超过设定的值(但是,并不是越小越好,GC停顿时间缩短是以牺牲吞吐量和新生代空间来换取的,如果设置的值太小,将会导致频繁GC,这样虽然GC停顿时间下来了,但是吞吐量也下来了)。 "-XX:GCTimeRatio":参数的值是一个大于0且小于100的整数,也就是垃圾收集时间占总时间的比率,默认值是99,就是允许最大1%(即1/(1+99))的垃圾收集时间。 "-XX:UseAdaptiveSizePolicy":参数是一个开关,如果这个参数打开之后,虚拟机会根据当前系统运行情况收集监控信息,动态调整新生代的比例、老年大大小等细节参数,以提供最合适的停顿时间或最大的吞吐量,这种调节方式称为GC自适应的调节策略。
-
-
4、Serial Old收集器
-
Serial收集器的老年代版本,单线程,标记-整理算法。主要用于Client模式下的虚拟机使用。
-
1、在JDK1.5及之前的版本与Parallel Scaveenge收集器搭配使用;2、用作CMS收集器的后备方案。
-
-
5、Parallel Old收集器
-
Parallel Scavenge收集器的老年代版本,多线程和’标记-整理算法‘,出现在JDK1。6
-
在注重吞吐量以及CPU资源 的场合,都可以优先考虑 Parallel Scavenge收集器和Parallel Old收集器。
-
-
6、CMS收集器:
-
CMS(Concurrent Mark Sweep)收集器是⼀种以获取最短回收停顿时间为⽬标的收集器。它⽽⾮常符合 在注重⽤户体验的应⽤上使⽤。
-
是HotSpot虚拟机第⼀款真正意义上的并发收集器,它第⼀次实 现了让垃圾收集线程与⽤户线程(基本上)同时⼯作。
-
CMS收集器是⼀种 “标记-清除”算法实现的,它的运作过程 相⽐于前⾯⼏种垃圾收集器来说更加复杂⼀些。整个过程分为四个步骤:
-
1、初始标记: 暂停所有的其他线程,并记录下直接与root相连的对象,速度很快 ;
-
2、 并发标记: 同时开启GC和⽤户线程,⽤⼀个闭包结构去记录可达对象。但在这个阶段,这个闭包结构并不能保证包含当前所有的可达对象。因为⽤户线程可能会不断的更新引⽤域,所以 GC线程⽆法保证可达性分析的实时性。所以这个算法⾥会跟踪记录这些发⽣引⽤更新的地⽅。
-
3、重新标记: 此阶段就是为了修正并发标记期间因为⽤户程序继续运⾏⽽导致标记产⽣变 动的那⼀部分对象的标记记录,这个阶段的停顿时间⼀般会⽐初始标记阶段的时间稍⻓,远远⽐ 并发标记阶段时间短
-
4、并发清除: 开启⽤户线程,同时GC线程开始对为标记的区域做清扫。
-
优点是:并发收集,低停顿 缺点是:对CPU资源敏感、无法处理浮动垃圾、标记清除算法产生大量空间碎片
-
-
7、G1收集器
G1 (Garbage-First)是⼀款⾯向服务器的垃圾收集器,主要针对配备多颗处理器及⼤容量内存的机器. 以极⾼概率满⾜GC停顿时间要求的同时,还具备⾼吞吐量性能特征.
-
并⾏与并发:G1能充分利⽤CPU、多核环境下的硬件优势,使⽤多个CPU(CPU或者CPU核⼼)来缩 短Stop-The-World停顿时间。部分其他收集器原本需要停顿Java线程执⾏的GC动作,G1收集器仍 然可以通过并发的⽅式让java程序继续执⾏。
-
分代收集:虽然G1可以不需要其他收集器配合就能独⽴管理整个GC堆,但是还是保留了分代的概 念。
-
空间整合:与CMS的“标记–清理”算法不同,G1从整体来看是基于“标记-整理”算法实现的收集 器;从局部上来看是基于“复制”算法实现的。
-
可预测的停顿:这是G1相对于CMS的另⼀个⼤优势,降低停顿时间是G1 和 CMS 共同的关注点, 但G1 除了追求低停顿外,还能建⽴可预测的停顿时间模型,能让使⽤者明确指定在⼀个⻓度为M 毫秒的时间⽚段内
初始标记—并发标记—最终标记—筛选回收
-
G1收集器在后台维护了⼀个优先列表,每次根据允许的收集时间,优先选择回收价值最⼤的Region(这 也就是它的名字Garbage-First的由来)。这种使⽤Region划分内存空间以及有优先级的区域回收⽅式, 保证了GF收集器在有限时间内可以尽可能⾼的收集效率(把内存化整为零)。
-
**G1分区的概念:**G1的堆区在分代的基础上,引入分区的概念。
-
G1将堆分成了若干Region(这些分区不要求是连续的内存空间),Region的大小可以通过G1HeapRegionSize参数进行设置,其必须是2的幂,范围允许为1Mb到32Mb。
-
VM的会基于堆内存的初始值和最大值的平均数计算分区的尺寸,平均的堆尺寸会分出约2000个Region。分区大小一旦设置,则启动之后不会再变化。
-- Eden regions(年轻代-Eden区)
- Survivor regions(年轻代-Survivor区)
- Old regions(老年代)
- Humongous regions(巨型对象区域)
- Free regions(未分配区域,也会叫做可用分区)
-
-