内存代管理器TenuredGeneration对垃圾对象的回收

内存代管理器TenuredGeneration作为基于内存分代管理的内存堆管理器GenCollectedHeap默认的旧生代管理器,它对垃圾对象的回收算法要比年青代Gc要复杂的多,但其主体思路就是:标记-清除-压缩.本文主要围绕内存代Gc时的三个过程来详细讲解TenuredGeneration是如何进行垃圾回收的.

一.Gc条件

     可对 TenuredGeneration管理的旧生代进行Gc的条件主要有4个,满足其中的任何一个即可对旧生代进行垃圾回收:

[html]   view plain copy
  1. 1.当前是Full Gc  
  2. 2.可在当前内存代分配请求的空间  
  3. 3.当前内存代空闲空间<10000  
  4. 4.当前内存代容量>上一次Gc之前的容量  
     具体代码可参见如下:
[cpp]   view plain copy 在CODE上查看代码片 派生到我的代码片
  1. bool TenuredGeneration::should_collect(bool  full, size_t size, bool   is_tlab) {  
  2.   // This should be one big conditional or (||), but I want to be able to tell  
  3.   // why it returns what it returns (without re-evaluating the conditionals  
  4.   // in case they aren't idempotent), so I'm doing it this way.  
  5.   // DeMorgan says it's okay.  
  6.   bool result = false;  
  7.   
  8.   if (!result && full) {  
  9.     result = true;  
  10.     if (PrintGC && Verbose) {  
  11.       gclog_or_tty->print_cr("TenuredGeneration::should_collect: because full");  
  12.     }  
  13.   }  
  14.   
  15.   if (!result && should_allocate(size, is_tlab)) {  
  16.     result = true;  
  17.     if (PrintGC && Verbose) {  
  18.       gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"  
  19.                     " should_allocate(" SIZE_FORMAT ")", size);  
  20.     }  
  21.   }  
  22.   
  23.   // If we don't have very much free space.  
  24.   // XXX: 10000 should be a percentage of the capacity!!!  
  25.   if (!result && free() < 10000) {  
  26.     result = true;  
  27.     if (PrintGC && Verbose) {  
  28.       gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"  
  29.                     " free(): " SIZE_FORMAT,  
  30.                     free());  
  31.     }  
  32.   }  
  33.   
  34.   // If we had to expand to accomodate promotions from younger generations  
  35.   if (!result && _capacity_at_prologue < capacity()) {  
  36.     result = true;  
  37.     if (PrintGC && Verbose) {  
  38.       gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"  
  39.                     "_capacity_at_prologue: " SIZE_FORMAT " < capacity(): " SIZE_FORMAT,  
  40.                     _capacity_at_prologue, capacity());  
  41.     }  
  42.   }  
  43.   
  44.   return result;  
  45. }  

二.Gc基本流程

       默认的旧生代管理器TenuredGeneration回收垃圾对象的基本思路就是:

[html]   view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 第一步: 标记所有的active对象  
  2.   
  3. 第二步: 计算所有active对象在其内存代压缩后的偏移位置  
  4.   
  5. 第三步: 更新所有active对象的地址映射表  
  6.   
  7. 第四步: 移动复制所有的active对象到新的存储位置  

1.标记所有的active对象

   TenuredGeneration标记所有active对象的过程跟年青代Gc相似,都是从根对象开始以深度优先的方式搜索标记所有的active对象,具体过程如下:

