复制算法(copy)
复制算法用于回收新生代
- GC复制算法将堆分成From和To两个内存块,当From被占满时GC将From中的存活对象复制到To中,同时将From和To交换。
- 通过递归遍历GC root(即采用深度优先)复制存活对象,对于已经复制过的标记其COPIED字段。
- 复制过的对象将在From的对象的forwarding记录To中该对象地址,以便于其余引用了该对象的引用进行修改。
- 分配对象时将先判断From中连续可用空间是否够用(复制算法不存在碎片),如果不够则进行一次GC,还不够则分配失败。
优缺点
优点
-
吞吐量大,只需要遍历一次From空间Sweep需要遍历两次,而且只复制存活的对象。
-
高速分配,不需要通过空闲链表直接在连续的内存上进行分配。
-
没有碎片。
-
与缓存兼容,复制存活对象时采用深度优先算法使相关联的对象都在附近。
缺点
- 堆的使用效率低,必须分配一个To,其不能分配对象。
- 不兼容保守式GC算法,需要移动对象。
- 递归调用,复制对象的深度优先算法是通过递归调用实现的,递归将消耗栈等资源。
标记清除(mark - sweep)
分为标记和清除两个阶段进行处理内存中的对象
弊端是空间碎片问题,垃圾回收后的空间是不连续的,不连续的内存空间的工作效率要低于连续的空间
标记整理 (mark - compact)
在标记清除法基础上做了优化,把存活的对象压缩到内存一端,然后进行垃圾清理
总结规律
频繁收集 新生区
较少收集 老年代
基本不动 perm
一般来说:
内存效率: copy算法 > mark-sweep>mark-compact
内存整齐度: copy = mark-compact > mark-sweep
分代收集
当前商业虚拟机的垃圾收集都采用"分代收集"(Generatonal Collecton) 算法,但是这种算法并没有什么创新,只是根据对象的存活周期不同将内存划分成新生代和老年代根据各个年代的特点采用最适当的收集算法。
比如:在新生代中,每次回收发现有大批对象死去,较少对象存活就选用copy算法,而老年代中因为对象存活较高就使用标记( mark-sweep)或者整理( mark-compact)就解决问题了。
以上先总结这些。