hotspot/src/share/vm/oops/klassVtable.cpp
void klassItable::initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
objArrayHandle methods(THREAD, instanceKlass::cast(interf_h())->methods());
int nof_methods = methods()->length();
HandleMark hm;
KlassHandle klass = _klass;
assert(nof_methods > 0, "at least one method must exist for interface to be in vtable");
Handle interface_loader (THREAD, instanceKlass::cast(interf_h())->class_loader());
int ime_num = 0;
{- -------------------------------------------
(1) static 初期化子(<clinit>) はスキップして開始する.
---------------------------------------- -}
// Skip first methodOop if it is a class initializer
int i = ((methodOop)methods()->obj_at(0))->is_static_initializer() ? 1 : 0;
{- -------------------------------------------
(1) 以下のループで定義されているメソッドを全て辿り, itable の初期化を行う.
---------------------------------------- -}
// m, method_name, method_signature, klass reset each loop so they
// don't need preserving across check_signature_loaders call
// methods needs a handle in case of gc from check_signature_loaders
for(; i < nof_methods; i++) {
{- -------------------------------------------
(1.1) (変数宣言など)
---------------------------------------- -}
methodOop m = (methodOop)methods()->obj_at(i);
Symbol* method_name = m->name();
Symbol* method_signature = m->signature();
{- -------------------------------------------
(1)
---------------------------------------- -}
// This is same code as in Linkresolver::lookup_instance_method_in_klasses
methodOop target = klass->uncached_lookup_method(method_name, method_signature);
while (target != NULL && target->is_static()) {
// continue with recursive lookup through the superclass
klassOop super = Klass::cast(target->method_holder())->super();
target = (super == NULL) ? methodOop(NULL) : Klass::cast(super)->uncached_lookup_method(method_name, method_signature);
}
{- -------------------------------------------
(1)
---------------------------------------- -}
if (target == NULL || !target->is_public() || target->is_abstract()) {
// Entry do not resolve. Leave it empty
} else {
{- -------------------------------------------
(1.1) もし, 引数で loader constraints をチェックするよう指定されていれば,
SystemDictionary::check_signature_loaders() を呼んでチェックを行う.
(チェックが失敗したら LinkageError)
---------------------------------------- -}
// Entry did resolve, check loader constraints before initializing
// if checkconstraints requested
methodHandle target_h (THREAD, target); // preserve across gc
if (checkconstraints) {
Handle method_holder_loader (THREAD, instanceKlass::cast(target->method_holder())->class_loader());
if (method_holder_loader() != interface_loader()) {
ResourceMark rm(THREAD);
char* failed_type_name =
SystemDictionary::check_signature_loaders(method_signature,
method_holder_loader,
interface_loader,
true, CHECK);
if (failed_type_name != NULL) {
const char* msg = "loader constraint violation in interface "
"itable initialization: when resolving method \"%s\" the class"
" loader (instance of %s) of the current class, %s, "
"and the class loader (instance of %s) for interface "
"%s have different Class objects for the type %s "
"used in the signature";
char* sig = target_h()->name_and_sig_as_C_string();
const char* loader1 = SystemDictionary::loader_name(method_holder_loader());
char* current = klass->name()->as_C_string();
const char* loader2 = SystemDictionary::loader_name(interface_loader());
char* iface = instanceKlass::cast(interf_h())->name()->as_C_string();
size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
strlen(current) + strlen(loader2) + strlen(iface) +
strlen(failed_type_name);
char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
iface, failed_type_name);
THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
}
}
}
{- -------------------------------------------
(1.1) itableOffsetEntry::method_entry() で対応する itableMethodEntry を取得し,
itableMethodEntry::initialize() で itable 中の該当箇所にメソッドを登録する.
---------------------------------------- -}
// ime may have moved during GC so recalculate address
itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target_h());
}
{- -------------------------------------------
(1.1) ループの次の周へ進む
---------------------------------------- -}
// Progress to next entry
ime_num++;
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.