分代垃圾回收,基于的是“大部分的对象,在生成后马上就会变成垃圾”这一经验上的事实为设计出发点。此前讨论过基于引事实的另一个垃圾回收算法,引用计数出的一些优化思路。

 

分代的关键是:

  1. 给对象记录下一个age,随着每一次垃圾回收,这个age会增加;

  2. 给不同age的对象分配不同的堆内内存空间,称为某一代;

  3. 对某一代的空间,有适合其的垃圾回收算法;

  4. 对每代进行不同垃圾回收,一般会需要一个额外的信息:即每代中对象被其他代中对象引用的信息。这个引用信息对于当前代来说,扮演与"root"一样的角色,也是本代垃圾回收的起点。

 

 

分代垃圾回收的典型是Ungar的分代垃圾回收。

它将堆分成如下形式:

seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

 

如上,分成新生代与老年代。

在新生代内,又分成了生成空间与幸存空间。当生成空间满了,会以复制算法进行垃圾回收,复制到幸存空间中。和前面的复制算法匹配,幸存空间又一分为二,分成from和to空间。每次新生代的垃圾回收,会同时进行生成空间到to、from空间到to的两个垃圾回收。

seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

 

对于老年代,则直接进行mark_sweep回收。

对于“记录集”(record set),是记录代间引用的一个数组。它内部不能只记录被引用对象,因为被引用对象被复制到to空间后,引用者本身的引用指针要更新,只记录被引用的新生代内对象是无法找到被引用者的。所以,必须在记录集中记录老年代内对象。

 

更新记录集的操作在分配新对象,并设置成老对象的一个field时进行:

 

seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

write_barrier(obj, field, new_obj) {  if obj >= $old_start && new_obj < $old_start && obj.remembered == false            // 条件,很明显
    $rs[$rs_idx++] = obj                   // 更新记录集