美文网首页
ReferenceProcessor 之 二

ReferenceProcessor 之 二

作者: 程序员札记 | 来源:发表于2022-11-19 09:42 被阅读0次

    本篇博客继续上一篇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);
          }
        }
      }
    

    其调用链如下:

    image.png

    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);
      }
    }
    

    其调用链如下:

    image.png

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

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

    image.png

    其实现如下:

    //从各类型的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;
    }
    

    该方法的调用链如下:

    image.png

    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);
    }
    

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

    image.png

    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属性被垃圾回收处理掉了。

    相关文章

      网友评论

          本文标题:ReferenceProcessor 之 二

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