Top


定義場所(file name)

hotspot/src/share/vm/oops/objArrayKlassKlass.cpp

名前(function name)

klassOop objArrayKlassKlass::allocate_objArray_klass_impl(objArrayKlassKlassHandle this_oop,
                                                          int n, KlassHandle element_klass, TRAPS) {

本体部(body)

  {- -------------------------------------------
  (1) スーパークラスの配列クラスを取得する (以下の super_klass 局所変数にセット).

      (なお, この際にスーパークラスの配列クラスや
      実装しているインターフェースの配列クラスが生成されているかもチェックしている.
      もしまだ生成されていなければ,  Klass::array_klass() を呼んで生成したあと,
      もう一度 element_klass 引数に対して Klass::array_klass() を再帰呼び出しして, 
      配列クラスの生成を行っている.
      この場合, 再起呼びから返ってきたら (配列生成処理は終わっているので) それをリターンするだけ)

      (なお, Object[] の場合には (Object にスーパークラスは無いので) Object をスーパークラスとして使用する)


      (ただし, 以上の処理は, HotSpot の起動時 (= Universe::is_bootstrapping() が true の場合) には行わない)
      ---------------------------------------- -}

      // Eagerly allocate the direct array supertype.
      KlassHandle super_klass = KlassHandle();
      if (!Universe::is_bootstrapping()) {
        KlassHandle element_super (THREAD, element_klass->super());
        if (element_super.not_null()) {
          // The element type has a direct super.  E.g., String[] has direct super of Object[].
          super_klass = KlassHandle(THREAD, element_super->array_klass_or_null());
          bool supers_exist = super_klass.not_null();
          // Also, see if the element has secondary supertypes.
          // We need an array type for each.
          objArrayHandle element_supers = objArrayHandle(THREAD,
                                                element_klass->secondary_supers());
          for( int i = element_supers->length()-1; i >= 0; i-- ) {
            klassOop elem_super = (klassOop) element_supers->obj_at(i);
            if (Klass::cast(elem_super)->array_klass_or_null() == NULL) {
              supers_exist = false;
              break;
            }
          }
          if (!supers_exist) {
            // Oops.  Not allocated yet.  Back out, allocate it, and retry.
    #ifndef PRODUCT
            if (WizardMode) {
              tty->print_cr("Must retry array klass creation for depth %d",n);
            }
    #endif
            KlassHandle ek;
            {
              MutexUnlocker mu(MultiArray_lock);
              MutexUnlocker mc(Compile_lock);   // for vtables
              klassOop sk = element_super->array_klass(CHECK_0);
              super_klass = KlassHandle(THREAD, sk);
              for( int i = element_supers->length()-1; i >= 0; i-- ) {
                KlassHandle elem_super (THREAD, element_supers->obj_at(i));
                elem_super->array_klass(CHECK_0);
              }
              // Now retry from the beginning
              klassOop klass_oop = element_klass->array_klass(n, CHECK_0);
              // Create a handle because the enclosing brace, when locking
              // can cause a gc.  Better to have this function return a Handle.
              ek = KlassHandle(THREAD, klass_oop);
            }  // re-lock
            return ek();
          }
        } else {
          // The element type is already Object.  Object[] has direct super of Object.
          super_klass = KlassHandle(THREAD, SystemDictionary::Object_klass());
        }
      }

  {- -------------------------------------------
  (1) 以下のどちらかの条件が成り立つなら, ここで配列クラスの名前(signature string)を作り, SymbolTable に登録しておく.
      * instanceKlass の配列ではない場合
      * instanceKlass の配列だが, まだ instanceKlass::_array_name フィールドが空の場合

      作られる signature は, "[L${クラス名};" という文字列.

      (なお, instanceKlass の場合には, 作った名前は instanceKlass::set_array_name() で
      instanceKlass::_array_name フィールドに登録しておく)
      ---------------------------------------- -}

      // Create type name for klass.
      Symbol* name = NULL;
      if (!element_klass->oop_is_instance() ||
          (name = instanceKlass::cast(element_klass())->array_name()) == NULL) {

        ResourceMark rm(THREAD);
        char *name_str = element_klass->name()->as_C_string();
        int len = element_klass->name()->utf8_length();
        char *new_str = NEW_RESOURCE_ARRAY(char, len + 4);
        int idx = 0;
        new_str[idx++] = '[';
        if (element_klass->oop_is_instance()) { // it could be an array or simple type
          new_str[idx++] = 'L';
        }
        memcpy(&new_str[idx], name_str, len * sizeof(char));
        idx += len;
        if (element_klass->oop_is_instance()) {
          new_str[idx++] = ';';
        }
        new_str[idx++] = '\0';
        name = SymbolTable::new_symbol(new_str, CHECK_0);
        if (element_klass->oop_is_instance()) {
          instanceKlass* ik = instanceKlass::cast(element_klass());
          ik->set_array_name(name);
        }
      }

  {- -------------------------------------------
  (1) arrayKlass::base_create_array_klass() を呼んで, 対応する配列クラスを生成する.
      ---------------------------------------- -}

      objArrayKlass o;
      arrayKlassHandle k = arrayKlass::base_create_array_klass(o.vtbl_value(),
                                                               objArrayKlass::header_size(),
                                                              this_oop,
                                                               CHECK_0);

  {- -------------------------------------------
  (1) 生成した arrayKlass 内のフィールドを初期化
      ---------------------------------------- -}

      // Initialize instance variables
      objArrayKlass* oak = objArrayKlass::cast(k());
      oak->set_dimension(n);
      oak->set_element_klass(element_klass());
      oak->set_name(name);
      // decrement refcount because object arrays are not explicitly freed.  The
      // instanceKlass array_name() keeps the name counted while the klass is
      // loaded.
      name->decrement_refcount();

      klassOop bk;
      if (element_klass->oop_is_objArray()) {
        bk = objArrayKlass::cast(element_klass())->bottom_klass();
      } else {
        bk = element_klass();
      }
      assert(bk != NULL && (Klass::cast(bk)->oop_is_instance() || Klass::cast(bk)->oop_is_typeArray()), "invalid bottom klass");
      oak->set_bottom_klass(bk);

      oak->set_layout_helper(array_layout_helper(T_OBJECT));
      assert(oak->oop_is_javaArray(), "sanity");
      assert(oak->oop_is_objArray(), "sanity");

  {- -------------------------------------------
  (1) 生成した配列クラスの vtable や mirror オブジェクト (Java レベルのクラスオブジェクト) を生成する.
      ---------------------------------------- -}

      // Call complete_create_array_klass after all instance variables has been initialized.
      arrayKlass::complete_create_array_klass(k, super_klass, CHECK_0);

  {- -------------------------------------------
  (1) 結果をリターン
      ---------------------------------------- -}

      return k();
    }

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