[cpp]   view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 从根对象开始递归迭代标记所有活动的对象 
  3.  */  
  4. void GenMarkSweep::mark_sweep_phase1(int level,  
  5.                                   bool clear_all_softrefs) {  
  6.   // Recursively traverse all live objects and mark them  
  7.   TraceTime tm("phase 1", PrintGC && Verbose, true, gclog_or_tty);  
  8.   trace(" 1");  
  9.   
  10.   VALIDATE_MARK_SWEEP_ONLY(reset_live_oop_tracking(false));  
  11.   
  12.   GenCollectedHeap* gch = GenCollectedHeap::heap();  
  13.   
  14.   // Because follow_root_closure is created statically, cannot  
  15.   // use OopsInGenClosure constructor which takes a generation,  
  16.   // as the Universe has not been created when the static constructors  
  17.   // are run.  
  18.   follow_root_closure.set_orig_generation(gch->get_gen(level));  
  19.   
  20.   /** 
  21.    * 遍历当前所有的根对象并标记,并递归遍历标记它们的引用对象 
  22.    */  
  23.   gch->gen_process_strong_roots(level,  
  24.                                 false// Younger gens are not roots.  
  25.                                 true,  // activate StrongRootsScope  
  26.                                 true,  // Collecting permanent generation.  
  27.                                 SharedHeap::SO_SystemClasses,  
  28.                                 &follow_root_closure,  
  29.                                 true,   // walk code active on stacks  
  30.                                 &follow_root_closure);  
  31.   
  32.   //标记所有的软引用对象  
  33.   {  
  34.     ref_processor()->setup_policy(clear_all_softrefs);  
  35.     ref_processor()->process_discovered_references(&is_alive, &keep_alive, &follow_stack_closure, NULL);  
  36.   }  
  37.   
  38.   // Follow system dictionary roots and unload classes  
  39.   bool purged_class = SystemDictionary::do_unloading(&is_alive);  
  40.   
  41.   // 清理代码高速缓冲区  
  42.   CodeCache::do_unloading(&is_alive, &keep_alive, purged_class);  
  43.   follow_stack(); // Flush marking stack  
  44.   
  45.   // Update subklass/sibling/implementor links of live klasses  
  46.   follow_weak_klass_links();  
  47.   assert(_marking_stack.is_empty(), "just drained");  
  48.   
  49.   //清理未被标记的软/弱引用对象  
  50.   follow_mdo_weak_refs();  
  51.   assert(_marking_stack.is_empty(), "just drained");  
  52.   
  53.   //清除没有被引用的常量字符串  
  54.   StringTable::unlink(&is_alive);  
  55.   
  56.   //清除符号表中没有被引用的符号  
  57.   SymbolTable::unlink();  
  58.   
  59.   assert(_marking_stack.is_empty(), "stack should be empty by now");  
  60. }  

2.计算所有active对象在其内存代压缩后的偏移位置

    以内存代为单位计算各内存代中的active对象压缩后的新存储位置:

[cpp]   view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 通过对象的标记,计算存活的对象在其内存区压缩后的偏移位置 
  3.  */  
  4. void GenMarkSweep::mark_sweep_phase2() {  
  5.   // Now all live objects are marked, compute the new object addresses.  
  6.   
  7.   // It is imperative that we traverse perm_gen LAST. If dead space is  
  8.   // allowed a range of dead object may get overwritten by a dead int  
  9.   // array. If perm_gen is not traversed last a klassOop may get  
  10.   // overwritten. This is fine since it is dead, but if the class has dead  
  11.   // instances we have to skip them, and in order to find their size we  
  12.   // need the klassOop!  
  13.   //  
  14.   // It is not required that we traverse spaces in the same order in  
  15.   // phase2, phase3 and phase4, but the ValidateMarkSweep live oops  
  16.   // tracking expects us to do so. See comment under phase4.  
  17.   
  18.   GenCollectedHeap* gch = GenCollectedHeap::heap();  
  19.   Generation* pg = gch->perm_gen();  
  20.   
  21.   TraceTime tm("phase 2", PrintGC && Verbose, true, gclog_or_tty);  
  22.   trace("2");  
  23.   
  24.   VALIDATE_MARK_SWEEP_ONLY(reset_live_oop_tracking(false));  
  25.   
  26.   //计算年青代+老生代中active对象在其内存代压缩后的偏移位置  
  27.   gch->prepare_for_compaction();  
  28.   
  29.   VALIDATE_MARK_SWEEP_ONLY(_live_oops_index_at_perm = _live_oops_index);  
  30.   
  31.   //计算永久代中active对象在其内存代压缩后的偏移位置  
  32.   CompactPoint perm_cp(pg, NULL, NULL);  
  33.   pg->prepare_for_compaction(&perm_cp);  
  34.   
  35. }  
   在内存代内部,又是以内存区为单位来计算的:
[cpp]   view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 计算内存代放入各个内存区中活着的对象在其压缩后的偏移位置 
  3.  */  
  4. void Generation::prepare_for_compaction(CompactPoint* cp) {  
  5.   // Generic implementation, can be specialized  
  6.   CompactibleSpace* space = first_compaction_space();  
  7.   while (space != NULL) {  
  8.     space->prepare_for_compaction(cp);  
  9.     space = space->next_compaction_space();  
  10.   }  
  11. }  
    内存区的计算方法是(对象新的存储地址存放在对象实例的_makr属性中):
