Hotspot 垃圾回收之ReferenceProcessor(二) 源码解析

  目录

1、process_discovered_reflist 

2、process_phaseJNI

3、process_discovered_references

4、preclean_discovered_references

5、clean_up_discovered_references

6、abandon_partial_discovery

7、总结


    本篇博客继续上一篇《Hotspot 垃圾回收之ReferenceProcessor(一) 源码解析》讲解ReferenceProcessor的其他关键方法的实现。

1、process_discovered_reflist 

     process_discovered_reflist用于对指定的DiscoveredList做过滤,移除referent是存活的Reference实例,然后根据参数clear_referent,要么将referent属性置为null,要么将referent对象标记为存活的,如果是discoveredSoftRefs则首先移除那些referent对象是死的但是ReferencePolicy判断不能清除的Reference实例。其实现如下:

size_t
ReferenceProcessor::process_discovered_reflist(
  DiscoveredList               refs_lists[],
  ReferencePolicy*             policy,
  bool                         clear_referent,
  BoolObjectClosure*           is_alive,
  OopClosure*                  keep_alive,
  VoidClosure*                 complete_gc,
  AbstractRefProcTaskExecutor* task_executor)
{
  bool mt_processing = task_executor != NULL && _processing_is_mt;
  //如果查找过程是并行的,则必须平衡refs_lists中的各个DiscoveredList
  bool must_balance = _discovery_is_mt;
  //ParallelRefProcBalancingEnabled默认为true,表示允许平衡各个处理队列
  if ((mt_processing && ParallelRefProcBalancingEnabled) ||
      must_balance) {
    balance_queues(refs_lists);
  }
  //统计总的Reference的个数
  size_t total_list_count = total_count(refs_lists);

  if (PrintReferenceGC && PrintGCDetails) {
    gclog_or_tty->print(", %u refs", total_list_count);
  }

  // Phase 1 只适用于SoftReferences对应的DiscoveredList
  if (policy != NULL) {
    if (mt_processing) {
      RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/);
      task_executor->execute(phase1);
    } else {
      //如果policy不为空,则认为refs_lists就是_discoveredSoftRefs
      for (uint i = 0; i < _max_num_q; i++) {
        process_phase1(refs_lists[i], policy,
                       is_alive, keep_alive, complete_gc);
      }
    }
  } else { // policy为NULL,则refs_lists不等于_discoveredSoftRefs
    assert(refs_lists != _discoveredSoftRefs,
           "Policy must be specified for soft references.");
  }

  // Phase 2:
  //遍历refs_lists,移除所有referent是存活的Reference实例
  if (mt_processing) {
    RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/);
    task_executor->execute(phase2);
  } else {
    for (uint i = 0; i < _max_num_q; i++) {
      process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);
    }
  }

  // Phase 3:
  //遍历refs_lists,根据参数clear_referent做适当处理
  if (mt_processing) {
    RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/);
    task_executor->execute(phase3);
  } else {
    for (uint i = 0; i < _max_num_q; i++) {
      process_phase3(refs_lists[i], clear_referent,
                     is_alive, keep_alive, complete_gc);
    }
  }
  //返回移除前的Reference实例的总的个数
  return total_list_count;
}

//统计总的Reference实例的个数
size_t ReferenceProcessor::total_count(DiscoveredList lists[]) {
  size_t total = 0;
  for (uint i = 0; i < _max_num_q; ++i) {
    total += lists[i].length();
  }
  return total;
}


