JVM垃圾回收

根據《JVM垃圾回收》我們對垃圾收集器有個初步的概念.

相關模塊介紹


//VM_Operation
//	VM_GC_Operation #是所有執行垃圾回收的VM_Operation的基類
//		VM_CollectForAllocation #與其子類都是內存分配失敗觸發垃圾回收,然後嘗試分配內存的操作
//			VM_GenCollectForAllocation

//表示一類在JVM線程中執行的操作,類似java中的任務
//hotspot/src/share/vm/runtime/vm_operations.hpp
class VM_Operation: public CHeapObj<mtInternal> {

  enum Mode {
    _safepoint,       //表示執行此操作需要加鎖+安全點
    _no_safepoint,    //表示執行此操作需要加鎖
    _concurrent,      //無需要任務條件
    _async_safepoint  //表示執行此操作需要安全點
  };
  
  //具體執行VM_Operation的方法,通過evaluate方法調用,子類不能改寫evaluate方法的實現
  doit:
  //用於執行準備工作,當Java線程調用VMThread::execute((VM_Operation*)執行某個VM_Operation時會先執行doit_prologue如果該方法返回true纔會執行evaluate方法,否則被取消不執行。
  doit_prologue
  //用於執行某些依賴於VM_Operation執行結果的動作,當VM_Operation執行完成,Java線程會調用doit_epilogue方法一次。
  doit_epilogue
}

//表示一個特殊的專門用來執行比較耗時的VM_Operation的原生線程
//hotspot/src/share/vm/runtime/vMThread.hpp
class VMThread {
    
    //當前執行的VM operation
    static VM_Operation*     _cur_vm_operation;   
    // 緩存待執行的VM operation 隊列
    static VMOperationQueue* _vm_queue;   
    
    
    void VMThread::create() {
       //創建VMThread線程,及VMOperationQueue隊列
    }
    
	void VMThread::execute(VM_Operation* op) {
	  //用於執行某個VM_Operation,execute方法會先執行doit_prologue,該方法執行成功後將該操作放入一個等待隊列中,然後等待VMThread執行該操作完成,最後再執行doit_epilogue
	}
	 
    void VMThread::run() {
        //其中loop方法執行的核心業務邏輯了,該方法不斷從待執行的VM Operation隊列_vm_queue中獲取待執行的VM_Operation實例,然後調用其evaluate方法
    }
}
//描述分代參數的一個類
//hotspot/src/share/vm/memory/generationSpec.hpp
class GenerationSpec : public CHeapObj<mtGC> {
  Generation::Name _name;//分代名
  size_t           _init_size;//初始大步
  size_t           _max_size;//最大大小

  // 返回這個分代所需要的 remembered set 空間.
  virtual int n_covered_regions() const { return 1; }
  
  //創建分帶代
  Generation* GenerationSpec::init(ReservedSpace rs, int level,
	                                 GenRemSet* remset) {
	  switch (name()) {
	    case Generation::DefNew:
	      return new DefNewGeneration(rs, init_size(), level);
	    case Generation::MarkSweepCompact:
	      return new TenuredGeneration(rs, init_size(), level, remset);	
	    case Generation::ParNew:
	      return new ParNewGeneration(rs, init_size(), level);
	    case Generation::ASParNew:
	      return new ASParNewGeneration(rs,init_size(),init_size() ,level);	
	    case Generation::ConcurrentMarkSweep: {
	      assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set");
	      CardTableRS* ctrs = remset->as_CardTableRS();
	      if (ctrs == NULL) {
	        vm_exit_during_initialization("Rem set incompatibility.");
	      }
	      // Otherwise
	      // The constructor creates the CMSCollector if needed,
	      // else registers with an existing CMSCollector
	      ConcurrentMarkSweepGeneration* g = NULL;
	      g = new ConcurrentMarkSweepGeneration(rs,
	                 init_size(), level, ctrs, UseCMSAdaptiveFreeLists,
	                 (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
	
	      g->initialize_performance_counters();
	
	      return g;
	    }
	    case Generation::ASConcurrentMarkSweep: {
	       //...
	    }	
	    default:
	      guarantee(false, "unrecognized GenerationName");
	      return NULL;
	  }
	}  
}

//用來記錄不同分代年齡的對象的大小,然後據此動態調整tenuring_threshold
//hotspot/src/share/vm/gc_implementation/shared/ageTable.hpp
class ageTable  {
  
  enum { table_size = markOopDesc::max_age + 1 };
  //sizes就是保存不同分代年齡的對象的大小的數組
  size_t sizes[table_size];

  //所對象存進行
  //如果想取1歲對象佔分代的大小,就直接sizes[1]
  void add(oop p, size_t oop_size) {
    add(p->age(), oop_size);
  }
 
 void add(uint age, size_t oop_size) {
	sizes[age] += oop_size;
 }
 
 //傳一個的survivor_capacity值,根據ageTable的數據,把對象重新畫區
 uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) 

}

//Space及其子類是Generation中用於內存分配管理的底層實現
//hotspot/src/share/vm/memory/space.hpp
class Space: public CHeapObj<mtGC> {
  //內存區域的起始地址
  HeapWord* _bottom;
  //內存區域的終止地址
  HeapWord* _end;

