经典的垃圾收集器!!!
首先需要了解并行和并发的概念
并行:垃圾收集器可以开启多个垃圾收集线程并行进行标记,清理等处理
(事情一起做,相当于三个人同时吃三个馒头)
并发:垃圾收集器的标记、清理线程和用户线程同时运行
(事情交替着做,在宏观上多个线程同时执行,微观上就是把时间划分若干个段,多个线程交替执行)
1.Serial收集器
最早的垃圾收集器,单线程的实现比较简单
serial:新生代收集器,单线程的,采用标记-复制法
serial old:老年代收集器,单线程的,采用标记-整理法
优点:简单、高效,额外内存消耗最小
缺点:停顿时间长
2.CMS收集器(并发收集、低停顿)
老年代收集器,标记-清除算法,获取最短回收停顿时间为目标,一般用于服务器端上比较关注服务响应速度的地方,运作过程分为四个步骤:
1)初始标记 需要stop the world
2)并发标记 从GCRoots的直接关联对象开始遍历整个对象图的过程,耗时间长不需要stop the world,可以与垃圾收集线程一起并发运行 (耗时长)
3)重新标记 需要stop the world (修正增量更新的部分)
4)并发清除 清理删除掉标记阶段判断的已经死亡的对象,不需要移动存活对象,所以这个阶段也可以是与用户线程同时并发的。 (耗时长)
总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的
缺点:
1)CMS收集器对处理器资源非常敏感。面向并发设计的程序对处理器资源都比较敏感,因为在并发阶段会占用一部分的线程导致应用程序变慢
2)CMS收集器无法处理“浮动垃圾”,就是在并发标记和并发清理的过程中也并发运行了一些用户线程,就会伴随一些垃圾对象出现(这些垃圾在标记过程后才出现),所以CMS无法在这一次就处理掉他们,只能留到下一次垃圾收集的时候在清理掉,这种垃圾就被称为是浮动垃圾
3)CMS是一款基于标记-清除的算法实现的收集器,所以会出现大量的空间碎片
3.Garbage First收集器(G1)
G1主要是未来想要取代CMS收集器
G1收集器相较于CMS一个突出的优点就是:
基于“标记-整理”算法,收集之后不会再产生内存碎片
可以非常精确控制停顿时间,再不牺牲吞吐量前提下,实现低停顿垃圾回收
G1不采用新生代和老年代物理隔离的布局方式,是将整个堆内存划分为2048个大小相等的独立内存块Region,每个Region是逻辑连续的一段内存,具体大小根据堆的实际大小而定,并使用不同的Region来表示新生代和老年代,G1不再要求相同类型的Region再物理内存上相邻,而是通过Region的动态分配方式实现逻辑上的连续。
G1收集器的运作过程:
1)初始标记:标记一下GC Roots能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新对象 (会暂停用户线程)
2)并发标记:从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但与用户程序并发执行。当对象图扫描完成以后,还要重新处理SATB记录下的再并发时有引用变动的对象
3)最终标记:对用户线程做另一个短暂的暂停,用于处理并发阶段接收后仍遗留下来的最后那少量的SATB记录 (会暂停用户线程)
4)筛选回收:负责更新Region的统计数据,对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多条收集器线程并行完成的。 (会暂停用户线程)