收集器总述:
- 新生代: 一般采用复制算法
- 老生代: 一般采用标记-清除,标记-整理算法。
具体收集器,及收集区域入图
cms收集器
cms(Concurrent Mark Sweep,CMS 并发标记清理)收集器。
分为四个步骤
- 初始标记: stop the world(全部进程停止),标记所有GC Roots能直接关联到的对象。
- 并发标记:标记GC Roots对象连接的其他对象(原文是:进行GC Roots Tracing的过程, 初始标记产生的集合中,标记出存活对象),同时程序运行。
- 重新标记:再次stop the world,标记在并发标记过程中,产生的新对象,却没有被标记的对象。(比如,并发标记A对象的时候,A只和B对象有关联。但是继续标记其他对象的时候,并发程序运行产生了C对象,也和A或者B对象有关联,然后没有被标记到。因为是并发标记,标记的时候,程序会执行,肯定会产生新对象的。如果没有标记,被Gc了,接下来程序找不到,肯定会报错的。所以有了这个标记过程。同时程序执行的时候,也会有被标记的对象不被使用了,这个叫浮动垃圾。这个可以在下次GC,没有问题。)
- 并发清除:回收所有的垃圾对象,同时程序也在运行。
因为并发标记和并发清除的时候,程序也在运行,所有真正的暂停时间只有初始标记和重新标记的时间。用户感觉起来,时间表短。
具体运行如图:
CMS在并发阶段默认启动的回收线程数为(cpu数量+3)/4。所以在4,8.16.32核这种机器上,垃圾回收线程资源不会超过cpu资源的25%。
CMS收集器适用于老生代,无法收集浮动垃圾,所以老生代的预留空间应该比较多。不能快填满了再收集,默认是68%。
CMS是基于标记-清除算法的,这样空间碎片会很多,当创建大的对象时,可能会提前触发GC Full。
G1收集器
- 并行于并发
- 分代收集,不需要配合其他收集器,就能独立管理整个GC堆。
- 空间整合:与CMS的“标记-清理”算法不同,G1从整体来看是基于“标记-整理”算法实现的收集器,从局部(两个Region之间)上来看是基于“复制”算法实现的,但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。
4.可预测的停顿:这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。(G1跟着各个Region里垃圾堆积的价值大小(回收空间大小和回收所需的时间经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region)。
1. 初始标记 :
标记GC roots能直接关联到的对象,并且修改TAMS(Next Top at Mart start)的值,让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象。
2.并发标记:
从GC roots开始对堆中对象进行可达性分析,找出存活对象。
3.最终标记
修正因并发标记期间因用户程序运行而导致标记变动的纪录。
4.筛选回收
根据各个Region的回收价值和成本进行回收。
Serial收集器(新生代)
虚拟机在Client模式下默认的新生代收集器,stop the world 时候单线程。
ParNew收集器(新生代)
Serial收集器的多线程版本,stop the world的时候多线程。但是他可以和CMS收集器配合使用。
Parallel Scavenge收集器(新生代)
采用复制算法,并行垃圾收集,在这里和parNew一样。但是他提供了两个参数用于精确控制吞吐量(cpu运行用户代码的时间与cpu总消耗的时间的比值)。垃圾回收时间越短,吞吐量越高。
- XX:MaxGCPauseMillis参数:控制最大垃圾收集停顿时间
- XX:GCTimeRatio:垃圾收集时间占总时间的比率。
Serial Old收集器(老生代)
单线程收集器,使用标记-整理算法,给Client模式下的虚拟机使用。
Parallel Old收集器
使用标记整理算法,和Parllael Scavenge搭配。
jdk1.6之后开始提供。