[cpp]   view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 计算内存区中所有活着(被标记)的对象在其被压缩后的偏移位置 
  3.  */  
  4. void CompactibleSpace::prepare_for_compaction(CompactPoint* cp) {  
  5.   SCAN_AND_FORWARD(cp, end, block_is_obj, block_size);  
  6. }  
  7.   
  8. #define SCAN_AND_FORWARD(cp,scan_limit,block_is_obj,block_size) {            \  
  9.   /* Compute the new addresses for the live objects and store it in the mark \ 
  10.    * Used by universe::mark_sweep_phase2()                                   \ 
  11.    */                                                                        \  
  12.   HeapWord* compact_top; /* This is where we are currently compacting to. */ \  
  13.                                                                              \  
  14.   /* We're sure to be here before any objects are compacted into this        \ 
  15.    * space, so this is a good time to initialize this:                       \ 
  16.    */                                                                        \  
  17.   set_compaction_top(bottom());                                              \  
  18.                                                                              \  
  19.   if (cp->space == NULL) {                                                   \  
  20.     assert(cp->gen != NULL, "need a generation");                            \  
  21.     assert(cp->threshold == NULL, "just checking");                          \  
  22.     assert(cp->gen->first_compaction_space() == this"just checking");      \  
  23.                                                                              \  
  24.     cp->space = cp->gen->first_compaction_space();                           \  
  25.     compact_top = cp->space->bottom();                                       \  
  26.     cp->space->set_compaction_top(compact_top);                              \  
  27.     cp->threshold = cp->space->initialize_threshold();                       \  
  28.   } else {                                                                   \  
  29.     compact_top = cp->space->compaction_top();                               \  
  30.   }                                                                          \  
  31.                                                                              \  
  32.   /* We allow some amount of garbage towards the bottom of the space, so     \ 
  33.    * we don't start compacting before there is a significant gain to be made.\ 
  34.    * Occasionally, we want to ensure a full compaction, which is determined  \ 
  35.    * by the MarkSweepAlwaysCompactCount parameter.                           \ 
  36.    */                                                                        \  
  37.   int invocations = SharedHeap::heap()->perm_gen()->stat_record()->invocations;\  
  38.   bool skip_dead = (MarkSweepAlwaysCompactCount < 1)                         \  
  39.     ||((invocations % MarkSweepAlwaysCompactCount) != 0);                    \  
  40.                                                                              \  
  41.   size_t allowed_deadspace = 0;                                              \  
  42.   if (skip_dead) {                                                           \  
  43.     const size_t ratio = allowed_dead_ratio();                               \  
  44.     allowed_deadspace = (capacity() * ratio / 100) / HeapWordSize;           \  
  45.   }                                                                          \  
  46.                                                                              \  
  47.   /**                                                                        \ 
  48.    * 当前内存区压缩的开始位置和结束位置                                                                                                                                                   \ 
  49.    */                                                                        \  
  50.   HeapWord* q = bottom();                                                    \  
  51.   HeapWord* t = scan_limit();                                                \  
  52.                                                                              \  
  53.   HeapWord*  end_of_live= q;    /* One byte beyond the last byte of the last \ 
  54.                                    live object. */                           \  
  55.   HeapWord*  first_dead = end();/* The first dead object. */                 \  
  56.   LiveRange* liveRange  = NULL; /* The current live range, recorded in the   \ 
  57.                                    first header of preceding free area. */   \  
  58.   _first_dead = first_dead;   /*当前内存区中最后一个active对象*/                 \  
  59.                                                                              \  
  60.   const intx interval = PrefetchScanIntervalInBytes;                         \  
  61.                                                                              \  
  62.    /**                                                                       \ 
  63.     * 开始遍历该内存区分配的所有对象                                                                                                                                                        \ 
  64.     */                                                                       \  
  65.   while (q < t) {                                                            \  
  66.     assert(!block_is_obj(q) ||                                               \  
  67.            oop(q)->mark()->is_marked() || oop(q)->mark()->is_unlocked() ||   \  
  68.            oop(q)->mark()->has_bias_pattern(),                               \  
  69.            "these are the only valid states during a mark sweep");           \  
  70.     /**                                                                      \ 
  71.      * active对象,则确定其新的存储位置                                           \ 
  72.      */                                                                      \  
  73.     if (block_is_obj(q) && oop(q)->is_gc_marked()) {                         \  
  74.       /* prefetch beyond q */                                                \  
  75.       Prefetch::write(q, interval);                                          \  
  76.       /* size_t size = oop(q)->size();  changing this for cms for perm gen */\  
  77.       /*对象大小*/                                                            \  
  78.       size_t size = block_size(q);                                           \  
  79.       compact_top = cp->space->forward(oop(q), size, cp, compact_top);       \  
  80.       q += size;                                                             \  
  81.       end_of_live = q;                                                       \  
  82.     } else {                                                                 \  
  83.       /* 垃圾对象,则一直遍历到其下一个active对象 */                                \  
  84.       HeapWord* end = q;                                                     \  
  85.       do {                                                                   \  
  86.         /* prefetch beyond end */                                            \  
  87.         Prefetch::write(end, interval);                                      \  
  88.         end += block_size(end);                                              \  
  89.       } while (end < t && (!block_is_obj(end) || !oop(end)->is_gc_marked()));\  
  90.                                                                              \  
  91.       /* see if we might want to pretend this object is alive so that        \ 
  92.        * we don't have to compact quite as often.                            \ 
  93.        */                                                                    \  
  94.       if (allowed_deadspace > 0 && q == compact_top) {                       \  
  95.         size_t sz = pointer_delta(end, q);                                   \  
  96.         if (insert_deadspace(allowed_deadspace, q, sz)) {                    \  
  97.           compact_top = cp->space->forward(oop(q), sz, cp, compact_top);     \  
  98.           q = end;                                                           \  
  99.           end_of_live = end;                                                 \  
  100.           continue;                                                          \  
  101.         }                                                                    \  
  102.       }                                                                      \  
  103.                                                                              \  
  104.       /* otherwise, it really is a free region. */                           \  
  105.                                                                              \  
  106.       /* for the previous LiveRange, record the end of the live objects. */  \  
  107.       if (liveRange) {                                                       \  
  108.         liveRange->set_end(q);                                               \  
  109.       }                                                                      \  
  110.                                                                              \  
  111.       /* record the current LiveRange object.                                \ 
  112.        * liveRange->start() is overlaid on the mark word.                    \ 
  113.        */                                                                    \  
  114.       liveRange = (LiveRange*)q;                                             \  
  115.       liveRange->set_start(end);                                             \  
  116.       liveRange->set_end(end);                                               \  
  117.                                                                              \  
  118.       /* see if this is the first dead region. */                            \  
  119.       if (q < first_dead) {                                                  \  
  120.         first_dead = q;                                                      \  
  121.       }                                                                      \  
  122.                                                                              \  
  123.       /* move on to the next object */                                       \  
  124.       q = end;                                                               \  
  125.     }                                                                        \  
  126.   }                                                                          \  
  127.                                                                              \  
  128.   assert(q == t, "just checking");                                           \  
  129.   if (liveRange != NULL) {                                                   \  
  130.     liveRange->set_end(q);                                                   \  
  131.   }                                                                          \  
  132.   _end_of_live = end_of_live;                                                \  
  133.   if (end_of_live < first_dead) {                                            \  
  134.     first_dead = end_of_live;                                                \  
  135.   }                                                                          \  
  136.   _first_dead = first_dead;                                                  \  
  137.                                                                              \  
  138.   /* save the compaction_top of the compaction space. */                     \  
  139.   cp->space->set_compaction_top(compact_top);                                \  
  140. }  