  // 用來遍歷Space內的MemRegion
  MemRegionClosure* _preconsumptionDirtyCardClosure;
}

//增加了壓縮操作的支持,即在垃圾回收後通過複製移動Java對象的位置減少Space內部的內存空洞和碎片問題,提升內存利用率
//hotspot/src/share/vm/memory/space.hpp
class CompactibleSpace: public Space {
}

//表示一個空閒內存空間是地址連續的Space,從而支持快速的內存分配和壓縮
//hotspot/src/share/vm/memory/space.hpp
class ContiguousSpace: public CompactibleSpace {
  //bottom到top之間的內存都是已經被分配出去的內存
  HeapWord* _top;
  //從bottom到_concurrent_iteration_safe_limit之間的對象都被認爲是已經初始化完成的對象,對於object_iterate_careful方法可以安全遍歷的,該屬性在初始化時通常設置爲bottom,在compact結束後設置爲compact_top。
  HeapWord* _concurrent_iteration_safe_limit;
  //負責對Space執行mangle的輔助類
  GenSpaceMangler* _mangler;
}

//用來表示Eden區
class EdenSpace : public ContiguousSpace {
  //關聯的年輕代DefNewGeneration實例
  DefNewGeneration* _gen;
  //分配內存的一個軟限制, 當達到了這個限制後,慢速分配的代碼可以執行其他的邏輯,然後調整_soft_end到一個新的限制或者end()
  HeapWord* _soft_end;
}

// CollectedHeap
//   SharedHeap 分層的堆基類
//     GenCollectedHeap 普通分帶法
//     G1CollectedHeap  G1分帶法
//   ParallelScavengeHeap ps分帶及策略
//一個抽象類,表示一個Java堆,定義了各種垃圾回收算法必須實現的公共接口,這些接口就是上層類用來分配Java對象,分配TLAB,獲取Java堆使用情況等的統一API
//hotspot/src/share/vm/gc_interface/collectedHeap.hpp
class CollectedHeap : public CHeapObj<mtInternal> {
	
  //填充數組的最大值	
  static size_t _filler_array_max_size;
  //用來打印GC日誌
  GCHeapLog* _gc_heap_log;
  //開啓C2編譯時使用,支持ReduceInitialCardMarks
  bool _defer_initial_card_mark;
  //Java堆對應的一段連續內存空間
  MemRegion _reserved;
  //卡表(CardTable)的基類
  //BarrierSet的功能類似於一個攔截器,在讀寫動作實際作用於內存前執行某些前置或者後置動作
  BarrierSet* _barrier_set;
  //是否正在執行GC
  bool _is_gc_active;
  //並行執行GC任務的線程數
  uint _n_par_threads;
  //從JVM啓動至今的GC次數
  unsigned int _total_collections;
  //從JVM啓動至今的Full GC次數
  unsigned int _total_full_collections;
  //當前GC被觸發的原因,Cause是GCCause定義的枚舉
  GCCause::Cause _gc_cause;
  //上一次GC被觸發的原因
  GCCause::Cause _gc_lastcause;
  //開啓UsePerfData時用來保存_gc_cause
  PerfStringVariable* _perf_gc_cause;
  //開啓UsePerfData時用來保存_gc_lastcause
  PerfStringVariable* _perf_gc_lastcause;
}

//hotspot/src/share/vm/memory/sharedHeap.hpp
class SharedHeap : public CollectedHeap {
  //靜態SharedHeap實例,單例
  static SharedHeap* _sh;
  // the Gen Remembered Set,卡表實現
  GenRemSet* _rem_set;
  //垃圾回收策略
  CollectorPolicy *_collector_policy;
  //遍歷Java線程包含的oop使用的
  int _strong_roots_parity;
  //執行並行GC(parallel GC)的線程池
  FlexibleWorkGang* _workers;

  //SharedHeap構造
  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();
	    }
	  }
	}

}

//heap具體的分帶實現
//hotspot/src/share/vm/memory/genCollectedHeap.hpp
class GenCollectedHeap : public SharedHeap {
  //靜態GenCollectedHeap實例,單例
  static GenCollectedHeap* _gch;
  //包含的Generation的個數,通常是2(老年代,年輕帶)
  int _n_gens;
  //Generation數組,分代的具體指針
  Generation* _gens[max_gens];
  //GenerationSpec主要用來存儲各分帶的創建數據
  GenerationSpec** _gen_specs;
  //垃圾回收策略
  GenCollectorPolicy* _gen_policy;
  //執行promote是否會失敗
  bool _incremental_collection_failed;
  //已經執行萬恆的Full GC的次數
  unsigned int _full_collections_completed;
  //用於控制根節點遍歷任務的並行執行
  SubTasksDone* _process_strong_tasks;

  //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");
	}
  
	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));
	 
	  //collector_policy()和gen_policy()表示相同變量
	  //根據各區域名需要的_rem_set區域,初始化GenRemSet
	  _rem_set = collector_policy()->create_rem_set(_reserved, n_covered_regions);
	  set_barrier_set(rem_set()->bs());
	 
	  _gch = this;
	  
	  //初始化各Generation
	  for (i = 0; i < _n_gens; i++) {
	    //提取出max_size的內存
	    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());
	    //將下次內存指針向下移max_size
	    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();
	}

    //執行垃圾回收的核心方法,其底層核心就是各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;
	  	  
	  //校驗處於安全點上
	  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; 
	  }
	 
	  //是否需要清除軟引用
	  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) {
	      //如果老年代設置了full Gc要先收集年輕代的話
	      //full_collects_younger_generations = false
	      //否則爲true,starting_level=1
	      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();
	 
	}

	//DefNewGeneration採用父類Generation的默認實現,返回false
	//ConcurrentMarkSweepGeneration的實現如下
	//UseCMSCompactAtFullCollection默認爲true,表示FullGC時所使用Mark-Sweep-Compact算法
	//CollectGen0First默認爲false,表示是否在FullGC前收集年輕代
	virtual bool full_collects_younger_generations() const {
	    return UseCMSCompactAtFullCollection && !CollectGen0First;
	  }


}

// Generation
//   CardGeneration 
//     ConcurrentMarkSweep #cms
//     	  ASConcurrentMarkSweep # 自適應cms
//     OneContigSpaceCardGeneration  
//     	  TenuredGeneration 
//   DefNewGeneration
//     ParNewGeneration
//     	  ASParNewGeneration 
//CMS算法使用的表示年輕代的DefNewGeneration和表示支持自適應調整堆內存大小的老年代的ASConcurrentMarkSweepGeneration類
//表示分代內存中的一個“代”對應的內存區域,是各種分代內存實現的抽象類
//hotspot/src/share/vm/memory/generation.hpp
class Generation: public CHeapObj<mtGC> {
  //記錄上一次GC的發生時間
  jlong _time_of_last_gc; 
  //在GC過程中的某個特殊時點使用的,用於記錄某個值
  MemRegion _prev_used_region; 
  //爲當前Generation保留的一段連續的內存地址空間,注意不能跟其他的Generation的地址空間有交叉
  MemRegion _reserved;
  // Memory area reserved for generation
  VirtualSpace _virtual_space;
  //當前Generation在類繼承關係中的級別
  int _level;
  //用於處理Reference實例的處理器
  ReferenceProcessor* _ref_processor;
  //用於GC性能跟蹤
  CollectorCounters* _gc_counters;
  //收集GC的統計數據
  GCStats* _gc_stats;

