一、三种垃圾回收算法
1、标记清除(已废弃)
- 找到根对象(局部变量正在引用的对象、静态变量正在引用的对象);
- 沿着根对象的引用链,查看当前的对象是否被根对象所引用,若被引用,则加上标记;
- 加标记的对象保留下来,其余的释放掉;
缺点:
- 会造成内存碎片问题;
因为未被引用的对象一般不连续,所以当需要一段连续的内存时,每一段内存都不够用;
2、标记整理(老年代)
- 前三步和标记清除法一致;
- 在清除后会将引用对象整理为一段连续的内存,从而避免了内存碎片的问题;
缺点:
- 效率较低:
因为有整理的操作,会有引用地址的重新计算和内存复制。
3、标记复制(新生代)
将存活的对象复制到新的内存空间中,将原来的内存直接删掉。
缺点:
- 占用了一份额外的内存;
- 当存活对象较多时,会复制很多次;
二、GC和分代回收算法
GC的目的在于实现无用对象内存自动释放,减少内存碎片、加快分配速度
- 回收区域是堆内存,不包括虚拟机栈,在方法调用结束会自动释放方法占用内存。
- 判断无用对象,使用可达性分析算法,三色标记法标记存活对象,回收未标记对象
- GC具体的实现称为垃圾回收器。
- GC大都采用了分代回收思想,理论依据是大部分对象朝生夕灭,用完立刻就可以回收,另有少部分对象会长时间存活,每次很难回收,根据这两类对象的特性将回收区域分为新生代和老年代,不同区域应用不同的回收策略。
- 根据GC的规模可以分成 Minor GC,Mixed GC,Full GC。
1、分代回收
- 伊甸园eden,最初对象都分配到这里,与幸存区合称新生代
- 幸存区survivor,当伊甸园内存不足,回收后的幸存对象到这里,分成 from和to,采用标记复制算法
- 老年代 old,当幸存区对象熬过几次回收(最多15次),晋升到老年代(幸存区内存不足或大对象会导致提前晋升)
2、GC规模
- Minor GC发生在新生代的垃圾回收,暂停时间短
- Mixed GC新生代+老年代部分区域的垃圾回收,G1收集器特有
- Full GC新生代+老年代完整垃圾回收,暂停时间长,应尽力避免
三、三色标记与并发漏标问题
- 黑色–已标记
- 灰色–标记中
- 白色–还未标记
1、lncremental Update
- 只要赋值发生,被赋值的对象就会被记录(用户线程结束后,重新检查引用)
2、Snapshot At The Beginning,SATB
- 新加对象会被记录(用户线程结束后,重新检查引用)
- 被删除引用关系的对象也被记录