hotspot/src/share/vm/interpreter/linkResolver.cpp
void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass,
Symbol* method_name, Symbol* method_signature,
KlassHandle current_klass, bool check_access, TRAPS) {
{- -------------------------------------------
(1) もし (クラスではなく) インターフェースだった場合は IncompatibleClassChangeError
---------------------------------------- -}
// 1. check if klass is not interface
if (resolved_klass->is_interface()) {
ResourceMark rm(THREAD);
char buf[200];
jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", Klass::cast(resolved_klass())->external_name());
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
{- -------------------------------------------
(1) まず LinkResolver::lookup_method_in_klasses() を呼んで,
resolved_klass クラス内, あるいはそのスーパークラス内からメソッドを探す.
---------------------------------------- -}
// 2. lookup method in resolved klass and its super klasses
lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);
{- -------------------------------------------
(1) もしメソッドが見つかっていなければ,
LinkResolver::lookup_method_in_interfaces() を呼んで
インターフェース内からメソッドを探す.
それでも見つからなければ, LinkResolver::lookup_implicit_method() を呼んで,
(もしそれでも見つからなければ NoSuchMethodError)
---------------------------------------- -}
if (resolved_method.is_null()) { // not found in the class hierarchy
// 3. lookup method in all the interfaces implemented by the resolved klass
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
if (resolved_method.is_null()) {
// JSR 292: see if this is an implicitly generated method MethodHandle.invoke(*...)
lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, CHECK);
}
if (resolved_method.is_null()) {
// 4. method lookup failed
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
method_name,
method_signature));
}
}
{- -------------------------------------------
(1) もし解決結果が abstract method だったら, AbstractMethodError.
---------------------------------------- -}
// 5. check if method is concrete
if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) {
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
method_name,
method_signature));
}
{- -------------------------------------------
(1) check_access 引数が true の場合には, 以下のチェックを行う
* LinkResolver::check_method_accessability() を呼んで, アクセス権をチェックする.
(アクセス権違反なら, この中で IllegalAccessError が出る)
* SystemDictionary::check_signature_loaders() を呼んで,
ロード制約(loading constraints)違反が起こっていないかどうかチェックする.
もし違反していたら, LinkageError.
---------------------------------------- -}
// 6. access checks, access checking may be turned off when calling from within the VM.
if (check_access) {
assert(current_klass.not_null() , "current_klass should not be null");
// check if method can be accessed by the referring class
check_method_accessability(current_klass,
resolved_klass,
KlassHandle(THREAD, resolved_method->method_holder()),
resolved_method,
CHECK);
// check loader constraints
Handle loader (THREAD, instanceKlass::cast(current_klass())->class_loader());
Handle class_loader (THREAD, instanceKlass::cast(resolved_method->method_holder())->class_loader());
{
ResourceMark rm(THREAD);
char* failed_type_name =
SystemDictionary::check_signature_loaders(method_signature, loader,
class_loader, true, CHECK);
if (failed_type_name != NULL) {
const char* msg = "loader constraint violation: when resolving method"
" \"%s\" the class loader (instance of %s) of the current class, %s,"
" and the class loader (instance of %s) for resolved class, %s, have"
" different Class objects for the type %s used in the signature";
char* sig = methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name,method_signature);
const char* loader1 = SystemDictionary::loader_name(loader());
char* current = instanceKlass::cast(current_klass())->name()->as_C_string();
const char* loader2 = SystemDictionary::loader_name(class_loader());
char* resolved = instanceKlass::cast(resolved_klass())->name()->as_C_string();
size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
strlen(current) + strlen(loader2) + strlen(resolved) +
strlen(failed_type_name);
char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
resolved, failed_type_name);
THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
}
}
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.