jvm系列算法
为了支持高频率的新生代的回收,虚拟机使用一种叫作卡表(Card Table)的数据结构,卡表做为一个比特位的集合,每个比特位能够用来表示年老代的某一区域中的全部对象是否持有新生代对象的引用。
这样新生代在GC时,能够不用花大量的时间扫描全部年老代对象,来肯定每个对象的引用关系,而能够先扫描卡表,只有卡表的标记位为1时,才须要扫描给定区域的年老代对象。而卡表位为0的所在区域的年老代对象,必定不包含有对新生代的引用。
卡表中每个位表示年老代4K的空间,卡表记录未0的年老代区域没有任何对象指向新生代,只有卡表位为1的区域才有对象包含新生代引用,所以在新生代GC时,只须要扫描卡表位为1所在的年老代空间。使用这种方式,能够大大加快新生代的回收速度。
卡表是个单字节数组,每一个数组元素对应堆中的一张卡。
每次年老代对象中某个引用新生代的字段发生变化时,Hotspot VM就必须将该卡所对应的卡表元素设置为适当的值,从而将该引用字段所在的卡标记为脏。在Minor GC过程当中,垃圾收集器只会在脏卡中扫描查找年老代-新生代引用。
Hotspot VM的字节码解释器和JIT编译器使用写屏障维护卡表。写屏障是一小段将卡状态设置为脏的代码。解释器每次执行更新引用的字节码时,都会执行一段写屏障,JIT编译器在生成更新引用的代码后,也会生成一段写屏障。虽然写屏障使得应用线程增长了一些性能开销,但Minor GC变快了许多,总体的垃圾收集效率也提升了许多,一般应用的吞吐量也会有所改善。