  //Generation定義了一個枚舉Name來描述各子類,其定義如下:
  enum Name {
    ASParNew,
    ASConcurrentMarkSweep,
    DefNew,
    ParNew,
    MarkSweepCompact,(對應繼承類TenuredGeneration)
    ConcurrentMarkSweep,
    Other
  };

  //默認種類返回
  virtual Generation::Name kind() { return Generation::Other;}
   
  //是否要收集
  //如果full爲true,強制收集
  //否則判斷空間是否充足 
  virtual bool should_collect(bool   full,
                              size_t word_size,
                              bool   is_tlab) {
    return (full || should_allocate(word_size, is_tlab));
  } 
}

//表示一個使用卡表來標記對象修改
//hotspot/src/share/vm/memory/generation.hpp
class CardGeneration: public Generation {
 
  //與其他Generation實例共享的卡表實現實例(指向SharedHeap中的)
  GenRemSet* _rs;
  //當前Generation獨享的BlockOffsetArray實現
  //記錄內存塊的起始位置
  BlockOffsetSharedArray* _bts;
  //老年代內存縮容的百分比,第一次是0,第二次是10,第三次是40,第四次是100,中間有一次擴容了則被重置爲0,重新開始累加,避免頻繁的縮容與擴容。
  size_t _shrink_factor;
  //老年代內存擴展或者縮容時的最低內存值 
  size_t _min_heap_delta_bytes;
  //GC開始時的內存容量
  size_t _capacity_at_prologue;
  //GC開始時的內存使用量
  size_t _used_at_prologue;
}

//表示CMS的老年代
//hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
class ConcurrentMarkSweepGeneration: public CardGeneration {
  //封裝了老年代垃圾回收的相關屬性和實現邏輯
  static CMSCollector*       _collector; 
  //老年代對應的Space實現
  CompactibleFreeListSpace*  _cmsSpace;   
  //直接從老年代分配而非promote時間接分配的內存的大小,是一個累加值,CMSStats使用的
  size_t _direct_allocated_words;
  //是否增量收集失敗
  bool _incremental_collection_failed;
  //實際是一個CMSParGCThreadState指針數組,元素個數就是ParallelGCThreads,即並行GC的線程數,CMSParGCThreadState是執行老年代promote時使用的
  CMSParGCThreadState** _par_gc_thread_states;
  //老年代擴展的原因,shouldConcurrentCollect()方法據此判斷是否應該GC
  CMSExpansionCause::Cause _expansion_cause;
  //是否完成壓縮
  bool _did_compact;
  //觸發老年代GC的內存佔用百分比,是一個兩位的小數 
  double _initiating_occupancy;


  //UseCMSCompactAtFullCollection默認爲true,表示FullGC時所使用Mark-Sweep-Compact算法
 //CollectGen0First默認爲false,表示是否在FullGC前收集年輕代
 virtual bool full_collects_younger_generations() const {
	    return UseCMSCompactAtFullCollection && !CollectGen0First;
	  }
}

//表示年輕代,包括(den, from- and to-space.)
//hotspot/src/share/vm/memory/defNewGeneration.hpp
class DefNewGeneration: public Generation {
  //對老年代的引用,初始化時爲null,第一次GC時會賦值
  Generation* _next_gen;
  //將對象拷貝到老年代的分代年齡閾值,大於該值拷貝到老年代,否則拷貝到to區,該值在初始化時賦值成參數MaxTenuringThreshold,默認是15;每次GC結束後都會通過ageTable調整。
  uint        _tenuring_threshold;   
  //記錄不同分代年齡的對象的總大小
  ageTable    _age_table;
  //表示年輕代中允許分配的對象的最大字寬數,默認是0,即無限制
  size_t      _pretenure_size_threshold_words;

