hotspot/src/share/vm/oops/objArrayKlassKlass.cpp
klassOop objArrayKlassKlass::allocate_objArray_klass_impl(objArrayKlassKlassHandle this_oop,
int n, KlassHandle element_klass, TRAPS) {
{- -------------------------------------------
(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.