第三章:垃圾回收器-G1收集器

G1是一款面向服务端的垃圾回收器,它是作用是替换到JDK1.5中发布的CMS收集器,与其他收集器相比,G1具有以下优点:
  • 并行与并发
利用多核CPU来缩短Stop the world停顿的时间,G1收集器可以通过并发的方式让Java程序与GC并发执行。
  • 分代收集
G1收集器任然保留分代收集的方式;
G1收集器可以不需要其他收集器配合就能单独管理整个堆,它可以采用不同的方式处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象从而获得更好的收集效果。
  • 空间整理
与GMS的“标记-清除”算法不同,G1收集器从整理上看是“标记-整理”算法实现的收集器,从局部看(两个Region之间)上看是基于“复制”算法实现的,从这两种算法来看那G1运行期间不会产生内存空间碎片,收集器能提供规整的可用空间,这种特性有利于程序长时间运行,分配大对象时不会因为无法分配到连续的内存空间而提前触发下一次GC。
  • 可预测的停顿
G1相比于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型:能让使用者明确指出在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不超过N毫秒。
 
G1之前的其他收集器进行收集的范围都是整个新生代或者老年代,但是G1是将整个堆划分为多个大小相等的独立区域(region),虽然也保留了新生代和老年代的概念,但是新生代和老年代不再是物理上隔离的,它们都是一部分region(不需要连续)的集合。
G1收集器之所以能够实现可预测的停顿时间,是因为它可以有计划的避免在整个Java堆中进行全区域的垃圾回收。G1跟踪每个region里的垃圾堆积的大小(回收所获得的空间大小以及回收所需要时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先收集价值最大的region,这种使用region划分空间以及有优先级的区域回收方式,保证了G1收集器在有限的时间内可以获得尽可能高的收集率。
需要注意的是Region不可能是孤立,一个对象分配在某个region中,它并非只能被本region中的其他对象引用,而是可以与整个Java堆任何的对象发生引用关系,那么在做可达性分析算法时,岂不是要扫描整个Java堆?
G1收集器解决上面问题的办法是G1在每个region都有一个与之对应的remembered Set,虚拟机发现程序对reference类型的数据进行写操作时,会产生一个Write Barrier暂时中断写操作,检查reference引用的对象是否处于不同的region中(老年代的对象引用了新生代的对象),如果是,变通过CardTable把相关引用信息记录到被引用对象所属的region的remembered Set中,当进行内存回收时,在GC枚举根节点时,可以对加入remembered Set,即保证不对全堆扫面也不会遗漏。
在不维护remembered set的操作情况下,G1操作分为以下几个步骤:
  • 初始标记
标记GC Roots能直接关联的对象,并且修改TAMS(next top at mark Start)的值,让下一阶段用户程序并发运行,这段时间需要停顿线程,但是耗时很短。
  • 并发标记
从GC Roots开始对堆中对象进行可达性分析,找出存货对象,这阶段耗时较长,但是可以用户程序并发执行。
  • 最终标记
为了修正在并发标记过程中由于用户线程运行导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象记录在线程remembered Set logs里。同时需要把remembered Set logs的数据合并到Remembered set中,这阶段将停止线程,但是可并行执行。
  • 筛选回收
首先对region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。这个步骤也需要停止用户线程。
 

猜你喜欢

转载自www.cnblogs.com/use-D/p/10674534.html