G1垃圾收集 - Mixed GC:
- 初始标记阶段 - Initial Mark
并发标记阶段 - Concurrent Mark
- 最终标记阶段 - Remark
- 清理阶段 - Clean Up
并发标记阶段 - Concurrent Mark
特性:
- 并发 - 与Mutator并发进行
- 并发阶段Mutator产生的新的引用或引用的更新,会被SATB的写屏障记录下来
- 以初始标记的根出发进行深度扫描
- 标记过程可以被Young GC打断
并发标记步骤:
markFromRoots
从根开始扫描标记- 创建并发标记任务类
CMConcurrentMarkingTask
- 循环执行标记任务
do_marking_step
- 处理satb缓冲区
drain_satb_buffers
、处理本地队列drain_local_queue
、处理全局栈drain_global_stack
process_grey_object
根据nextMarkBitMap中标记的对象,针对每个对象的field递归并发标记、即染灰
结果:
标记出整个堆的存活对象,统计存活数量
源码分析:
并发标记源码在:concurrentMark.cpp
void ConcurrentMark::markFromRoots() {
//重置溢出启动标记标志
_restart_for_overflow = false;
force_overflow_conc()->init();
//获取并行标记线程
_parallel_marking_threads = calc_parallel_marking_threads();
uint active_workers = MAX2(1U, parallel_marking_threads());
//设置并行任务结束符
set_concurrency_and_phase(active_workers, true /* concurrent */);
//创建任务类CMConcurrentMarkingTask 执行并发标记
CMConcurrentMarkingTask markingTask(this, cmThread());
//根据并行策略执行
if (use_parallel_marking_threads()) {
_parallel_workers->set_active_workers((int)active_workers);
_parallel_workers->run_task(&markingTask);
} else {
markingTask.work(0);
}
print_stats();
}
我们继续追CMConcurrentMarkingTask
的work
方法:
- 处理SATB 缓存
- 根据已经标记的分区nextBitMap位图对象进行处理,针对每个已标记对象的每个field进行递归并发标记
public:void work(uint worker_id) {
ResourceMark rm;
//当发生同步时,进行等待
SuspendibleThreadSet::join();
//根据work_id 读取并发标记任务
CMTask* the_task = _cm->task(worker_id);
if (!_cm->has_aborted()) {
do {
// 可以通过参数设置并发标记目标时间,默认值10ms,标识并发标记在10ms内完成
double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
//开始执行并发标记
the_task->do_marking_step(mark_step_duration_ms,//超时时间
true /* do_termination */,
false /* is_serial*/);
......
//清理溢出标记
_cm->clear_has_overflown();
_cm