hotspot/src/share/vm/classfile/classFileParser.cpp
typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_interface,
struct FieldAllocationCount *fac,
objArrayHandle* fields_annotations, TRAPS) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ClassFileStream* cfs = stream();
typeArrayHandle nullHandle;
{- -------------------------------------------
(1) まず, フィールドの個数を読み込む.
---------------------------------------- -}
cfs->guarantee_more(2, CHECK_(nullHandle)); // length
u2 length = cfs->get_u2_fast();
{- -------------------------------------------
(1) 次に, フィールド情報を格納するための typeArrayOop を作成する.
typeArrayOop の大きさは, (上述の通り)「フィールド個数 * (u2 7個分)」.
---------------------------------------- -}
// Tuples of shorts [access, name index, sig index, initial value index, byte offset, generic signature index]
typeArrayOop new_fields = oopFactory::new_permanent_shortArray(length*instanceKlass::next_offset, CHECK_(nullHandle));
typeArrayHandle fields(THREAD, new_fields);
{- -------------------------------------------
(1) 次に, フィールドの個数分だけループし, 以下のようにしてフィールド情報の読み込み処理を行う
---------------------------------------- -}
int index = 0;
typeArrayHandle field_annotations;
for (int n = 0; n < length; n++) {
cfs->guarantee_more(8, CHECK_(nullHandle)); // access_flags, name_index, descriptor_index, attributes_count
{- -------------------------------------------
(1.1) access_flags を読み込み, ClassFileParser::verify_legal_field_modifiers() で
おかしな設定ではないかどうか確認する.
---------------------------------------- -}
AccessFlags access_flags;
jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_FIELD_MODIFIERS;
verify_legal_field_modifiers(flags, is_interface, CHECK_(nullHandle));
access_flags.set_flags(flags);
{- -------------------------------------------
(1.1) name_index を読み込み, その index 値が Constant Pool 内に収まっており,
utf8_info を指していることを確認する.
また, ClassFileParser::verify_legal_field_name() で
フィールド名として妥当な utf8 文字列かどうかも確認する.
---------------------------------------- -}
u2 name_index = cfs->get_u2_fast();
int cp_size = cp->length();
check_property(
valid_cp_range(name_index, cp_size) && cp->tag_at(name_index).is_utf8(),
"Invalid constant pool index %u for field name in class file %s",
name_index, CHECK_(nullHandle));
Symbol* name = cp->symbol_at(name_index);
verify_legal_field_name(name, CHECK_(nullHandle));
{- -------------------------------------------
(1.1) signature_index (JVMS では descriptor_index) を読み込み,
その index 値が Constant Pool 内に収まっており, utf8_info を指していることを確認する.
また, ClassFileParser::verify_legal_field_signature() で
フィールドの型情報(フィールド・ディスクリプタ)として妥当な utf8 文字列かどうかも確認する.
---------------------------------------- -}
u2 signature_index = cfs->get_u2_fast();
check_property(
valid_cp_range(signature_index, cp_size) &&
cp->tag_at(signature_index).is_utf8(),
"Invalid constant pool index %u for field signature in class file %s",
signature_index, CHECK_(nullHandle));
Symbol* sig = cp->symbol_at(signature_index);
verify_legal_field_signature(name, sig, CHECK_(nullHandle));
{- -------------------------------------------
(1.1) attributes_count を読み込んで attribute の個数を取得し,
ClassFileParser::parse_field_attributes() で, その個数分の attributes 情報を読み込む.
---------------------------------------- -}
u2 constantvalue_index = 0;
bool is_synthetic = false;
u2 generic_signature_index = 0;
bool is_static = access_flags.is_static();
u2 attributes_count = cfs->get_u2_fast();
if (attributes_count > 0) {
parse_field_attributes(cp, attributes_count, is_static, signature_index,
&constantvalue_index, &is_synthetic,
&generic_signature_index, &field_annotations,
CHECK_(nullHandle));
{- -------------------------------------------
(1.1) ClassFileParser::parse_field_attributes() の結果を調べ,
annotation や synthetic があった場合には処理を行う.
---------------------------------------- -}
{- -------------------------------------------
(1.1) * attributes 中に annotation があった場合:
引数として渡された objArrayHandle (以下の fields_annotations) に結果を書き込む.
(fields_annotations が未確保であれば, oopFactory::new_system_objArray() による確保処理も行う)
---------------------------------------- -}
if (field_annotations.not_null()) {
if (fields_annotations->is_null()) {
objArrayOop md = oopFactory::new_system_objArray(length, CHECK_(nullHandle));
*fields_annotations = objArrayHandle(THREAD, md);
}
(*fields_annotations)->obj_at_put(n, field_annotations());
}
{- -------------------------------------------
(1.1) * attributes 中に Synthetic attributes があった場合:
access_flags に追加する.
---------------------------------------- -}
if (is_synthetic) {
access_flags.set_is_synthetic();
}
}
{- -------------------------------------------
(1.1) 次に, ここまでで読み込んだフィールド情報のいくつかを, 確保しておいた typeArrayOop (以下の "fields") に詰め込む
---------------------------------------- -}
fields->short_at_put(index++, access_flags.as_short());
fields->short_at_put(index++, name_index);
fields->short_at_put(index++, signature_index);
fields->short_at_put(index++, constantvalue_index);
{- -------------------------------------------
(1.1) 次に, フィールド・ディスクリプタ文字列を基に,
フィールドの allocation type (FieldAllocationType) を決定する.
<= 結果はビット数(および static フィールドかどうか)に応じて以下のようにまとめられる.
bool, byte => STATIC_BYTE or NONSTATIC_BYTE
char, short => STATIC_SHORT or NONSTATIC_SHORT
int, float => STATIC_WORD or NONSTATIC_WORD
long, double => STATIC_DOUBLE or NONSTATIC_DOUBLE (もしくは STATIC_ALIGNED_DOUBLE or NONSTATIC_ALIGNED_DOUBLE)
object, array => STATIC_OOP or NONSTATIC_OOP
また, 合わせてこのフィールドの allocation type 情報を引数で渡された fac に加算していく.
(なお, ConstantPoolOop::basic_type_for_signature_at() は,
フィールド・ディスクリプタの先頭1文字だけを見て, 大まかな型を表す BasicType オブジェクトを返す関数)
---------------------------------------- -}
// Remember how many oops we encountered and compute allocation type
BasicType type = cp->basic_type_for_signature_at(signature_index);
FieldAllocationType atype;
if ( is_static ) {
switch ( type ) {
case T_BOOLEAN:
case T_BYTE:
fac->static_byte_count++;
atype = STATIC_BYTE;
break;
case T_LONG:
case T_DOUBLE:
if (Universe::field_type_should_be_aligned(type)) {
atype = STATIC_ALIGNED_DOUBLE;
} else {
atype = STATIC_DOUBLE;
}
fac->static_double_count++;
break;
case T_CHAR:
case T_SHORT:
fac->static_short_count++;
atype = STATIC_SHORT;
break;
case T_FLOAT:
case T_INT:
fac->static_word_count++;
atype = STATIC_WORD;
break;
case T_ARRAY:
case T_OBJECT:
fac->static_oop_count++;
atype = STATIC_OOP;
break;
case T_ADDRESS:
case T_VOID:
default:
assert(0, "bad field type");
}
} else {
switch ( type ) {
case T_BOOLEAN:
case T_BYTE:
fac->nonstatic_byte_count++;
atype = NONSTATIC_BYTE;
break;
case T_LONG:
case T_DOUBLE:
if (Universe::field_type_should_be_aligned(type)) {
atype = NONSTATIC_ALIGNED_DOUBLE;
} else {
atype = NONSTATIC_DOUBLE;
}
fac->nonstatic_double_count++;
break;
case T_CHAR:
case T_SHORT:
fac->nonstatic_short_count++;
atype = NONSTATIC_SHORT;
break;
case T_FLOAT:
case T_INT:
fac->nonstatic_word_count++;
atype = NONSTATIC_WORD;
break;
case T_ARRAY:
case T_OBJECT:
fac->nonstatic_oop_count++;
atype = NONSTATIC_OOP;
break;
case T_ADDRESS:
case T_VOID:
default:
assert(0, "bad field type");
}
}
{- -------------------------------------------
(1.1) 次に, 残りのフィールド情報を, 確保しておいた typeArrayOop (以下の "fields") に詰め込む.
<= なお, low_offset, high_offset についてはまだ確定していないので,
代わりに FieldAllocationType 情報 (以下の "atype") と適当な値 (以下の "0") を埋めている.
---------------------------------------- -}
// The correct offset is computed later (all oop fields will be located together)
// We temporarily store the allocation type in the offset field
fields->short_at_put(index++, atype);
fields->short_at_put(index++, 0); // Clear out high word of byte offset
fields->short_at_put(index++, generic_signature_index);
{- -------------------------------------------
(1) (ここまでで, ClassFileParser::parse_fields() 内のフィールド個数分のループは終了)
---------------------------------------- -}
}
{- -------------------------------------------
(1) 次に, フィールドの定義が重複していないかどうかをチェックする.
(ただし _need_verify が立っていなければチェックしない)
重複していたら ClassFormatError にする.
---------------------------------------- -}
if (_need_verify && length > 1) {
// Check duplicated fields
ResourceMark rm(THREAD);
NameSigHash** names_and_sigs = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, NameSigHash*, HASH_ROW_SIZE);
initialize_hashtable(names_and_sigs);
bool dup = false;
{
debug_only(No_Safepoint_Verifier nsv;)
for (int i = 0; i < length*instanceKlass::next_offset; i += instanceKlass::next_offset) {
int name_index = fields->ushort_at(i + instanceKlass::name_index_offset);
Symbol* name = cp->symbol_at(name_index);
int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset);
Symbol* sig = cp->symbol_at(sig_index);
// If no duplicates, add name/signature in hashtable names_and_sigs.
if (!put_after_lookup(name, sig, names_and_sigs)) {
dup = true;
break;
}
}
}
if (dup) {
classfile_parse_error("Duplicate field name&signature in class file %s",
CHECK_(nullHandle));
}
}
{- -------------------------------------------
(1) パース結果をリターンする
---------------------------------------- -}
return fields;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.