hotspot/src/share/vm/classfile/classFileParser.cpp
この関数では attributes 個数分のループで読み込み&確認処理をする.
なお, 結果は (返り値ではなく) 引数で渡されたポインタに書き込まれて返される. それぞれの引数に書き込まれる値は以下の通り.
ConstantValue attribute があった場合, それが指す CP の index が書き込まれる
Synthetic attribute があった場合, true が書き込まれる
Signature attribute があった場合, それが指す CP の index が書き込まれる
RunTimeVisible(およびInvisible)Annotation があった場合, それら全てを ClassFileParser::assemble_annotations() でまとめた typeArrayHandle へのポインタが書き込まれる (#TODO)(どんな Annotation がつく?)
// Parse attributes for a field.
void ClassFileParser::parse_field_attributes(constantPoolHandle cp,
u2 attributes_count,
bool is_static, u2 signature_index,
u2* constantvalue_index_addr,
bool* is_synthetic_addr,
u2* generic_signature_index_addr,
typeArrayHandle* field_annotations,
TRAPS) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ClassFileStream* cfs = stream();
assert(attributes_count > 0, "length should be greater than 0");
u2 constantvalue_index = 0;
u2 generic_signature_index = 0;
bool is_synthetic = false;
u1* runtime_visible_annotations = NULL;
int runtime_visible_annotations_length = 0;
u1* runtime_invisible_annotations = NULL;
int runtime_invisible_annotations_length = 0;
{- -------------------------------------------
(1) 引数で指定された attribute の個数分だけループ
---------------------------------------- -}
while (attributes_count--) {
{- -------------------------------------------
(1.1) attribute_name_index と attribute_length を読み込む.
attribute_name_index については, その index 値が Constant Pool 内に収まっており,
utf8_info を指していることを確認する.
---------------------------------------- -}
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
u2 attribute_name_index = cfs->get_u2_fast();
u4 attribute_length = cfs->get_u4_fast();
check_property(valid_cp_range(attribute_name_index, cp->length()) &&
cp->tag_at(attribute_name_index).is_utf8(),
"Invalid field attribute index %u in class file %s",
attribute_name_index,
CHECK);
Symbol* attribute_name = cp->symbol_at(attribute_name_index);
{- -------------------------------------------
(1.1) 以下, 読み込んだ attribute_name に応じて, 適切に読み込み&内容の確認処理を行う.
---------------------------------------- -}
{- -------------------------------------------
(1.1) * ConstantValue attribute の場合は, static でないといけない
(non-static な ConstantValue attribute は無視することになっている).
また, 1つのフィールドに複数の ConstantValue attribute が指定されてはいけない.
(局所変数 constantvalue_index は, 初期値はゼロで,
ConstantValue attribute が見つかればその constantvalue_index 値がセットされる.
よって, これが 0 でなければ複数の ConstantValue attribute が指定されていることになる)
また, attribute_length が 2 でないといけない.
以上のチェックが終わったら, constantvalue_index を読み込み,
(_need_verify が立っていれば) ClassFileParser::verify_constantvalue() で
フィールドの型と指示先の定数の型があっているかどうかをチェック.
---------------------------------------- -}
if (is_static && attribute_name == vmSymbols::tag_constant_value()) {
// ignore if non-static
if (constantvalue_index != 0) {
classfile_parse_error("Duplicate ConstantValue attribute in class file %s", CHECK);
}
check_property(
attribute_length == 2,
"Invalid ConstantValue field attribute length %u in class file %s",
attribute_length, CHECK);
constantvalue_index = cfs->get_u2(CHECK);
if (_need_verify) {
verify_constantvalue(constantvalue_index, signature_index, cp, CHECK);
}
{- -------------------------------------------
(1.1) * Synthetic attribute の場合は, attribute_length が 0 でないといけない.
(Synthetic attribute には他に情報は無いので単にこれだけ)
以上のチェックが終わったら, is_synthetic を true にセットし,
呼び出し元に Synthetic があったことを通知できるようにしておく.
---------------------------------------- -}
} else if (attribute_name == vmSymbols::tag_synthetic()) {
if (attribute_length != 0) {
classfile_parse_error(
"Invalid Synthetic field attribute length %u in class file %s",
attribute_length, CHECK);
}
is_synthetic = true;
{- -------------------------------------------
(1.1) * Deprecated attribute の場合は, attribute_length が 0 でないといけない.
(Deprecated attribute には他に情報は無いので単にこれだけ)
(Deprecated attribute については, 呼び出し元には何の情報も返されない)
---------------------------------------- -}
} else if (attribute_name == vmSymbols::tag_deprecated()) { // 4276120
if (attribute_length != 0) {
classfile_parse_error(
"Invalid Deprecated field attribute length %u in class file %s",
attribute_length, CHECK);
}
{- -------------------------------------------
(1.1) バージョンが Java 5 以降であれば, Java 5 で追加されたアノテーションの処理も行う. (#TODO)
---------------------------------------- -}
} else if (_major_version >= JAVA_1_5_VERSION) {
if (attribute_name == vmSymbols::tag_signature()) {
if (attribute_length != 2) {
classfile_parse_error(
"Wrong size %u for field's Signature attribute in class file %s",
attribute_length, CHECK);
}
generic_signature_index = cfs->get_u2(CHECK);
} else if (attribute_name == vmSymbols::tag_runtime_visible_annotations()) {
runtime_visible_annotations_length = attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
} else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
runtime_invisible_annotations_length = attribute_length;
runtime_invisible_annotations = cfs->get_u1_buffer();
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
cfs->skip_u1(runtime_invisible_annotations_length, CHECK);
{- -------------------------------------------
(1.1) もし認識できない attribute であれば, 単に読み飛ばすだけ.
(なお 2つあるのは, _major_version >= JAVA_1_5_VERSION の場合とそうでない場合に対応. どちらにせよ読み飛ばすだけだけど)
---------------------------------------- -}
} else {
cfs->skip_u1(attribute_length, CHECK); // Skip unknown attributes
}
} else {
cfs->skip_u1(attribute_length, CHECK); // Skip unknown attributes
}
}
{- -------------------------------------------
(1) 最後に, パース結果を引数で渡されたポインタに書き込んでリターン.
---------------------------------------- -}
*constantvalue_index_addr = constantvalue_index;
*is_synthetic_addr = is_synthetic;
*generic_signature_index_addr = generic_signature_index;
*field_annotations = assemble_annotations(runtime_visible_annotations,
runtime_visible_annotations_length,
runtime_invisible_annotations,
runtime_invisible_annotations_length,
CHECK);
return;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.