// Condensed information from constant pool to use to resolve the method or field. // resolved_klass = specified class (i.e., static receiver class) // current_klass = sending method holder (i.e., class containing the method // containing the call being resolved) // current_method = sending method (relevant for field resolution) classLinkInfo : public StackObj { Symbol* _name; // extracted from JVM_CONSTANT_NameAndType Symbol* _signature; KlassHandle _resolved_klass; // class that the constant pool entry points to KlassHandle _current_klass; // class that owns the constant pool methodHandle _current_method; // sending method bool _check_access; constantTag _tag;
LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, TRAPS) { // resolve klass Klass* result = pool->klass_ref_at(index, CHECK); _resolved_klass = KlassHandle(THREAD, result);
// Get name, signature, and static klass _name = pool->name_ref_at(index); _signature = pool->signature_ref_at(index); _tag = pool->tag_ref_at(index); _current_klass = KlassHandle(THREAD, pool->pool_holder()); _current_method = methodHandle();
// Coming from the constant pool always checks access _check_access = true; }
int ConstantPool::impl_klass_ref_index_at(int which, bool uncached) { guarantee(!ConstantPool::is_invokedynamic_index(which), "an invokedynamic instruction does not have a klass"); inti= which; if (!uncached && cache() != NULL) { // change byte-ordering and go via cache i = remap_instruction_operand_from_cache(which); } assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); jintref_index= *int_at_addr(i); return extract_low_short_from_int(ref_index); }
Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which, bool save_resolution_error, TRAPS) { assert(THREAD->is_Java_thread(), "must be a Java thread");
// A resolved constantPool entry will contain a Klass*, otherwise a Symbol*. // It is not safe to rely on the tag bit's here, since we don't have a lock, and // the entry and tag is not updated atomicly. CPSlotentry= this_cp->slot_at(which); if (entry.is_resolved()) { assert(entry.get_klass()->is_klass(), "must be"); // Already resolved - return entry. return entry.get_klass(); }
// This tag doesn't change back to unresolved class unless at a safepoint. if (this_cp->tag_at(which).is_unresolved_klass_in_error()) { // The original attempt to resolve this constant pool entry failed so find the // class of the original error and throw another error of the same class // (JVMS 5.4.3). // If there is a detail message, pass that detail message to the error. // The JVMS does not strictly require us to duplicate the same detail message, // or any internal exception fields such as cause or stacktrace. But since the // detail message is often a class name or other literal string, we will repeat it // if we can find it in the symbol table. throw_resolution_error(this_cp, which, CHECK_0); ShouldNotReachHere(); }
Handle mirror_handle; Symbol* name = entry.get_symbol(); Handle loader(THREAD, this_cp->pool_holder()->class_loader()); Handle protection_domain(THREAD, this_cp->pool_holder()->protection_domain()); Klass* kk = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD); KlassHandle k(THREAD, kk); if (!HAS_PENDING_EXCEPTION) { // preserve the resolved klass from unloading mirror_handle = Handle(THREAD, kk->java_mirror()); // Do access check for klasses verify_constant_pool_resolve(this_cp, k, THREAD); }
// Failed to resolve class. We must record the errors so that subsequent attempts // to resolve this constant pool entry fail with the same error (JVMS 5.4.3). if (HAS_PENDING_EXCEPTION) { if (save_resolution_error) { save_and_throw_exception(this_cp, which, constantTag(JVM_CONSTANT_UnresolvedClass), CHECK_NULL); // If CHECK_NULL above doesn't return the exception, that means that // some other thread has beaten us and has resolved the class. // To preserve old behavior, we return the resolved class. entry = this_cp->resolved_klass_at(which); assert(entry.is_resolved(), "must be resolved if exception was cleared"); assert(entry.get_klass()->is_klass(), "must be resolved to a klass"); return entry.get_klass(); } else { return NULL; // return the pending exception } }
// Make this class loader depend upon the class loader owning the class reference ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data(); this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
// logging for class+resolve. if (log_is_enabled(Debug, class, resolve)){ trace_class_resolution(this_cp, k); } this_cp->klass_at_put(which, k()); entry = this_cp->resolved_klass_at(which); assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point"); return entry.get_klass(); }