hotspot/src/share/vm/interpreter/linkResolver.cpp
void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
KlassHandle resolved_klass,
Symbol* method_name,
Symbol* method_signature,
KlassHandle current_klass,
bool check_access, TRAPS) {
{- -------------------------------------------
(1) もし (インターフェースではなく) クラスだった場合は IncompatibleClassChangeError
---------------------------------------- -}
// check if klass is interface
if (!resolved_klass->is_interface()) {
ResourceMark rm(THREAD);
char buf[200];
jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", Klass::cast(resolved_klass())->external_name());
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
{- -------------------------------------------
(1) まず LinkResolver::lookup_instance_method_in_klasses() を呼んで,
resolved_klass 内, あるいはそのスーパークラスである java.lang.Object 内からメソッドを探す.
---------------------------------------- -}
// lookup method in this interface or its super, java.lang.Object
lookup_instance_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);
{- -------------------------------------------
(1) もしメソッドが見つかっていなければ,
LinkResolver::lookup_method_in_interfaces() を呼んで
インターフェース内からメソッドを探す.
(もしそれでも見つからなければ NoSuchMethodError)
---------------------------------------- -}
if (resolved_method.is_null()) {
// lookup method in all the super-interfaces
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
if (resolved_method.is_null()) {
// no method found
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) check_access 引数が true の場合には, 以下のチェックを行う
* SystemDictionary::check_signature_loaders() を呼んで,
ロード制約(loading constraints)違反が起こっていないかどうかチェックする.
もし違反していたら, LinkageError.
---------------------------------------- -}
if (check_access) {
HandleMark hm(THREAD);
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 "
"interface 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.