3.更新所有active对象的地址映射表

   该过程的实现和标记所有的active对象很相似,就是一个是标记,一个是更新地址指针:

[cpp]   view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 从根对象开始递归迭代更新所有活动对象的地址映射表(调整所有的对象指针) 
  3.  */  
  4. void GenMarkSweep::mark_sweep_phase3(int level) {  
  5.   GenCollectedHeap* gch = GenCollectedHeap::heap();  
  6.   Generation* pg = gch->perm_gen();  
  7.   
  8.   // Adjust the pointers to reflect the new locations  
  9.   TraceTime tm("phase 3", PrintGC && Verbose, true, gclog_or_tty);  
  10.   trace("3");  
  11.   
  12.   VALIDATE_MARK_SWEEP_ONLY(reset_live_oop_tracking(false));  
  13.   
  14.   // Needs to be done before the system dictionary is adjusted.  
  15.   pg->pre_adjust_pointers();  
  16.   
  17.   // Because the two closures below are created statically, cannot  
  18.   // use OopsInGenClosure constructor which takes a generation,  
  19.   // as the Universe has not been created when the static constructors  
  20.   // are run.  
  21.   adjust_root_pointer_closure.set_orig_generation(gch->get_gen(level));  
  22.   adjust_pointer_closure.set_orig_generation(gch->get_gen(level));  
  23.   
  24.   gch->gen_process_strong_roots(level,  
  25.                                 false// Younger gens are not roots.  
  26.                                 true,  // activate StrongRootsScope  
  27.                                 true,  // Collecting permanent generation.  
  28.                                 SharedHeap::SO_AllClasses,  
  29.                                 &adjust_root_pointer_closure,  
  30.                                 false// do not walk code  
  31.                                 &adjust_root_pointer_closure);  
  32.   
  33.   // Now adjust pointers in remaining weak roots.  (All of which should  
  34.   // have been cleared if they pointed to non-surviving objects.)  
  35.   CodeBlobToOopClosure adjust_code_pointer_closure(&adjust_pointer_closure,  
  36.                                                    /*do_marking=*/ false);  
  37.   gch->gen_process_weak_roots(&adjust_root_pointer_closure,  
  38.                               &adjust_code_pointer_closure,  
  39.                               &adjust_pointer_closure);  
  40.   
  41.   adjust_marks();  
  42.   GenAdjustPointersClosure blk;  
  43.   gch->generation_iterate(&blk, true);  
  44.   pg->adjust_pointers();  
  45. }  
   这里的对象地址映射表实际上就是前面的博文 内存堆Gc时公认的根对象  中提到的实例对象句柄.
