hotspot串行GC之full gc分析

1.概述

hotspot串行GC之full gc主要包括四个步骤,依次是:

1.从根引用出发,标记所有可达对象(如图灰色部分)

hotspot串行GC之full gc分析_第1张图片
 

2.为每个可达对象计算full gc后将移动到的新位置(图中虚线框其实与contigCompatableSpace是重叠的,分开只是为了更加清晰)

hotspot串行GC之full gc分析_第2张图片
 

3.将根引用以及所有可达对象中的oop字段修改为指向第二步中计算出的新位置(实线箭头修改为双实线箭头)

hotspot串行GC之full gc分析_第3张图片
 

4.将所有可达对象移动到第二步中计算出的新位置

hotspot串行GC之full gc分析_第4张图片
 

2.伪代码

http://leafinwind.iteye.com/blog/2013687

 

phase1的关键之处在于依靠一个stack来遍历根引用的所有可达对象。

 

phase2有两个很精妙的地方,首先是对space从bottom开始的连续的活对象,清除了这些对象的gc_mark标记已经forward字段,因为这些对象最终并不需要移动,space的_first_dead记录了第一个死对象的地址;第二是对连续的死对象,将其中第一个死对象的forward字段置为了右端最近的活对象地址,这样后续的phase3和phase4就可以跳过对这片连续死对象区域的扫描。

 

phase3遍历所有活对象,将它们的oop字段都修改为第二步中计算出的新位置。这里需要说明的是对[bottom,_first_dead)区间的特殊处理,因为其中的对象在第二步中已经清除gc_mark了。

 

phase4遍历所有活对象,将它们移动到新的位置。注意处理过程[bottom,_first_dead->forwardee())区间都可以跳过。

 

3.与hotspot代码的对应关系

phase1对应hotspot代码的GenMarkSweep::mark_sweep_phase1方法

调用gch->gen_process_strong_roots处理根引用,使用的follow_root_closure是一个FollowRootClosure,其do_oop方法在mark当前根引用指向对象的同时,还会将该对象中的所有oop字段压入一个栈中(见MarkSweep::mark_and_push方法),然后从“右侧”深度优先的mark所有间接引用的对象,直到栈为空。

 

phase2对应GenMarkSweep::mark_sweep_phase2(),要点在伪代码中都已提到,不同之处主要在于:

1.伪代码只用了一个space,而hotspot是三个:依次遍历old gen,eden和from中的对象,将它们的forward地址首先置为old gen中的地址,填满后则依次再使用eden和from。注意这里的一个暗含的意思是full gc会将young gen中的对象直接拷入old gen,与对象年龄什么的都没有关系,并且很可能一次full gc后young gen会被清空。

2.为尽量在old gen的开头获得一片连续的活对象区间,hotspot在一定的设置下允许将部分死对象初始化为无意义的对象填充进去。

 

phase3对应GenMarkSweep::mark_sweep_phase3。

 

phase4对应GenMarkSweep::mark_sweep_phase4(),与伪代码的不同也在于hotspot有三个space。另外如果eden和from中的对象都拷入了old gen,那么它们的compact_top指针会等于bottom指针,这时会对相应space做一些清理工作。

 

 

你可能感兴趣的:(HotSpot)