hotspot/src/share/vm/interpreter/linkResolver.cpp
// throws runtime exceptions
void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass,
KlassHandle current_klass, bool check_access, TRAPS) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// resolved method is selected method unless we have an old-style lookup
methodHandle sel_method(THREAD, resolved_method());
{- -------------------------------------------
(1) もし以下の 3つの条件が成り立つ場合は解決をやり直す.
*
*
*
(再解決する場合, もし見つからなければ AbstractMethodError)
(この条件については, Java 仮想マシン仕様の invokespecial の仕様を参照)
---------------------------------------- -}
// check if this is an old-style super call and do a new lookup if so
{ KlassHandle method_klass = KlassHandle(THREAD,
resolved_method->method_holder());
if (check_access &&
// a) check if ACC_SUPER flag is set for the current class
current_klass->is_super() &&
// b) check if the method class is a superclass of the current class (superclass relation is not reflexive!)
current_klass->is_subtype_of(method_klass()) && current_klass() != method_klass() &&
// c) check if the method is not <init>
resolved_method->name() != vmSymbols::object_initializer_name()) {
// Lookup super method
KlassHandle super_klass(THREAD, current_klass->super());
lookup_instance_method_in_klasses(sel_method, super_klass,
resolved_method->name(),
resolved_method->signature(), CHECK);
// check if found
if (sel_method.is_null()) {
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
resolved_method->name(),
resolved_method->signature()));
}
}
}
{- -------------------------------------------
(1) もし解決結果が static method であれば IncompatibleClassChangeError.
---------------------------------------- -}
// check if not static
if (sel_method->is_static()) {
ResourceMark rm(THREAD);
char buf[200];
jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
resolved_method->name(),
resolved_method->signature()));
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
{- -------------------------------------------
(1) もし解決結果が abstract method だったら, AbstractMethodError.
---------------------------------------- -}
// check if abstract
if (sel_method->is_abstract()) {
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
sel_method->name(),
sel_method->signature()));
}
{- -------------------------------------------
(1) CallInfo::set_static() を呼んで,
引数で渡された CallInfo オブジェクト内に
解決結果をセットする
---------------------------------------- -}
// setup result
result.set_static(resolved_klass, sel_method, CHECK);
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.