亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

源碼分析HotSpotGC過程(一)

2019-11-14 14:56:30
字體:
來源:轉載
供稿:網友

  對于HotSpot虛擬機垃圾回收過程,這里將分析介紹默認配置下MarkSweepPolicy的DefNewGeneration和TenuredGeneration的垃圾回收內容以及介紹其他GC策略和代實現的GC思想。GC的過程姑且簡單地分為內存代實現無關的GC過程和內存代GC過程。 
本文將先進行內存代實現無關的GC過程分析,內存代GC過程將在后面進行分析。

  從GenCollectedHeap的do_collection()說起: 
  1.在GC之前有許多必要的檢查和統計任務,比如對回收內存代的統計、堆內存大小的統計等,注意本節內容將不再去分析一些性能統計的內容,有興趣的可自行分析。 
  (1).檢查是否已經GC鎖是否已經激活,并設置需要進行GC的標志為true,這時,通過is_active_and_needs_gc()就可以判斷是否已經有線程觸發了GC。

 if (GC_locker::check_active_before_gc()) {    return; // GC is disabled (e.g. JNI GetXXXCritical Operation)  }

  (2).檢查是否需要回收所有的軟引用。

 const bool do_clear_all_soft_refs = clear_all_soft_refs ||                          collector_policy()->should_clear_all_soft_refs();

  (3).記錄永久代已經使用的內存空間大小。

const size_t perm_PRev_used = perm_gen()->used();

  (4).確定回收類型是否是FullGC以及gc觸發類型(GC/Full GC(system)/Full GC,用作Log輸出)。

bool complete = full && (max_level == (n_gens()-1));    const char* gc_cause_str = "GC ";    if (complete) {      GCCause::Cause cause = gc_cause();      if (cause == GCCause::_java_lang_system_gc) {        gc_cause_str = "Full GC (System) ";      } else {        gc_cause_str = "Full GC ";      }    }

  (5).gc計數加1操作(包括總GC計數和FullGC計數)。

increment_total_collections(complete);

  (6).統計堆已被使用的空間大小。

size_t gch_prev_used = used();

  (7).如果是FullGC,那么從最高的內存代到最低的內存代,若某個內存代不希望對比其更低的內存代進行單獨回收,那么就以該內存代作為GC的起始內存代。這里說明下什么是單獨回收。新生代比如DefNewGeneration的實現將對新生代使用復制算法進行垃圾回收,而老年代TenuredGeneration的垃圾回收則會使用其標記-壓縮-清理算法對新生代也進行處理。所以可以說DefNewGeneration的垃圾回收是對新生代進行單獨回收,而TenuredGeneration的垃圾回收則是對老年代和更低的內存代都進行回收。

  int starting_level = 0;  if (full) {      // Search for the oldest generation which will collect all younger      // generations, and start collection loop there.      for (int i = max_level; i >= 0; i--) {        if (_gens[i]->full_collects_younger_generations()) {          starting_level = i;          break;        }      }    }

  2.接下來從GC的起始內存代開始,向最老的內存代進行回收 。
  (1).其中should_collect()將根據該內存代GC條件返回是否應該對該內存代進行GC。若當前回收的內存代是最老的內存代,如果本次gc不是FullGC,將調用increment_total_full_collections()修正之前的FulllGC計數值。

   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) {            // The full_collections increment was missed above.            increment_total_full_collections();          }

  (2).統計GC前該內存代使用空間大小以及其他記錄工作 。
  (3).驗證工作 。

  先調用prepare_for_verify()使各內存代進行驗證的準備工作(正常情況下什么都不需要做),隨后調用Universe的verify()進行GC前驗證

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;          }          gclog_or_tty->print(" VerifyBeforeGC:");          Universe::verify(true);        }

  線程、堆(各內存代)、符號表、字符串表、代碼緩沖、系統字典等,如對堆的驗證將對堆內的每個oop對象的類型Klass進行驗證,驗證對象是否是oop,類型klass是否在永久代,oop的klass域是否是klass 。那么為什么在這里進行GC驗證?GC前驗證和GC后驗證又分別有什么作用? VerifyBeforeGC和VerifyAfterGC都需要和UnlockDiagnosticVMOptions配合使用以用來診斷JVM問題,但是驗證過程非常耗時,所以在正常的編譯版本中并沒有將驗證內容進行輸出。 
  (4).保存內存代各區域的碰撞指針到該區域的_save_mark_Word變量。