//只适用于SoftReferences对应的DiscoveredList,会遍历所有的SoftReference,找到所有的referent对象是死的但是通过ReferencePolicy
//判断不需要清理的SoftReference实例,将其标记为Active状态,将referent对象标记为存活的
void
ReferenceProcessor::process_phase1(DiscoveredList&    refs_list,
                                   ReferencePolicy*   policy,
                                   BoolObjectClosure* is_alive,
                                   OopClosure*        keep_alive,
                                   VoidClosure*       complete_gc) {
  assert(policy != NULL, "Must have a non-NULL policy");
  //创建一个迭代器
  DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
  //执行遍历
  while (iter.has_next()) {
    //获取当前Reference的discovered及referent属性的内存地址和值
    iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */));
    //判断referent对象是否存活
    bool referent_is_dead = (iter.referent() != NULL) && !iter.is_referent_alive();
    //如果referent对象是死的,即没有其他的强引用了,且暂不清理该Reference实例
    if (referent_is_dead &&
        !policy->should_clear_reference(iter.obj(), _soft_ref_timestamp_clock)) {
      if (TraceReferenceGC) {
        gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s"  ") by policy",
                               (void *)iter.obj(), iter.obj()->klass()->internal_name());
      }
      //将该Reference实例从DiscoveredList中移除
      iter.remove();
      //将该Reference实例标记为Active状态,即将next属性置为null
      iter.make_active();
      //让该referent对象是存活的
      iter.make_referent_alive();
      //切换到下一个Reference实例
      iter.move_to_next();
    } else {
      //不做处理,然后该Reference实例就会被ReferenceHandle Thread处理掉
      iter.next();
    }
  }
  // Close the reachable set
  complete_gc->do_void();
}

void DiscoveredListIterator::make_active() {
  if (UseG1GC) {
    //G1下需要调用额外的bs方法
    HeapWord* next_addr = java_lang_ref_Reference::next_addr(_ref);
    if (UseCompressedOops) {
      oopDesc::bs()->write_ref_field_pre((narrowOop*)next_addr, NULL);
    } else {
      oopDesc::bs()->write_ref_field_pre((oop*)next_addr, NULL);
    }
  }
  //将next属性置为NULL
  java_lang_ref_Reference::set_next_raw(_ref, NULL);
}

  // Make the referent alive.
inline void make_referent_alive() {
    if (UseCompressedOops) {
      _keep_alive->do_oop((narrowOop*)_referent_addr);
    } else {
      _keep_alive->do_oop((oop*)_referent_addr);
    }
  }

//从DiscoveredList中移除referent是存活的Reference实例,并行处理时还需要移除referent是null或者next属性不为空的Reference实例
inline void process_phase2(DiscoveredList&    refs_list,
                             BoolObjectClosure* is_alive,
                             OopClosure*        keep_alive,
                             VoidClosure*       complete_gc) {
    if (discovery_is_atomic()) {
      //非并发场景下
      pp2_work(refs_list, is_alive, keep_alive);
    } else {
      //并发场景下
      assert(complete_gc != NULL, "Error");
      pp2_work_concurrent_discovery(refs_list, is_alive,
                                    keep_alive, complete_gc);
    }
  }

void
ReferenceProcessor::pp2_work(DiscoveredList&    refs_list,
                             BoolObjectClosure* is_alive,
                             OopClosure*        keep_alive) {
  assert(discovery_is_atomic(), "Error");
  //执行遍历
  DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
  while (iter.has_next()) {
    iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */));
    DEBUG_ONLY(oop next = java_lang_ref_Reference::next(iter.obj());)
    assert(next == NULL, "Should not discover inactive Reference");
    if (iter.is_referent_alive()) {
      //如果referent对象是存活的
      if (TraceReferenceGC) {
        gclog_or_tty->print_cr("Dropping strongly reachable reference (" INTPTR_FORMAT ": %s)",
                               (void *)iter.obj(), iter.obj()->klass()->internal_name());
      }
      //将当前Reference实例从DiscoveredList中移除
      iter.remove();
      //将referent对象标记成存活的
      iter.make_referent_alive();
      //切换到下一个Reference实例
      iter.move_to_next();
    } else {
      iter.next();
    }
  }
  
}

void
ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList&    refs_list,
                                                  BoolObjectClosure* is_alive,
                                                  OopClosure*        keep_alive,
                                                  VoidClosure*       complete_gc) {
  assert(!discovery_is_atomic(), "Error");
  DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
  while (iter.has_next()) {
    iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
    HeapWord* next_addr = java_lang_ref_Reference::next_addr(iter.obj());
    oop next = java_lang_ref_Reference::next(iter.obj());
    //next属性如果不为空,则指向它自己
    if ((iter.referent() == NULL || iter.is_referent_alive() ||
         next != NULL)) {
      assert(next->is_oop_or_null(), "bad next field");
      // Remove Reference object from list
      iter.remove();
      // Trace the cohorts
      iter.make_referent_alive();
      //多了一步,让next属性即它自己保持alive
      if (UseCompressedOops) {
        keep_alive->do_oop((narrowOop*)next_addr);
      } else {
        keep_alive->do_oop((oop*)next_addr);
      }
      iter.move_to_next();
    } else {
      iter.next();
    }
  }
  // Now close the newly reachable set
  complete_gc->do_void();
 
}