[cpp]   view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 调整对象的物理地址指针 
  3.  */  
  4. template <class T> inline void MarkSweep::adjust_pointer(T* p, bool isroot) {  
  5.   T heap_oop = oopDesc::load_heap_oop(p);  
  6.   
  7.   if (!oopDesc::is_null(heap_oop)) {  
  8.     oop obj     = oopDesc::decode_heap_oop_not_null(heap_oop);  
  9.     oop new_obj = oop(obj->mark()->decode_pointer()); //对象新的地址指针  
  10.     assert(new_obj != NULL ||                         // is forwarding ptr?  
  11.            obj->mark() == markOopDesc::prototype() || // not gc marked?  
  12.            (UseBiasedLocking && obj->mark()->has_bias_pattern()) ||  
  13.                                                       // not gc marked?  
  14.            obj->is_shared(),                          // never forwarded?  
  15.            "should be forwarded");  
  16.   
  17.     if (new_obj != NULL) {  
  18.       assert(Universe::heap()->is_in_reserved(new_obj),  
  19.              "should be in object space");  
  20.   
  21.       //更新对象的物理地址指针  
  22.       oopDesc::encode_store_heap_oop_not_null(p, new_obj);  
  23.     }  
  24.   }  
  25.   
  26.   VALIDATE_MARK_SWEEP_ONLY(track_adjusted_pointer(p, isroot));  
  27. }  

4.移动复制所有的active对象到新的存储位置

    该过程跟计算所有active对象在其内存代压缩后的偏移位置的操作流程很相似,这里不在详细赘述.

三.Gc后的内存代大小调整

       内存堆管理器在对某些内存代进行Gc之后,基本都会调整他们的内存容量,即对内存代进行扩容还是缩容.这个操作主要受控于两个参数:最小空闲率(MinHeapFreeRatio)和最大空闲率MaxHeapFreeRatio.TenuredGeneration根据这两个参数来调整旧生代的容量过程如下:

