hotspot/src/share/vm/interpreter/linkResolver.cpp
void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, bool update_pool, TRAPS) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
byte == Bytecodes::_getfield || byte == Bytecodes::_putfield, "bad bytecode");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic);
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// resolve specified klass
KlassHandle resolved_klass;
{- -------------------------------------------
(1) LinkResolver::resolve_klass() を呼んで, 対象フィールドが属しているクラスを取得する
(resolved_klass 局所変数にセットされる).
(この際, 対象クラスが constantPoolOopDesc 中でまだ解決されてなければ解決も行われる)
(ただし, update_pool 引数が false の場合には
代わりに LinkResolver::resolve_klass_no_update() で取得する.
この場合, 対象クラスが constantPoolOopDesc 中でまだ解決されていなくても, 解決は行われない)
---------------------------------------- -}
if (update_pool) {
resolve_klass(resolved_klass, pool, index, CHECK);
} else {
resolve_klass_no_update(resolved_klass, pool, index, CHECK);
}
{- -------------------------------------------
(1) (変数宣言など)
(ここで... #TODO)
---------------------------------------- -}
// Load these early in case the resolve of the containing klass fails
Symbol* field = pool->name_ref_at(index);
Symbol* sig = pool->signature_ref_at(index);
{- -------------------------------------------
(1) (そもそも, そのフィールドを含んでいるはずのクラス自体が見つからなければ, NoSuchFieldError)
---------------------------------------- -}
// Check if there's a resolved klass containing the field
if( resolved_klass.is_null() ) {
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
}
{- -------------------------------------------
(1) instanceKlass::find_field() を呼んで, 対象フィールドの情報を取得する.
(fd 局所変数と sel_klass 局所変数にセットされる. sel_klass は, そのフィールドを定義しているクラス.
(定義しているのは, resolved_klass 自体とは限らず, スーパークラスやスーパーインターフェースの可能性もある))
(もし定義しているクラスが見つからなければ, NoSuchFieldError)
---------------------------------------- -}
// Resolve instance field
fieldDescriptor fd; // find_field initializes fd if found
KlassHandle sel_klass(THREAD, instanceKlass::cast(resolved_klass())->find_field(field, sig, &fd));
// check if field exists; i.e., if a klass containing the field def has been selected
if (sel_klass.is_null()){
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
}
{- -------------------------------------------
(1) LinkResolver::check_field_accessability() を呼んで, アクセス権をチェックする.
(アクセス権違反なら, この中で IllegalAccessError が出る)
---------------------------------------- -}
// check access
KlassHandle ref_klass(THREAD, pool->pool_holder());
check_field_accessability(ref_klass, resolved_klass, sel_klass, fd, CHECK);
{- -------------------------------------------
(1) もし対象フィールドの ACC_STATIC 属性(static かどうかを示す属性) が
引数で指定された内容(is_static)と食い違っていれば, IncompatibleClassChangeError.
---------------------------------------- -}
// check for errors
if (is_static != fd.is_static()) {
ResourceMark rm(THREAD);
char msg[200];
jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", Klass::cast(resolved_klass())->external_name(), fd.name()->as_C_string());
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
}
{- -------------------------------------------
(1) もし final field がその定義クラス以外から変更されようとしていたら, IllegalAccessError.
---------------------------------------- -}
// Final fields can only be accessed from its own class.
if (is_put && fd.access_flags().is_final() && sel_klass() != pool->pool_holder()) {
THROW(vmSymbols::java_lang_IllegalAccessError());
}
{- -------------------------------------------
(1) 必要があれば, Klass::initialize() を呼んで定義クラスを初期化しておく
---------------------------------------- -}
// initialize resolved_klass if necessary
// note 1: the klass which declared the field must be initialized (i.e, sel_klass)
// according to the newest JVM spec (5.5, p.170) - was bug (gri 7/28/99)
//
// note 2: we don't want to force initialization if we are just checking
// if the field access is legal; e.g., during compilation
if (is_static && !check_only) {
sel_klass->initialize(CHECK);
}
{- -------------------------------------------
(1) SystemDictionary::check_signature_loaders() を呼んで,
ロード制約(loading constraints)違反が起こっていないかどうかチェックする.
もし違反していたら, LinkageError.
---------------------------------------- -}
{
HandleMark hm(THREAD);
Handle ref_loader (THREAD, instanceKlass::cast(ref_klass())->class_loader());
Handle sel_loader (THREAD, instanceKlass::cast(sel_klass())->class_loader());
Symbol* signature_ref = pool->signature_ref_at(index);
{
ResourceMark rm(THREAD);
char* failed_type_name =
SystemDictionary::check_signature_loaders(signature_ref,
ref_loader, sel_loader,
false,
CHECK);
if (failed_type_name != NULL) {
const char* msg = "loader constraint violation: when resolving field"
" \"%s\" the class loader (instance of %s) of the referring class, "
"%s, and the class loader (instance of %s) for the field's resolved "
"type, %s, have different Class objects for that type";
char* field_name = field->as_C_string();
const char* loader1 = SystemDictionary::loader_name(ref_loader());
char* sel = instanceKlass::cast(sel_klass())->name()->as_C_string();
const char* loader2 = SystemDictionary::loader_name(sel_loader());
size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1) +
strlen(sel) + strlen(loader2) + strlen(failed_type_name);
char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
jio_snprintf(buf, buflen, msg, field_name, loader1, sel, loader2,
failed_type_name);
THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
}
}
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// return information. note that the klass is set to the actual klass containing the
// field, otherwise access of static fields in superclasses will not work.
KlassHandle holder (THREAD, fd.field_holder());
Symbol* name = fd.name();
{- -------------------------------------------
(1) FieldAccessInfo::set() を呼んで,
引数で渡された FieldAccessInfo オブジェクト内に
解決結果をセットする
---------------------------------------- -}
result.set(holder, name, fd.index(), fd.offset(), fd.field_type(), fd.access_flags());
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.