  //真實地址大內存在ReservedSpace已經外面
  //用EdenSpace與ContiguousSpace等類,標識已計算出給年代代的東西
  //barrier_set也得新高監聽區域
  DefNewGeneration::DefNewGeneration(ReservedSpace rs,
	                                   size_t initial_size,
	                                   int level,
	                                   const char* policy)
	  : Generation(rs, initial_size, level),
	    _promo_failure_drain_in_progress(false),
	    _should_allocate_from_space(false)
	{
	  MemRegion cmr((HeapWord*)_virtual_space.low(),
	                (HeapWord*)_virtual_space.high());
	  //重置bs對應的內存區域
	  Universe::heap()->barrier_set()->resize_covered_region(cmr);
	  //has_soft_ended_eden方法的返回值取決於屬性CMSIncrementalMode,默認爲false
	  //初始化三個內存區域
	  if (GenCollectedHeap::heap()->collector_policy()->has_soft_ended_eden()) {
	    _eden_space = new ConcEdenSpace(this);
	  } else {
	    _eden_space = new EdenSpace(this);
	  }
	  _from_space = new ContiguousSpace();
	  _to_space   = new ContiguousSpace();
	 
	  if (_eden_space == NULL || _from_space == NULL || _to_space == NULL)
	    vm_exit_during_initialization("Could not allocate a new gen space");
	 
	  //計算survivor區和eden區的最大空間,即年輕代最大內存時survivor區和eden區的內存空間
	  uintx alignment = GenCollectedHeap::heap()->collector_policy()->space_alignment();
	  uintx size = _virtual_space.reserved_size();
	  _max_survivor_size = compute_survivor_size(size, alignment);
	  _max_eden_size = size - (2*_max_survivor_size);
	 
	  //計算三個內存區的大小和邊界,並初始化
	  compute_space_boundaries(0, SpaceDecorator::Clear, SpaceDecorator::Mangle);
	   //...
	}

   
  HeapWord* DefNewGeneration::allocate(size_t word_size,
	                                     bool is_tlab) {
	  //正常情況下只有慢速分配對象時纔會進入此方法,此時在GenCollectHeap層已經獲取了鎖                                   
	  //par_allocate不要求調用方獲取全局鎖,底層使用cmpxchg原子指令,更快
	  HeapWord* result = eden()->par_allocate(word_size);
	  if (result != NULL) {
	    //如果分配成功
	    //CMSEdenChunksRecordAlways表示是否記錄eden區分配的內存塊,默認爲true
	    if (CMSEdenChunksRecordAlways && _next_gen != NULL) {
	      _next_gen->sample_eden_chunk();
	    }
	    return result;
	  }
	  do {
	    HeapWord* old_limit = eden()->soft_end();
	    if (old_limit < eden()->end()) {
	      //通知老年代,年輕代已經達到了分配限制soft_end,老年代會返回一個新的限制
	      //非iCMS模式下,該方法就是返回NULL,就end和soft_end一直
	      HeapWord* new_limit =
	        next_gen()->allocation_limit_reached(eden(), eden()->top(), word_size);
	      if (new_limit != NULL) {
	        //原子的修改eden區的soft_end屬性
	        Atomic::cmpxchg_ptr(new_limit, eden()->soft_end_addr(), old_limit);
	      } else {
	        assert(eden()->soft_end() == eden()->end(),
	               "invalid state after allocation_limit_reached returned null");
	      }
	    } else {
	      //soft_end跟end一致了,必須擴容才能繼續分配,終止循環
	      assert(old_limit == eden()->end(), "sanity check");
	      break;
	    }
	    //再次嘗試分配,直到分配成功或者soft_end跟end一致
	    result = eden()->par_allocate(word_size);
	  } while (result == NULL);
	 
	  if (result == NULL) {
	    //從from區域分配內存
	    result = allocate_from_space(word_size);
	  } else if (CMSEdenChunksRecordAlways && _next_gen != NULL) {
	    //while循環重試分配成功
	    _next_gen->sample_eden_chunk();
	  }
	  return result;
	} 
	//此方法的四個參數只有clear_all_soft_refs是有用的參數,如果爲true表示會清除所有的軟引用
	//如果是false則按照默認邏輯處理
	void DefNewGeneration::collect(bool   full,
	                               bool   clear_all_soft_refs,
	                               size_t size,
	                               bool   is_tlab) {
	  assert(full || size > 0, "otherwise we don't want to collect");
	 
	  GenCollectedHeap* gch = GenCollectedHeap::heap();
	  
	  //記錄GC的開始時間和原因
	  //...
	 
	  //老年代
	  _next_gen = gch->next_gen(this);
	 
	  //判斷老年代是否有足夠的空間保存年輕代複製過去的對象
	  if (!collection_attempt_is_safe()) {
	    //通知GCH老年代空間不足
	    gch->set_incremental_collection_failed(); // Slight lie: we did not even attempt one
	    //老年代空間不足,終止年輕代的GC
	    return;
	  }
	  assert(to()->is_empty(), "Else not collection_attempt_is_safe");
	  
	  //將_promotion_failed屬性置爲false,記錄promote失敗信息的PromotionFailedInfo重置成初始狀態
	  init_assuming_no_promotion_failure();
	 
	  GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, gc_tracer.gc_id());
	  // Capture heap used before collection (for printing).
	  size_t gch_prev_used = gch->used();
	  
	  //設置GC Tracer
	  gch->trace_heap_before_gc(&gc_tracer);
	 
	  SpecializationStats::clear();
	 
	  //初始化兩個遍歷器
	  IsAliveClosure is_alive(this);
	  ScanWeakRefClosure scan_weak_ref(this);
	  
	  //重置ageTable
	  age_table()->clear();
	  //重置to區
	  to()->clear(SpaceDecorator::Mangle);
	  //重置cur_youngergen_card_val,並行遍歷髒的卡表項時使用
	  gch->rem_set()->prepare_for_younger_refs_iterate(false);
	 
	  assert(gch->no_allocs_since_save_marks(0),
	         "save marks have not been newly set.");
	 
	  CollectorPolicy* cp = gch->collector_policy();
	  
	  //FastScanClosure用來遍歷年輕代中的存活對象oop,第二個參數爲true,表示會將oop對應的卡表項置爲youngergen_card
	  FastScanClosure fsc_with_no_gc_barrier(this, false);
	  FastScanClosure fsc_with_gc_barrier(this, true);
	  
	  //KlassScanClosure用來遍歷在上一次GC到當前GC之間創建的新的Klass對應的Class實例
	  KlassScanClosure klass_scan_closure(&fsc_with_no_gc_barrier,
	                                      gch->rem_set()->klass_rem_set());
	  //CLDToKlassAndOopClosure用來遍歷一個ClassLoader加載的所有類對應的Class實例和依賴等                                    
	  CLDToKlassAndOopClosure cld_scan_closure(&klass_scan_closure,
	                                           &fsc_with_no_gc_barrier,
	                                           false);
	  //設置promote失敗時的遍歷器
	  set_promo_failure_scan_stack_closure(&fsc_with_no_gc_barrier);
	  //FastEvacuateFollowersClosure主要用來遍歷被promote到老年代的對象,恢復其對象頭並遍歷其引用類型屬性
	  FastEvacuateFollowersClosure evacuate_followers(gch, _level, this,
	                                                  &fsc_with_no_gc_barrier,
	                                                  &fsc_with_gc_barrier);
	 
	  assert(gch->no_allocs_since_save_marks(0),
	         "save marks have not been newly set.");
	  
	  //執行根節點遍歷以及老年代新應用的oop遍歷
	  gch->gen_process_roots(_level, //level就是0
	                         true,  //因爲level是0,所以此參數實際無意義
	                         true,  // StrongRootsScope的active入參爲true
	                         GenCollectedHeap::SO_ScavengeCodeCache, //只遍歷nmethod中的oop
	                         GenCollectedHeap::StrongAndWeakRoots,//StrongAndWeakRoots是靜態常量,值爲false,表示會遍歷weak root,如StringTable中的String對象
	                         &fsc_with_no_gc_barrier,
	                         &fsc_with_gc_barrier,
	                         &cld_scan_closure);
	 
	  //遍歷所有promote到老年代的對象,恢復其對象頭,遍歷其引用類型屬性
	  evacuate_followers.do_void();
	 
