经典垃圾收集器

201 阅读4分钟

经典垃圾收集器

“垃圾收集器”并不能形容它全部的职责,更贴切的名字应该是——“自动内存管理子系统”。一个垃圾收集器处理垃圾收集这个本职工作之外,他还要负责堆的管理与布局、对象的分配、与解释器的协作、与编译器的协作、与监控子系统协作等职责,其中至少** **这部分功能是Java虚拟机能够正常运行的必要支持,是一个最小化功能的垃圾收集器也必须实现的额内容。

image-20210527001327142.png

​ HotSpot虚拟机的垃圾收集器

1.Serial收集器

特点:

这个收集器是一个单线程工作的收集器,但它的“单线程”的意义并不仅仅是说明它只会使用一个处理器或一个收集线程去完成垃圾收集工作,更重要的强调在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束

负责区域:新生代

2.ParNew 收集器

特点:

ParNew收集器是Serial收集器的多线程并行版本

负责区域:新生代

在JDK 5发布时,HotSpot推出了一款在强交互应用中几乎可称为具有划时代意义的垃圾收集器——CMS收集器。这款收集器是Hotspot虚拟机中第一款真正意义上支持并发的垃圾收集器,它首次实现了让垃圾收集器与用户线程(基本上)同时工作。遗憾的是CMS作为老年代的收集器,却无法与JDK1.4.0中已经存在的新生代收集器Paralle Scavenge配合工作,所以在JDK5中使用CMS来收集老年代的时候,新生代只能选择ParNew或者Serial收集器中的一个

补充说明:HotSpot虚拟机的Serial、ParNew等新生代收集器采用了一种优化的“半区复制”分代策略,现在成为“Apple 式回收”。Apple 式回收的具体做法是把新生代分为一块较大的Eden空间和两块较小的Survivor空间,每次分配内存只使用Eden和其中一块Survivor。发生垃圾搜集时,将Eden和Survivor中仍然存活的对象一次性复制到另外一块Srivivor空间上,然后直接清理掉Eden和已用过的那块Survivor空间。Hotspot虚拟机默认Eden和Survivor的大小比例是8:1,也即每次新生代中可用内存空间为整个新生代容量的90%(Eden的80%和Survivor的10%),只有一个Survivor空间,即10%的新生代会被“浪费”掉。当Survivor空间不足以容纳一次Minor GC存活的对象时,就需要依赖其他内存区域(实际上就是老年代)进行分配担保

3.Parallel Scavenge收集器

特点:

与ParNew类似,也是能够并行收集的多线程收集器。

但是主要优化点是:注重吞吐量:

吞吐量=运行用户代码时间运行用户代码时间+运行垃圾收集时间 吞吐量= \frac{运行用户代码时间}{运行用户代码时间 + 运行垃圾收集时间}

以上三个都是基于标记-复制算法


4.Parallel old收集器

特点:

1.是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法

5.CMS收集器

特点:

CMS收集器是一种以获取最短回收停顿时间为目标的收集器。从名字(包含“Mark Sweep”)上就可以看出CMS收集器是基于标记-清除算法实现的

1)初始标记

标记一下GC Roots能直接关联到的对象,速度很快。但是需要“stop the world”。

2)并发标记

从GC Roots的直接关联对象开始遍历整个对象图的过程,耗时较长但用户线程可以和垃圾收集线程一起工作

3)重新标记

为了修正并发标记期间由于用户线程运行导致标记产生变动的那一部分对象的标记记录。需要“stop the world”

4)并发清除

清理删除掉已经死亡的对象。可以和用户线程一起并发。

6.Garbge First收集器(JDK 9)

又称G1收集器。

特点:

开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。

G1开创的基于Region的堆内存布局是它能够实现这个目标的关键。虽然G1也是遵循分代收集理论设计的,但其堆内存的布局与其他收集器有非常明显的区别:G1不再坚持固定大小以及固定数量的分代区域划分**,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。**