美文网首页
GenCollectedHeap

GenCollectedHeap

作者: 程序员札记 | 来源:发表于2022-12-12 10:39 被阅读0次

    本篇开始讲解表示分代堆内存的GenCollectedHeap的实现细节。

    1、定义
    GenCollectedHeap的定义在hotspot\src\share\vm\memory\genCollectedHeap.hpp中,其类继承关系如下:

    image.png

    其中CollectedHeap的讲解参考《Hotspot 垃圾回收之CollectedHeap 源码解析》 ,SharedHeap新增的属性如下:

    • static SharedHeap* _sh; //静态SharedHeap实例
    • GenRemSet* _rem_set; //卡表实现
    • CollectorPolicy *_collector_policy; //垃圾回收策略
    • int _strong_roots_parity; //遍历Java线程包含的oop使用的
    • FlexibleWorkGang* _workers; //执行并行GC的线程池
    • bool _thread_holds_heap_lock_for_gc;

    GenCollectedHeap新增的属性如下:

    • static GenCollectedHeap* _gch; //静态GenCollectedHeap实例
    • int _n_gens; //包含的Generation的个数,通常是2
    • Generation* _gens[max_gens]; //Generation数组
    • GenerationSpec** _gen_specs; //用来初始化Generation的GenerationSpec数组
    • GenCollectorPolicy* _gen_policy; //垃圾回收策略
    • bool _incremental_collection_failed; // 执行promote是否会失败
    • unsigned int _full_collections_completed; //已经执行万恒的Full GC的次数
    • SubTasksDone* _process_strong_tasks; //用于控制根节点遍历任务的并行执行

    其中max_gens是一个常量枚举,其定义如下:

    image.png

    除此之外还有一个表示并行执行任务的序号的枚举GCH_strong_roots_tasks,其定义如下:


    image.png

    重点关垃圾回收相关方法的实现。

    2、构造方法 / initialize / post_initialize
    这三个方法按照顺序依次调用,用来初始化GenCollectedHeap,其实现如下:

    GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy) :
      SharedHeap(policy),
      _gen_policy(policy),
      _process_strong_tasks(new SubTasksDone(GCH_PS_NumElements)),
      _full_collections_completed(0)
    {
      assert(policy != NULL, "Sanity check");
    }
     
    SharedHeap::SharedHeap(CollectorPolicy* policy_) :
      CollectedHeap(),
      _collector_policy(policy_),
      _rem_set(NULL),
      _strong_roots_parity(0),
      _workers(NULL)
    {
      //初始化静态属性_sh
      _sh = this;  // ch is static, should be set only once.
      if ((UseParNewGC ||
          (UseConcMarkSweepGC && (CMSParallelInitialMarkEnabled ||
                                  CMSParallelRemarkEnabled)) ||
           UseG1GC) &&
          ParallelGCThreads > 0) {
        //初始化执行并行GC的线程池  
        _workers = new FlexibleWorkGang("Parallel GC Threads", ParallelGCThreads,
                                /* are_GC_task_threads */true,
                                /* are_ConcurrentGC_threads */false);
        if (_workers == NULL) {
          vm_exit_during_initialization("Failed necessary allocation.");
        } else {
          _workers->initialize_workers();
        }
      }
    }
     
    GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy) :
      SharedHeap(policy),
      _gen_policy(policy),
      _process_strong_tasks(new SubTasksDone(GCH_PS_NumElements)),
      _full_collections_completed(0)
    {
      assert(policy != NULL, "Sanity check");
    }
     
    jint GenCollectedHeap::initialize() {
      CollectedHeap::pre_initialize();
     
      int i;
      //_n_gens表示有多少代,通常是2代,年轻代和老年代
      _n_gens = gen_policy()->number_of_generations();
     
      guarantee(HeapWordSize == wordSize, "HeapWordSize must equal wordSize");
     
      size_t gen_alignment = Generation::GenGrain;
      _gen_specs = gen_policy()->generations();
      for (i = 0; i < _n_gens; i++) {
        //将内存的初始值和最大值按照内存分配粒度对齐
        _gen_specs[i]->align(gen_alignment);
      }
     
      char* heap_address;
      size_t total_reserved = 0;
      int n_covered_regions = 0;
      ReservedSpace heap_rs;
     
      size_t heap_alignment = collector_policy()->heap_alignment();
      //根据各GenerationSpec的最大大小计算总的需要保留的内存空间,然后申请指定大小的连续内存空间
      heap_address = allocate(heap_alignment, &total_reserved,
                              &n_covered_regions, &heap_rs);
     
      if (!heap_rs.is_reserved()) {
        //申请失败
        vm_shutdown_during_initialization(
          "Could not reserve enough space for object heap");
        return JNI_ENOMEM;
      }
     
      //设置_reserved相关属性
      _reserved = MemRegion((HeapWord*)heap_rs.base(),
                            (HeapWord*)(heap_rs.base() + heap_rs.size()));
      _reserved.set_word_size(0);
      _reserved.set_start((HeapWord*)heap_rs.base());
      size_t actual_heap_size = heap_rs.size();
      _reserved.set_end((HeapWord*)(heap_rs.base() + actual_heap_size));
     
      //初始化GenRemSet
      _rem_set = collector_policy()->create_rem_set(_reserved, n_covered_regions);
      set_barrier_set(rem_set()->bs());
     
      _gch = this;
     
      for (i = 0; i < _n_gens; i++) {
        //初始化各Generation
        ReservedSpace this_rs = heap_rs.first_part(_gen_specs[i]->max_size(), false, false);
        _gens[i] = _gen_specs[i]->init(this_rs, i, rem_set());
        heap_rs = heap_rs.last_part(_gen_specs[i]->max_size());
      }
     
      //将_incremental_collection_failed置为false
      clear_incremental_collection_failed();
     
    #if INCLUDE_ALL_GCS
      if (collector_policy()->is_concurrent_mark_sweep_policy()) {
        //如果是CMS则创建CMSCollector
        bool success = create_cms_collector();
        if (!success) return JNI_ENOMEM;
      }
    #endif // INCLUDE_ALL_GCS
     
      return JNI_OK;
    }
     
    char* GenCollectedHeap::allocate(size_t alignment,
                                     size_t* _total_reserved,
                                     int* _n_covered_regions,
                                     ReservedSpace* heap_rs){
      const char overflow_msg[] = "The size of the object heap + VM data exceeds "
        "the maximum representable size";
     
      // Now figure out the total size.
      size_t total_reserved = 0;
      int n_covered_regions = 0;
      const size_t pageSize = UseLargePages ?
          os::large_page_size() : os::vm_page_size();
     
      assert(alignment % pageSize == 0, "Must be");
      
      //遍历所有的_gen_specs,累加各GenerationSpec的max_size和n_covered_regions
      for (int i = 0; i < _n_gens; i++) {
        total_reserved += _gen_specs[i]->max_size();
        if (total_reserved < _gen_specs[i]->max_size()) {
          vm_exit_during_initialization(overflow_msg);
        }
        n_covered_regions += _gen_specs[i]->n_covered_regions();
      }
      //校验累加后的total_reserved已经是内存对齐的
      assert(total_reserved % alignment == 0,
             err_msg("Gen size; total_reserved=" SIZE_FORMAT ", alignment="
                     SIZE_FORMAT, total_reserved, alignment));
     
      //加2是为卡表保留的
      n_covered_regions += 2;
      
      //赋值
      *_total_reserved = total_reserved;
      *_n_covered_regions = n_covered_regions;
      //申请指定大小的连续内存空间
      *heap_rs = Universe::reserve_heap(total_reserved, alignment);
      //返回基地址
      return heap_rs->base();
    }
     
    void SharedHeap::set_barrier_set(BarrierSet* bs) {
      _barrier_set = bs;
      oopDesc::set_bs(bs);
    }
     
      void clear_incremental_collection_failed() {
        _incremental_collection_failed = false;
      }
     
    void GenCollectedHeap::post_initialize() {
      SharedHeap::post_initialize();
      TwoGenerationCollectorPolicy *policy =
        (TwoGenerationCollectorPolicy *)collector_policy();
      guarantee(policy->is_two_generation_policy(), "Illegal policy type");
      //校验Generation被正确的设置了
      DefNewGeneration* def_new_gen = (DefNewGeneration*) get_gen(0);
      assert(def_new_gen->kind() == Generation::DefNew ||
             def_new_gen->kind() == Generation::ParNew ||
             def_new_gen->kind() == Generation::ASParNew,
             "Wrong generation kind");
     
      Generation* old_gen = get_gen(1);
      assert(old_gen->kind() == Generation::ConcurrentMarkSweep ||
             old_gen->kind() == Generation::ASConcurrentMarkSweep ||
             old_gen->kind() == Generation::MarkSweepCompact,
        "Wrong generation kind");
      //初始化TwoGenerationCollectorPolicy
      policy->initialize_size_policy(def_new_gen->eden()->capacity(),
                                     old_gen->capacity(),
                                     def_new_gen->from()->capacity());
      policy->initialize_gc_policy_counters();
    }
     
    void SharedHeap::post_initialize() {
      CollectedHeap::post_initialize();
      ref_processing_init();
    }
     
    void CollectedHeap::post_initialize() {
      collector_policy()->post_heap_initialize();
    }
     
    void GenCollectedHeap::ref_processing_init() {
      SharedHeap::ref_processing_init();
      for (int i = 0; i < _n_gens; i++) {
        //初始化各代的ReferenceProcessor
        _gens[i]->ref_processor_init();
      }
    }
     
      Generation* get_gen(int i) const {
        guarantee(i >= 0 && i < _n_gens, "Out of bounds");
        return _gens[i];
      }
    

    其调用链如下:

    image.png
    image.png image.png

    3、do_collection
    do_collection是GenCollectedHeap执行垃圾回收的核心方法,其底层核心就是各Genaration的collect方法,注意其实现如下:

    void GenCollectedHeap::do_collection(bool  full,
                                         bool   clear_all_soft_refs,
                                         size_t size,
                                         bool   is_tlab,
                                         int    max_level) {
      bool prepared_for_verification = false;
      ResourceMark rm;
      DEBUG_ONLY(Thread* my_thread = Thread::current();)
      
      //校验处于安全点上
      assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
      //校验调用线程是VMThread 或者CMS Thread
      assert(my_thread->is_VM_thread() ||
             my_thread->is_ConcurrentGC_thread(),
             "incorrect thread type capability");
      //校验获取了Heap_lock锁
      assert(Heap_lock->is_locked(),
             "the requesting thread should have the Heap_lock");
      guarantee(!is_gc_active(), "collection is not reentrant");
      assert(max_level < n_gens(), "sanity check");
     
      //检查是否有线程处于JNI关键区,check_active_before_gc返回true表示有,则终止当前GC,等待线程退出
      //最后一个退出的线程会负责执行GC
      if (GC_locker::check_active_before_gc()) {
        return; // GC is disabled (e.g. JNI GetXXXCritical operation)
      }
     
      //是否需要清除软引用
      const bool do_clear_all_soft_refs = clear_all_soft_refs ||
                              collector_policy()->should_clear_all_soft_refs();
      
      //ClearedAllSoftRefs通过析构函数设置CollectorPolicy的_all_soft_refs_clear属性
      ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy());
      
      //获取元空间已使用内存
      const size_t metadata_prev_used = MetaspaceAux::used_bytes();
      //打印GC的堆内存使用情况
      print_heap_before_gc();
     
      {
        //临时设置_is_gc_active为true,表示GC开始了
        FlagSetting fl(_is_gc_active, true);
     
        bool complete = full && (max_level == (n_gens()-1));
        const char* gc_cause_prefix = complete ? "Full GC" : "GC";
        TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
        GCTraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, NULL, GCId::peek());
        
        //遍历各Generation执行GC准备工作
        gc_prologue(complete);
        //增加GC次数
        increment_total_collections(complete);
        //统计总的内存使用量
        size_t gch_prev_used = used();
     
        int starting_level = 0;
        if (full) {
          //找到老年代对应的level
          for (int i = max_level; i >= 0; i--) {
            if (_gens[i]->full_collects_younger_generations()) {
              starting_level = i;
              break;
            }
          }
        }
     
        bool must_restore_marks_for_biased_locking = false;
     
        int max_level_collected = starting_level;
        for (int i = starting_level; i <= max_level; i++) {
          if (_gens[i]->should_collect(full, size, is_tlab)) {
            //如果需要垃圾回收
            if (i == n_gens() - 1) {  // a major collection is to happen
              //如果是老年代
              if (!complete) {
                //increment_total_collections方法只有在complete为true时才会增加_total_full_collections计数
                //此处complete为false,但还是老年代的GC,所以增加计数
                increment_total_full_collections();
              }
              //根据参数配置dump
              pre_full_gc_dump(NULL);    // do any pre full gc dumps
            }
        
            GCTraceTime t1(_gens[i]->short_name(), PrintGCDetails, false, NULL, GCId::peek());
            TraceCollectorStats tcs(_gens[i]->counters());
            TraceMemoryManagerStats tmms(_gens[i]->kind(),gc_cause());
     
            size_t prev_used = _gens[i]->used();
            //增加计数
            _gens[i]->stat_record()->invocations++;
            _gens[i]->stat_record()->accumulated_time.start();
     
            //记录各Generation的Space的top指针,生产版本为空实现
            record_gen_tops_before_GC();
     
            if (PrintGC && Verbose) {
              gclog_or_tty->print("level=%d invoke=%d size=" SIZE_FORMAT,
                         i,
                         _gens[i]->stat_record()->invocations,
                         size*HeapWordSize);
            }
     
            if (VerifyBeforeGC && i >= VerifyGCLevel &&
                total_collections() >= VerifyGCStartAt) {
              HandleMark hm;  // Discard invalid handles created during verification
              if (!prepared_for_verification) {
                prepare_for_verify();
                prepared_for_verification = true;
              }
              Universe::verify(" VerifyBeforeGC:");
            }
            COMPILER2_PRESENT(DerivedPointerTable::clear());
     
            if (!must_restore_marks_for_biased_locking &&
               //DefNewGeneration返回false,ConcurrentMarkSweepGeneration采用父类默认实现返回true
                _gens[i]->performs_in_place_marking()) {
              must_restore_marks_for_biased_locking = true;
              //将各线程的持有偏向锁的oop的对象头保存起来
              BiasedLocking::preserve_marks();
            }
     
            // Do collection work
            {
              
              HandleMark hm;  // Discard invalid handles created during gc
              save_marks();   // save marks for all gens
              
              ReferenceProcessor* rp = _gens[i]->ref_processor();
             
              if (rp->discovery_is_atomic()) {
                rp->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
                rp->setup_policy(do_clear_all_soft_refs);
              } else {
                //collect方法会调用enable_discovery方法
              }
              //执行垃圾回收
              _gens[i]->collect(full, do_clear_all_soft_refs, size, is_tlab);
              if (!rp->enqueuing_is_done()) {
                //enqueuing_is_done为false
                //将处理后剩余的References实例加入到pending-list中
                rp->enqueue_discovered_references();
              } else {
                //enqueuing_is_done为true,已经加入到pending-list中了,将其恢复成默认值
                rp->set_enqueuing_is_done(false);
              }
              rp->verify_no_references_recorded();
            }
            max_level_collected = i;
     
            // Determine if allocation request was met.
            if (size > 0) {
              if (!is_tlab || _gens[i]->supports_tlab_allocation()) {
                if (size*HeapWordSize <= _gens[i]->unsafe_max_alloc_nogc()) {
                  size = 0;
                }
              }
            }
     
            COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
      
            _gens[i]->stat_record()->accumulated_time.stop();
            //更新各Generation的GC统计信息
            update_gc_stats(i, full);
     
            if (VerifyAfterGC && i >= VerifyGCLevel &&
                total_collections() >= VerifyGCStartAt) {
              HandleMark hm;  // Discard invalid handles created during verification
              Universe::verify(" VerifyAfterGC:");
            }
     
            if (PrintGCDetails) {
              gclog_or_tty->print(":");
              _gens[i]->print_heap_change(prev_used);
            }
          }
        }//for循环结束
     
        //是否Full GC
        complete = complete || (max_level_collected == n_gens() - 1);
     
        if (complete) { // We did a "major" collection
          //根据配置dump
          post_full_gc_dump(NULL);   // do any post full gc dumps
        }
     
        if (PrintGCDetails) {
          print_heap_change(gch_prev_used);
     
          if (complete) {
            MetaspaceAux::print_metaspace_change(metadata_prev_used);
          }
        }
     
        for (int j = max_level_collected; j >= 0; j -= 1) {
          //调整各Generation的容量
          _gens[j]->compute_new_size();
        }
     
        if (complete) {
          //删掉被卸载的ClassLoader实例及其相关元数据
          ClassLoaderDataGraph::purge();
          MetaspaceAux::verify_metrics();
          //重置元空间大小
          MetaspaceGC::compute_new_size();
          update_full_collections_completed();
        }
     
        //跟踪GC后的内存使用
        MemoryService::track_memory_usage();
     
        gc_epilogue(complete);
     
        if (must_restore_marks_for_biased_locking) {
          BiasedLocking::restore_marks();
        }
      }
     
      AdaptiveSizePolicy* sp = gen_policy()->size_policy();
      AdaptiveSizePolicyOutput(sp, total_collections());
     
      print_heap_after_gc();
     
    #ifdef TRACESPINNING
      ParallelTaskTerminator::print_termination_counts();
    #endif
    }
     
    //父类方法
    bool is_gc_active() const { return _is_gc_active; }
     
    GCCause::Cause gc_cause() { return _gc_cause; }
     
    void GenCollectedHeap::gc_prologue(bool full) {
      assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer");
     
      always_do_update_barrier = false;
      //收集GC前的TLAB的统计数据
      CollectedHeap::accumulate_statistics_all_tlabs();
      //遍历各Generation执行ensure_parsability
      ensure_parsability(true);   // retire TLABs
     
      //遍历各Generation执行gc_prologue
      GenGCPrologueClosure blk(full);
      generation_iterate(&blk, false);  // not old-to-young.
    };
     
    void GenCollectedHeap::ensure_parsability(bool retire_tlabs) {
      CollectedHeap::ensure_parsability(retire_tlabs);
      GenEnsureParsabilityClosure ep_cl;
      generation_iterate(&ep_cl, false);
    }
     
    //old_to_young决定了遍历的顺序,如果为true则先遍历老年代再遍历年轻代
    void GenCollectedHeap::generation_iterate(GenClosure* cl,
                                              bool old_to_young) {
      if (old_to_young) {
        for (int i = _n_gens-1; i >= 0; i--) {
          cl->do_generation(_gens[i]);
        }
      } else {
        for (int i = 0; i < _n_gens; i++) {
          cl->do_generation(_gens[i]);
        }
      }
    }
     
    class GenEnsureParsabilityClosure: public GenCollectedHeap::GenClosure {
     public:
      void do_generation(Generation* gen) {
        gen->ensure_parsability();
      }
    };
     
    class GenGCPrologueClosure: public GenCollectedHeap::GenClosure {
     private:
      bool _full;
     public:
      void do_generation(Generation* gen) {
        gen->gc_prologue(_full);
      }
      GenGCPrologueClosure(bool full) : _full(full) {};
    };
     
    void increment_total_collections(bool full = false) {
        //增加总的GC次数
        _total_collections++;
        if (full) {
          //增加Full GC的次数
          increment_total_full_collections();
        }
      }
     
    void increment_total_full_collections() { _total_full_collections++; }
     
    size_t GenCollectedHeap::used() const {
      size_t res = 0;
      //遍历各Generation累加内存使用量
      for (int i = 0; i < _n_gens; i++) {
        res += _gens[i]->used();
      }
      return res;
    }
     
     
    //DefNewGeneration采用父类Generation的默认实现,返回false
    //ConcurrentMarkSweepGeneration的实现如下
    //UseCMSCompactAtFullCollection默认为true,表示FullGC时所使用Mark-Sweep-Compact算法
    //CollectGen0First默认为false,表示是否在FullGC前收集年轻代
     virtual bool full_collects_younger_generations() const {
        return UseCMSCompactAtFullCollection && !CollectGen0First;
      }
     
    void CollectedHeap::pre_full_gc_dump(GCTimer* timer) {
      //HeapDumpBeforeFullGC默认为false
      if (HeapDumpBeforeFullGC) {
        GCTraceTime tt("Heap Dump (before full gc): ", PrintGCDetails, false, timer, GCId::create());
        HeapDumper::dump_heap();
      }
      //PrintClassHistogramBeforeFullGC默认为false
      if (PrintClassHistogramBeforeFullGC) {
        GCTraceTime tt("Class Histogram (before full gc): ", PrintGCDetails, true, timer, GCId::create());
        VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */);
        inspector.doit();
      }
    }
     
    #ifndef PRODUCT
    class GenGCSaveTopsBeforeGCClosure: public GenCollectedHeap::GenClosure {
     private:
     public:
      void do_generation(Generation* gen) {
        gen->record_spaces_top();
      }
    };
     
    void GenCollectedHeap::record_gen_tops_before_GC() {
      if (ZapUnusedHeapArea) {
        GenGCSaveTopsBeforeGCClosure blk;
        generation_iterate(&blk, false);  // not old-to-young.
      }
    }
    #endif 
     
    void GenCollectedHeap::save_marks() {
      for (int i = 0; i < _n_gens; i++) {
        _gens[i]->save_marks();
      }
    }
     
     void update_gc_stats(int current_level, bool full) {
        for (int i = 0; i < _n_gens; i++) {
          _gens[i]->update_gc_stats(current_level, full);
        }
      }
     
    void CollectedHeap::post_full_gc_dump(GCTimer* timer) {
      //HeapDumpAfterFullGC默认为false
      if (HeapDumpAfterFullGC) {
        GCTraceTime tt("Heap Dump (after full gc): ", PrintGCDetails, false, timer, GCId::create());
        HeapDumper::dump_heap();
      }
      //PrintClassHistogramAfterFullGC默认为false
      if (PrintClassHistogramAfterFullGC) {
        GCTraceTime tt("Class Histogram (after full gc): ", PrintGCDetails, true, timer, GCId::create());
        VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */);
        inspector.doit();
      }
    }
     
    unsigned int GenCollectedHeap::update_full_collections_completed() {
      MonitorLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
      assert(_full_collections_completed <= _total_full_collections,
             "Can't complete more collections than were started");
      //获取锁FullGCCount_lock,更新_full_collections_completed属性
      _full_collections_completed = _total_full_collections;
      ml.notify_all();
      return _full_collections_completed;
    }
     
    void GenCollectedHeap::gc_epilogue(bool full) {
    #ifdef COMPILER2
      assert(DerivedPointerTable::is_empty(), "derived pointer present");
      size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));
      guarantee(actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
    #endif /* COMPILER2 */
      //重新计算各线程的TLAB的分配大小
      resize_all_tlabs();
     
      //遍历各Generation执行gc_epilogue方法
      GenGCEpilogueClosure blk(full);
      generation_iterate(&blk, false);  // not old-to-young.
     
      //CleanChunkPoolAsync默认为false
      if (!CleanChunkPoolAsync) {
        //清理ChunkPool
        Chunk::clean_chunk_pool();
      }
      
      //更新计数器
      MetaspaceCounters::update_performance_counters();
      CompressedClassSpaceCounters::update_performance_counters();
     
      always_do_update_barrier = UseConcMarkSweepGC;
    };
     
    void CollectedHeap::resize_all_tlabs() {
      if (UseTLAB) {
        assert(SafepointSynchronize::is_at_safepoint() ||
             !is_init_completed(),
             "should only resize tlabs at safepoint");
        //重新计算各线程的TLAB的大小
        ThreadLocalAllocBuffer::resize_all_tlabs();
      }
    }
     
    class GenGCEpilogueClosure: public GenCollectedHeap::GenClosure {
     private:
      bool _full;
     public:
      void do_generation(Generation* gen) {
        gen->gc_epilogue(_full);
      }
      GenGCEpilogueClosure(bool full) : _full(full) {};
    };
    

    上述代码中的ClearedAllSoftRefs的定义如下:


    image.png

    FlagSetting的定义如下:


    image.png

    该方法的调用链如下:


    image.png

    4、do_full_collection
    do_full_collection有两个重载版本,用来执行年轻代或者老年代的“full gc”,即底层调用do_collection方法时,full参数是true,其实现如下:

    void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) {
       do_full_collection(clear_all_soft_refs, _n_gens - 1);
    }
     
    void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs,
                                              int max_level) {
      int local_max_level;
      if (!incremental_collection_will_fail(false /* don't consult_young */) && //此时返回false说明老年代空间是足够的
          gc_cause() == GCCause::_gc_locker) { //如果是最后一个从JNI关键区退出的线程触发的GC,满足这两个条件则只执行年轻代的垃圾回收
        local_max_level = 0;
      } else {
        local_max_level = max_level;
      }
     
      do_collection(true                 /* full */,
                    clear_all_soft_refs  /* clear_all_soft_refs */,
                    0                    /* size */,
                    false                /* is_tlab */,
                    local_max_level      /* max_level */);
      //如果只执行年轻代的GC,但是因为老年满了导致GC失败,则重试
      if (local_max_level == 0 && gc_cause() == GCCause::_gc_locker &&
          incremental_collection_will_fail(false /* don't consult_young */)) {
        if (PrintGCDetails) {
          gclog_or_tty->print_cr("GC locker: Trying a full collection "
                                 "because scavenge failed");
        }
        //会执行老年代和年轻代的GC
        do_collection(true                 /* full */,
                      clear_all_soft_refs  /* clear_all_soft_refs */,
                      0                    /* size */,
                      false                /* is_tlab */,
                      n_gens() - 1         /* max_level */);
      }
    }
     
    bool incremental_collection_will_fail(bool consult_young) {
        assert(heap()->collector_policy()->is_two_generation_policy(),
               "the following definition may not be suitable for an n(>2)-generation system");
        return incremental_collection_failed() ||
               (consult_young && !get_gen(0)->collection_attempt_is_safe());
      }
     
    //当老年代空间不足以promote,年轻代执行GC前调用collection_attempt_is_safe方法返回false,就会将_incremental_collection_failed属性置为false
    bool incremental_collection_failed() const {
        return _incremental_collection_failed;
      }
    

    _incremental_collection_failed属性通过set_incremental_collection_failed方法设置为true,该方法的调用链如下:

    image.png

    都是在collection_attempt_is_safe方法返回false,即利用老年代执行promote时因为老年代内存不足可能会失败时调用的。

    GCCause::_gc_locker的调用链如下:


    image.png

    其中只有GC_locker::jni_unlock方法不是判断GC的原因是否是_gc_locker,如下:

    image.png

    该方法就是用于在最后一个线程从JNI关键区退出后负责触发GC。

    do_full_collection方法的调用链如下:


    image.png

    5、collect
    collect方法是对JVM外部如JNI接口使用的触发垃圾回收的方法,其调用链如下:

    image.png

    上述调用场景都是基于JNI接口的调用,其中JVM_GC就是System.gc()方法的底层实现,其实现如下:

    image.png

    collect方法的实现如下:

    void GenCollectedHeap::collect(GCCause::Cause cause) {
      if (should_do_concurrent_full_gc(cause)) {
    #if INCLUDE_ALL_GCS
        // mostly concurrent full collection
        collect_mostly_concurrent(cause);
    #else  // INCLUDE_ALL_GCS
        ShouldNotReachHere();
    #endif // INCLUDE_ALL_GCS
      } else if (cause == GCCause::_wb_young_gc) {
        // minor collection for WhiteBox API
        collect(cause, 0);
      } else {
        // Stop-the-world full collection
        collect(cause, n_gens() - 1);
      }
    }
     
    bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
    //UseConcMarkSweepGC表示使用CMS GC算法
    //GCLockerInvokesConcurrent的默认值为false
    //ExplicitGCInvokesConcurrent的默认值也是false
      return UseConcMarkSweepGC &&
             ((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
              (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent));
    }
     
    void GenCollectedHeap::collect_mostly_concurrent(GCCause::Cause cause) {
      assert(!Heap_lock->owned_by_self(), "Should not own Heap_lock");
     
      MutexLocker ml(Heap_lock);
      // Read the GC counts while holding the Heap_lock
      unsigned int full_gc_count_before = total_full_collections();
      unsigned int gc_count_before      = total_collections();
      {
        MutexUnlocker mu(Heap_lock);
        //底层调用do_full_collection
        VM_GenCollectFullConcurrent op(gc_count_before, full_gc_count_before, cause);
        VMThread::execute(&op);
      }
    }
     
    void GenCollectedHeap::collect(GCCause::Cause cause, int max_level) {
      // The caller doesn't have the Heap_lock
      assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
      MutexLocker ml(Heap_lock);
      collect_locked(cause, max_level);
    }
     
     
    void GenCollectedHeap::collect_locked(GCCause::Cause cause, int max_level) {
      // Read the GC count while holding the Heap_lock
      unsigned int gc_count_before      = total_collections();
      unsigned int full_gc_count_before = total_full_collections();
      {
        //获取Heap_lock锁
        MutexUnlocker mu(Heap_lock);  // give up heap lock, execute gets it back
        //底层还是调用do_full_collection
        VM_GenCollectFull op(gc_count_before, full_gc_count_before,
                             cause, max_level);
        VMThread::execute(&op);
      }
    }
    

    6、VM_GenCollectFullConcurrent / VM_GenCollectFull
    VM_GenCollectFull比较简单,就是调用do_full_collection方法;VM_GenCollectFullConcurrent要复杂点,年轻代通过do_full_collection方法执行GC,老年代通过触发CMSThread执行GC,即异步完成GC,其实现如下:

    VM_GenCollectFull(uint gc_count_before,
                        uint full_gc_count_before,
                        GCCause::Cause gc_cause,
                        int max_level)
        : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */),
          _max_level(max_level) { }
     
    void VM_GenCollectFull::doit() {
      SvcGCMarker sgcm(SvcGCMarker::FULL);
     
      GenCollectedHeap* gch = GenCollectedHeap::heap();
      GCCauseSetter gccs(gch, _gc_cause);
      gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
    }
     
    VM_GenCollectFullConcurrent(uint gc_count_before,
                                  uint full_gc_count_before,
                                  GCCause::Cause gc_cause)
        : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */),
          _disabled_icms(false)
      {
        assert(FullGCCount_lock != NULL, "Error");
        assert(UseAsyncConcMarkSweepGC, "Else will hang caller");
      }
     
    //判断是否需要在安全点上执行
    bool VM_GenCollectFullConcurrent::evaluate_at_safepoint() const {
      Thread* thr = Thread::current();
      assert(thr != NULL, "Unexpected tid");
      if (!thr->is_Java_thread()) {
        //如果是VMThread执行的
        assert(thr->is_VM_thread(), "Expected to be evaluated by VM thread");
        GenCollectedHeap* gch = GenCollectedHeap::heap();
        if (_gc_count_before != gch->total_collections()) {
          //如果已经完成了一次Young GC
          assert(_gc_count_before < gch->total_collections(),
                 "total_collections() should be monotnically increasing");
          return false;  // no need for foreground young gc
        }
      }
      //如果是JavaThread调用的,如System.gc()方法
      return true;       // may still need foreground young gc
    }
     
    void VM_GenCollectFullConcurrent::doit() {
      assert(Thread::current()->is_VM_thread(), "Should be VM thread");
      assert(GCLockerInvokesConcurrent || ExplicitGCInvokesConcurrent, "Unexpected");
     
      GenCollectedHeap* gch = GenCollectedHeap::heap();
      if (_gc_count_before == gch->total_collections()) {
        //GC的次数没有变说明未执行young gc
        assert(SafepointSynchronize::is_at_safepoint(),
          "We can only be executing this arm of if at a safepoint");
        GCCauseSetter gccs(gch, _gc_cause);
        //执行年轻代的垃圾回收
        gch->do_full_collection(gch->must_clear_all_soft_refs(),
                                0 /* collect only youngest gen */);
      } // Else no need for a foreground young gc
      assert((_gc_count_before < gch->total_collections()) || //执行过GC了
             (GC_locker::is_active()   
              && (_gc_count_before == gch->total_collections())), //因为有线程处于JNI关键区,GC被中止了
             "total_collections() should be monotonically increasing");
     
      //获取锁FullGCCount_lock
      MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
      assert(_full_gc_count_before <= gch->total_full_collections(), "Error");
      if (gch->total_full_collections() == _full_gc_count_before) {
        //total_full_collections未变,说明老年代的GC未执行
        //禁用icms
        CMSCollector::disable_icms();
        _disabled_icms = true;
        //唤醒在icms_wait()上等待的CMS Thread
        CMSCollector::start_icms();
        //推动CMS Thread执行一次老年代的GC
        CMSCollector::request_full_gc(_full_gc_count_before, _gc_cause);
      } else {
        //说明已经执行过一次老年代GC了,不用再执行
        assert(_full_gc_count_before < gch->total_full_collections(), "Error");
        FullGCCount_lock->notify_all();  // Inform the Java thread its work is done
      }
    }
     
    //GC结束后调用
    void VM_GenCollectFullConcurrent::doit_epilogue() {
      Thread* thr = Thread::current();
      assert(thr->is_Java_thread(), "just checking");
      JavaThread* jt = (JavaThread*)thr;
      //释放锁
      Heap_lock->unlock();
      release_and_notify_pending_list_lock();
     
      GenCollectedHeap* gch = GenCollectedHeap::heap();
      if (_gc_cause != GCCause::_gc_locker &&
          gch->total_full_collections_completed() <= _full_gc_count_before) {
        //正常只有调用System.gc()时会走此方法
        assert(_gc_cause == GCCause::_java_lang_system_gc,
               "the only way to get here if this was a System.gc()-induced GC");
        assert(ExplicitGCInvokesConcurrent, "Error");
        //调整线程状态由in vm到in nativee
        ThreadToNativeFromVM native(jt);
        //获取锁MutexLockerEx
        MutexLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
     
        while (gch->total_full_collections_completed() <= _full_gc_count_before) {
          //还是小于等于,说明GC未完成,在FullGCCount_lock上等待直到total_full_collections_completed大于_full_gc_count_before
          //即GC结束
          FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
        }
      }
      if (_disabled_icms) {
        //重新开启icms
        CMSCollector::enable_icms();
      }
    }
     
    bool GenCollectedHeap::must_clear_all_soft_refs() {
      return _gc_cause == GCCause::_last_ditch_collection;
    }
     
    void CMSCollector::request_full_gc(unsigned int full_gc_count, GCCause::Cause cause) {
      GenCollectedHeap* gch = GenCollectedHeap::heap();
      unsigned int gc_count = gch->total_full_collections();
      if (gc_count == full_gc_count) {
        MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag);
        _full_gc_requested = true;
        _full_gc_cause = cause;
        CGC_lock->notify();   //唤醒CMS Thread,该线程检查_full_gc_requested为true会触发一次老年代的GC
      } else {
        assert(gc_count > full_gc_count, "Error: causal loop");
      }
    }
     
    unsigned int total_full_collections_completed() {
        assert(_full_collections_completed <= _total_full_collections,
               "Can't complete more collections than were started");
        return _full_collections_completed;
      }
    

    上述代码中的ThreadToNativeFromVM用于将当前线程的状态从in vm调整成in native,其实现如下:

    7、gen_process_roots / gen_process_weak_roots
    gen_process_roots用于遍历处理ClassLoaderDataGraph,Threads,Universe等组件中包含的oop,将这些oop作为根节点遍历其所引用的其他oop,根据参数还能遍历年轻代和老年代中的所有oop,遍历脏的卡表项对应的内存区域中包含的oop。gen_process_weak_roots用于遍历JNI弱引用和Reference弱引用实例。

    void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) {
      //遍历JNI弱引用
      JNIHandles::weak_oops_do(root_closure);
      for (int i = 0; i < _n_gens; i++) {
        //遍历所有的Reference实例
        _gens[i]->ref_processor()->weak_oops_do(root_closure);
      }
    }
     
    void GenCollectedHeap::gen_process_roots(int level,
                                             bool younger_gens_as_roots,
                                             bool activate_scope,
                                             ScanningOption so,
                                             bool only_strong_roots,
                                             OopsInGenClosure* not_older_gens,
                                             OopsInGenClosure* older_gens,
                                             CLDClosure* cld_closure) {
      const bool is_adjust_phase = !only_strong_roots && !younger_gens_as_roots;
     
      bool is_moving_collection = false;
      if (level == 0 || is_adjust_phase) {
        //is_moving_collection表示垃圾回收过程中是否会移动对象
        is_moving_collection = true;
      }
      
      //is_moving_collection实际对应_fix_relocations属性,如果为true,则遍历nmethod完后,会调用
    //其fix_oop_relocations方法用于让nmethod中的oop指向对象移动后的地址
      MarkingCodeBlobClosure mark_code_closure(not_older_gens, is_moving_collection);
     
      //weak_roots主要用于遍历StringTable中保存的String对象和SystemDictionary中保存的ProtectionDomain对象,这些对象如果不遍历且不被其他存活对象引用则会被回收掉
      OopsInGenClosure* weak_roots = only_strong_roots ? NULL : not_older_gens;
     
      //weak_cld_closure用来遍历keep_live属性为false的ClassLoaderData,同上,如果不遍历则会被回收掉
      CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure;
      
      //处理ClassLoaderDataGraph,Threads,Universe等组件中包含的oop,这些都作为根节点
      process_roots(activate_scope, so,
                    not_older_gens, weak_roots,
                    cld_closure, weak_cld_closure,
                    &mark_code_closure);
     
      if (younger_gens_as_roots) {
        //younger_gens_as_roots为true,表示需要遍历年轻代中的所有对象,将其作为根节点
        //is_task_claimed返回false表示这个任务还未执行
        if (!_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) {
          //因为是i小于level,所以对年轻代而言,即使younger_gens_as_roots为true,也不会执行
          //只有老年代,level=1时才会进入此分支
          for (int i = 0; i < level; i++) {
            not_older_gens->set_generation(_gens[i]);
            _gens[i]->oop_iterate(not_older_gens);
          }
          not_older_gens->reset_generation();
        }
      }
      //level最低是0,即年轻代GC会调用老年代的younger_refs_iterate方法,如果level是1则不做任何处理,即老年代GC不会执行此逻辑
      for (int i = level+1; i < _n_gens; i++) {
        older_gens->set_generation(_gens[i]);
        //younger_refs_iterate支持并行遍历,注意年轻代的该方法是一个空实现
        rem_set()->younger_refs_iterate(_gens[i], older_gens);
        older_gens->reset_generation();
      }
      
      //标识当前线程执行完成
      _process_strong_tasks->all_tasks_completed();
    }
     
    void GenCollectedHeap::process_roots(bool activate_scope,
                                         ScanningOption so,
                                         OopClosure* strong_roots,
                                         OopClosure* weak_roots,
                                         CLDClosure* strong_cld_closure,
                                         CLDClosure* weak_cld_closure,
                                         CodeBlobToOopClosure* code_roots) {
      //修改SharedHeap的_strong_roots_parity属性                                  
      StrongRootsScope srs(this, activate_scope);
     
      // General roots.
      assert(_strong_roots_parity != 0, "must have called prologue code");
      assert(code_roots != NULL, "code root closure should always be set");
      
      //如果这个任务还未执行
      if (!_process_strong_tasks->is_task_claimed(GCH_PS_ClassLoaderDataGraph_oops_do)) {
        //遍历所有的ClassLoaderData,如果ClassLoaderData的keep_alive为true则使用strong_cld_closure处理,否则使用weak_cld_closure
        ClassLoaderDataGraph::roots_cld_do(strong_cld_closure, weak_cld_closure);
      }
     
      CLDClosure* roots_from_clds_p = (strong_cld_closure != weak_cld_closure) ? strong_cld_closure : NULL;
      //so & SO_AllCodeCache为true即so等于SO_AllCodeCache或者SO_ScavengeCodeCache
      CodeBlobToOopClosure* roots_from_code_p = (so & SO_AllCodeCache) ? NULL : code_roots;
      
      //遍历所有JavaThread和VMThread中包含的oop,包含通过JNI创建的oop和栈上的oop
      Threads::possibly_parallel_oops_do(strong_roots, roots_from_clds_p, roots_from_code_p);
     
      if (!_process_strong_tasks->is_task_claimed(GCH_PS_Universe_oops_do)) {
        //遍历Universe中包含的oop
        Universe::oops_do(strong_roots);
      }
      // Global (strong) JNI handles
      if (!_process_strong_tasks->is_task_claimed(GCH_PS_JNIHandles_oops_do)) {
        //遍历JNI全局引用中的oop
        JNIHandles::oops_do(strong_roots);
      }
     
      if (!_process_strong_tasks->is_task_claimed(GCH_PS_ObjectSynchronizer_oops_do)) {
        //遍历ObjectSynchronizer即synchronize关键字的实现中包含的oop,主要是锁对象
        ObjectSynchronizer::oops_do(strong_roots);
      }
      if (!_process_strong_tasks->is_task_claimed(GCH_PS_FlatProfiler_oops_do)) {
        FlatProfiler::oops_do(strong_roots);
      }
      if (!_process_strong_tasks->is_task_claimed(GCH_PS_Management_oops_do)) {
        //遍历MemoryService和ThreadService中的oop
        Management::oops_do(strong_roots);
      }
      if (!_process_strong_tasks->is_task_claimed(GCH_PS_jvmti_oops_do)) {
        JvmtiExport::oops_do(strong_roots);
      }
     
      if (!_process_strong_tasks->is_task_claimed(GCH_PS_SystemDictionary_oops_do)) {
        //遍历SystemDictionary系统字典中的oop
        SystemDictionary::roots_oops_do(strong_roots, weak_roots);
      }
     
      //所有线程都要执行一遍StringTable的oop遍历
      if (weak_roots != NULL) {
        if (CollectedHeap::use_parallel_gc_threads()) {
          StringTable::possibly_parallel_oops_do(weak_roots);
        } else {
          StringTable::oops_do(weak_roots);
        }
      }
     
      if (!_process_strong_tasks->is_task_claimed(GCH_PS_CodeCache_oops_do)) {
        //SO_AllCodeCache是包含SO_ScavengeCodeCache的,所以如果是SO_ScavengeCodeCache
    //也会执行此逻辑
        if (so & SO_ScavengeCodeCache) {
          assert(code_roots != NULL, "must supply closure for code cache");
          //遍历nmethods
          CodeCache::scavenge_root_nmethods_do(code_roots);
        }
        if (so & SO_AllCodeCache) {
          assert(code_roots != NULL, "must supply closure for code cache");
          // 遍历整个CodeBlob
          CodeCache::blobs_do(code_roots);
        }
      
      }
    }
     
    void CardTableRS::younger_refs_iterate(Generation* g,
                                           OopsInGenClosure* blk) {
      _last_cur_val_in_gen[g->level()+1] = cur_youngergen_card_val();
      //年轻代该方法是空实现,老年代下底层是调用CardTableRS::younger_refs_in_space_iterate方法来遍历脏的卡表项
      //将脏的卡表项对应的内存区域中包含的oop作为根节点
      g->younger_refs_iterate(blk);
    }
    

    StrongRootsScope用来改变SharedHeap的_strong_roots_parity属性,其实现如下:

    image.png image.png

    其调用链如下:

    image.png

    CardTableRS::younger_refs_iterate方法相关实现可以参考《Hotspot 垃圾回收之BarrierSet(三) 源码解析》、《Hotspot 垃圾回收之ConcurrentMarkSweepGeneration(三) 源码解析》和《Hotspot 垃圾回收之CompactibleFreeListSpace(三) 源码解析》,整体实现比较复杂。

    8、save_marks / oop_since_save_marks_iterate / no_allocs_since_save_marks

    oop_since_save_marks_iterate并不是简单的调用底层Generation的oop_since_save_marks_iterate方法,而是有特殊逻辑在里面,其定义同样是通过宏实现的,如下:

    void GenCollectedHeap::save_marks() {
      for (int i = 0; i < _n_gens; i++) {
        _gens[i]->save_marks();
      }
    }
     
     
    #define GCH_SINCE_SAVE_MARKS_ITERATE_DEFN(OopClosureType, nv_suffix)    \
    void GenCollectedHeap::                                                 \
    oop_since_save_marks_iterate(int level,                                 \
                                 OopClosureType* cur,                       \
                                 OopClosureType* older) {                   \
      //先遍历指定level的
      _gens[level]->oop_since_save_marks_iterate##nv_suffix(cur);           \
      //再遍历老年代,如果level本身就是1则不做处理
      for (int i = level+1; i < n_gens(); i++) {                            \
        _gens[i]->oop_since_save_marks_iterate##nv_suffix(older);           \
      }                                                                     \
    }
     
    ALL_SINCE_SAVE_MARKS_CLOSURES(GCH_SINCE_SAVE_MARKS_ITERATE_DEFN)
     
    //只要有一个Generation的no_allocs_since_save_marks返回false,则no_allocs_since_save_marks同样返回false
    bool GenCollectedHeap::no_allocs_since_save_marks(int level) {
      for (int i = level; i < _n_gens; i++) {
        if (!_gens[i]->no_allocs_since_save_marks()) return false;
      }
      return true;
    }
    

    各方法的调用链如下:

    image.png image.png

    即如果是年轻代调用,则会处理年轻代和老年代,如果是老年代调用,则只处理老年代。年轻代调用oop_since_save_marks_iterate是遍历saved_mark_word到top之间的对象,主要是年轻代并行遍历和老年代通过CMSThread遍历时使用,如果是单线程的年轻代遍历则不做任何处理,因为此时saved_mark_word就是top,老年代是遍历所有被promoted的对象。

    9、ensure_parsability

    GenCollectedHeap改写了父类的实现,在父类的基础上增加了各各Generation的ensure_parsability方法的调用,但是CMS下年轻代和老年代都是空实现,父类方法的实现可以参考BarrierSet(三。

    void GenCollectedHeap::ensure_parsability(bool retire_tlabs) {
      //调用父类实现,父类实现会遍历所有的JavaThread,让其TLAB被填充或者退休,不再用于分配对象,同时将上一次本地代码创建的对象对应的卡表项置为脏的
      CollectedHeap::ensure_parsability(retire_tlabs);
      //调用各Generation的ensure_parsability方法,CMS下年轻代和老年代都是空实现
      GenEnsureParsabilityClosure ep_cl;
      generation_iterate(&ep_cl, false);
    }
     
    class GenEnsureParsabilityClosure: public GenCollectedHeap::GenClosure {
     public:
      void do_generation(Generation* gen) {
        gen->ensure_parsability();
      }
    };
    

    相关文章

      网友评论

          本文标题:GenCollectedHeap

          本文链接:https://www.haomeiwen.com/subject/frwqqdtx.html