	  FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
	  ReferenceProcessor* rp = ref_processor();
	  rp->setup_policy(clear_all_soft_refs);
	  //處理do_void方法遍歷引用類型屬性過程中找到的Reference實例,如果該實例的referent對象是存活的,則從待處理列表中移除,否則將referent屬性置爲null
	  const ReferenceProcessorStats& stats =
	  rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
	                                    NULL, _gc_timer, gc_tracer.gc_id());
	  gc_tracer.report_gc_reference_stats(stats);
	 
	  if (!_promotion_failed) {
	    //promote沒有失敗的
	    //重置清空eden區和from區
	    eden()->clear(SpaceDecorator::Mangle);
	    from()->clear(SpaceDecorator::Mangle);
	    if (ZapUnusedHeapArea) {
	      to()->mangle_unused_area();
	    }
	    //交換from區和to區
	    swap_spaces();
	    //交換後,原來的from區變成to區,必須是空的
	    assert(to()->is_empty(), "to space should be empty now");
	    //調整tenuring_threshold
	    adjust_desired_tenuring_threshold();
	 
	    AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
	    //重置gc_overhead_limit_count
	    size_policy->reset_gc_overhead_limit_count();
	    if (PrintGC && !PrintGCDetails) {
	      gch->print_heap_change(gch_prev_used);
	    }
	    assert(!gch->incremental_collection_failed(), "Should be clear");
	  } else {
	    //如果存在promote失敗的情形
	    assert(_promo_failure_scan_stack.is_empty(), "post condition");
	    //drain_promo_failure_scan_stack方法會負責處理掉裏面保存的oop,遍歷其所引用的其他oop,找到的oop的處理邏輯就是fsc_with_no_gc_barrier
	    //釋放_promo_failure_scan_stack的內存,
	    _promo_failure_scan_stack.clear(true); // Clear cached segments.
	    //移除from區和eden區包含的對象的froward指針
	    remove_forwarding_pointers();
	    if (PrintGCDetails) {
	      gclog_or_tty->print(" (promotion failed) ");
	    }
	    //交換from區和to區,注意此時eden區和from區因爲promote失敗所以不是空的,還有存活對象
	    swap_spaces();   // For uniformity wrt ParNewGeneration.
	    //將to區作爲from區的next_compaction_space,正常爲NULL
	    from()->set_next_compaction_space(to());
	    //將incremental_collection_failed置爲true
	    gch->set_incremental_collection_failed();
	 
	    //通知老年代promote失敗,CMS老年代實際不做處理
	    _next_gen->promotion_failure_occurred();
	    gc_tracer.report_promotion_failed(_promotion_failed_info);
	  }
	  //設置並行遍歷時的邊界
	  from()->set_concurrent_iteration_safe_limit(from()->top());
	  to()->set_concurrent_iteration_safe_limit(to()->top());
	  SpecializationStats::print();
	 
	  //更新GC完成時間
	  jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
	  update_time_of_last_gc(now);
	 
	  gch->trace_heap_after_gc(&gc_tracer);
	  gc_tracer.report_tenuring_threshold(tenuring_threshold());
	 
	  _gc_timer->register_gc_end();
	  //更新GC日誌
	  gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
	}

	oop DefNewGeneration::copy_to_survivor_space(oop old) {
	  assert(is_in_reserved(old) && !old->is_forwarded(),
	         "shouldn't be scavenging this oop");
	  size_t s = old->size();
	  oop obj = NULL;
	 
	  // Try allocating obj in to-space (unless too old)
	  if (old->age() < tenuring_threshold()) {
	    //如果對象的年齡低於tenuring_threshold,則該在to區申請一塊同樣大小的內存
	    obj = (oop) to()->allocate_aligned(s);
	  }
	 
	  // Otherwise try allocating obj tenured
	  if (obj == NULL) {
	    //如果如果對象的年齡大於tenuring_threshold或者to區申請內存失敗
	    //則嘗試將該對象複製到老年代
	    obj = _next_gen->promote(old, s);
	    if (obj == NULL) {
	      //複製失敗
	      handle_promotion_failure(old);
	      return old;
	    }
	  } else {
	    //to區中申請內存成功
	    const intx interval = PrefetchCopyIntervalInBytes;
	    Prefetch::write(obj, interval);
	 
	    //對象複製
	    Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)obj, s);
	 
	    //增加年齡,並修改age_table,增加對應年齡的總對象大小
	    //注意此處是增加複製對象而非原來對象的分代年齡
	    obj->incr_age();
	    age_table()->add(obj, s);
	  }
	 
	  //將對象頭指針指向新地址
	  old->forward_to(obj);
	 
	  return obj;
	}

 
}

//定義垃圾回收器使用的全局屬性,並初始化分代內存及其他共享資源
// CollectorPolicy
//   G1CollectorPolicy 
//     G1CollectorPolicyExt
//   GenCollectorPolicy
//     TwoGenerationCollectorPolicy
//     	  ConcurrentMarkSweepPolicy 
//     	    ASConcurrentMarkSweepPolicy 
//     	  GenerationSizer 
//     	  MarkSweepPolicy 
//hotspot/src/share/vm/memory/collectorPolicy.hpp
class CollectorPolicy : public CHeapObj<mtGC> {
  //跟蹤分代內存的性能的計數器
  GCPolicyCounters* _gc_policy_counters;
  //初始堆內存
  size_t _initial_heap_byte_size;
  //最大堆內存
  size_t _max_heap_byte_size;
  //最小堆內存
  size_t _min_heap_byte_size;
  //space分配粒度
  size_t _space_alignment;
  //heap分配粒度,_heap_alignment必須大於_space_alignment,且是_space_alignment的整數倍
  size_t _heap_alignment;
  //是否通過命令行參數設置了最大堆內存
  bool _max_heap_size_cmdline;
  //用來自適應調整堆內存大小的策略實現
  AdaptiveSizePolicy* _size_policy;
  //是否需要清除所有的軟引用,當軟引用清除結束,垃圾回收器會將其置爲false
  bool _should_clear_all_soft_refs;
  //當GC剛清除完所有的軟引用時會設置該屬性爲true,當返回mutator時被設置成false
  bool _all_soft_refs_clear;

