BYTECODES

垃圾回收算法

分代收集理论

是一套经验法则

  1. 弱分代假说:大部分对象都是短暂存活的

  2. 强分代假说:熬过越多次垃圾回收的对象越难消亡

  3. 跨代引用假说:跨代引用相对于同代引用来说,只占极少数

    基于这两个假说,绝大多数垃圾回收器都是把堆划分为不同的区域,然后将对象根据不同的年龄放到不同的区域中。但是因为不同的年龄代肯定会相互引用,为了避免回收一个区域,还需要把另一个区域遍历一次带来的性能问题,就还有一个假设,即跨代引用假设。根据这条假说,只需要在新生代维护一个全局的数据结构,这个结构把老年代分为若干小区域,并标识哪一块内存存在跨代引用。垃圾收集时只需要包含这些区域的对象即可。

标记清除

分两个阶段:先标记,然后清除

缺点:

  1. 效率不稳定,如果存在大量的对象需要回收,那就需要大量的标记和清理动作。

  2. 碎片问题

标记复制

将内存区域分为两半,每次分配对象内存时使用其中一个区域,需要回收时,把存活下来的对象复制到另一个区域,本区域直接清除。

优点是简单高效

缺点:

  1. 太浪费内存,改善的办法是可以不按1:1划分区域,比如Appel式回收:把新生代一块较大的Eden空间和两块较小的 Survivor空间,每次内存分配时只使用Eden和其中的一个Survivor空间,发生垃圾回收时,把存活的对象一次性复制到另一块Survivor空间然后直接清理掉Eden和已用过的那块Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8∶1,当Survivor空间不足以容纳一次Minor GC之后存活的对象时,就需要依赖其他内存区域(实际上大多就是老年代)进行分配担保(Handle Promotion)。

  2. 如果存在大量存活对象,那么就需要很多的复制操作,导致效率低下。

标记整理

由于第二个缺点,通常老年代不直接使用标记复制算法。

针对老年代对象的存亡特征, 1974年Edward Lueders设计了标记整理算法,也分两阶段,但整理阶段是把存活的对象向内存空间的一端进行移动。然后清理掉剩余的内存。

缺点:由于移动对象,当存活对象比较多时,移动对象并更新引用将会是比较繁重的操作。