//遍历DiscoveredList,根据参数clear_referent,要么将referent属性置为null,要么将referent对象标记为存活的
void
ReferenceProcessor::process_phase3(DiscoveredList&    refs_list,
                                   bool               clear_referent,
                                   BoolObjectClosure* is_alive,
                                   OopClosure*        keep_alive,
                                   VoidClosure*       complete_gc) {
  ResourceMark rm;
  DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
  while (iter.has_next()) {
    //将当前Reference实例标记为存活的
    iter.update_discovered();
    iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */));
    if (clear_referent) {
      //将referent属性置为null
      iter.clear_referent();
    } else {
      //将referent属性标记为存活的
      iter.make_referent_alive();
    }
    if (TraceReferenceGC) {
      gclog_or_tty->print_cr("Adding %sreference (" INTPTR_FORMAT ": %s) as pending",
                             clear_referent ? "cleared " : "",
                             (void *)iter.obj(), iter.obj()->klass()->internal_name());
    }
    assert(iter.obj()->is_oop(UseConcMarkSweepGC), "Adding a bad reference");
    iter.next();
  }
  // Remember to update the next pointer of the last ref.
  iter.update_discovered();
  // Close the reachable set
  complete_gc->do_void();
}

void DiscoveredListIterator::clear_referent() {
  oop_store_raw(_referent_addr, NULL);
}

inline void update_discovered() {
    //_prev_next实际指向当前Reference实例
    if (UseCompressedOops) {
      if (!oopDesc::is_null(*(narrowOop*)_prev_next)) {
        _keep_alive->do_oop((narrowOop*)_prev_next);
      }
    } else {
      if (!oopDesc::is_null(*(oop*)_prev_next)) {
        _keep_alive->do_oop((oop*)_prev_next);
      }
    }
  }

其调用链如下:

2、process_phaseJNI

    process_phaseJNI用于处理JNIHandleBlock中保存的JNI弱引用oop,如果这个oop是存活的则将其标记为存活的,如果说是死的,则将其置为null,其实现如下:

void ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive,
                                          OopClosure*        keep_alive,
                                          VoidClosure*       complete_gc) {
  JNIHandles::weak_oops_do(is_alive, keep_alive);
  complete_gc->do_void();
}

void JNIHandles::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
  _weak_global_handles->weak_oops_do(is_alive, f);
}

void JNIHandleBlock::weak_oops_do(BoolObjectClosure* is_alive,
                                  OopClosure* f) {
  //遍历所有保存弱引用的JNIBlock                                
  for (JNIHandleBlock* current = this; current != NULL; current = current->_next) {
    assert(current->pop_frame_link() == NULL,
      "blocks holding weak global JNI handles should not have pop frame link set");
    //遍历JNIBlock中保存的所有弱引用oop
    for (int index = 0; index < current->_top; index++) {
      oop* root = &(current->_handles)[index];
      oop value = *root;
      // traverse heap pointers only, not deleted handles or free list pointers
      if (value != NULL && Universe::heap()->is_in_reserved(value)) {
        if (is_alive->do_object_b(value)) {
          //如果这个oop是存活的,则将其打标为存活的
          f->do_oop(root);
        } else {
          if (TraceReferenceGC) {
            tty->print_cr("Clearing JNI weak reference (" INTPTR_FORMAT ")", root);
          }
          //如果oop不是存活的,则将其置为null
          *root = NULL;
        }
      }
    }
    //只有当前JNIBlock是满的才会遍历下一个JNIBlock
    if (current->_top < block_size_in_oops) {
      break;
    }
  }

  //发布JVMTI事件
  JvmtiExport::weak_oops_do(is_alive, f);
}

其调用链如下:

3、process_discovered_references

     process_discovered_references是实际对外的用于处理查找出来的位于不同类型的DiscoveredList中的Reference实例,底层实际调用process_discovered_reflist和process_phaseJNI方法,其实现如下:

ReferenceProcessorStats ReferenceProcessor::process_discovered_references(
  BoolObjectClosure*           is_alive,
  OopClosure*                  keep_alive,
  VoidClosure*                 complete_gc,
  AbstractRefProcTaskExecutor* task_executor,
  GCTimer*                     gc_timer,
  GCId                         gc_id) {
  NOT_PRODUCT(verify_ok_to_handle_reflists());

  assert(!enqueuing_is_done(), "If here enqueuing should not be complete");
  //停止Reference实例查找
  disable_discovery();

  //使用SoftReference的clock属性更新_soft_ref_timestamp_clock,因为之前并发查找的时候可能通过反射或者Unsafe改变了clock属性
  _soft_ref_timestamp_clock = java_lang_ref_SoftReference::clock();

  bool trace_time = PrintGCDetails && PrintReferenceGC;

  // Soft references
  size_t soft_count = 0;
  {
    GCTraceTime tt("SoftReference", trace_time, false, gc_timer, gc_id);
    soft_count =
      //处理_discoveredSoftRefs,注意传入的clear_referent的值为true,除_discoveredSoftRefs传入的ReferencePolicy有具体值外,其他类型的都是传NULL
      process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
                                 is_alive, keep_alive, complete_gc, task_executor);
  }

  update_soft_ref_master_clock();

  // Weak references
  size_t weak_count = 0;
  {
    GCTraceTime tt("WeakReference", trace_time, false, gc_timer, gc_id);
    weak_count =
       //处理_discoveredSoftRefs,注意传入的clear_referent的值为true
      process_discovered_reflist(_discoveredWeakRefs, NULL, true,
                                 is_alive, keep_alive, complete_gc, task_executor);
  }

  // Final references
  size_t final_count = 0;
  {
    GCTraceTime tt("FinalReference", trace_time, false, gc_timer, gc_id);
    //处理_discoveredFinalRefs,注意传入的clear_referent的值为false,因为后续需要调用referent对象的finalize方法
    final_count =
      process_discovered_reflist(_discoveredFinalRefs, NULL, false,
                                 is_alive, keep_alive, complete_gc, task_executor);
  }

  // Phantom references
  size_t phantom_count = 0;
  {
    GCTraceTime tt("PhantomReference", trace_time, false, gc_timer, gc_id);
    ///处理_discoveredPhantomRefs,注意传入的clear_referent的值为false,子类可能需要使用referent对象
    phantom_count =
      process_discovered_reflist(_discoveredPhantomRefs, NULL, false,
                                 is_alive, keep_alive, complete_gc, task_executor);

    //处理_discoveredCleanerRefs,将返回的数据和phantom_count算在一起
    phantom_count +=
      process_discovered_reflist(_discoveredCleanerRefs, NULL, true,
                                 is_alive, keep_alive, complete_gc, task_executor);
  }
  
  {
    GCTraceTime tt("JNI Weak Reference", trace_time, false, gc_timer, gc_id);
    if (task_executor != NULL) {
      task_executor->set_single_threaded_mode();
    }
    //处理JNI的弱引用
    process_phaseJNI(is_alive, keep_alive, complete_gc);
  }
  //ReferenceProcessorStats就是一个简单的数据结构
  return ReferenceProcessorStats(soft_count, weak_count, final_count, phantom_count);
}

void disable_discovery()  { _discovering_refs = false; }

void ReferenceProcessor::update_soft_ref_master_clock() {
  
  jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
  jlong soft_ref_clock = java_lang_ref_SoftReference::clock();
  assert(soft_ref_clock == _soft_ref_timestamp_clock, "soft ref clocks out of sync");

  NOT_PRODUCT(
  if (now < _soft_ref_timestamp_clock) {
    warning("time warp: "INT64_FORMAT" to "INT64_FORMAT,
            _soft_ref_timestamp_clock, now);
  }
  )
  
  if (now > _soft_ref_timestamp_clock) {
     //重置_soft_ref_timestamp_clock并更新clock属性
    _soft_ref_timestamp_clock = now;
    java_lang_ref_SoftReference::set_clock(now);
  }
}

