Top


定義場所(file name)

hotspot/src/share/vm/memory/referenceProcessor.cpp

名前(function name)

void
ReferenceProcessor::process_discovered_reflist(
  DiscoveredList               refs_lists[],
  ReferencePolicy*             policy,
  bool                         clear_referent,
  BoolObjectClosure*           is_alive,
  OopClosure*                  keep_alive,
  VoidClosure*                 complete_gc,
  AbstractRefProcTaskExecutor* task_executor)
{

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      (マルチスレッドで処理するかどうかを示す)
      ---------------------------------------- -}

      bool mt_processing = task_executor != NULL && _processing_is_mt;

  {- -------------------------------------------
  (1) マルチスレッドで並列処理する場合, 
      参照オブジェクトの discovery 処理を行っていた時点と
      この ReferenceProcessor::process_discovered_reflist() 時点で
      処理スレッド数が異なる可能性がある.

      そこで, ReferenceProcessor::balance_queues() を呼んで
      DiscoveredList の本数を
      この ReferenceProcessor::process_discovered_reflist() 内で使用するスレッド数にあわせておく.
      (ついでに, DiscoveredList 間で要素数に偏りがあるかもしれないので, 要素数も平均化しておく)
      ---------------------------------------- -}

      // If discovery used MT and a dynamic number of GC threads, then
      // the queues must be balanced for correctness if fewer than the
      // maximum number of queues were used.  The number of queue used
      // during discovery may be different than the number to be used
      // for processing so don't depend of _num_q < _max_num_q as part
      // of the test.
      bool must_balance = _discovery_is_mt;

      if ((mt_processing && ParallelRefProcBalancingEnabled) ||
          must_balance) {
        balance_queues(refs_lists);
      }

  {- -------------------------------------------
  (1) (トレース出力)
      ---------------------------------------- -}

      if (PrintReferenceGC && PrintGCDetails) {
        size_t total = 0;
        for (int i = 0; i < _max_num_q; ++i) {
          total += refs_lists[i].length();
        }
        gclog_or_tty->print(", %u refs", total);
      }

  {- -------------------------------------------
  (1) 各リストに対して ReferenceProcessor::process_phase1() を呼び出し, 
      リスト中のそれぞれの soft reference オブジェクトについて, 消去すべきかどうかを判定する.
        (この判定には ReferencePolicy オブジェクトが用いられる.)
      消去しなくてもよい soft reference については, 特に処理をする必要は無いので, リストから除外される.
        (また, 除外した soft reference から再帰的に辿れる範囲のオブジェクトもあわせて除外する)

      なお, 上の説明の通り, この処理は処理対象が soft reference である場合のみ行われる.
        (つまり, weak/phantom/final reference の場合には ReferenceProcessor::process_phase1() の処理は行われない)
      処理対処が soft refernce かどうかは, 
      ReferencePolicy オブジェクト型の引数(以下の policy) が null かどうかで判断する.
      * null でなければ(= ReferencePolicy オブジェクトが渡されてきていれば), soft reference の処理だと判断する.
      * null であれば, soft reference 以外の処理だと判断する (= この phase 1 の処理はスキップされる)

      なお, 以下の条件の両方が満たされる場合には, この処理はマルチスレッドを用いて並列に処理する.
      * AbstractRefProcTaskExecutor 型の引数(以下の mt_processing)が null ではない 
        (= 有効な AbstractRefProcTaskExecutor オブジェクトが渡されている)
      * この ReferenceProcessor オブジェクトの _processing_is_mt フィールドが true
      (並列処理する場合には, AbstractRefProcTaskExecutor オブジェクトと RefProcPhase1Task オブジェクトが用いられる.
       See: AbstractRefProcTaskExecutor, RefProcPhase1Task::work())
      ---------------------------------------- -}

      // Phase 1 (soft refs only):
      // . Traverse the list and remove any SoftReferences whose
      //   referents are not alive, but that should be kept alive for
      //   policy reasons. Keep alive the transitive closure of all
      //   such referents.
      if (policy != NULL) {
        if (mt_processing) {
          RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/);
          task_executor->execute(phase1);
        } else {
          for (int i = 0; i < _max_num_q; i++) {
            process_phase1(refs_lists[i], policy,
                           is_alive, keep_alive, complete_gc);
          }
        }
      } else { // policy == NULL
        assert(refs_lists != _discoveredSoftRefs,
               "Policy must be specified for soft references.");
      }

  {- -------------------------------------------
  (1) 各リストに対して ReferenceProcessor::process_phase2() を呼び出し, 
      リスト中のそれぞれの参照オブジェクトについて, その差し先が生きているかどうかを判定する.
      差し先が生きている参照オブジェクトについては, 特に特殊な処理をする必要は無いので, リストから除外される.

      なお, 以下の条件の両方が満たされる場合には, この処理はマルチスレッドを用いて並列に処理する.
      * AbstractRefProcTaskExecutor 型の引数(以下の mt_processing)が null ではない 
        (= 有効な AbstractRefProcTaskExecutor オブジェクトが渡されている)
      * この ReferenceProcessor オブジェクトの _processing_is_mt フィールドが true
      (並列処理する場合には, AbstractRefProcTaskExecutor オブジェクトと RefProcPhase2Task オブジェクトが用いられる.
       See: AbstractRefProcTaskExecutor, RefProcPhase2Task::work())
      ---------------------------------------- -}

      // Phase 2:
      // . Traverse the list and remove any refs whose referents are alive.
      if (mt_processing) {
        RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/);
        task_executor->execute(phase2);
      } else {
        for (int i = 0; i < _max_num_q; i++) {
          process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);
        }
      }

  {- -------------------------------------------
  (1) 各リストに対して ReferenceProcessor::process_phase3() を呼び出し, 
      リストに残った参照オブジェクトおよびその差し先を live 状態にしておく
      (この先 ReferenceQueue に入れて処理される場合, この時点で死んでしまうとまずいので).

      (なお差し先については, dead にしてよいと指定されていた場合は
      live 状態にせず, 代わりに参照オブジェクトの差し先を示すフィールドを null にしておく)
      ---------------------------------------- -}

      // Phase 3:
      // . Traverse the list and process referents as appropriate.
      if (mt_processing) {
        RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/);
        task_executor->execute(phase3);
      } else {
        for (int i = 0; i < _max_num_q; i++) {
          process_phase3(refs_lists[i], clear_referent,
                         is_alive, keep_alive, complete_gc);
        }
      }
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.