Generation GC and CardTable

分代垃圾回收

现代所有带有垃圾回收功能的语言都采用了分代垃圾回收机制,其原因主要基于以下几点:

  1. 几乎所有的对象生命周期都很短,存活的时间不超过数个垃圾回收周期
  2. 一次GC中通常有超过90%的对象都是上次GC后所创建的
  3. 假如一个对象存活了多个垃圾回收周期,GC将会一次又一次对这个对象进行标记

Bytes allocated

分代垃圾回收算法实现

程序运行时产生的对象可通过多种方式被分为不同的代,通常是根据对象存活的时间来确定。

通常低代的内存块将被回收得更加频繁,引起较短的系统暂停;高代的内存块回收评论较低,但会引起较长的系统暂停。

假设我们程序的内存被分为两块:低代的Gen0与高代的Gen1。新分配的对象使用Gen0中的空间。

gen-1

内存中一共有4个对象,此时我们将内存中的一个引用释放掉

gen-2

假如此时触发了GC,程序会发现Gen0中有两个对象已经不可达了,于是将它们清理掉。

gen-3

经过多轮GC后,这两个对象仍然处于存活状态,程序会将其晋升至Gen1中,即老年代中

gen-4

现在,假设在程序运行过程中分配了许多个对象出来,在下一次GC开始时内存里的对象保存情况如下:

gen-5

当我们只进行Gen0(新生代)的GC时,从Root开始寻找可达的对象,在不扫描Gen1的情况下,只能找到标记有✓的这几个。因为它们是root直接可达的,红色箭头所指向的对象由于是间接可达将无法被扫描到。

如果对整个内存空间进行扫描,时间耗费将非常巨大,因为Gen1(老年代)中所包含的对象数量将远远大于Gen0中的对象数。

因此,所有的分代收集算法都会采用一定方式将含有Gen0对象引用的Gen1对象记录下来,当执行Gen0内存区域的垃圾回收时,将这些对象也作为root对待,就避免了对Gen1区域的整体扫描。是一种典型的以空间换时间的算法。具体实现如下图所示:

gen-6

Card Table

通常来说,老年代的空间大小往往比新生代要大得多,里面对象的数量也非常多。如果我们以引用的方式来保存对象,这个数据结构所占用的空间可能非常大。为了加快一点GC的速度,使得程序整体内存占用上升了30%-40%,这样的开销是否值就有待商榷了。因此,记录老年代空间大小的数据结构有以下两个特点:

  1. 占用的内存空间必须非常小
  2. 老年代中持有新生代对象的数量通常较少,是一种比较稀疏的映射结构

基于以上两点,几乎所有的分代算法都采用了Card Table的方式保存持有新生代引用的老年代对象信息。

保存对象二元状态且最省空间的数据结构必然是bitmap,Card Table也是bitmap的一个变种。它采用一个bit位代表老年代内存中的一片空间,如果这片空间中包含持有新生代引用的对象,就将这片空间至1(标记为dirty)。这样,我们就得到了一个不那么精确的结果:我们知道了哪些空间中包含了持有新生代对象引用的老年代对象。在进行垃圾回收时,只需要将这些对象遍历一次,就能够精确的知道哪些对象是我们所需的。

cardtable

如上图所示,Card Table中一个bit代表实际内存中4KB的空间。从原理可知:CardTable中bit所映射的空间越小,所包含的信息也就越模糊;映射的空间越大,所占用的内存空间也就越多。JVM中Card Table一个bit对应的内存空间为512byte。

Write Barrier

从CardTable原理可知,每当引用关系被创建或改变时,都有可能需要对Card Table进行修改。因此,在含有GC的高级语言中,通常会在赋值语句(即含有=)的前后进行一些逻辑操作。这种类似AOP的机制就被成为Write Barrier。例如:

a.val = b;

当JVM执行上述语句时,实际上在虚拟机中执行的语句为:

void oop_field_store(oop* field, oop value) { 
  pre_write_barrier(field); 
  *field = value; // the actual store 
  post_write_barrier(field, value); 
}

代码中的pre_write_barrier()与post_write_barrier()都是write barrier,JVM会在这个方法中对引用或对象做一些额外的操作。其他高级语言类似C#、js等都有此类机制。

总结

分代垃圾回收机制是计算机科学家们根据实际使用的情况对于GC算法做的一种倾向性优化,为了避免分代之后对整个程序运行的内存空间进行遍历,各个高级语言采用了Card Table与Write Barrier以空间换时间的方式优化了新生代的垃圾收集效率,最终得到了一种效率非常高的垃圾回收算法。

原文:大专栏  Generation GC and CardTable


猜你喜欢

转载自www.cnblogs.com/wangziqiang123/p/11618365.html
GC