其调用链如下:

该方法是在enqueue_discovered_references之前调用的,参考CMSCollector::refProcessingWork的实现。

4、 preclean_discovered_references

     该方法用于从各类型的DiscoveredList中移除referent属性是存活的或者是null或者next属性不为null的Reference实例,移除逻辑等同于process_phase2方法的实现,只有CMSCollector调用,其调用链如下:

其实现如下:


//从各类型的DiscoveredList中移除referent属性是存活的或者是null或者next属性不为null的Reference实例,移除逻辑等同于process_phase2方法的实现
//各类型的DiscoveredList的处理顺序是随意的,可以并发执行
void ReferenceProcessor::preclean_discovered_references(
  BoolObjectClosure* is_alive,
  OopClosure* keep_alive,
  VoidClosure* complete_gc,
  YieldClosure* yield,
  GCTimer* gc_timer,
  GCId     gc_id) {

  NOT_PRODUCT(verify_ok_to_handle_reflists());

  // Soft references
  {
    GCTraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC,
              false, gc_timer, gc_id);
    for (uint i = 0; i < _max_num_q; i++) {
      if (yield->should_return()) {
        return;
      }
      preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
                                  keep_alive, complete_gc, yield);
    }
  }

  // Weak references
  {
    GCTraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC,
              false, gc_timer, gc_id);
    for (uint i = 0; i < _max_num_q; i++) {
      if (yield->should_return()) {
        return;
      }
      preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
                                  keep_alive, complete_gc, yield);
    }
  }

  // Final references
  {
    GCTraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC,
              false, gc_timer, gc_id);
    for (uint i = 0; i < _max_num_q; i++) {
      if (yield->should_return()) {
        return;
      }
      preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
                                  keep_alive, complete_gc, yield);
    }
  }

  // Phantom references
  {
    GCTraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC,
              false, gc_timer, gc_id);
    for (uint i = 0; i < _max_num_q; i++) {
      if (yield->should_return()) {
        return;
      }
      preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
                                  keep_alive, complete_gc, yield);
    }

    for (uint i = 0; i < _max_num_q; i++) {
      if (yield->should_return()) {
        return;
      }
      preclean_discovered_reflist(_discoveredCleanerRefs[i], is_alive,
                                  keep_alive, complete_gc, yield);
    }
  }
}

void
ReferenceProcessor::preclean_discovered_reflist(DiscoveredList&    refs_list,
                                                BoolObjectClosure* is_alive,
                                                OopClosure*        keep_alive,
                                                VoidClosure*       complete_gc,
                                                YieldClosure*      yield) {
  //执行遍历                                              
  DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
  while (iter.has_next()) {
    //获取当前Reference实例的discovered和referent属性
    iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
    oop obj = iter.obj();
    //获取当前Reference实例的next属性
    oop next = java_lang_ref_Reference::next(obj);
    //如果referent属性为null或者是存活的或者next属性不为空,即当前Reference实例不是Active状态
    if (iter.referent() == NULL || iter.is_referent_alive() ||
        next != NULL) {
      if (TraceReferenceGC) {
        gclog_or_tty->print_cr("Precleaning Reference (" INTPTR_FORMAT ": %s)",
                               (void *)iter.obj(), iter.obj()->klass()->internal_name());
      }
      //将当前Reference实例从DiscoveredList中移除
      iter.remove();
      //将referent属性标记为存活的
      iter.make_referent_alive();
      //将next属性标记为存活的
      if (UseCompressedOops) {
        narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj);
        keep_alive->do_oop(next_addr);
      } else {
        oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj);
        keep_alive->do_oop(next_addr);
      }
      //切换到下一个Reference实例
      iter.move_to_next();
    } else {
      iter.next();
    }
  }
  // Close the reachable set
  complete_gc->do_void();
}

5、clean_up_discovered_references

      该方法用于从各类型的DiscoveredList中移除referent属性为null或者next属性不为null的Reference实例,其实现与之前的preclean_discovered_references等遍历处理方法大同小异,如下:

