在G1收集器中.Regin之间的对象引用以及其他收集器中的新生代与老年代之间的对象引用,虚拟机都是使用Remenbered Set 来避免全堆扫描的.G1中每个Regin都有一个与之对应的Remenbered Set,虚拟机发现程序在对Reference类型的数据进行写操作时,会产生一个Write Barrier暂时中断写操作,检查Reference引用的对象是否处于不同的Regin之中(在分代的例子中就是检查是否老年代中的对象引用了新生代的对象).如果是,便通过CardTable把相关引用信息记录到被引用对象所属的Regin的Remenbered Set即可保证不对全堆扫描也不会有遗漏.
G1收集器的运作大致可划分为一下几个步骤: I.初始化标记(Initial Marking) II.并发标记(Concurrent Marking) III.最终标记(Final Marking) IV. 筛选回收(Live Data Counting and Evacuation)
初始标记阶段仅仅是标记一下GC Roots能直接关联到的对象,并且修改TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的Regin中创建对象.这阶段需要停顿线程,但耗时很短. 并发标记阶段是从GC Root 开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户进程并发执行. 最终标记阶段则是为了修正在并发标记期间因用户程序继续执行运作导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remenbered Set Logs里面,最终标记阶段需要把Remenbered Set Logs的数据合并到Remenbered Set中,这个阶段需要停顿线程,但是可并行执行. 筛选回收阶段首先对各个Regin的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划.这个阶段也可以做到与用户程序一起并发执行,但是因为回收一部分Regin,时间是用户可控制的,而且停顿用户线程将大幅度提高收集效率. 本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-03/129398.htm