save_marks();

  (5).初始化引用處理器。

ReferenceProcessor* rp = _gens[i]->ref_processor();if (rp->discovery_is_atomic()) {            rp->verify_no_references_recorded();            rp->enable_discovery();            rp->setup_policy(do_clear_all_soft_refs);          } else {            // collect() below will enable discovery as appropriate          }

  (6).由各內存代完成gc

_gens[i]->collect(full, do_clear_all_soft_refs, size, is_tlab);

  (7).將不可觸及的引用對象加入到Reference的pending鏈表

if (!rp->enqueuing_is_done()) {            rp->enqueue_discovered_references();          } else {            rp->set_enqueuing_is_done(false);          }          rp->verify_no_references_recorded();        }

  其中enqueue_discovered_references根據是否使用壓縮指針選擇不同的enqueue_discovered_ref_helper()模板函數 ,enqueue_discovered_ref_helper()實現如下:
  

template <class T>bool enqueue_discovered_ref_helper(ReferenceProcessor* ref,                                   AbstractRefProcTaskExecutor* task_executor) {  T* pending_list_addr = (T*)java_lang_ref_Reference::pending_list_addr();  T old_pending_list_value = *pending_list_addr;  ref->enqueue_discovered_reflists((HeapWord*)pending_list_addr, task_executor);  oop_store(pending_list_addr, oopDesc::load_decode_heap_oop(pending_list_addr));  ref->disable_discovery();  return old_pending_list_value != *pending_list_addr;}

  pending_list_addr是Reference的私有靜態(類)成員pending鏈表的首元素的地址,gc階段當引用對象的可達狀態變化時,會將引用加入到pending鏈表中而Reference的私有靜態(類)成員ReferenceHandler將不斷地從pending鏈表中取出引用加入ReferenceQueue。 
  enqueue_discovered_reflists()根據是否使用多線程有著不同的處理方式,若采用多線程則會創建一個RefProcEnqueueTask交由AbstractRefProcTaskExecutor進行處理,這里我們分析單線程的串行處理情況: 
這里,DiscoveredList數組_discoveredSoftRefs保存了最多_max_num_q*subclasses_of_ref個軟引用的鏈表。在將引用鏈表處理后會將引用鏈表的起始引用置為哨兵引用,并設置引用鏈長度為0,表示該列表為空。