  enum Name {
    CollectorPolicyKind,
    TwoGenerationCollectorPolicyKind,
    ConcurrentMarkSweepPolicyKind,
    ASConcurrentMarkSweepPolicyKind,
    G1CollectorPolicyKind
  };
  
  virtual CollectorPolicy::Name kind() {
    return CollectorPolicy::CollectorPolicyKind;
  }
}

//表示分代內存使用的CollectorPolicy
//hotspot/src/share/vm/memory/collectorPolicy.hpp
class GenCollectorPolicy : public CollectorPolicy {
  //gen0的內存最小值
  size_t _min_gen0_size;
  //gen0的內存初始值
  size_t _initial_gen0_size;
  //gen0的內存最大值
  size_t _max_gen0_size;
  //分代內存分配粒度,_gen_alignment必須被_space_alignment整除,_heap_alignment被_gen_alignment整除
  size_t _gen_alignment;
  //一種特殊的Generation實現
  GenerationSpec **_generations;

  HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size,
	                                                        bool   is_tlab) {
	  //獲取Java堆                                                      
	  GenCollectedHeap *gch = GenCollectedHeap::heap();
	  //初始化GCCause
	  GCCauseSetter x(gch, GCCause::_allocation_failure);
	  HeapWord* result = NULL;
	 
	  assert(size != 0, "Precondition violated");
	  if (GC_locker::is_active_and_needs_gc()) {
	    // GC_locker是active說明還有線程處於JNI關鍵區未開始GC
	    if (!gch->is_maximal_no_gc()) {
	      result = expand_heap_and_allocate(size, is_tlab);
	    }
	    return result;   // could be null if we are out of space
	  } else if (!gch->incremental_collection_will_fail(false /* don't consult_young */)) {
	    //incremental_collection_will_fail表示如果執行增量收集是否會失敗,參考上一次增量收集的結果
	    //如果可以執行增量收集
	    gch->do_collection(false            /* full */,
	                       false            /* clear_all_soft_refs */,
	                       size             /* size */,
	                       is_tlab          /* is_tlab */,
	                       number_of_generations() - 1 /* max_level */);
	  } else {
	    if (Verbose && PrintGCDetails) {
	      gclog_or_tty->print(" :: Trying full because partial may fail :: ");
	    }
	    //執行全量的full GC
	    gch->do_collection(true             /* full */,
	                       false            /* clear_all_soft_refs */,
	                       size             /* size */,
	                       is_tlab          /* is_tlab */,
	                       number_of_generations() - 1 /* max_level */);
	  }
	  //嘗試分配內存
	  result = gch->attempt_allocation(size, is_tlab, false /*first_only*/);
	 
	  if (result != NULL) {
	    //分配成功
	    assert(gch->is_in_reserved(result), "result not in heap");
	    return result;
	  }
	 
	  //分配失敗,嘗試擴展Java堆並分配內存
	  result = expand_heap_and_allocate(size, is_tlab);
	  if (result != NULL) {
	    return result;
	  }
	 
	  //分配失敗,說明已經內存不足了,這時需要強制清理軟引用,強制壓實Java堆,任何可能的獲取可用內存的方法都會執行,儘管代價昂貴
	  //如果嘗試失敗,拋出OOM異常
	  {
	    UIntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted
	 
	    gch->do_collection(true             /* full */,
	                       true             /* clear_all_soft_refs */,
	                       size             /* size */,
	                       is_tlab          /* is_tlab */,
	                       number_of_generations() - 1 /* max_level */);
	  }
	 
	  //再次嘗試分配內存
	  result = gch->attempt_allocation(size, is_tlab, false /* first_only */);
	  if (result != NULL) {
	    assert(gch->is_in_reserved(result), "result not in heap");
	    return result;
	  }
	  //分配失敗,軟引用已經清理的,標誌位被置爲false
	  assert(!should_clear_all_soft_refs(),
	    "Flag should have been handled and cleared prior to this point");
	 
	  return NULL;
	}
 

}

//表示一個只有兩個Generation的CollectorPolicy,現有的GenCollectedHeap的所有子類都是隻有兩個Generation,第一個Generation相同,對應GenCollectorPolicy中新增的gen0的相關屬性,第二個Generation的實現各不相同。TwoGenerationCollectorPolicy增加了第二個Generation即gen1相關的屬性
//hotspot/src/share/vm/memory/collectorPolicy.hpp
class TwoGenerationCollectorPolicy : public GenCollectorPolicy {
  //gen1的內存最小值
  size_t _min_gen1_size;
  //gen1的內存初始值
  size_t _initial_gen1_size;
  //gen1的內存最大值
  size_t _max_gen1_size;
}

//UseAdaptiveSizePolicy爲false時使用的CollectorPolicy實現.該類沒有添加新的屬性
//hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp
class ConcurrentMarkSweepPolicy : public TwoGenerationCollectorPolicy {
	void ConcurrentMarkSweepPolicy::initialize_alignments() {
	  //初始化_space_alignment等屬性
	  _space_alignment = _gen_alignment = (uintx)Generation::GenGrain;
	  _heap_alignment = compute_heap_alignment();
	}
	 
	void ConcurrentMarkSweepPolicy::initialize_generations() {
	  //初始化_generations
	  _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC,
	    CURRENT_PC, AllocFailStrategy::RETURN_NULL);
	  if (_generations == NULL)
	    vm_exit_during_initialization("Unable to allocate gen spec");
	  //UseParNewGC表示在新生代使用併發收集,默認爲false
	  if (UseParNewGC) {
	    if (UseAdaptiveSizePolicy) {
	      _generations[0] = new GenerationSpec(Generation::ASParNew,
	                                           _initial_gen0_size, _max_gen0_size);
	    } else {
	      _generations[0] = new GenerationSpec(Generation::ParNew,
	                                           _initial_gen0_size, _max_gen0_size);
	    }
	  } else {
	    _generations[0] = new GenerationSpec(Generation::DefNew,
	                                         _initial_gen0_size, _max_gen0_size);
	  }
	  //UseAdaptiveSizePolicy表示使用自適應策略動態調整各代的大小,默認爲true
	  if (UseAdaptiveSizePolicy) {
	    _generations[1] = new GenerationSpec(Generation::ASConcurrentMarkSweep,
	                            _initial_gen1_size, _max_gen1_size);
	  } else {
	    _generations[1] = new GenerationSpec(Generation::ConcurrentMarkSweep,
	                            _initial_gen1_size, _max_gen1_size);
	  }
	 
