GC算法基础
标记可达对象(Marking Reachable Objects)
首先重温一下GCROOTS,GCROOTS为Garbage Collection Roots的缩写,被指定为GCROOTS的对象包括:
- 当前 正在执行的方法里 的 局部变量和输入参数
- 活动线程(Active threads)
- 内存中所有类的静态字段
- JNI引用
GC遍历内存中的整体对象关系图,从GC根元素开始扫描,所有GC访问到的对象都会被标记为存活对象
执行标记期间需要暂停所有应用线程,以遍历所有对象的引用关系,这种情景叫做 全线停顿(stop the world pause),可以安全的暂停线程的点叫安全点(safe point)。标记阶段完成后,GC进行下一步操作,删除不可达对象。
删除不可达对象
GC算法在删除不可达对象时的操作可以分成三类:清除(sweeping)、整理(compacting)、复制(copying)。
清除操作
在标记-清除算法(Mark and Sweep)中所有不可达对象占用的空间被认为是空闲的,因此需要一张空闲表(free-list)来记录所有的空闲区域,以及每一个区域的大小
其缺陷就是维护空闲表增加了对象分配时的开销,还有就是可能没有一个区域大小能够存放需要分配的对象从而导致分配失败。
整理操作
因为内存碎片可能会引发OOM的缘故,对内存进行整理的操作应运而生,在空闲表的基础上将可达对象内存复制整理,修改指向这些对象的引用。
缺点是GC暂停时间会增加。
复制操作
整理操作之所以耗时是因为需要先标记完成才可以执行整理,而复制操作可以边标记边复制到存活区。
缺点是需要额外的内存空间作为存活区使用。