随着内存大小的不断增长而迭代:
- Serial 和Serial Old单线程 STW (stop the world)年轻代和老年代都是单线程回收,回收期间,其他线程(业务线程)全部停止,不准创建对象,垃圾等。
- parallel 并行多线程,多线程回收垃圾,但是回收期间,其他线程依旧是等待。
- Concurrent GC 包括(CMS,ParNew等): GC线程和业务线程可以同时运行。
ParNew:工作在年轻代的垃圾回收线程。ParNew收集器就是Serial收集器的多线程版本,它也是一个新生代收集器。除了使用多线程进行垃圾收集外,其他行为包括Serial收集器可用的全部控制参数、收集算法(复制算法)、Stop The World、对象分配规则、回收策略等与Serial收集器彻底相同,二者共用了至关多的代码。
CMS:分为新生代和老年代,新生代和老年代是物理隔离的。并发的标记清除 ,工作在老年代
CMS从线程角度:
初始标记,并发标记,重新标记,并发清理
初始标记:找到root对象, (GC root 概念),但是依然是STW的,但是时间非常短,因为只要花时间找到root对象就行,不用整体全部回收,所以效率还可以。
并发标记:
- 著名的三色标记算法:
前言: 垃圾回收线程开始对产生的垃圾对象进行标记,但是已经标记了的垃圾如果又被引用了呢?谁去记录,怎么记录?或者是原先引用的对象被断开引用了呢?
黑色标记(black)标记参数都记录在MarkWorld里面,和锁的参数记录在一起: 该对象,和依赖该对象的所有(fields),都已经被标记了,那么下一次垃圾回收器扫描时,就不再扫描它了。
灰色标记: :该对象自己被标记,但是例如孩子等,没有被标记,那么成为灰色标记,下一次垃圾回收扫描时,不扫描它本身,只扫描它的孩子等。
白色标记:还没标记到的。、
如果灰色标记了一个对象A,A的孩子是B,第一次扫描时已经标记好了A,但是B还没被标记到,此时B是白色,A是黑色,如果之后A和B断开引用,那么B会成为浮动垃圾 (float),浮动垃圾会被下一次整体扫描覆盖到,然后被标记,不是很危险的问题。
但是在A和B断开引用后,有一个黑色标记C,引用了白色标记B,此时白色B,就无法被扫描了。扫描不到的,就是说没有引用的,就是垃圾,就会被清除,那么这样就会有问题。
所以有一种程序跟踪的机制,如果黑色标记对象C,又引用了别的对象,那么黑色会变成灰色。
这就是CMS的解决方案。
CMS天生的bug :Incremental Update ,并发标记,产生漏标。被迫走到重新标记这一步,而重新标记是STW的,所以CMS诞生就是为了解决STW的效率问题,但是最终又不得不回到STW。
举例:
原本一个资源A是被一个灰色标记对象所引用,即将开始扫描。此时灰色标记对象对A的引用断开,并且有一个黑色标记(已经完全扫描)引用了资源A,此时垃圾回收线程会认为黑色标记已经不需要扫描标记,所以不再扫描,那么,此时资源A身上,就不会再被标记,没有标记的对象,称之为不可达,无引用,将会被垃圾回收器收集清除。
重新标记(remark):也是STW的,解决漏标问题
并发清理:多线程清理没有被标记到的资源。
G1:新诞生了分区算法。物理上不分代,逻辑分代,
G1打破了以往将收集范围固定在新生代或老年代的模式,GI 将 Java 堆空间分割成了若干相同大小的 区域,即 region,包括 Eden、
Survivor、 Old、 Humongous 四种类型。其中, Humongous 是特殊的 Old 类型,专门 放置大型对象。这样的划分方式意昧着不需要一个连续的内存空间管理对象。 GI 将 空间分为多个区域,优先回收垃圾最多的 区域。 GI 采用的是 好的空间整合能力’不会产生大量的空间碎片。
Region的数值是在1M到32M字节之间的一个2的幂值数,JVM会尽量划分2048个左右、同等大小的Region。
在G1中,还有一种特殊的区域,叫Humongous区域。 若是一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象。这些巨型对象,默认直接会被分配在年老代,可是若是它是一个短时间存在的巨型对象,就会对垃圾收集器形成负面影响。为了解决这个问题,G1划分了一个Humongous区,它用来专门存放巨型对象。若是一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC。
Region概念
- 横跨整个堆内存
- 在G1以前的其余收集器进行收集的范围都是整个新生代或者老生代,而G1再也不是这样。
- G1在使用时,Java堆的内存布局与其余收集器有很大区别,
- 它将整个Java堆划分为多个大小相等的独立区域(Region),
- 虽然还保留新生代和老年代的概念,但新生代和老年代再也不是物理隔离的了,而都是一部分Region(能够不连续)的集合。
GI 的一大优势在于可预测的停顿时间, 能够尽可能快地在指定时间内完成垃圾回收任务。在 JDKl l 中,已经将 GI 设为默认 垃圾回收器。
ZGC:
ZGC主要新增了两项技术,一个是着色指针Colored Pointer,另外一个是读屏障Load Barrier。
ZGC 是一个并发、基于区域(region)、增量式压缩的收集器。Stop-The-World 阶段只会在根对象扫描(root scanning)阶段发生,这样的话 GC 暂停时间并不会随着堆和存活对象的数量而增长。