	  if (_generations[0] == NULL || _generations[1] == NULL) {
	    //如果初始化失敗,則退出
	    vm_exit_during_initialization("Unable to allocate gen spec");
	  }
	}
	 
	int number_of_generations()          { return 2; }
}

//UseAdaptiveSizePolicy爲true時使用的CollectorPolicy實現.該類沒有添加新的屬性
//hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp
class ASConcurrentMarkSweepPolicy : public ConcurrentMarkSweepPolicy {
}

垃圾收集器的初始化

根據《JVM內存池》一文中,堆內存初始化

jint Universe::initialize_heap() {

  if (UseParallelGC) {
    Universe::_collectedHeap = new ParallelScavengeHeap();
  } else if (UseG1GC) {
    G1CollectorPolicyExt* g1p = new G1CollectorPolicyExt();
    g1p->initialize_all();
    G1CollectedHeap* g1h = new G1CollectedHeap(g1p);
    Universe::_collectedHeap = g1h;
  } else {
    //主要存儲各種不同收集器堆的模型參數
    GenCollectorPolicy *gc_policy;

    if (UseSerialGC) {
      gc_policy = new MarkSweepPolicy();
    } else if (UseConcMarkSweepGC) {
      if (UseAdaptiveSizePolicy) {
        gc_policy = new ASConcurrentMarkSweepPolicy();
      } else {
        //cms堆的模型參數
        gc_policy = new ConcurrentMarkSweepPolicy();
      }
    } else { // default old generation
      gc_policy = new MarkSweepPolicy();
    }
    //根據JVM參數,對堆模型參數初始化
    gc_policy->initialize_all();

    Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
  }
  //eden中tlab表申請
  ThreadLocalAllocBuffer::set_max_size(Universe::heap()->max_tlab_size());
  //堆申請,及分帶初始化
  jint status = Universe::heap()->initialize();
  if (status != JNI_OK) {
    return status;
  }
  // .....
}  

其中最常用的爲cms垃圾收集器。其觸發參數爲

-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC

  1. Policy中根據參數設置分代數據,根據參數並行gc線程

Threads::create_vm()《openJdk的啓動流程》中的方法
  init_globals()
  Universe::universe_init()
   Universe::initialize_heap()
    ConcurrentMarkSweepPolicy::initialize_all
     ConcurrentMarkSweepPolicy::initialize_generations # 分代數據設置
    GenCollectedHeap::GenCollectedHeap
     SharedHeap::SharedHeap # GC線程創建

//年輕代參數設置
 _generations[0] = new GenerationSpec(Generation::ParNew,
                                           _initial_gen0_size, _max_gen0_size);
 
//老年代參數設置                                           
_generations[1] = new GenerationSpec(Generation::ConcurrentMarkSweep,
                            _initial_gen1_size, _max_gen1_size);
//初始化執行並行GC的線程池 
_workers = new FlexibleWorkGang("Parallel GC Threads", ParallelGCThreads,
                            /* are_GC_task_threads */true,
                            /* are_ConcurrentGC_threads */false);
  1. 根據分代參數,具體初始化分代

Threads::create_vm()《openJdk的啓動流程》中的方法
  init_globals()
  Universe::universe_init()
   Universe::initialize_heap()
    GenCollectedHeap::initialize()

  //根據各GenerationSpec的最大大小計算總的需要保留的內存空間,然後申請指定大小的連續內存空間
heap_address = allocate(heap_alignment, &total_reserved,
                          &n_covered_regions, &heap_rs);

//分帶初始化 
_gen_specs[i]->init(this_rs, i, rem_set()); 