void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr,  AbstractRefProcTaskExecutor* task_executor) {  if (_processing_is_mt && task_executor != NULL) {    // Parallel code    RefProcEnqueueTask tsk(*this, _discoveredSoftRefs,                           pending_list_addr, sentinel_ref(), _max_num_q);    task_executor->execute(tsk);  } else {    // Serial code: call the parent class's implementation    for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {      enqueue_discovered_reflist(_discoveredSoftRefs[i], pending_list_addr);      _discoveredSoftRefs[i].set_head(sentinel_ref());      _discoveredSoftRefs[i].set_length(0);    }  }}

  enqueue_discovered_reflist()如下:

  取出refs_list鏈上的首元素,next為discovered域所成鏈表上的下一個元素

  oop obj = refs_list.head();  while (obj != sentinel_ref()) {    assert(obj->is_instanceRef(), "should be reference object");    oop next = java_lang_ref_Reference::discovered(obj);

  如果next是最后的哨兵引用,那么,原子交換discovered域所成鏈表上的表尾元素與pending_list_addr的值,即將其加入到pending鏈表的表頭,接下來根據插入到表頭的鏈表的處理方式,當pending鏈表為空時,作為表尾元素其next域指向自身,否則,將其next域指向鏈表的原表頭元素,這樣就將該元素插入到pending鏈表的原表頭位置,即:

if (next == sentinel_ref()) {  // obj is last      // Swap refs_list into pendling_list_addr and      // set obj's next to what we read from pending_list_addr.      oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);      // Need oop_check on pending_list_addr above;      // see special oop-check code at the end of      // enqueue_discovered_reflists() further below.      if (old == NULL) {        // obj should be made to point to itself, since        // pending list was empty.        java_lang_ref_Reference::set_next(obj, obj);      } else {        java_lang_ref_Reference::set_next(obj, old);      } 

  否則若next不是最后的哨兵引用,設置引用對象的next域為next,即將從引用鏈表的表頭元素開始,將虛擬機所使用的discovered域所成鏈表轉化為Java層可使用的next域所成pending列表。

} else {      java_lang_ref_Reference::set_next(obj, next);    }

  最后設置引用對象的discovered域為NULL,即切斷當前引用在discovered域所成鏈表中的引用關系,并繼續遍歷引用鏈   

java_lang_ref_Reference::set_discovered(obj, (oop) NULL);    obj = next;  }

  綜上所述,入隊的操作就是通過原來的discovered域進行遍歷,將引用鏈表用next域重新連接后切斷discovered域的關系并將新鏈表附在pending鏈表的表頭。

  (9).回到GC完成后的處理:更新統計信息和進行GC后驗證

  3.輸出一些GC的日志信息

 

    complete = complete || (max_level_collected == n_gens() - 1);        if (complete) { // We did a "major" collection      post_full_gc_dump();   // do any post full gc dumps    }    if (PrintGCDetails) {      print_heap_change(gch_prev_used);      // Print perm gen info for full GC with PrintGCDetails flag.      if (complete) {        print_perm_heap_change(perm_prev_used);      }    }

 

  4.更新各內存代的大小

 for (int j = max_level_collected; j >= 0; j -= 1) {      // Adjust generation sizes.      _gens[j]->compute_new_size();    }

  5.FullGC后更新和調整永久代內存大小

if (complete) {      // Ask the permanent generation to adjust size for full collections      perm()->compute_new_size();      update_full_collections_completed();    }

6.若配置了ExitAfterGCNum,則當gc次數達到用戶配置的最大GC計數時退出VM

 if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) {    tty->print_cr("Stopping after GC #%d", ExitAfterGCNum);    vm_exit(-1);  }

GC的內存代實現無關的流程圖如下: 

    

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久国产精品www| 国产日产亚洲精品| 日韩在线观看免费高清| 国产美女久久精品香蕉69| 欧美日韩国产精品一区二区不卡中文| 精品国产91久久久| 国产丝袜精品视频| 欧美激情影音先锋| 欧美午夜www高清视频| 亚洲免费av网址| 全色精品综合影院| 亚洲免费电影在线观看| 亚洲护士老师的毛茸茸最新章节| 国产精品一二三在线| 日韩电影在线观看中文字幕| 欧美最近摘花xxxx摘花| 欧美视频中文字幕在线| 亚洲视屏在线播放| 国产精品a久久久久久| 色偷偷偷综合中文字幕;dd| xxxx欧美18另类的高清| 亚洲第一偷拍网| 久久久国产在线视频| 日韩成人性视频| 中文字幕日韩欧美| 国产精品一区二区女厕厕| 日韩欧美在线免费| 中文字幕欧美日韩va免费视频| 668精品在线视频| 国产综合在线观看视频| 69av成年福利视频| 91国内揄拍国内精品对白| 久久综合国产精品台湾中文娱乐网| 日韩在线视频导航| 一级做a爰片久久毛片美女图片| 国产美女被下药99| 日韩综合中文字幕| 欧美成人午夜影院| 亚洲精品一区久久久久久| 日韩午夜在线视频| 国产精品678| 国内免费久久久久久久久久久| 色先锋资源久久综合5566| 国产精品91久久久久久| 国产自产女人91一区在线观看| 亚洲精品国产拍免费91在线| 国产精品美女av| 久久夜色精品国产欧美乱| 中文字幕国产精品久久| 中文字幕视频在线免费欧美日韩综合在线看| 91综合免费在线| 亚洲视频在线视频| 久久成人精品视频| 91精品国产乱码久久久久久久久| 最近2019中文字幕mv免费看| 成人免费视频xnxx.com| 另类少妇人与禽zozz0性伦| 国产精品久久久av久久久| 成人美女av在线直播| 亚洲欧美制服丝袜| 精品丝袜一区二区三区| 国产精品主播视频| 亚洲xxxxx性| 亚洲一区二区自拍| 中文字幕在线看视频国产欧美在线看完整| 日韩高清免费观看| 高清亚洲成在人网站天堂| 4388成人网| 亚洲精品福利免费在线观看| 午夜精品久久久久久久99热浪潮| 欧美另类99xxxxx| 欧美一级免费视频| 国产精品久久久久久超碰| 91国内揄拍国内精品对白| 亚洲第一精品福利| 国产99久久精品一区二区| 亚洲人成电影网站色| 亚洲bt天天射| 国内揄拍国内精品少妇国语| 日本一区二区三区四区视频| 最近中文字幕2019免费| 国产www精品| 欧美精品18videos性欧美| 视频一区视频二区国产精品| 97成人在线视频| 欧美精品国产精品日韩精品| 欧美小视频在线观看| 正在播放亚洲1区| 精品少妇一区二区30p| 欧美情侣性视频| 日本三级韩国三级久久| 久久人人爽人人爽人人片av高请| 成人免费网站在线观看| 欧美成人在线影院| 亚洲综合av影视| 日韩av色综合| 亚洲精品狠狠操| 一区二区欧美久久| 国产精品自产拍在线观看中文| 亚洲级视频在线观看免费1级| 欧美日韩在线一区| 久久久国产精品免费| 亚洲福利视频网| 亚洲国产小视频| 欧美在线视频网站| 97久久久免费福利网址| 国产mv久久久| 成人信息集中地欧美| 精品福利在线看| 亚洲精品黄网在线观看| 欧美精品手机在线| 97人人爽人人喊人人模波多| 17婷婷久久www| 亚洲三级黄色在线观看| 亚洲自拍小视频| 日本一欧美一欧美一亚洲视频| 欧美日韩亚洲精品一区二区三区| 韩国精品美女www爽爽爽视频| 日本一欧美一欧美一亚洲视频| 91亚洲国产成人久久精品网站| 国产精品入口免费视| 午夜免费日韩视频| 久久在线免费观看视频| 羞羞色国产精品| 97久久精品在线| 中文字幕国内精品| 欧美一级视频在线观看| 8x海外华人永久免费日韩内陆视频| 91久久久久久久久| 日韩三级影视基地| 亚洲欧美福利视频| 久久久国产视频| 欧美性高潮在线| 亚洲网址你懂得| 久久久午夜视频| 欧美成人自拍视频| 精品美女国产在线| 91亚洲精品在线观看| 91精品国产99| 久久影视电视剧免费网站| 国产精品久久国产精品99gif| 最近2019中文字幕在线高清| 久久久久久久久久国产| 欧美日韩国产成人在线观看| 中文字幕欧美日韩精品| 亚洲成人网在线观看| 日韩在线中文视频| 97国产在线视频| 91精品久久久久久久久不口人| 亚洲免费电影在线观看| 国产精品6699| 色无极影院亚洲| 精品国产一区二区三区久久狼黑人| 日韩视频免费看| 亚洲福利视频久久| 欧美精品性视频| 亚洲www视频| 亚洲91精品在线观看| 伊人av综合网| 久久视频在线免费观看| 97视频人免费观看| 日韩在线免费高清视频| 亚洲a区在线视频| 亚洲欧美国内爽妇网|