Skip to content

g1 mark Meta_Space_GC

ceragon edited this page Dec 18, 2021 · 1 revision

元空间回收触发标记

触发流程

  1. 在元空间的收集时,也会触发到 GC 的逻辑中。下面是调用的方法
bool VM_CollectForMetadataAllocation::initiate_concurrent_GC() {
    // 是否 G1 GC,另一个参数的默认值是 true
    if (UseG1GC && ClassUnloadingWithConcurrentMark) {
        // 是否应该启动标记循环
        bool should_start = g1h->g1_policy()->force_initial_mark_if_outside_cycle(_gc_cause);
        if (should_start) {
            g1h->do_collection_pause_at_safepoint(pause_target);
        }
        return true;
    }
}
  1. 调用 initiate_concurrent_GC() 的类和方法如下:
class VM_CollectForMetadataAllocation: public VM_GC_Operation: public VM_Operation {
    // 所有继承自 VM_Operation 的类都是在 VM Thread 中执行
    // 该类的对象一旦被 VM Thread 开始执行,会先申请 STW
    // 等 STW 成功后,会执行 doit() 方法
}
void VM_CollectForMetadataAllocation::doit() {
    // 该参数默认是 false
    if (!MetadataAllocationFailALot) {
        // 默认情况下,会进入到该方法
        // 可以理解为尝试在元空间分配空间,分配成功返回 true
        _result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
        if (_result != NULL) {
            // 分配成功
            return;
        }
    }
    // 调用目标方法
    if (initiate_concurrent_GC()) {
    }
}
  1. 调用上面那个类构造方法的位置如下
MetaWord* CollectedHeap::satisfy_failed_metadata_allocation(ClassLoaderData* loader_data,
                                                            size_t word_size,
                                                            Metaspace::MetadataType mdtype) {
    // 在元空间分配空间
    MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype);
    if (result != NULL) {
        // 分配成功
        return result;
    }
    // 分配空间失败,被迫走 GC 流程
    VM_CollectForMetadataAllocation op(loader_data,
                                       word_size,
                                       mdtype,
                                       gc_count,
                                       full_gc_count,
                                       GCCause::_metadata_GC_threshold);
    VMThread::execute(&op);
}

Clone this wiki locally