//年輕代
new ParNewGeneration(rs, init_size(), 0);
//老年代
new ConcurrentMarkSweepGeneration(rs,
               init_size(), 1, ctrs, UseCMSAdaptiveFreeLists,
                 (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);                         
  1. 驗證堆模型的正確性,及進一些初始化參數,具體參考GenCollectedHeap::post_initialize

垃圾收集觸發

  1. 創建vm_threads,用於處理虛擬機各種延時任務

Threads::create_vm()《openJdk的啓動流程》中的方法
  VMThread::create()

  1. 編寫一觸放eden垃圾回收代碼
/*-verbose:gc
-Xms20M
-Xmx20M
-Xmn10M
-XX:SurvivorRatio=8
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+UseConcMarkSweepGC
-XX:MaxTenuringThreshold=1*/       
       byte[] b1, b2, b3, b4;
       b1 = new byte[2 * _1MB];
       b2 = new byte[2* _1MB];
       b3 = new byte[2* _1MB];
       b2 = null;
       b3 = null;
       b4 = new byte[2* _1MB]; //eden用完,必須回收
  1. 內存申請失敗生成VM_GenCollectForAllocation並向vm_threads提交

創建b4時通過JNI調用
InterpreterRuntime::newarray
  TypeArrayKlass::allocate_common
    CollectedHeap::common_mem_allocate_init
     GenCollectorPolicy::mem_allocate_work

//VM_GenCollectForAllocation是內存分配失敗觸發垃圾回收,然後嘗試分配內存的操作
VM_GenCollectForAllocation op(size, is_tlab, gc_count_before);
VMThread::execute(&op);
  1. VMThread處理VM_GenCollectForAllocation事件,進行垃圾回收

VMThread::run
  VMThread::loop
    VM_Operation::evaluate
     VM_GenCollectForAllocation::doit
       GenCollectorPolicy::satisfy_failed_allocation

//如果執行增量收集是否會失敗,參考上一次增量收集的結果
if(!incremental_collection_will_fail(false)){
    //如果可以執行增量收集
    gch->do_collection(false            /* full */,
                       false            /* clear_all_soft_refs */,
                       size             /* size */,
                       is_tlab          /* is_tlab */,
                       number_of_generations() - 1 /* max_level */);
}else{
    //執行全量的full GC
    gch->do_collection(true             /* full */,
                       false            /* clear_all_soft_refs */,
                       size             /* size */,
                       is_tlab          /* is_tlab */,
                       number_of_generations() - 1 /* max_level */);
}
  1. 根據上例子do_collection執行流程爲
int starting_level = 0;
boolean full = false;
int max_level = 1;
//full爲false,空間不充足
ParNewGeneration.should_collect() //返回true
ParNewGeneration.collect(full, do_clear_all_soft_refs, size, is_tlab);
//full爲false,空間充足
ConcurrentMarkSweepGeneration.should_collect() //false

ParNew年輕代

  1. 年輕代初始化

Threads::create_vm()《openJdk的啓動流程》中的方法
  init_globals()
  Universe::universe_init()
   Universe::initialize_heap()
    GenCollectedHeap::initialize
     GenerationSpec::init
      ParNewGeneration::ParNewGeneration
       DefNewGeneration::DefNewGeneration

//總體申請了個_virtual_space空間
//其中又用EdenSpace,ContiguousSpace進行進一步劃分
_eden_space = new EdenSpace(this);
_from_space = new ContiguousSpace();
_to_space   = new ContiguousSpace();
//計算survivor區和eden區的最大空間,即年輕代最大內存時survivor區和eden區的內存空間
  uintx size = _virtual_space.reserved_size();
  _max_survivor_size = compute_survivor_size(size, alignment);
  _max_eden_size = size - (2*_max_survivor_size);
//計算三個內存區的大小和邊界,並初始化
  compute_space_boundaries(0, SpaceDecorator::Clear, SpaceDecorator::Mangle);
  1. 年輕代對象分配主要在eden區,只有在eden區和老年代都滿了,纔可能在from區中分配內存,正常情況下to區是空的

數組創建時通過JNI調用
InterpreterRuntime::newarray
  TypeArrayKlass::allocate_common
    CollectedHeap::common_mem_allocate_init
     GenCollectorPolicy::mem_allocate_work
      GenCollectedHeap::attempt_allocation
       DefNewGeneration::allocate

//正常請求分配eden的空間
//word_size爲此次對象所要的空間
HeapWord* result = eden()->par_allocate(word_size);
if (result != NULL) {
    return result;
}
//從from申請空間
result = allocate_from_space(word_size);
  1. 年輕代垃圾收集ParNewGeneration.collect
  //FastScanClosure用來遍歷年輕代中的存活對象oop,第二個參數爲true,表示會將oop對應的卡表項置爲youngergen_card
  FastScanClosure fsc_with_no_gc_barrier(this, false);
  FastScanClosure fsc_with_gc_barrier(this, true);
  KlassScanClosure klass_scan_closure(&fsc_with_no_gc_barrier,
                                      gch->rem_set()->klass_rem_set());
  //CLDToKlassAndOopClosure用來遍歷一個ClassLoader加載的所有類對應的Class實例和依賴等                                    
  CLDToKlassAndOopClosure cld_scan_closure(&klass_scan_closure,
                                           &fsc_with_no_gc_barrier,
                                           false)

      //上面把所有的遍歷器都準備好了,遍歷器的底層原理是space 
      //gen_process_roots用於遍歷處理ClassLoaderDataGraph,Threads,Universe等組件中包含的oop,將這些oop作爲根節點遍歷其所引用的其他oop,根據參數還能遍歷年輕代和老年代中的所有oop,遍歷髒的卡表項對應的內存區域中包含的oop
	  gch->gen_process_roots(_level, //level就是0
	                         true,  //因爲level是0,所以此參數實際無意義
	                         true,  // StrongRootsScope的active入參爲true
	                         GenCollectedHeap::SO_ScavengeCodeCache, //只遍歷nmethod中的oop
	                         GenCollectedHeap::StrongAndWeakRoots,//StrongAndWeakRoots是靜態常量,值爲false,表示會遍歷weak root,如StringTable中的String對象
	                         &fsc_with_no_gc_barrier,
	                         &fsc_with_gc_barrier,
	                         &cld_scan_closure);
	 
  1. promote 操作

DefNewGeneration::collect
  GenCollectedHeap::gen_process_roots
    ClassLoaderDataGraph::roots_cld_do
     FastScanClosure::do_oop
      DefNewGeneration::copy_to_survivor_space

if (old->age() < tenuring_threshold()) {
    //如果對象的年齡低於tenuring_threshold,則該在to區申請一塊同樣大小的內存
    obj = (oop) to()->allocate_aligned(s);
}
if(obj == null){
    //如果如果對象的年齡大於tenuring_threshold或者to區申請內存失敗
    //則嘗試將該對象複製到老年代
    obj = _next_gen->promote(old, s);
    if (obj == NULL) {
      //複製失敗
      handle_promotion_failure(old);
      return old;
    }
}else{
   //to區中申請內存成功
}

//將對象頭指針指向新地址
old->forward_to(obj);
//promote就是指將某個存活對象oop從eden區拷貝到from區或者老年代的過程
//如果對象年齡大於閾值則拷貝到老年代,否則拷貝到to區
//如果to區內存不足則拷貝到老年代
//如果老年代空間不足則會臨時保存該oop,因爲有可能是該對象較大,此時其他較小的對象可以正常promote成功的。
//從to區或者老年代按照對象大小分配好同樣大小的內存後,就會將舊對象的數據複製到新分配的內存上,然後增加複製對象的對象年齡,最後將複製對象的地址寫入原對象的對象頭中並打標,這個動作就是forword。

CMS老年代垃圾收集

待續

主要參數

《hotspot實戰》
Hotspot 垃圾回收之VM_Operation 源碼解析
Hotspot 垃圾回收之CollectedHeap 源碼解析
Hotspot 垃圾回收之GenCollectedHeap 源碼解析
Hotspot 垃圾回收之CompactibleSpace 源碼解析
Hotspot 垃圾回收之EdenSpace 源碼解析
Hotspot 垃圾回收之DefNewGeneration(一) 源碼解析
Hotspot 垃圾回收之DefNewGeneration(二) 源碼解析
Hotspot 垃圾回收之CollectorPolicy (一) 源碼解析
Hotspot 垃圾回收之CollectorPolicy (二) 源碼解析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章