前言
在一个比较庞大而且复杂的程序的运行过程中因为需要支撑各种逻辑,那么必然就会创建出大量的对象,而我们的硬件内存等容量都是有限,所以我们就需要判断一个对象的生命周期,并在使用完成后及时清理内存给后来者使用,这样才能在有限的物理内存中运行更加复杂的系统,而GC就是jvm中用来自动清理失效对象内存的一种策略。
一、对象失效的判断依据?
对象失效的主要判断依据就是对象不再被使用,而判断不被使用最简单的方法就是引用计数器的方式,但引用计数器存在对于循环引用无法判断的缺陷。所以有了另一种方法可达性分析算法,可达性分析算法描述的是从被对规定为GC Roots的节点进行向下搜索,如果某个对象没有对应引用链即为可回收。并且引用还分有四种等级强引用、软引用、弱引用、虚引用每个等级的引用回收的条件是不同的。
GC Root集合:
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI引用的对象
- 基本数据类型的class对象
- 常驻异常对象
二、GC触发及基本算法
触发时机
基于分代收集理论把堆上需要收集的区域划分为新生代和老年代,而两块区域的触发则分为两种:
- 新生代(Eden)空间不足时,触发GC称为minor gc
- 老年代空间不足,触发GC称为major gc或者full gc
基本算法
- 标记复制
- 标记清理
- 标记整理
三、GC的分类
基于分代理论的收集器
名称 | 分代 |
---|---|
Serial 串行收集器 | 新生代、老年代 |
Parallel 串行收集器 | 新生代、老年代 |
CMS收集器 | 老年代 |
新型收集器
名称 | 描述 |
---|---|
G1 | G1中主要思想是将整个内存空间划分为相同大小的区域Region,而新生代、老年代都由不连续的Region组成,回收则是针对Region进行回收 |
ZGC | ZGC也采用了Region的概念,但是对Region进行了区分规定了小型、中型、大型三个等级,小型固定为2M,中型为32M,大型不固定只要是2次幂大小即可 |
Shenandoah | shenandoah收集器也采用了Region区域的思想,并且抛弃了分代的思想 |
收集器发展
首先是串行回收既代表在回收时停止所有的用户线程,然后单线程采用标记整理算法实现垃圾回收,然后再重启用户进程,接着并行回收所做的优化则是在停止过程中采用多线程并发加速这个过程。
接着是CMS的优化则是引入了三色标记算法,只需要在初始标记(指只标记GCRoot的直接引用,减少了标记数量)和重新标记(少量发生变动的对象被标记)时停止用户线程,以此来缩短时间。
接着是G1垃圾回收,主要优化功能之一就是可预测停顿,G1对所有的Region有一个性价比的优先级排序,在可预测停顿时间内做到一个最大程序的回收,既不要求完全清除只需要足够使用的思想来优化回收过程。
ZGC的优化依赖很多细节如NUMA、颜色指针、读屏障等,并且ZGC中去除了分代理论和分代产生的消耗、ZGC的主要停顿时间在标记上,而清除过程中都是和用户线程并发进行的。
shenandoah收集器的优化目标也是低停顿收集,通常与ZGC进行比较两者相同点是实现了并发回收(比G1筛选回收更优),并且主要采用的是转发指针(Brooks Pointers)既当需要引用时通过转发指针转发到其他位置来实现并发回收