[cpp]   view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 调整当前内存代的容量(一般发生在一次Gc之后) 
  3.  */  
  4. void TenuredGeneration::compute_new_size() {  
  5.   assert(_shrink_factor <= 100, "invalid shrink factor");  
  6.   size_t current_shrink_factor = _shrink_factor;  
  7.   _shrink_factor = 0;  
  8.   
  9.   printf("%s[%d] [tid: %lu]: 当前内存代[%s]开始调整其容量大小.\n", __FILE__, __LINE__, pthread_self(), this->name());  
  10.   
  11.   // We don't have floating point command-line arguments  
  12.   // Note:  argument processing ensures that MinHeapFreeRatio < 100.  
  13.   const double minimum_free_percentage = MinHeapFreeRatio / 100.0;  //内存代的最小空闲率  
  14.   const double maximum_used_percentage = 1.0 - minimum_free_percentage;  
  15.   
  16.   //一次Gc之后,当前内存代的使用量和容量  
  17.   const size_t used_after_gc = used();  
  18.   const size_t capacity_after_gc = capacity();  
  19.   
  20.   //计算当前内存代期望的最小容量  
  21.   const double min_tmp = used_after_gc / maximum_used_percentage;  
  22.   size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));  
  23.   // Don't shrink less than the initial generation size  
  24.   minimum_desired_capacity = MAX2(minimum_desired_capacity, spec()->init_size());  
  25.   
  26.   assert(used_after_gc <= minimum_desired_capacity, "sanity check");  
  27.   
  28.   if (PrintGC && Verbose) {  
  29.     const size_t free_after_gc = free();  
  30.     const double free_percentage = ((double)free_after_gc) / capacity_after_gc;  
  31.     gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: ");  
  32.     gclog_or_tty->print_cr("  "  
  33.                   "  minimum_free_percentage: %6.2f"  
  34.                   "  maximum_used_percentage: %6.2f",  
  35.                   minimum_free_percentage,  
  36.                   maximum_used_percentage);  
  37.     gclog_or_tty->print_cr("  "  
  38.                   "   free_after_gc   : %6.1fK"  
  39.                   "   used_after_gc   : %6.1fK"  
  40.                   "   capacity_after_gc   : %6.1fK",  
  41.                   free_after_gc / (double) K,  
  42.                   used_after_gc / (double) K,  
  43.                   capacity_after_gc / (double) K);  
  44.     gclog_or_tty->print_cr("  "  
  45.                   "   free_percentage: %6.2f",  
  46.                   free_percentage);  
  47.   }  
  48.   
  49.   //当前内存代的实际容量小于期望的容量,则扩展当前内存代的容量  
  50.   if (capacity_after_gc < minimum_desired_capacity) {  
  51.     // If we have less free space than we want then expand  
  52.     size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;  
  53.   
  54.     // Don't expand unless it's significant  
  55.     if (expand_bytes >= _min_heap_delta_bytes) {  
  56.       printf("%s[%d] [tid: %lu]: Gc之后,试图为内存代[%s]的容量扩大 %lu bytes.\n", __FILE__, __LINE__, pthread_self(), this->name(), expand_bytes);  
  57.       expand(expand_bytes, 0); // safe if expansion fails  
  58.     }  
  59.   
  60.     if (PrintGC && Verbose) {  
  61.       gclog_or_tty->print_cr("    expanding:"  
  62.                     "  minimum_desired_capacity: %6.1fK"  
  63.                     "  expand_bytes: %6.1fK"  
  64.                     "  _min_heap_delta_bytes: %6.1fK",  
  65.                     minimum_desired_capacity / (double) K,  
  66.                     expand_bytes / (double) K,  
  67.                     _min_heap_delta_bytes / (double) K);  
  68.     }  
  69.   
  70.     return;  
  71.   }  
  72.   
  73.   // No expansion, now see if we want to shrink  
  74.   size_t shrink_bytes = 0;  
  75.   // We would never want to shrink more than this  
  76.   size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity;  
  77.   
  78.   if (MaxHeapFreeRatio < 100) {  
  79.     //计算当前内存代期望的大容量  
  80.     const double maximum_free_percentage = MaxHeapFreeRatio / 100.0;  
  81.     const double minimum_used_percentage = 1.0 - maximum_free_percentage;  
  82.     const double max_tmp = used_after_gc / minimum_used_percentage;  
  83.     size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));  
  84.     maximum_desired_capacity = MAX2(maximum_desired_capacity, spec()->init_size());  
  85.   
  86.     if (PrintGC && Verbose) {  
  87.       gclog_or_tty->print_cr("  "  
  88.                              "  maximum_free_percentage: %6.2f"  
  89.                              "  minimum_used_percentage: %6.2f",  
  90.                              maximum_free_percentage,  
  91.                              minimum_used_percentage);  
  92.       gclog_or_tty->print_cr("  "  
  93.                              "  _capacity_at_prologue: %6.1fK"  
  94.                              "  minimum_desired_capacity: %6.1fK"  
  95.                              "  maximum_desired_capacity: %6.1fK",  
  96.                              _capacity_at_prologue / (double) K,  
  97.                              minimum_desired_capacity / (double) K,  
  98.                              maximum_desired_capacity / (double) K);  
  99.     }  
  100.     assert(minimum_desired_capacity <= maximum_desired_capacity,  
  101.            "sanity check");  
  102.   
  103.     //当前内存代Gc之后的容量大于期望的最大容量  
  104.     if (capacity_after_gc > maximum_desired_capacity) {  
  105.       // Capacity too large, compute shrinking size  
  106.       shrink_bytes = capacity_after_gc - maximum_desired_capacity;  
  107.       // We don't want shrink all the way back to initSize if people call  
  108.       // System.gc(), because some programs do that between "phases" and then  
  109.       // we'd just have to grow the heap up again for the next phase.  So we  
  110.       // damp the shrinking: 0% on the first call, 10% on the second call, 40%  
  111.       // on the third call, and 100% by the fourth call.  But if we recompute  
  112.       // size without shrinking, it goes back to 0%.  
  113.       shrink_bytes = shrink_bytes / 100 * current_shrink_factor;  
  114.       assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");  
  115.   
  116.       if (current_shrink_factor == 0) {  
  117.         _shrink_factor = 10;  
  118.       } else {  
  119.         _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);  
  120.       }  
  121.   
  122.       if (PrintGC && Verbose) {  
  123.         gclog_or_tty->print_cr("  "  
  124.                       "  shrinking:"  
  125.                       "  initSize: %.1fK"  
  126.                       "  maximum_desired_capacity: %.1fK",  
  127.                       spec()->init_size() / (double) K,  
  128.                       maximum_desired_capacity / (double) K);  
  129.         gclog_or_tty->print_cr("  "  
  130.                       "  shrink_bytes: %.1fK"  
  131.                       "  current_shrink_factor: %d"  
  132.                       "  new shrink factor: %d"  
  133.                       "  _min_heap_delta_bytes: %.1fK",  
  134.                       shrink_bytes / (double) K,  
  135.                       current_shrink_factor,  
  136.                       _shrink_factor,  
  137.                       _min_heap_delta_bytes / (double) K);  
  138.       }  
  139.     }  
  140.   }  
  141.   
  142.   if (capacity_after_gc > _capacity_at_prologue) {  
  143.     //当前内存代Gc之后的容量大于Gc之前的容量,那么就是在内存代Gc时为了存储升级来的active对象而扩展了内存容量,  
  144.     //现在至少应该缩小到Gc之前的容量大小  
  145.     size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue;  
  146.     expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes);  
  147.     // We have two shrinking computations, take the largest  
  148.     shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion);  
  149.   
  150.     assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");  
  151.     if (PrintGC && Verbose) {  
  152.       gclog_or_tty->print_cr("  "  
  153.                              "  aggressive shrinking:"  
  154.                              "  _capacity_at_prologue: %.1fK"  
  155.                              "  capacity_after_gc: %.1fK"  
  156.                              "  expansion_for_promotion: %.1fK"  
  157.                              "  shrink_bytes: %.1fK",  
  158.                              capacity_after_gc / (double) K,  
  159.                              _capacity_at_prologue / (double) K,  
  160.                              expansion_for_promotion / (double) K,  
  161.                              shrink_bytes / (double) K);  
  162.     }  
  163.   }  
  164.   
  165.   // Don't shrink unless it's significant  
  166.   if (shrink_bytes >= _min_heap_delta_bytes) {  
  167.     printf("%s[%d] [tid: %lu]: Gc之后,试图为内存代[%s]的容量缩小 %lu bytes.\n", __FILE__, __LINE__, pthread_self(), this->name(), shrink_bytes);  
  168.     shrink(shrink_bytes);  
  169.   }  
  170.   
  171.   assert(used() == used_after_gc && used_after_gc <= capacity(),  
  172.          "sanity check");  
  173. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值