CMS和G1是最重要的
新生代一般采用标记复制,老年代一般采用标记整理算法
Serial:垃圾回收线程只有一个,而且垃圾回收线程工作的时候其他用户线程要停下来
Parnew:Serial的多线程版本,有多个垃圾回收线程,垃圾回收线程工作的时候,其他用户线程要停下来
Parrel:多个垃圾回收线程,垃圾线程工作的时候其他用户线程需要停止工作,跟Parnew很像。可以设置参数:垃圾收集导致地最大停顿时间和设置吞吐量的大小。通过GC自适应调节策略(虚拟机会根据系统的运行状况动态地设置参数)来达到目标停顿时间和吞吐量。特点是获取最大吞吐量(一共运行100分钟,垃圾回收器花掉3分钟,吞吐量就是97%)
CMS:第一款实现垃圾收集线程和用户线程同时工作的垃圾回收器,第一款并发收集器,目的是追求最短停顿时间(垃圾回收线程工作导致用户线程停顿的时间)
CMS垃圾回收器工作的的四个阶段:在初始标记和重新标记阶段只能有垃圾回收线程在工作,用户线程需要停止,其他两个阶段垃圾回收线程和用户线程可以同时工作
(1)初始标记:标记和GC Root直接相连的对象,这个阶段很快,但是这个阶段其他用户线程无法工作,还是会发生stop the world(STW)
(2)并发标记:CMS线程会从与GC Roots直接相连的对象出发,遍历所有对象,标记所有存活的对象,这个阶段,CMS线程和其他用户线程在并发执行
(3)重新标记:并发标记阶段由于CMS线程和其他用户线程并行运行,所以其他用户线程可能产生一些新的对象,这些新对象还没有打上是否存活的标记,所以需要标记出这些新对象中存活的对象,这个过程是只有CMS线程,用户线程需要停止工作,所以这个过程会引起STW
(4)并发清除:清除那些没有标记存活的对象,然后最后将这些对象的标记取消
助记:三个标记阶段,一个清除阶段
缺点:这种标记清除的回收方式会产生内存碎片
虽然STW时间很短,但是没法预测,G1就建立了一个预测模型
G1:STW时间可预测,可设置
整个Java堆划分成约2048个大小相同的Region块,继续保留新生代和老年代的概念,但是并不是一块连续的内存是新生代,另一块连续的内存是老年代,而是一些不连续的Region组成新生代,另一些不连续的Region组成老年代
G1会跟踪各个Region里存活对象的数量,回收该区域所需要的时间经验值,在后台维护一个优先队列,每次根据允许的收集时间优先回收垃圾对象数量Region(也就是价值最大的垃圾)
总结:
CMS:追求最短的停顿时间,并行的,垃圾回收线程可以和用户线程同时执行(只有初始标记阶段需要暂停用户线程,其他阶段不需要暂停用户线程) 采用三色标记法
G1:HotSpot 开发团队赋予它的使命是未来可以替换掉 CMS 收集器
Serial 单个垃圾回收线程执行(单线程),其他所有用户线程都要停下来
Serial是用于新生代的垃圾回收器,它的老年代版本是Serial old
Parnew多个垃圾回收线程执行(多线程),其他所有用户线程都要停下来
下面是 HotSpot 虚拟机中的 7 个垃圾收集器。上面是新生代的垃圾回收器,下面是老年代的垃圾回收器,G1既可以用于新生代的垃圾回收,也可以用于老年代的垃圾回收,连线表示垃圾收集器可以配合使用
首先要理解以下两个概念:
(1)单线程和多线程: 垃圾收集器只使用一个线程就说垃圾收集器是单线程的,垃圾收集器使用多个线程就说垃圾收集器是多线程
(2)串行和并行:
串行指的是垃圾收集器和用户程序交替执行(执行垃圾收集器的时候需要停止用户程序,即用户现线程和GC线程交替执行),
并行是指垃圾收集器和用户程序同时执行(也就是执行垃圾收集器的时候不需要停止用户程序,即用户线程和GC线程可以一起执行)
1.Serial垃圾回收器
Serial(串行)收集器是最基本、历史最悠久的垃圾收集器了,是一个单线程收集器(也就是它只会使用一个垃圾收集线程去完成垃圾收集工作)
它在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束
Serial垃圾回收器在回收垃圾的时候,新生代采用标记-复制算法,老年代采用标记-整理算法。
Serial 收集器由于没有线程交互的开销,自然可以获得很高的单线程收集效率
2.ParNew收集器
Serial 收集器的多线程版本,也是新生代采用标记-复制算法,老年代采用标记-整理算法
除了 Serial 收集器,只有它能与 CMS 收集器配合使用
3.CMS垃圾回收器
追求最短的停顿时间(STW),分为四个阶段:初始标记,并发标记,重新标记,并发清理,只有初始标记阶段和重新标记阶段需要暂停用户线程,其他阶段不需要暂停用户线程,可以和用户线程并行),所以适用于暂停时间要求比较高的,比如实时系统,交互式系统
整个过程分为以下几个步骤:
(1)初始标记:标记直接与 root 相连的对象 (不直接相连,间接相连的不标记),这是一个STW(stop the world)阶段,其他用户线程是不能工作的
(2)并发标记:CMS线程会从与GC Roots直接相连的对象出发,遍历整个对象图 ,标记所有存活的对象,这个阶段,CMS线程和其他用户线程在并发执行,
(3)重新标记: 由于上一个阶段并发标记阶段其他用户线程实际上还是在运行的,有可能用户线程在这个阶段产生了新的对象(这些新的对象中的存活对象是没有打上标记的),这里采用三色标记法来标记那些新产生的对象中存活对象
(4)并发清理:清除所有没有被标记的对象,这个阶段如果有新增对象会被标记为黑色,不做任何处理
最后并发重置就是把 标记过的对象取消标记
三色标记算法:
黑色:这个对象及其所有的引用的对象都被遍历过,那这个对象就是黑色,黑色的对象不会被回收
灰色:这个对象被遍历过,但是它的部分引用还没被遍历过,在重新标记阶段会将这个对象标记为灰色
白色:这个对象没有被遍历过,在重新标记阶段如果是白色的话,这个对象将被回收
4.G1垃圾收集算法:
G1(Garbage-First),HotSpot 开发团队赋予它的使命是未来可以替换掉 CMS 收集器
优先清理垃圾占比较高的区域
其它收集器将堆分为新生代和老年代,进行收集的范围都是整个新生代或者老年代,而 G1 垃圾回收器不再将堆分成新生代和老年代,而是将整个内存切成一段一段大小相等的内存区域(每块区域称为region),每个region可能处于新生代或者老年代,所有处于新生代的region组成新生代,所有处于老年代的region组成老年代,也就是说新生代和老年代不再物理隔离
工作流程
(1)初始标记:标记所有直接与GC Root相连的对象,用户线程暂停,STW
(2)并发标记:多线程标记所有存活的对象,用户线程可以继续运行
(3)最终标记:由于上一个阶段并发标记阶段其他用户线程实际上还是在运行的,有可能用户线程在这个阶段产生了新的对象(这些新的对象中的存活对象是没有打上标记的)STW
(4)筛选回收:清理所有没被标记的对象
G1垃圾回收器可以设置一个垃圾回收的预期时间(比如指定这个垃圾回收器在一个小时之内发生stw的停顿时间不超过1分钟,这样回收器就会尽量在这个时间范围内完成垃圾回收任务)
G1 把堆划分成多个大小相等的独立区域(Region),,通过引入 Region 的概念,从而将原来的一整块内存空间划分成多个的小空间,使得每个小空间可以单独进行垃圾回收。这种划分方法带来了很大的灵活性
记录每个 Region 垃圾回收时间以及回收所获得的空间(这两个值是通过过去回收的经验获得),然后维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的 Region。
CMS垃圾回收器和G1垃圾回收器之间的区别:
(1)CMS是针对老年代的垃圾收集器,而G1既可以对年轻代,又可以对老年代进行收集
(2)CMS采用的是标记清除算法,会产生很多内存碎片,G1采用的是标记整理算法,避免了垃圾碎片
(3)CMS的设计目标是减少垃圾收集引起的用户线程暂停stop the world的时间,而G1垃圾回收器既能缩短暂停时间,又能适用于吞吐量较高的程序(相同时间内能处理更多任务)