关于GC的家长里短

122 阅读4分钟

所谓GC就是垃圾.......额 garbage collection 作为高级语言的福利 不需要手动释放无用的内存 非常的方便。 那么垃圾回收器都有哪些呢,根据我的见识(书里看来的)知道的垃圾收集器罗列一下先。 serial, parNew, parallel scavenge, serial old, parallel old ,cms ,garbage first(g1), shenandoah, zgc.

下图是各个收集器搭配使用的关系 image.png

1 serial (单线程 复制算法) serial垃圾收集器翻译为连续,是最基础的单线程垃圾收集器,使用复制算法,jdk1.3之前新生代唯一的垃圾收集器。serial不但只会使用一个cpu或者一条线程完成垃圾收集工作,并且在收集垃圾的同时必须暂停其他所有线程直到垃圾收集结束。因为没有线程交互的开销,所以很高效。在单机环境下可以非常高效的完成垃圾收集工作。

2 parNew (多线程 serial)
parNew与serial相比除了使用多线程的方式外其他地方都是一样的,同样是新生代垃圾收集器,使用复制算法收集垃圾的时候需要停止所有线程直到回收完成。

3 parallel scavenge (高效 parnew) parallel scavenge 收集器也是新生代收集器,使用复制算法,也是多线程的垃圾收集器,他关注的重点是程序可达到可控制的吞吐量(执行客户代码时间/ 执行客户代码时间 + 采集垃圾时间),比parnew 更高效的吞吐量以便于更高效的利用cpu.另外parallel scavenge的自适应调节策略也是parnew没有的,配置这个模式可以动态的对新生代中的eden, survivor from,survivor to 的内存空间进行管理不需要默认或者人为的去指定。

4 serial old (单线程 标记整理算法) serial old 对应serial的老年代版本。同样是单线程收集器,采用标记整理算法。在jdk1.5之前与新生代parallel scavenge搭配使用,或者作为cms的后备方案。

5 parallel old (多线程 标记整理算法) parallel old 是parallel scavenge 的老年代版本,采用的是多线程的标记整理算法。如果对吞吐量要求比较高可以采用这个方案。

6 cms收集器(多线程 标记清楚算法) concurrent market sweep 老年代收集器,其目标是获取最短垃圾回收停顿时间,采用的是标记清除算法,并不是标记整理算法。
cms工作机制
初始标记:标记gcroot 直接关联的对象,速度很快,需要停止所有线程
并发标记:跟踪gcroot 跟用户线程一起工作
重新标记:修正并发标记时产生的变动,需要停止所有线程
并发清除:清除gc root 不可达对象,和用户线程一起工作不用停止用户线程。

7 G1垃圾收集器 garbage first 相比于cms比较突出的改进是采用标记整理算法,不会产生内存碎片。并且可以精准的控制停止时间。不影响吞吐量的前提下实现低停顿回收。g1避免整个区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域的垃圾回收进度,同时维护一个优先级列表,每次根据允许的收集时间优先回收垃圾最多的区域。概括一下就是区域划分和优先级区域。
工作机制
初始标记:仅仅标记gc root 直接关联的对象。
并发标记:跟踪gc root 最终标记:处理遗留的状态记录 筛选回收:更新每个区域的数据

8 shenandoah 非官方发布的垃圾收集器,基于g1垃圾收集器做了一些优化,目的是在尽可能减少吞吐量的影响下将任意大小的内存垃圾采集的停顿时间降低到10毫秒以下。不仅可以并发标记还可以并发清除。而且没有采用分代采集的方案,采用的region分区的结构。

9 zgc zgc是一款基于region内存布局的。暂时不设置分代,使用读屏障。染色针和内存多重映射等技术实现可并发的标记-整理算法,以低延迟为首要目标的一款垃圾收集器。