hotspot/src/share/vm/classfile/classFileParser.cpp
// The promoted_flags parameter is used to pass relevant access_flags
// from the methods back up to the containing klass. These flag values
// are added to klass's access_flags.
objArrayHandle ClassFileParser::parse_methods(constantPoolHandle cp, bool is_interface,
AccessFlags* promoted_flags,
bool* has_final_method,
objArrayOop* methods_annotations_oop,
objArrayOop* methods_parameter_annotations_oop,
objArrayOop* methods_default_annotations_oop,
TRAPS) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ClassFileStream* cfs = stream();
objArrayHandle nullHandle;
typeArrayHandle method_annotations;
typeArrayHandle method_parameter_annotations;
typeArrayHandle method_default_annotations;
{- -------------------------------------------
(1) まず, メソッドの個数を読み込む.
---------------------------------------- -}
cfs->guarantee_more(2, CHECK_(nullHandle)); // length
u2 length = cfs->get_u2_fast();
{- -------------------------------------------
(1) 次に, メソッド情報を格納するための objArrayHandle を作成する (これが返値になる).
(objArrayOop の長さはメソッドの個数)
(なお, 長さが 0 だった場合はこの時点でリターン)
---------------------------------------- -}
if (length == 0) {
return objArrayHandle(THREAD, Universe::the_empty_system_obj_array());
} else {
objArrayOop m = oopFactory::new_system_objArray(length, CHECK_(nullHandle));
objArrayHandle methods(THREAD, m);
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
HandleMark hm(THREAD);
objArrayHandle methods_annotations;
objArrayHandle methods_parameter_annotations;
objArrayHandle methods_default_annotations;
{- -------------------------------------------
(1) 次に, メソッドの個数分だけループし, 以下のようにしてメソッド情報の読み込み処理を行う
---------------------------------------- -}
for (int index = 0; index < length; index++) {
{- -------------------------------------------
(1.1) ClassFileParser::parse_method() を呼び出して, 実際のパース処理を行う.
---------------------------------------- -}
methodHandle method = parse_method(cp, is_interface,
promoted_flags,
&method_annotations,
&method_parameter_annotations,
&method_default_annotations,
CHECK_(nullHandle));
{- -------------------------------------------
(1.1) メソッドが final だった場合には,
引数として渡された has_final_method に true を書き込む.
---------------------------------------- -}
if (method->is_final()) {
*has_final_method = true;
}
{- -------------------------------------------
(1.1) パース結果を返値として返す配列に追加する.
---------------------------------------- -}
methods->obj_at_put(index, method());
{- -------------------------------------------
(1.1) メソッド中に annotation があった場合,
呼び出し元に伝えるために, その情報を蓄えていく.
(annotation があったかどうかは, ClassFileParser::parse_method() に渡した
method_*_annotations の not_null() メソッドで判定できる)
(なお, 情報を溜めるために配列が未確保であれば,
oopFactory::new_system_objArray() による確保処理も行う)
---------------------------------------- -}
if (method_annotations.not_null()) {
if (methods_annotations.is_null()) {
objArrayOop md = oopFactory::new_system_objArray(length, CHECK_(nullHandle));
methods_annotations = objArrayHandle(THREAD, md);
}
methods_annotations->obj_at_put(index, method_annotations());
}
if (method_parameter_annotations.not_null()) {
if (methods_parameter_annotations.is_null()) {
objArrayOop md = oopFactory::new_system_objArray(length, CHECK_(nullHandle));
methods_parameter_annotations = objArrayHandle(THREAD, md);
}
methods_parameter_annotations->obj_at_put(index, method_parameter_annotations());
}
if (method_default_annotations.not_null()) {
if (methods_default_annotations.is_null()) {
objArrayOop md = oopFactory::new_system_objArray(length, CHECK_(nullHandle));
methods_default_annotations = objArrayHandle(THREAD, md);
}
methods_default_annotations->obj_at_put(index, method_default_annotations());
}
{- -------------------------------------------
(1) (ここまでで, ClassFileParser::parse_methods() 内のメソッド個数分のループは終了)
---------------------------------------- -}
}
{- -------------------------------------------
(1) 次に, メソッドの定義が重複していないかどうかをチェックする.
(ただし _need_verify が立っていなければチェックしない)
重複していたら ClassFormatError にする
---------------------------------------- -}
if (_need_verify && length > 1) {
// Check duplicated methods
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; i++) {
methodOop m = (methodOop)methods->obj_at(i);
// If no duplicates, add name/signature in hashtable names_and_sigs.
if (!put_after_lookup(m->name(), m->signature(), names_and_sigs)) {
dup = true;
break;
}
}
}
if (dup) {
classfile_parse_error("Duplicate method name&signature in class file %s",
CHECK_(nullHandle));
}
}
{- -------------------------------------------
(1) 次に, ループ処理で蓄えていた annotation の情報を, 引数で渡されていたポインタに書き込む.
---------------------------------------- -}
*methods_annotations_oop = methods_annotations();
*methods_parameter_annotations_oop = methods_parameter_annotations();
*methods_default_annotations_oop = methods_default_annotations();
{- -------------------------------------------
(1) パース結果をリターンする.
---------------------------------------- -}
return methods;
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.