G1垃圾收集器(6)之写屏障

2021-05-17 12:34:56 浏览数 (1)

Remember Set的写屏障

写屏障是指,在改变特定内存的值(实际上也就是写入内存)的时候额外执行的一些动作。在大多数的垃圾回收算法中,都利用到了写屏障。写屏障通常用于在运行时探测并记录回收相关指针(interesting pointer),在回收器只回收堆中部分区域的时候,任何来自该区域外的指针都需要被写屏障捕获,这些指针将会在垃圾回收的时候作为标记开始的根。JAVA使用的其余的分代的垃圾回收器,都有写屏障。举例来说,每一次将一个老年代对象的引用修改为指向年轻代对象,都会被写屏障捕获,并且记录下来。因此在年轻代回收的时候,就可以避免扫描整个老年代来查找根。

G1垃圾回收器的写屏障和RS是相辅相成的,也就是记录Region内部的指针。这种记录发生在写操作之后。对于一个写屏障来说,过滤掉不必要的写操作是十分有必要的。这种过滤既能加快赋值器的速度,也能减轻回收器的负担。G1垃圾回收器采用的双重过滤

1.过滤掉同一个Region内部引用;2.过滤掉空引用;

G1的垃圾回收器的写屏障使用一种两级的log buffer结构:

1.global set of filled buffer:所有线程共享的一个全局的,存放填满了的log buffer的集合;2.thread log buffer:每个线程自己的log buffer。所有的线程都会把写屏障的记录先放进去自己的log buffer中,装满了之后,就会把log buffer放到 global set of filled buffer中,而后再申请一个log buffer;

写屏障 (Write Barrier) 也是GC里的一个关键技术(不是linux里的membarrier),当发生引用关系的更新时,通过写屏障来(这里指转移用的写入屏障)记录这个引用关系的变更,只是一系列函数而已,就像这样(伪代码):

代码语言:javascript复制
def evacuation_write_barrier(obj, field, newobj){
    //检查引用和被引用新对象是否在同一个区域
    if(!check_cross_ref(obj, newobj)){
        return 
    }
    //不重复添加dirty_card
    if(is_dirty_card(obj)){
        return 
    }
    to_dirty(obj);
    //将obj添加到newobj所在region的rs
    add_to_rs(obj, newobj);
}

为了便于理解,上面的伪代码屏蔽了一些细节,了解核心工作内容即可

0 人点赞