Top


定義場所(file name)

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

名前(function name)

HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size,
                                                        bool   is_tlab) {

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      GenCollectedHeap *gch = GenCollectedHeap::heap();
      GCCauseSetter x(gch, GCCause::_allocation_failure);
      HeapWord* result = NULL;

  {- -------------------------------------------
  (1) (assert)
      ---------------------------------------- -}

      assert(size != 0, "Precondition violated");

  {- -------------------------------------------
  (1) もし, 現在 GC が禁止されており(= GC_locker が active で), かつ 
      既に誰かが GC のエントリ処理を実行して GC の必要性を GC_locker に通知している場合, 
      (可能であれば, GenCollectorPolicy::expand_heap_and_allocate() による確保を試みた後で, )
      ここでリターン.
      ---------------------------------------- -}

      if (GC_locker::is_active_and_needs_gc()) {
        // GC locker is active; instead of a collection we will attempt
        // to expand the heap, if there's room for expansion.
        if (!gch->is_maximal_no_gc()) {
          result = expand_heap_and_allocate(size, is_tlab);
        }
        return result;   // could be null if we are out of space

  {- -------------------------------------------
  (1) そうでなければ, Minor GC または Full GC を実行する.
      (GenCollectedHeap::incremental_collection_will_fail() が false を返せば Minor GC を実行する.
       逆に true を返せば Full GC を実行する.)
      ---------------------------------------- -}

      } else if (!gch->incremental_collection_will_fail(false /* don't consult_young */)) {

    {- -------------------------------------------
  (1.1) GenCollectedHeap::do_collection() で Minor GC を実行.
        ---------------------------------------- -}

        // Do an incremental collection.
        gch->do_collection(false            /* full */,
                           false            /* clear_all_soft_refs */,
                           size             /* size */,
                           is_tlab          /* is_tlab */,
                           number_of_generations() - 1 /* max_level */);
      } else {

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

        if (Verbose && PrintGCDetails) {
          gclog_or_tty->print(" :: Trying full because partial may fail :: ");
        }

    {- -------------------------------------------
  (1.1) GenCollectedHeap::do_collection() で Full GC を実行.
        ---------------------------------------- -}

        // Try a full collection; see delta for bug id 6266275
        // for the original code and why this has been simplified
        // with from-space allocation criteria modified and
        // such allocation moved out of the safepoint path.
        gch->do_collection(true             /* full */,
                           false            /* clear_all_soft_refs */,
                           size             /* size */,
                           is_tlab          /* is_tlab */,
                           number_of_generations() - 1 /* max_level */);
      }

  {- -------------------------------------------
  (1) GenCollectedHeap::attempt_allocation() で確保を試みる.
      確保が成功したら, ここでリターン.
      ---------------------------------------- -}

      result = gch->attempt_allocation(size, is_tlab, false /*first_only*/);

      if (result != NULL) {
        assert(gch->is_in_reserved(result), "result not in heap");
        return result;
      }

  {- -------------------------------------------
  (1) GenCollectorPolicy::expand_heap_and_allocate() での確保を試みる.
      確保が成功したら, ここでリターン.
      ---------------------------------------- -}

      // OK, collection failed, try expansion.
      result = expand_heap_and_allocate(size, is_tlab);
      if (result != NULL) {
        return result;
      }

  {- -------------------------------------------
  (1) (ここまで到達してしまったら本当にメモリが足りてない状態)
      GenCollectedHeap::do_collection() でもう一度 Full GC を実行する.
      (今度は soft reference は全部消すことにする. 他にもありとあらゆる手段を駆使してメモリを回収する.)
      ---------------------------------------- -}

      // If we reach this point, we're really out of memory. Try every trick
      // we can to reclaim memory. Force collection of soft references. Force
      // a complete compaction of the heap. Any additional methods for finding
      // free memory should be here, especially if they are expensive. If this
      // attempt fails, an OOM exception will be thrown.
      {
        IntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted

        gch->do_collection(true             /* full */,
                           true             /* clear_all_soft_refs */,
                           size             /* size */,
                           is_tlab          /* is_tlab */,
                           number_of_generations() - 1 /* max_level */);
      }

  {- -------------------------------------------
  (1) GenCollectedHeap::attempt_allocation() で確保を試みる.
      確保が成功したら, ここでリターン.
      ---------------------------------------- -}

      result = gch->attempt_allocation(size, is_tlab, false /* first_only */);
      if (result != NULL) {
        assert(gch->is_in_reserved(result), "result not in heap");
        return result;
      }

  {- -------------------------------------------
  (1) (assert)
      ---------------------------------------- -}

      assert(!should_clear_all_soft_refs(),
        "Flag should have been handled and cleared prior to this point");

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

      // What else?  We might try synchronous finalization later.  If the total
      // space available is large enough for the allocation, then a more
      // complete compaction phase than we've tried so far might be
      // appropriate.
      return NULL;
    }

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