void ReferenceProcessor::clean_up_discovered_references() {
  // loop over the lists
  for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
    if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) {
      gclog_or_tty->print_cr(
        "\nScrubbing %s discovered list of Null referents",
        list_name(i));
    }
    clean_up_discovered_reflist(_discovered_refs[i]);
  }
}

void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) {
  assert(!discovery_is_atomic(), "Else why call this method?");
  //执行遍历
  DiscoveredListIterator iter(refs_list, NULL, NULL);
  while (iter.has_next()) {
    //获取当前Reference实例的discovered和referent属性
    iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
    //获取当前Reference实例的next属性
    oop next = java_lang_ref_Reference::next(iter.obj());
    assert(next->is_oop_or_null(), "bad next field");
    //如果referent属性为null,即被清除了,或者next属性不为null,即当前Reference实例不是Active状态
    if (iter.referent() == NULL || next != NULL) {
      debug_only(
        if (PrintGCDetails && TraceReferenceGC) {
          gclog_or_tty->print_cr("clean_up_discovered_list: Dropping Reference: "
            INTPTR_FORMAT " with next field: " INTPTR_FORMAT
            " and referent: " INTPTR_FORMAT,
            (void *)iter.obj(), (void *)next, (void *)iter.referent());
        }
      )
      //将Reference从DiscoveredList中移除
      iter.remove();
      //切换到下一个Reference实例
      iter.move_to_next();
    } else {
      iter.next();
    }
  }
  
}

const char* ReferenceProcessor::list_name(uint i) {
   assert(i >= 0 && i <= _max_num_q * number_of_subclasses_of_ref(),
          "Out of bounds index");

   int j = i / _max_num_q;
   switch (j) {
     case 0: return "SoftRef";
     case 1: return "WeakRef";
     case 2: return "FinalRef";
     case 3: return "PhantomRef";
     case 4: return "CleanerRef";
   }
   ShouldNotReachHere();
   return NULL;
}

该方法的调用链如下:

6、abandon_partial_discovery

     该方法用于清空所有DiscoveredList中的Reference实例,将Reference实例的discovered属性置为null,将DiscoveredList恢复成初始状态,其实现如下:

void ReferenceProcessor::abandon_partial_discovery() {
  // loop over the lists
  for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
    if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) {
      gclog_or_tty->print_cr("\nAbandoning %s discovered list", list_name(i));
    }
    abandon_partial_discovered_list(_discovered_refs[i]);
  }
}

void
ReferenceProcessor::abandon_partial_discovered_list(DiscoveredList& refs_list) {
  clear_discovered_references(refs_list);
}

void
ReferenceProcessor::clear_discovered_references(DiscoveredList& refs_list) {
  oop obj = NULL;
  oop next = refs_list.head();
  //遍历DiscoveredList,将所有的Reference实例的discovered属性置为null
  while (next != obj) {
    obj = next;
    next = java_lang_ref_Reference::discovered(obj);
    java_lang_ref_Reference::set_discovered_raw(obj, NULL);
  }
  //将DiscoveredList恢复成初始状态
  refs_list.set_head(NULL);
  refs_list.set_length(0);
}

 该方法的调用链如下,注意该方法只能在安全点的时候调用:

7、总结

    在垃圾回收器遍历所有Java对象时,判断该对象是Reference实例就会调用discover_reference方法将该实例加入到对应类型的 DiscoveredList中,遍历结束会调用process_discovered_references对各类型的DiscoveredList中包含的Reference实例和JNIBlock中包含的弱引用oop做必要的处理,如移除referent属性是存活的Reference实例,最后调用enqueue_discovered_references方法将各类型的DiscoveredList包含的Reference实例加入到由Reference静态属性pending和实例属性discovered构成的一个链表中并更新静态pending属性指向最新的链表头,更新Reference实例的next属性指向它自己,即将Reference实例标记成Pending状态,处理完成后再将DiscoveredList恢复成初始状态。然后处于Pending状态的Reference实例就会被ReferenceHandler从链表中移除加入到Reference实例创建时传入的ReferenceQueue中,如果是Cleaner实例则调用该实例的clean方法,调用方可以通过遍历ReferenceQueue知道有哪些Reference实例的referent属性被垃圾回收处理掉了。

发布了117 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_31865983/article/details/104070299
今日推荐