Top


定義場所(file name)

hotspot/src/share/vm/runtime/jniHandles.cpp

名前(function name)

jobject JNIHandleBlock::allocate_handle(oop obj) {

本体部(body)

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

      assert(Universe::heap()->is_in_reserved(obj), "sanity check");

  {- -------------------------------------------
  (1) もし _top フィールドの値が 0 の場合, 以下のように初期化処理を行う.
      (この JNIHandleBlock オブジェクトに対して初めて JNIHandleBlock::allocate_handle() が呼ばれた場合か, 
       または, この JNIHandleBlock オブジェクトが JNIHandleBlock::zap() で破壊されていた場合.)
      ---------------------------------------- -}

      if (_top == 0) {
        // This is the first allocation or the initial block got zapped when
        // entering a native function. If we have any following blocks they are
        // not valid anymore.

    {- -------------------------------------------
  (1.1) このブロックから _next でつながる全部の JNIHandleBlock を空にし (_top を 0 にし), 
        さらに ZapJNIHandleArea オプションが指定されている場合は JNIHandleBlock::zap() を呼び出して中身を破壊する.)
        ---------------------------------------- -}

        for (JNIHandleBlock* current = _next; current != NULL;
             current = current->_next) {
          assert(current->_last == NULL, "only first block should have _last set");
          assert(current->_free_list == NULL,
                 "only first block should have _free_list set");
          current->_top = 0;
          if (ZapJNIHandleArea) current->zap();
        }

    {- -------------------------------------------
  (1.1) このブロック自体の _free_list や _allocate_before_rebuild, _last フィールドを以下のように初期化する.
        (さらに ZapJNIHandleArea オプションが指定されている場合は JNIHandleBlock::zap() を呼び出して中身を破壊する.)
        ---------------------------------------- -}

        // Clear initial block
        _free_list = NULL;
        _allocate_before_rebuild = 0;
        _last = this;
        if (ZapJNIHandleArea) zap();
      }

  {- -------------------------------------------
  (1) もし _last が指しているブロック(= 現在確保に使用しているブロック)に空きがあれば, 
      新しい JNIHandle はそこに確保し, 確保先に引数の oop を書き込んでリターン.
      ---------------------------------------- -}

      // Try last block
      if (_last->_top < block_size_in_oops) {
        oop* handle = &(_last->_handles)[_last->_top++];
        *handle = obj;
        return (jobject) handle;
      }

  {- -------------------------------------------
  (1) (_last が指しているブロックに空きがない場合, )
      _free_list が NULL でなければ
      新しい JNIHandle は _free_list から確保し, 引数の oop を書き込んでリターン.
      ---------------------------------------- -}

      // Try free list
      if (_free_list != NULL) {
        oop* handle = _free_list;
        _free_list = (oop*) *_free_list;
        *handle = obj;
        return (jobject) handle;
      }

  {- -------------------------------------------
  (1) (_last が指しているブロックに空きがなく, かつ _free_list にも空きがない場合, )
      _last が指しているブロックの後ろに未使用のブロックが残っていれば, 
      _last の値を後続の未使用ブロックに更新してから, この関数自身(JNIHandleBlock::allocate_handle())を再帰呼びする.
      (新しい JNIHandle はその未使用ブロックから確保し, 引数の oop を書き込んでリターンすることになる.)
      ---------------------------------------- -}

      // Check if unused block follow last
      if (_last->_next != NULL) {
        // update last and retry
        _last = _last->_next;
        return allocate_handle(obj);
      }

  {- -------------------------------------------
  (1) もし, 以上で探したどこにも空きがなければ, 以下のようにして空き領域を確保する.
      その後, この関数自身(JNIHandleBlock::allocate_handle())を再帰呼びして, もう一度確保処理を試みる.

      空き領域の確保処理: 
        JNIHandleBlock::allocate_block() で新しい JNIHandleBlock を確保する.
        ただし, ここで新しい JNIHandleBlock を確保する度に 
        _allocate_before_rebuild フィールドの値を decrement しており, 
        もし _allocate_before_rebuild フィールドの値が 0 まで下がっていれば
        新しい JNIHandleBlock を確保する代わりに JNIHandleBlock::rebuild_free_list() で
        確保済みの JNIHandleBlock 内から deleted な箇所を探して free list につなぐだけにする.
        (なお, 0 になってしまった_allocate_before_rebuild フィールドには, 
         JNIHandleBlock::rebuild_free_list() 内で新しい値がセットされる.)
      ---------------------------------------- -}

      // No space available, we have to rebuild free list or expand
      if (_allocate_before_rebuild == 0) {
          rebuild_free_list();        // updates _allocate_before_rebuild counter
      } else {
        // Append new block
        Thread* thread = Thread::current();
        Handle obj_handle(thread, obj);
        // This can block, so we need to preserve obj accross call.
        _last->_next = JNIHandleBlock::allocate_block(thread);
        _last = _last->_next;
        _allocate_before_rebuild--;
        obj = obj_handle();
      }
      return allocate_handle(obj);  // retry
    }

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