/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// private: called to verify that k is a static member of this nest. // We know that k is an instance class in the same package and hence the // same classloader. bool InstanceKlass::has_nest_member(JavaThread* current, InstanceKlass* k) const {
assert(!is_hidden(), "unexpected hidden class"); if (_nest_members == NULL || _nest_members == Universe::the_empty_short_array()) { if (log_is_enabled(Trace, class, nestmates)) {
ResourceMark rm(current);
log_trace(class, nestmates)("Checked nest membership of %s in non-nest-host class %s",
k->external_name(), this->external_name());
} returnfalse;
}
if (log_is_enabled(Trace, class, nestmates)) {
ResourceMark rm(current);
log_trace(class, nestmates)("Checking nest membership of %s in %s",
k->external_name(), this->external_name());
}
// Check for the named class in _nest_members. // We don't resolve, or load, any classes. for (int i = 0; i < _nest_members->length(); i++) { int cp_index = _nest_members->at(i);
Symbol* name = _constants->klass_name_at(cp_index); if (name == k->name()) {
log_trace(class, nestmates)("- named class found at nest_members[%d] => cp[%d]", i, cp_index); returntrue;
}
}
log_trace(class, nestmates)("- class is NOT a nest member!"); returnfalse;
}
// Called to verify that k is a permitted subclass of this class bool InstanceKlass::has_as_permitted_subclass(const InstanceKlass* k) const {
Thread* current = Thread::current();
assert(k != NULL, "sanity check");
assert(_permitted_subclasses != NULL && _permitted_subclasses != Universe::the_empty_short_array(), "unexpected empty _permitted_subclasses array");
if (log_is_enabled(Trace, class, sealed)) {
ResourceMark rm(current);
log_trace(class, sealed)("Checking for permitted subclass of %s in %s",
k->external_name(), this->external_name());
}
// Check that the class and its super are in the same module. if (k->module() != this->module()) {
ResourceMark rm(current);
log_trace(class, sealed)("Check failed for same module of permitted subclass %s and sealed class %s",
k->external_name(), this->external_name()); returnfalse;
}
if (!k->is_public() && !is_same_class_package(k)) {
ResourceMark rm(current);
log_trace(class, sealed)("Check failed, subclass %s not public and not in the same package as sealed class %s",
k->external_name(), this->external_name()); returnfalse;
}
for (int i = 0; i < _permitted_subclasses->length(); i++) { int cp_index = _permitted_subclasses->at(i);
Symbol* name = _constants->klass_name_at(cp_index); if (name == k->name()) {
log_trace(class, sealed)("- Found it at permitted_subclasses[%d] => cp[%d]", i, cp_index); returntrue;
}
}
log_trace(class, sealed)("- class is NOT a permitted subclass!"); returnfalse;
}
// Return nest-host class, resolving, validating and saving it if needed. // In cases where this is called from a thread that cannot do classloading // (such as a native JIT thread) then we simply return NULL, which in turn // causes the access check to return false. Such code will retry the access // from a more suitable environment later. Otherwise the _nest_host is always // set once this method returns. // Any errors from nest-host resolution must be preserved so they can be queried // from higher-level access checking code, and reported as part of access checking // exceptions. // VirtualMachineErrors are propagated with a NULL return. // Under any conditions where the _nest_host can be set to non-NULL the resulting // value of it and, if applicable, the nest host resolution/validation error, // are idempotent.
InstanceKlass* InstanceKlass::nest_host(TRAPS) {
InstanceKlass* nest_host_k = _nest_host; if (nest_host_k != NULL) { return nest_host_k;
}
ResourceMark rm(THREAD);
// need to resolve and save our nest-host class. if (_nest_host_index != 0) { // we have a real nest_host // Before trying to resolve check if we're in a suitable context bool can_resolve = THREAD->can_call_java(); if (!can_resolve && !_constants->tag_at(_nest_host_index).is_klass()) {
log_trace(class, nestmates)("Rejected resolution of nest-host of %s in unsuitable thread",
this->external_name()); return NULL; // sentinel to say "try again from a different context"
}
log_trace(class, nestmates)("Resolving nest-host of %s using cp entry for %s",
this->external_name(),
_constants->klass_name_at(_nest_host_index)->as_C_string());
Klass* k = _constants->klass_at(_nest_host_index, THREAD); if (HAS_PENDING_EXCEPTION) { if (PENDING_EXCEPTION->is_a(vmClasses::VirtualMachineError_klass())) { return NULL; // propagate VMEs
}
stringStream ss; char* target_host_class = _constants->klass_name_at(_nest_host_index)->as_C_string();
ss.print("Nest host resolution of %s with host %s failed: ",
this->external_name(), target_host_class);
java_lang_Throwable::print(PENDING_EXCEPTION, &ss); constchar* msg = ss.as_string(true/* on C-heap */);
constantPoolHandle cph(THREAD, constants());
SystemDictionary::add_nest_host_error(cph, _nest_host_index, msg);
CLEAR_PENDING_EXCEPTION;
log_trace(class, nestmates)("%s", msg);
} else { // A valid nest-host is an instance class in the current package that lists this // class as a nest member. If any of these conditions are not met the class is // its own nest-host. constchar* error = NULL;
// JVMS 5.4.4 indicates package check comes first if (is_same_class_package(k)) { // Now check actual membership. We can't be a member if our "host" is // not an instance class. if (k->is_instance_klass()) {
nest_host_k = InstanceKlass::cast(k); bool is_member = nest_host_k->has_nest_member(THREAD, this); if (is_member) {
_nest_host = nest_host_k; // save resolved nest-host value
log_trace(class, nestmates)("Resolved nest-host of %s to %s",
this->external_name(), k->external_name()); return nest_host_k;
} else {
error = "current type is not listed as a nest member";
}
} else {
error = "host is not an instance class";
}
} else {
error = "types are in different packages";
}
// something went wrong, so record what and log it
{
stringStream ss;
ss.print("Type %s (loader: %s) is not a nest member of type %s (loader: %s): %s",
this->external_name(),
this->class_loader_data()->loader_name_and_id(),
k->external_name(),
k->class_loader_data()->loader_name_and_id(),
error); constchar* msg = ss.as_string(true/* on C-heap */);
constantPoolHandle cph(THREAD, constants());
SystemDictionary::add_nest_host_error(cph, _nest_host_index, msg);
log_trace(class, nestmates)("%s", msg);
}
}
} else {
log_trace(class, nestmates)("Type %s is not part of a nest: setting nest-host to self",
this->external_name());
}
// Either not in an explicit nest, or else an error occurred, so // the nest-host is set to `this`. Any thread that sees this assignment // will also see any setting of nest_host_error(), if applicable. return (_nest_host = this);
}
// Dynamic nest member support: set this class's nest host to the given class. // This occurs as part of the class definition, as soon as the instanceKlass // has been created and doesn't require further resolution. The code: // lookup().defineHiddenClass(bytes_for_X, NESTMATE); // results in: // class_of_X.set_nest_host(lookup().lookupClass().getNestHost()) // If it has an explicit _nest_host_index or _nest_members, these will be ignored. // We also know the "host" is a valid nest-host in the same package so we can // assert some of those facts. void InstanceKlass::set_nest_host(InstanceKlass* host) {
assert(is_hidden(), "must be a hidden class");
assert(host != NULL, "NULL nest host specified");
assert(_nest_host == NULL, "current class has resolved nest-host");
assert(nest_host_error() == NULL, "unexpected nest host resolution error exists: %s",
nest_host_error());
assert((host->_nest_host == NULL && host->_nest_host_index == 0) ||
(host->_nest_host == host), "proposed host is not a valid nest-host"); // Can't assert this as package is not set yet: // assert(is_same_class_package(host), "proposed host is in wrong package");
if (log_is_enabled(Trace, class, nestmates)) {
ResourceMark rm; constchar* msg = ""; // a hidden class does not expect a statically defined nest-host if (_nest_host_index > 0) {
msg = "(the NestHost attribute in the current class is ignored)";
} elseif (_nest_members != NULL && _nest_members != Universe::the_empty_short_array()) {
msg = "(the NestMembers attribute in the current class is ignored)";
}
log_trace(class, nestmates)("Injected type %s into the nest of %s %s",
this->external_name(),
host->external_name(),
msg);
} // set dynamic nest host
_nest_host = host; // Record dependency to keep nest host from being unloaded before this class.
ClassLoaderData* this_key = class_loader_data();
assert(this_key != NULL, "sanity");
this_key->record_dependency(host);
}
// check if 'this' and k are nestmates (same nest_host), or k is our nest_host, // or we are k's nest_host - all of which is covered by comparing the two // resolved_nest_hosts. // Any exceptions (i.e. VMEs) are propagated. bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) {
assert(this != k, "this should be handled by higher-level code");
// Per JVMS 5.4.4 we first resolve and validate the current class, then // the target class k.
// Allocation if (parser.is_instance_ref_klass()) { // java.lang.ref.Reference
ik = new (loader_data, size, THREAD) InstanceRefKlass(parser);
} elseif (class_name == vmSymbols::java_lang_Class()) { // mirror - java.lang.Class
ik = new (loader_data, size, THREAD) InstanceMirrorKlass(parser);
} elseif (is_stack_chunk_class(class_name, loader_data)) { // stack chunk
ik = new (loader_data, size, THREAD) InstanceStackChunkKlass(parser);
} elseif (is_class_loader(class_name, parser)) { // class loader - java.lang.ClassLoader
ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(parser);
} else { // normal
ik = new (loader_data, size, THREAD) InstanceKlass(parser);
}
// Check for pending exception before adding to the loader data and incrementing // class count. Can get OOM here. if (HAS_PENDING_EXCEPTION) { return NULL;
}
return ik;
}
// copy method ordering from resource area to Metaspace void InstanceKlass::copy_method_ordering(const intArray* m, TRAPS) { if (m != NULL) { // allocate a new array and copy contents (memcpy?)
_method_ordering = MetadataFactory::new_array<int>(class_loader_data(), m->length(), CHECK); for (int i = 0; i < m->length(); i++) {
_method_ordering->at_put(i, m->at(i));
}
} else {
_method_ordering = Universe::the_empty_int_array();
}
}
// create a new array of vtable_indices for default methods
Array<int>* InstanceKlass::create_new_default_vtable_indices(int len, TRAPS) {
Array<int>* vtable_indices = MetadataFactory::new_array<int>(class_loader_data(), len, CHECK_NULL);
assert(default_vtable_indices() == NULL, "only create once");
set_default_vtable_indices(vtable_indices); return vtable_indices;
}
void InstanceKlass::deallocate_methods(ClassLoaderData* loader_data,
Array<Method*>* methods) { if (methods != NULL && methods != Universe::the_empty_method_array() &&
!methods->is_shared()) { for (int i = 0; i < methods->length(); i++) {
Method* method = methods->at(i); if (method == NULL) continue; // maybe null if error processing // Only want to delete methods that are not executing for RedefineClasses. // The previous version will point to them so they're not totally dangling
assert (!method->on_stack(), "shouldn't be called with methods on stack");
MetadataFactory::free_metadata(loader_data, method);
}
MetadataFactory::free_array<Method*>(loader_data, methods);
}
}
void InstanceKlass::deallocate_interfaces(ClassLoaderData* loader_data, const Klass* super_klass,
Array<InstanceKlass*>* local_interfaces,
Array<InstanceKlass*>* transitive_interfaces) { // Only deallocate transitive interfaces if not empty, same as super class // or same as local interfaces. See code in parseClassFile.
Array<InstanceKlass*>* ti = transitive_interfaces; if (ti != Universe::the_empty_instance_klass_array() && ti != local_interfaces) { // check that the interfaces don't come from super class
Array<InstanceKlass*>* sti = (super_klass == NULL) ? NULL :
InstanceKlass::cast(super_klass)->transitive_interfaces(); if (ti != sti && ti != NULL && !ti->is_shared()) {
MetadataFactory::free_array<InstanceKlass*>(loader_data, ti);
}
}
// local interfaces can be empty if (local_interfaces != Universe::the_empty_instance_klass_array() &&
local_interfaces != NULL && !local_interfaces->is_shared()) {
MetadataFactory::free_array<InstanceKlass*>(loader_data, local_interfaces);
}
}
void InstanceKlass::deallocate_record_components(ClassLoaderData* loader_data,
Array<RecordComponent*>* record_components) { if (record_components != NULL && !record_components->is_shared()) { for (int i = 0; i < record_components->length(); i++) {
RecordComponent* record_component = record_components->at(i);
MetadataFactory::free_metadata(loader_data, record_component);
}
MetadataFactory::free_array<RecordComponent*>(loader_data, record_components);
}
}
// This function deallocates the metadata and C heap pointers that the // InstanceKlass points to. void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { // Orphan the mirror first, CMS thinks it's still live. if (java_mirror() != NULL) {
java_lang_Class::set_klass(java_mirror(), NULL);
}
// Also remove mirror from handles
loader_data->remove_handle(_java_mirror);
// Need to take this class off the class loader data list.
loader_data->remove_class(this);
// The array_klass for this class is created later, after error handling. // For class redefinition, we keep the original class so this scratch class // doesn't have an array class. Either way, assert that there is nothing // to deallocate.
assert(array_klasses() == NULL, "array classes shouldn't be created for this class yet");
// Release C heap allocated data that this points to, which includes // reference counting symbol names. // Can't release the constant pool or MethodData C heap data here because the constant // pool can be deallocated separately from the InstanceKlass for default methods and // redefine classes. MethodData can also be released separately.
release_C_heap_structures(/* release_sub_metadata */ false);
// default methods can be empty if (default_methods() != NULL &&
default_methods() != Universe::the_empty_method_array() &&
!default_methods()->is_shared()) {
MetadataFactory::free_array<Method*>(loader_data, default_methods());
} // Do NOT deallocate the default methods, they are owned by superinterfaces.
set_default_methods(NULL);
// default methods vtable indices can be empty if (default_vtable_indices() != NULL &&
!default_vtable_indices()->is_shared()) {
MetadataFactory::free_array<int>(loader_data, default_vtable_indices());
}
set_default_vtable_indices(NULL);
// This array is in Klass, but remove it with the InstanceKlass since // this place would be the only caller and it can share memory with transitive // interfaces. if (secondary_supers() != NULL &&
secondary_supers() != Universe::the_empty_klass_array() && // see comments in compute_secondary_supers about the following cast
(address)(secondary_supers()) != (address)(transitive_interfaces()) &&
!secondary_supers()->is_shared()) {
MetadataFactory::free_array<Klass*>(loader_data, secondary_supers());
}
set_secondary_supers(NULL);
// If a method from a redefined class is using this constant pool, don't // delete it, yet. The new class's previous version will point to this. if (constants() != NULL) {
assert (!constants()->on_stack(), "shouldn't be called if anything is onstack"); if (!constants()->is_shared()) {
MetadataFactory::free_metadata(loader_data, constants());
} // Delete any cached resolution errors for the constant pool
SystemDictionary::delete_resolution_error(constants());
// We should deallocate the Annotations instance if it's not in shared spaces. if (annotations() != NULL && !annotations()->is_shared()) {
MetadataFactory::free_metadata(loader_data, annotations());
}
set_annotations(NULL);
// JVMTI spec thinks there are signers and protection domain in the // instanceKlass. These accessors pretend these fields are there. // The hprof specification also thinks these fields are in InstanceKlass.
oop InstanceKlass::protection_domain() const { // return the protection_domain from the mirror return java_lang_Class::protection_domain(java_mirror());
}
objArrayOop InstanceKlass::signers() const { // return the signers from the mirror return java_lang_Class::signers(java_mirror());
}
// See "The Virtual Machine Specification" section 2.16.5 for a detailed explanation of the class initialization // process. The step comments refers to the procedure described in that section. // Note: implementation moved to static method to expose the this pointer. void InstanceKlass::initialize(TRAPS) { if (this->should_be_initialized()) {
initialize_impl(CHECK); // Note: at this point the class may be initialized // OR it may be in the state of being initialized // in case of recursive initialization!
} else {
assert(is_initialized(), "sanity check");
}
}
// Another thread is linking this class, wait. while (is_being_linked() && !is_init_thread(current)) {
ml.wait();
}
// This thread is recursively linking this class, continue if (is_being_linked() && is_init_thread(current)) { return;
}
// If this class wasn't linked already, set state to being_linked if (!is_linked()) {
set_init_state(being_linked);
set_init_thread(current);
}
}
// Called to verify that a class can link during initialization, without // throwing a VerifyError. bool InstanceKlass::link_class_or_fail(TRAPS) {
assert(is_loaded(), "must be loaded"); if (!is_linked()) {
link_class_impl(CHECK_false);
} return is_linked();
}
bool InstanceKlass::link_class_impl(TRAPS) { if (DumpSharedSpaces && SystemDictionaryShared::has_class_failed_verification(this)) { // This is for CDS dumping phase only -- we use the in_error_state to indicate that // the class has failed verification. Throwing the NoClassDefFoundError here is just // a convenient way to stop repeat attempts to verify the same (bad) class. // // Note that the NoClassDefFoundError is not part of the JLS, and should not be thrown // if we are executing Java code. This is not a problem for CDS dumping phase since // it doesn't execute any Java code.
ResourceMark rm(THREAD);
Exceptions::fthrow(THREAD_AND_LOCATION,
vmSymbols::java_lang_NoClassDefFoundError(), "Class %s, or one of its supertypes, failed class initialization",
external_name()); returnfalse;
} // return if already verified if (is_linked()) { returntrue;
}
// Timing // timer handles recursion
JavaThread* jt = THREAD;
// link super class before linking this class
Klass* super_klass = super(); if (super_klass != NULL) { if (super_klass->is_interface()) { // check if super class is an interface
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(), "class %s has interface %s as super class",
external_name(),
super_klass->external_name()
); returnfalse;
}
// link all interfaces implemented by this class before linking this class
Array<InstanceKlass*>* interfaces = local_interfaces(); int num_interfaces = interfaces->length(); for (int index = 0; index < num_interfaces; index++) {
InstanceKlass* interk = interfaces->at(index);
interk->link_class_impl(CHECK_false);
}
// in case the class is linked in the process of linking its superclasses if (is_linked()) { returntrue;
}
// trace only the link time for this klass that includes // the verification time
PerfClassTraceTime vmtimer(ClassLoader::perf_class_link_time(),
ClassLoader::perf_class_link_selftime(),
ClassLoader::perf_classes_linked(),
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_LINK);
// rewritten will have been set if loader constraint error found // on an earlier link attempt // don't verify or rewrite if already rewritten //
if (!is_linked()) { if (!is_rewritten()) { if (is_shared()) {
assert(!verified_at_dump_time(), "must be");
}
{ bool verify_ok = verify_code(THREAD); if (!verify_ok) { returnfalse;
}
}
// Just in case a side-effect of verify linked this class already // (which can sometimes happen since the verifier loads classes // using custom class loaders, which are free to initialize things) if (is_linked()) { returntrue;
}
// relocate jsrs and link methods after they are all rewritten
link_methods(CHECK_false);
// Initialize the vtable and interface table after // methods have been rewritten since rewrite may // fabricate new Method*s. // also does loader constraint checking // // initialize_vtable and initialize_itable need to be rerun // for a shared class if // 1) the class is loaded by custom class loader or // 2) the class is loaded by built-in class loader but failed to add archived loader constraints or // 3) the class was not verified during dump time bool need_init_table = true; if (is_shared() && verified_at_dump_time() &&
SystemDictionaryShared::check_linking_constraints(THREAD, this)) {
need_init_table = false;
} if (need_init_table) {
vtable().initialize_vtable_and_check_constraints(CHECK_false);
itable().initialize_itable_and_check_constraints(CHECK_false);
} #ifdef ASSERT
vtable().verify(tty, true); // In case itable verification is ever added. // itable().verify(tty, true); #endif
set_initialization_state_and_notify(linked, THREAD); if (JvmtiExport::should_post_class_prepare()) {
JvmtiExport::post_class_prepare(THREAD, this);
}
}
} returntrue;
}
// Rewrite the byte codes of all of the methods of a class. // The rewriter must be called exactly once. Rewriting must happen after // verification but before the first method of the class is executed. void InstanceKlass::rewrite_class(TRAPS) {
assert(is_loaded(), "must be loaded"); if (is_rewritten()) {
assert(is_shared(), "rewriting an unshared class?"); return;
}
Rewriter::rewrite(this, CHECK);
set_rewritten();
}
// Now relocate and link method entry points after class is rewritten. // This is outside is_rewritten flag. In case of an exception, it can be // executed more than once. void InstanceKlass::link_methods(TRAPS) { int len = methods()->length(); for (int i = len-1; i >= 0; i--) {
methodHandle m(THREAD, methods()->at(i));
// Set up method entry points for compiler and interpreter .
m->link_method(m, CHECK);
}
}
// Eagerly initialize superinterfaces that declare default methods (concrete instance: any access) void InstanceKlass::initialize_super_interfaces(TRAPS) {
assert (has_nonstatic_concrete_methods(), "caller should have checked this"); for (int i = 0; i < local_interfaces()->length(); ++i) {
InstanceKlass* ik = local_interfaces()->at(i);
// Initialization is depth first search ie. we start with top of the inheritance tree // has_nonstatic_concrete_methods drives searching superinterfaces since it // means has_nonstatic_concrete_methods in its superinterface hierarchy if (ik->has_nonstatic_concrete_methods()) {
ik->initialize_super_interfaces(CHECK);
}
// Only initialize() interfaces that "declare" concrete methods. if (ik->should_be_initialized() && ik->declares_nonstatic_concrete_methods()) {
ik->initialize(CHECK);
}
}
}
void InstanceKlass::add_initialization_error(JavaThread* current, Handle exception) { // Create the same exception with a message indicating the thread name, // and the StackTraceElements. // If the initialization error is OOM, this might not work, but if GC kicks in // this would be still be helpful.
JavaThread* THREAD = current;
Handle cause = java_lang_Throwable::get_cause_with_stack_trace(exception, THREAD); if (HAS_PENDING_EXCEPTION || cause.is_null()) {
CLEAR_PENDING_EXCEPTION; return;
}
MutexLocker ml(THREAD, ClassInitError_lock);
OopHandle elem = OopHandle(Universe::vm_global(), cause()); bool created = false;
_initialization_error_table.put_if_absent(this, elem, &created);
assert(created, "Initialization is single threaded");
ResourceMark rm(THREAD);
log_trace(class, init)("Initialization error added for class %s", external_name());
}
// Make sure klass is linked (verified) before initialization // A class could already be verified, since it has been reflected upon.
link_class(CHECK);
DTRACE_CLASSINIT_PROBE(required, -1);
bool wait = false; bool throw_error = false;
JavaThread* jt = THREAD;
// refer to the JVM book page 47 for description of steps // Step 1
{
MonitorLocker ml(THREAD, _init_monitor);
stringStream ss;
ss.print("Could not initialize class %s", external_name()); if (cause.is_null()) {
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), ss.as_string());
} else {
THROW_MSG_CAUSE(vmSymbols::java_lang_NoClassDefFoundError(),
ss.as_string(), cause);
}
}
// Step 7 // Next, if C is a class rather than an interface, initialize it's super class and super // interfaces. if (!is_interface()) {
Klass* super_klass = super(); if (super_klass != NULL && super_klass->should_be_initialized()) {
super_klass->initialize(THREAD);
} // If C implements any interface that declares a non-static, concrete method, // the initialization of C triggers initialization of its super interfaces. // Only need to recurse if has_nonstatic_concrete_methods which includes declaring and // having a superinterface that declares, non-static, concrete methods if (!HAS_PENDING_EXCEPTION && has_nonstatic_concrete_methods()) {
initialize_super_interfaces(THREAD);
}
// If any exceptions, complete abruptly, throwing the same exception as above. if (HAS_PENDING_EXCEPTION) {
Handle e(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
{
EXCEPTION_MARK;
add_initialization_error(THREAD, e); // Locks object, set state, and notify all waiting threads
set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION;
}
DTRACE_CLASSINIT_PROBE_WAIT(super__failed, -1, wait);
THROW_OOP(e());
}
}
// Step 8
{
DTRACE_CLASSINIT_PROBE_WAIT(clinit, -1, wait); if (class_initializer() != NULL) { // Timer includes any side effects of class initialization (resolution, // etc), but not recursive entry into call_class_initializer().
PerfClassTraceTime timer(ClassLoader::perf_class_init_time(),
ClassLoader::perf_class_init_selftime(),
ClassLoader::perf_classes_inited(),
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_CLINIT);
call_class_initializer(THREAD);
} else { // The elapsed time is so small it's not worth counting. if (UsePerfData) {
ClassLoader::perf_classes_inited()->inc();
}
call_class_initializer(THREAD);
}
}
// Step 9 if (!HAS_PENDING_EXCEPTION) {
set_initialization_state_and_notify(fully_initialized, THREAD);
debug_only(vtable().verify(tty, true);)
} else { // Step 10 and 11
Handle e(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION; // JVMTI has already reported the pending exception // JVMTI internal flag reset is needed in order to report ExceptionInInitializerError
JvmtiExport::clear_detected_exception(jt);
{
EXCEPTION_MARK;
add_initialization_error(THREAD, e);
set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below // JVMTI has already reported the pending exception // JVMTI internal flag reset is needed in order to report ExceptionInInitializerError
JvmtiExport::clear_detected_exception(jt);
}
DTRACE_CLASSINIT_PROBE_WAIT(error, -1, wait); if (e->is_a(vmClasses::Error_klass())) {
THROW_OOP(e());
} else {
JavaCallArguments args(e);
THROW_ARG(vmSymbols::java_lang_ExceptionInInitializerError(),
vmSymbols::throwable_void_signature(),
&args);
}
}
DTRACE_CLASSINIT_PROBE_WAIT(end, -1, wait);
}
// Now flush all code that assume the class is not linked. // Set state under the Compile_lock also. if (state == linked && UseVtableBasedCHA && Universe::is_fully_initialized()) {
MutexLocker ml(current, Compile_lock);
set_init_thread(NULL); // reset _init_thread before changing _init_state
set_init_state(state);
int InstanceKlass::nof_implementors() const {
InstanceKlass* ik = implementor(); if (ik == NULL) { return 0;
} elseif (ik != this) { return 1;
} else { return 2;
}
}
// The embedded _implementor field can only record one implementor. // When there are more than one implementors, the _implementor field // is set to the interface Klass* itself. Following are the possible // values for the _implementor field: // NULL - no implementor // implementor Klass* - one implementor // self - more than one implementor // // The _implementor field only exists for interfaces. void InstanceKlass::add_implementor(InstanceKlass* ik) { if (Universe::is_fully_initialized()) {
assert_lock_strong(Compile_lock);
}
assert(is_interface(), "not interface"); // Filter out my subinterfaces. // (Note: Interfaces are never on the subklass list.) if (ik->is_interface()) return;
// Filter out subclasses whose supers already implement me. // (Note: CHA must walk subclasses of direct implementors // in order to locate indirect implementors.)
InstanceKlass* super_ik = ik->java_super(); if (super_ik != NULL && super_ik->implements_interface(this)) // We only need to check one immediate superclass, since the // implements_interface query looks at transitive_interfaces. // Any supers of the super have the same (or fewer) transitive_interfaces. return;
InstanceKlass* iklass = implementor(); if (iklass == NULL) {
set_implementor(ik);
} elseif (iklass != this && iklass != ik) { // There is already an implementor. Use itself as an indicator of // more than one implementors.
set_implementor(this);
}
// The implementor also implements the transitive_interfaces for (int index = 0; index < local_interfaces()->length(); index++) {
local_interfaces()->at(index)->add_implementor(ik);
}
}
void InstanceKlass::init_implementor() { if (is_interface()) {
set_implementor(NULL);
}
}
void InstanceKlass::process_interfaces() { // link this class into the implementors list of every interface it implements for (int i = local_interfaces()->length() - 1; i >= 0; i--) {
assert(local_interfaces()->at(i)->is_klass(), "must be a klass");
InstanceKlass* interf = local_interfaces()->at(i);
assert(interf->is_interface(), "expected interface");
interf->add_implementor(this);
}
}
GrowableArray<Klass*>* InstanceKlass::compute_secondary_supers(int num_extra_slots,
Array<InstanceKlass*>* transitive_interfaces) { // The secondaries are the implemented interfaces.
Array<InstanceKlass*>* interfaces = transitive_interfaces; int num_secondaries = num_extra_slots + interfaces->length(); if (num_secondaries == 0) { // Must share this for correct bootstrapping!
set_secondary_supers(Universe::the_empty_klass_array()); return NULL;
} elseif (num_extra_slots == 0) { // The secondary super list is exactly the same as the transitive interfaces, so // let's use it instead of making a copy. // Redefine classes has to be careful not to delete this! // We need the cast because Array<Klass*> is NOT a supertype of Array<InstanceKlass*>, // (but it's safe to do here because we won't write into _secondary_supers from this point on).
set_secondary_supers((Array<Klass*>*)(address)interfaces); return NULL;
} else { // Copy transitive interfaces to a temporary growable array to be constructed // into the secondary super list with extra slots.
GrowableArray<Klass*>* secondaries = new GrowableArray<Klass*>(interfaces->length()); for (int i = 0; i < interfaces->length(); i++) {
secondaries->push(interfaces->at(i));
} return secondaries;
}
}
bool InstanceKlass::implements_interface(Klass* k) const { if (this == k) returntrue;
assert(k->is_interface(), "should be an interface class"); for (int i = 0; i < transitive_interfaces()->length(); i++) { if (transitive_interfaces()->at(i) == k) { returntrue;
}
} returnfalse;
}
bool InstanceKlass::is_same_or_direct_interface(Klass *k) const { // Verify direct super interface if (this == k) returntrue;
assert(k->is_interface(), "should be an interface class"); for (int i = 0; i < local_interfaces()->length(); i++) { if (local_interfaces()->at(i) == k) { returntrue;
}
} returnfalse;
}
objArrayOop InstanceKlass::allocate_objArray(int n, int length, TRAPS) {
check_array_allocation_length(length, arrayOopDesc::max_array_length(T_OBJECT), CHECK_NULL);
size_t size = objArrayOopDesc::object_size(length);
Klass* ak = array_klass(n, CHECK_NULL);
objArrayOop o = (objArrayOop)Universe::heap()->array_allocate(ak, size, length, /* do_zero */ true, CHECK_NULL); return o;
}
instanceOop InstanceKlass::register_finalizer(instanceOop i, TRAPS) { if (TraceFinalizerRegistration) {
tty->print("Registered ");
i->print_value_on(tty);
tty->print_cr(" (" PTR_FORMAT ") as finalizable", p2i(i));
}
instanceHandle h_i(THREAD, i); // Pass the handle as argument, JavaCalls::call expects oop as jobjects
JavaValue result(T_VOID);
JavaCallArguments args(h_i);
methodHandle mh(THREAD, Universe::finalizer_register_method());
JavaCalls::call(&result, mh, &args, CHECK_NULL);
MANAGEMENT_ONLY(FinalizerService::on_register(h_i(), THREAD);) return h_i();
}
instanceOop InstanceKlass::allocate_instance(TRAPS) { bool has_finalizer_flag = has_finalizer(); // Query before possible GC
size_t size = size_helper(); // Query before forming handle.
instanceOop i;
i = (instanceOop)Universe::heap()->obj_allocate(this, size, CHECK_NULL); if (has_finalizer_flag && !RegisterFinalizersAtInit) {
i = register_finalizer(i, CHECK_NULL);
} return i;
}
Klass* InstanceKlass::array_klass(int n, TRAPS) { // Need load-acquire for lock-free read if (array_klasses_acquire() == NULL) {
ResourceMark rm(THREAD);
JavaThread *jt = THREAD;
{ // Atomic creation of array_klasses
MutexLocker ma(THREAD, MultiArray_lock);
// Check if update has already taken place if (array_klasses() == NULL) {
ObjArrayKlass* k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), 1, this, CHECK_NULL); // use 'release' to pair with lock-free load
release_set_array_klasses(k);
}
}
} // array_klasses() will always be set at this point
ObjArrayKlass* oak = array_klasses(); return oak->array_klass(n, THREAD);
}
Klass* InstanceKlass::array_klass_or_null(int n) { // Need load-acquire for lock-free read
ObjArrayKlass* oak = array_klasses_acquire(); if (oak == NULL) { return NULL;
} else { return oak->array_klass_or_null(n);
}
}
void InstanceKlass::call_class_initializer(TRAPS) { if (ReplayCompiles &&
(ReplaySuppressInitializers == 1 ||
(ReplaySuppressInitializers >= 2 && class_loader() != NULL))) { // Hide the existence of the initializer for the purpose of replaying the compile return;
}
#if INCLUDE_CDS // This is needed to ensure the consistency of the archived heap objects. if (has_archived_enum_objs()) {
assert(is_shared(), "must be"); bool initialized = HeapShared::initialize_enum_klass(this, CHECK); if (initialized) { return;
}
} #endif
void InstanceKlass::mask_for(const methodHandle& method, int bci,
InterpreterOopMap* entry_for) { // Lazily create the _oop_map_cache at first request // Lock-free access requires load_acquire.
OopMapCache* oop_map_cache = Atomic::load_acquire(&_oop_map_cache); if (oop_map_cache == NULL) {
MutexLocker x(OopMapCacheAlloc_lock); // Check if _oop_map_cache was allocated while we were waiting for this lock if ((oop_map_cache = _oop_map_cache) == NULL) {
oop_map_cache = new OopMapCache(); // Ensure _oop_map_cache is stable, since it is examined without a lock
Atomic::release_store(&_oop_map_cache, oop_map_cache);
}
} // _oop_map_cache is constant after init; lookup below does its own locking.
oop_map_cache->lookup(method, bci, entry_for);
}
Klass* InstanceKlass::find_interface_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { constint n = local_interfaces()->length(); for (int i = 0; i < n; i++) {
Klass* intf1 = local_interfaces()->at(i);
assert(intf1->is_interface(), "just checking type"); // search for field in current interface if (InstanceKlass::cast(intf1)->find_local_field(name, sig, fd)) {
assert(fd->is_static(), "interface field must be static"); return intf1;
} // search for field in direct superinterfaces
Klass* intf2 = InstanceKlass::cast(intf1)->find_interface_field(name, sig, fd); if (intf2 != NULL) return intf2;
} // otherwise field lookup fails return NULL;
}
Klass* InstanceKlass::find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { // search order according to newest JVM spec (5.4.3.2, p.167). // 1) search for field in current klass if (find_local_field(name, sig, fd)) { returnconst_cast<InstanceKlass*>(this);
} // 2) search for field recursively in direct superinterfaces
{ Klass* intf = find_interface_field(name, sig, fd); if (intf != NULL) return intf;
} // 3) apply field lookup recursively if superclass exists
{ Klass* supr = super(); if (supr != NULL) return InstanceKlass::cast(supr)->find_field(name, sig, fd);
} // 4) otherwise field lookup fails return NULL;
}
Klass* InstanceKlass::find_field(Symbol* name, Symbol* sig, bool is_static, fieldDescriptor* fd) const { // search order according to newest JVM spec (5.4.3.2, p.167). // 1) search for field in current klass if (find_local_field(name, sig, fd)) { if (fd->is_static() == is_static) returnconst_cast<InstanceKlass*>(this);
} // 2) search for field recursively in direct superinterfaces if (is_static) {
Klass* intf = find_interface_field(name, sig, fd); if (intf != NULL) return intf;
} // 3) apply field lookup recursively if superclass exists
{ Klass* supr = super(); if (supr != NULL) return InstanceKlass::cast(supr)->find_field(name, sig, is_static, fd);
} // 4) otherwise field lookup fails return NULL;
}
bool InstanceKlass::find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const {
Klass* klass = const_cast<InstanceKlass*>(this); while (klass != NULL) { if (InstanceKlass::cast(klass)->find_local_field_from_offset(offset, is_static, fd)) { returntrue;
}
klass = klass->super();
} returnfalse;
}
void InstanceKlass::methods_do(void f(Method* method)) { // Methods aren't stable until they are loaded. This can be read outside // a lock through the ClassLoaderData for profiling // Redefined scratch classes are on the list and need to be cleaned if (!is_loaded() && !is_scratch_class()) { return;
}
int len = methods()->length(); for (int index = 0; index < len; index++) {
Method* m = methods()->at(index);
assert(m->is_method(), "must be method");
f(m);
}
}
NOINLINE int linear_search(const Array<Method*>* methods, const Symbol* name) { int len = methods->length(); int l = 0; int h = len - 1; while (l <= h) {
Method* m = methods->at(l); if (m->name() == name) { return l;
}
l++;
} return -1;
}
inlineint InstanceKlass::quick_search(const Array<Method*>* methods, const Symbol* name) { if (_disable_method_binary_search) {
assert(DynamicDumpSharedSpaces, "must be"); // At the final stage of dynamic dumping, the methods array may not be sorted // by ascending addresses of their names, so we can't use binary search anymore. // However, methods with the same name are still laid out consecutively inside the // methods array, so let's look for the first one that matches. return linear_search(methods, name);
}
int len = methods->length(); int l = 0; int h = len - 1;
// methods are sorted by ascending addresses of their names, so do binary search while (l <= h) { int mid = (l + h) >> 1;
Method* m = methods->at(mid);
assert(m->is_method(), "must be method"); int res = m->name()->fast_compare(name); if (res == 0) { return mid;
} elseif (res < 0) {
l = mid + 1;
} else {
h = mid - 1;
}
} return -1;
}
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(const Symbol* name, const Symbol* signature) const { return find_method_impl(name, signature,
OverpassLookupMode::find,
StaticLookupMode::find,
PrivateLookupMode::find);
}
// find_instance_method looks up the name/signature in the local methods array // and skips over static methods
Method* InstanceKlass::find_instance_method(const Array<Method*>* methods, const Symbol* name, const Symbol* signature,
PrivateLookupMode private_mode) {
Method* const meth = InstanceKlass::find_method_impl(methods,
name,
signature,
OverpassLookupMode::find,
StaticLookupMode::skip,
private_mode);
assert(((meth == NULL) || !meth->is_static()), "find_instance_method should have skipped statics"); return meth;
}
// find_instance_method looks up the name/signature in the local methods array // and skips over static methods
Method* InstanceKlass::find_instance_method(const Symbol* name, const Symbol* signature,
PrivateLookupMode private_mode) const { return InstanceKlass::find_instance_method(methods(), name, signature, private_mode);
}
// Find looks up the name/signature in the local methods array // and filters on the overpass, static and private flags // This returns the first one found // note that the local methods array can have up to one overpass, one static // and one instance (private or not) with the same name/signature
Method* InstanceKlass::find_local_method(const Symbol* name, const Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode) const { return InstanceKlass::find_method_impl(methods(),
name,
signature,
overpass_mode,
static_mode,
private_mode);
}
// Find looks up the name/signature in the local methods array // and filters on the overpass, static and private flags // This returns the first one found // note that the local methods array can have up to one overpass, one static // and one instance (private or not) with the same name/signature
Method* InstanceKlass::find_local_method(const Array<Method*>* methods, const Symbol* name, const Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode) { return InstanceKlass::find_method_impl(methods,
name,
signature,
overpass_mode,
static_mode,
private_mode);
}
// Used directly for default_methods to find the index into the // default_vtable_indices, and indirectly by find_method // find_method_index looks in the local methods array to return the index // of the matching name/signature. If, overpass methods are being ignored, // the search continues to find a potential non-overpass match. This capability // is important during method resolution to prefer a static method, for example, // over an overpass method. // There is the possibility in any _method's array to have the same name/signature // for a static method, an overpass method and a local instance method // To correctly catch a given method, the search criteria may need // to explicitly skip the other two. For local instance methods, it // is often necessary to skip private methods int InstanceKlass::find_method_index(const Array<Method*>* methods, const Symbol* name, const Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode) { constbool skipping_overpass = (overpass_mode == OverpassLookupMode::skip); constbool skipping_static = (static_mode == StaticLookupMode::skip); constbool skipping_private = (private_mode == PrivateLookupMode::skip); constint hit = quick_search(methods, name); if (hit != -1) { const Method* const m = methods->at(hit);
// Do linear search to find matching signature. First, quick check // for common case, ignoring overpasses if requested. if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) { return hit;
}
// search downwards through overloaded methods int i; for (i = hit - 1; i >= 0; --i) { const Method* const m = methods->at(i);
assert(m->is_method(), "must be method"); if (m->name() != name) { break;
} if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) { return i;
}
} // search upwards for (i = hit + 1; i < methods->length(); ++i) { const Method* const m = methods->at(i);
assert(m->is_method(), "must be method"); if (m->name() != name) { break;
} if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) { return i;
}
} // not found #ifdef ASSERT constint index = (skipping_overpass || skipping_static || skipping_private) ? -1 :
linear_search(methods, name, signature);
assert(-1 == index, "binary search should have found entry %d", index); #endif
} return -1;
}
int InstanceKlass::find_method_by_name(const Array<Method*>* methods, const Symbol* name, int* end_ptr) {
assert(end_ptr != NULL, "just checking"); int start = quick_search(methods, name); int end = start + 1; if (start != -1) { while (start - 1 >= 0 && (methods->at(start - 1))->name() == name) --start; while (end < methods->length() && (methods->at(end))->name() == name) ++end;
*end_ptr = end; return start;
} return -1;
}
// uncached_lookup_method searches both the local class methods array and all // superclasses methods arrays, skipping any overpass methods in superclasses, // and possibly skipping private methods.
Method* InstanceKlass::uncached_lookup_method(const Symbol* name, const Symbol* signature,
OverpassLookupMode overpass_mode,
PrivateLookupMode private_mode) const {
OverpassLookupMode overpass_local_mode = overpass_mode; const Klass* klass = this; while (klass != NULL) {
Method* const method = InstanceKlass::cast(klass)->find_method_impl(name,
signature,
overpass_local_mode,
StaticLookupMode::find,
private_mode); if (method != NULL) { return method;
}
klass = klass->super();
overpass_local_mode = OverpassLookupMode::skip; // Always ignore overpass methods in superclasses
} return NULL;
}
#ifdef ASSERT // search through class hierarchy and return true if this class or // one of the superclasses was redefined bool InstanceKlass::has_redefined_this_or_super() const { const Klass* klass = this; while (klass != NULL) { if (InstanceKlass::cast(klass)->has_been_redefined()) { returntrue;
}
klass = klass->super();
} returnfalse;
} #endif
// lookup a method in the default methods list then in all transitive interfaces // Do NOT return private or static methods
Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name,
Symbol* signature) const {
Method* m = NULL; if (default_methods() != NULL) {
m = find_method(default_methods(), name, signature);
} // Look up interfaces if (m == NULL) {
m = lookup_method_in_all_interfaces(name, signature, DefaultsLookupMode::find);
} return m;
}
// lookup a method in all the interfaces that this class implements // Do NOT return private or static methods, new in JDK8 which are not externally visible // They should only be found in the initial InterfaceMethodRef
Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name,
Symbol* signature,
DefaultsLookupMode defaults_mode) const {
Array<InstanceKlass*>* all_ifs = transitive_interfaces(); int num_ifs = all_ifs->length();
InstanceKlass *ik = NULL; for (int i = 0; i < num_ifs; i++) {
ik = all_ifs->at(i);
Method* m = ik->lookup_method(name, signature); if (m != NULL && m->is_public() && !m->is_static() &&
((defaults_mode != DefaultsLookupMode::skip) || !m->is_default_method())) { return m;
}
} return NULL;
}
void InstanceKlass::set_enclosing_method_indices(u2 class_index,
u2 method_index) {
Array<jushort>* inner_class_list = inner_classes();
assert (inner_class_list != NULL, "_inner_classes list is not set up"); int length = inner_class_list->length(); if (length % inner_class_next_offset == enclosing_method_attribute_size) { int index = length - enclosing_method_attribute_size;
inner_class_list->at_put(
index + enclosing_method_class_index_offset, class_index);
inner_class_list->at_put(
index + enclosing_method_method_index_offset, method_index);
}
}
// Lookup or create a jmethodID. // This code is called by the VMThread and JavaThreads so the // locking has to be done very carefully to avoid deadlocks // and/or other cache consistency problems. //
jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) {
size_t idnum = (size_t)method_h->method_idnum();
jmethodID* jmeths = methods_jmethod_ids_acquire();
size_t length = 0;
jmethodID id = NULL;
// We use a double-check locking idiom here because this cache is // performance sensitive. In the normal system, this cache only // transitions from NULL to non-NULL which is safe because we use // release_set_methods_jmethod_ids() to advertise the new cache. // A partially constructed cache should never be seen by a racing // thread. We also use release_store() to save a new jmethodID // in the cache so a partially constructed jmethodID should never be // seen either. Cache reads of existing jmethodIDs proceed without a // lock, but cache writes of a new jmethodID requires uniqueness and // creation of the cache itself requires no leaks so a lock is // generally acquired in those two cases. // // If the RedefineClasses() API has been used, then this cache can // grow and we'll have transitions from non-NULL to bigger non-NULL. // Cache creation requires no leaks and we require safety between all // cache accesses and freeing of the old cache so a lock is generally // acquired when the RedefineClasses() API has been used.
if (jmeths != NULL) { // the cache already exists if (!idnum_can_increment()) { // the cache can't grow so we can just get the current values
get_jmethod_id_length_value(jmeths, idnum, &length, &id);
} else {
MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag);
get_jmethod_id_length_value(jmeths, idnum, &length, &id);
}
} // implied else: // we need to allocate a cache so default length and id values are good
if (jmeths == NULL || // no cache yet
length <= idnum || // cache is too short
id == NULL) { // cache doesn't contain entry
// This function can be called by the VMThread or GC worker threads so we // have to do all things that might block on a safepoint before grabbing the lock. // Otherwise, we can deadlock with the VMThread or have a cache // consistency issue. These vars keep track of what we might have // to free after the lock is dropped.
jmethodID to_dealloc_id = NULL;
jmethodID* to_dealloc_jmeths = NULL;
// may not allocate new_jmeths or use it if we allocate it
jmethodID* new_jmeths = NULL; if (length <= idnum) { // allocate a new cache that might be used
size_t size = MAX2(idnum+1, (size_t)idnum_allocated_count());
new_jmeths = NEW_C_HEAP_ARRAY(jmethodID, size+1, mtClass);
memset(new_jmeths, 0, (size+1)*sizeof(jmethodID)); // cache size is stored in element[0], other elements offset by one
new_jmeths[0] = (jmethodID)size;
}
// allocate a new jmethodID that might be used
{
MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag);
jmethodID new_id = NULL; if (method_h->is_old() && !method_h->is_obsolete()) { // The method passed in is old (but not obsolete), we need to use the current version
Method* current_method = method_with_idnum((int)idnum);
assert(current_method != NULL, "old and but not obsolete, so should exist");
new_id = Method::make_jmethod_id(class_loader_data(), current_method);
} else { // It is the current version of the method or an obsolete method, // use the version passed in
new_id = Method::make_jmethod_id(class_loader_data(), method_h());
}
id = get_jmethod_id_fetch_or_update(idnum, new_id, new_jmeths,
&to_dealloc_id, &to_dealloc_jmeths);
}
// The lock has been dropped so we can free resources. // Free up either the old cache or the new cache if we allocated one. if (to_dealloc_jmeths != NULL) {
FreeHeap(to_dealloc_jmeths);
} // free up the new ID since it wasn't needed if (to_dealloc_id != NULL) {
Method::destroy_jmethod_id(class_loader_data(), to_dealloc_id);
}
} return id;
}
// Figure out how many jmethodIDs haven't been allocated, and make // sure space for them is pre-allocated. This makes getting all // method ids much, much faster with classes with more than 8 // methods, and has a *substantial* effect on performance with jvmti // code that loads all jmethodIDs for all classes. void InstanceKlass::ensure_space_for_methodids(int start_offset) { int new_jmeths = 0; int length = methods()->length(); for (int index = start_offset; index < length; index++) {
Method* m = methods()->at(index);
jmethodID id = m->find_jmethod_id_or_null(); if (id == NULL) {
new_jmeths++;
}
} if (new_jmeths != 0) {
Method::ensure_jmethod_ids(class_loader_data(), new_jmeths);
}
}
// Common code to fetch the jmethodID from the cache or update the // cache with the new jmethodID. This function should never do anything // that causes the caller to go to a safepoint or we can deadlock with // the VMThread or have cache consistency issues. //
jmethodID InstanceKlass::get_jmethod_id_fetch_or_update(
size_t idnum, jmethodID new_id,
jmethodID* new_jmeths, jmethodID* to_dealloc_id_p,
jmethodID** to_dealloc_jmeths_p) {
assert(new_id != NULL, "sanity check");
assert(to_dealloc_id_p != NULL, "sanity check");
assert(to_dealloc_jmeths_p != NULL, "sanity check");
assert(JmethodIdCreation_lock->owned_by_self(), "sanity check");
// reacquire the cache - we are locked, single threaded or at a safepoint
jmethodID* jmeths = methods_jmethod_ids_acquire();
jmethodID id = NULL;
size_t length = 0;
if (jmeths == NULL || // no cache yet
(length = (size_t)jmeths[0]) <= idnum) { // cache is too short if (jmeths != NULL) { // copy any existing entries from the old cache for (size_t index = 0; index < length; index++) {
new_jmeths[index+1] = jmeths[index+1];
}
*to_dealloc_jmeths_p = jmeths; // save old cache for later delete
}
release_set_methods_jmethod_ids(jmeths = new_jmeths);
} else { // fetch jmethodID (if any) from the existing cache
id = jmeths[idnum+1];
*to_dealloc_jmeths_p = new_jmeths; // save new cache for later delete
} if (id == NULL) { // No matching jmethodID in the existing cache or we have a new // cache or we just grew the cache. This cache write is done here // by the first thread to win the foot race because a jmethodID // needs to be unique once it is generally available.
id = new_id;
// The jmethodID cache can be read while unlocked so we have to // make sure the new jmethodID is complete before installing it // in the cache.
Atomic::release_store(&jmeths[idnum+1], id);
} else {
*to_dealloc_id_p = new_id; // save new id for later delete
} return id;
}
// Common code to get the jmethodID cache length and the jmethodID // value at index idnum if there is one. // void InstanceKlass::get_jmethod_id_length_value(jmethodID* cache,
size_t idnum, size_t *length_p, jmethodID* id_p) {
assert(cache != NULL, "sanity check");
assert(length_p != NULL, "sanity check");
assert(id_p != NULL, "sanity check");
// cache size is stored in element[0], other elements offset by one
*length_p = (size_t)cache[0]; if (*length_p <= idnum) { // cache is too short
*id_p = NULL;
} else {
*id_p = cache[idnum+1]; // fetch jmethodID (if any)
}
}
// Lookup a jmethodID, NULL if not found. Do no blocking, no allocations, no handles
jmethodID InstanceKlass::jmethod_id_or_null(Method* method) {
size_t idnum = (size_t)method->method_idnum();
jmethodID* jmeths = methods_jmethod_ids_acquire();
size_t length; // length assigned as debugging crumb
jmethodID id = NULL; if (jmeths != NULL && // If there is a cache
(length = (size_t)jmeths[0]) > idnum) { // and if it is long enough,
id = jmeths[idnum+1]; // Look up the id (may be NULL)
} return id;
}
void InstanceKlass::clean_implementors_list() {
assert(is_loader_alive(), "this klass should be live"); if (is_interface()) {
assert (ClassUnloading, "only called for ClassUnloading"); for (;;) { // Use load_acquire due to competing with inserts
InstanceKlass* impl = Atomic::load_acquire(adr_implementor()); if (impl != NULL && !impl->is_loader_alive()) { // NULL this field, might be an unloaded instance klass or NULL
InstanceKlass* volatile* iklass = adr_implementor(); if (Atomic::cmpxchg(iklass, impl, (InstanceKlass*)NULL) == impl) { // Successfully unlinking implementor. if (log_is_enabled(Trace, class, unload)) {
ResourceMark rm;
log_trace(class, unload)("unlinking class (implementor): %s", impl->external_name());
} return;
}
} else { return;
}
}
}
}
void InstanceKlass::clean_method_data() { for (int m = 0; m < methods()->length(); m++) {
MethodData* mdo = methods()->at(m)->method_data(); if (mdo != NULL) {
MutexLocker ml(SafepointSynchronize::is_at_safepoint() ? NULL : mdo->extra_data_lock());
mdo->clean_method_data(/*always_clean*/false);
}
}
}
// _fields might be written into by Rewriter::scan_method() -> fd.set_has_initialized_final_update()
it->push(&_fields, MetaspaceClosure::_writable);
if (itable_length() > 0) {
itableOffsetEntry* ioe = (itableOffsetEntry*)start_of_itable(); int method_table_offset_in_words = ioe->offset()/wordSize; int nof_interfaces = (method_table_offset_in_words - itable_offset_in_words())
/ itableOffsetEntry::size();
for (int i = 0; i < nof_interfaces; i ++, ioe ++) { if (ioe->interface_klass() != NULL) {
it->push(ioe->interface_klass_addr());
itableMethodEntry* ime = ioe->first_method_entry(this); int n = klassItable::method_count_for_interface(ioe->interface_klass()); for (int index = 0; index < n; index ++) {
it->push(ime[index].method_addr());
}
}
}
}
if (is_linked()) {
assert(can_be_verified_at_dumptime(), "must be"); // Remember this so we can avoid walking the hierarchy at runtime.
set_verified_at_dump_time();
}
Klass::remove_unshareable_info();
if (SystemDictionaryShared::has_class_failed_verification(this)) { // Classes are attempted to link during dumping and may fail, // but these classes are still in the dictionary and class list in CLD. // If the class has failed verification, there is nothing else to remove. return;
}
// Reset to the 'allocated' state to prevent any premature accessing to // a shared class at runtime while the class is still being loaded and // restored. A class' init_state is set to 'loaded' at runtime when it's // being added to class hierarchy (see SystemDictionary:::add_to_hierarchy()).
_init_state = allocated;
{ // Otherwise this needs to take out the Compile_lock.
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
init_implementor();
}
constants()->remove_unshareable_info();
for (int i = 0; i < methods()->length(); i++) {
Method* m = methods()->at(i);
m->remove_unshareable_info();
}
// do array classes also. if (array_klasses() != NULL) {
array_klasses()->remove_unshareable_info();
}
// These are not allocated from metaspace. They are safe to set to NULL.
_source_debug_extension = NULL;
_dep_context = NULL;
_osr_nmethods_head = NULL; #if INCLUDE_JVMTI
_breakpoints = NULL;
_previous_versions = NULL;
_cached_class_file = NULL;
_jvmti_cached_class_field_map = NULL; #endif
void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain,
PackageEntry* pkg_entry, TRAPS) { // SystemDictionary::add_to_hierarchy() sets the init_state to loaded // before the InstanceKlass is added to the SystemDictionary. Make // sure the current state is <loaded.
assert(!is_loaded(), "invalid init state");
assert(!shared_loading_failed(), "Must not try to load failed class again");
set_package(loader_data, pkg_entry, CHECK);
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
Array<Method*>* methods = this->methods(); int num_methods = methods->length(); for (int index = 0; index < num_methods; ++index) {
methods->at(index)->restore_unshareable_info(CHECK);
} #if INCLUDE_JVMTI if (JvmtiExport::has_redefined_a_class()) { // Reinitialize vtable because RedefineClasses may have changed some // entries in this vtable for super classes so the CDS vtable might // point to old or obsolete entries. RedefineClasses doesn't fix up // vtables in the shared system dictionary, only the main one. // It also redefines the itable too so fix that too. // First fix any default methods that point to a super class that may // have been redefined. bool trace_name_printed = false;
adjust_default_methods(&trace_name_printed);
vtable().initialize_vtable();
itable().initialize_itable();
} #endif
// restore constant pool resolved references
constants()->restore_unshareable_info(CHECK);
if (array_klasses() != NULL) { // To get a consistent list of classes we need MultiArray_lock to ensure // array classes aren't observed while they are being restored.
MutexLocker ml(MultiArray_lock); // Array classes have null protection domain. // --> see ArrayKlass::complete_create_array_klass()
array_klasses()->restore_unshareable_info(ClassLoaderData::the_null_class_loader_data(), Handle(), CHECK);
}
// Initialize @ValueBased class annotation if (DiagnoseSyncOnValueBasedClasses && has_value_based_class_annotation()) {
set_is_value_based();
}
// restore the monitor
_init_monitor = create_init_monitor("InstanceKlassInitMonitorRestored_lock");
}
// Check if a class or any of its supertypes has a version older than 50. // CDS will not perform verification of old classes during dump time because // without changing the old verifier, the verification constraint cannot be // retrieved during dump time. // Verification of archived old classes will be performed during run time. bool InstanceKlass::can_be_verified_at_dumptime() const { if (MetaspaceShared::is_in_shared_metaspace(this)) { // This is a class that was dumped into the base archive, so we know // it was verified at dump time. returntrue;
} if (major_version() < 50 /*JAVA_6_VERSION*/) { returnfalse;
} if (java_super() != NULL && !java_super()->can_be_verified_at_dumptime()) { returnfalse;
}
Array<InstanceKlass*>* interfaces = local_interfaces(); int len = interfaces->length(); for (int i = 0; i < len; i++) { if (!interfaces->at(i)->can_be_verified_at_dumptime()) { returnfalse;
}
} returntrue;
} #endif// INCLUDE_CDS
#if INCLUDE_JVMTI staticvoid clear_all_breakpoints(Method* m) {
m->clear_all_breakpoints();
} #endif
staticvoid method_release_C_heap_structures(Method* m) {
m->release_C_heap_structures();
}
// Called also by InstanceKlass::deallocate_contents, with false for release_sub_metadata. void InstanceKlass::release_C_heap_structures(bool release_sub_metadata) { // Clean up C heap
Klass::release_C_heap_structures();
// Deallocate and call destructors for MDO mutexes if (release_sub_metadata) {
methods_do(method_release_C_heap_structures);
}
assert(_dep_context == NULL, "dependencies should already be cleaned");
#if INCLUDE_JVMTI // Deallocate breakpoint records if (breakpoints() != 0x0) {
methods_do(clear_all_breakpoints);
assert(breakpoints() == 0x0, "should have cleared breakpoints");
}
// deallocate the cached class file if (_cached_class_file != NULL) {
os::free(_cached_class_file);
_cached_class_file = NULL;
} #endif
FREE_C_HEAP_ARRAY(char, _source_debug_extension);
if (release_sub_metadata) {
constants()->release_C_heap_structures();
}
}
void InstanceKlass::set_source_debug_extension(constchar* array, int length) { if (array == NULL) {
_source_debug_extension = NULL;
} else { // Adding one to the attribute length in order to store a null terminator // character could cause an overflow because the attribute length is // already coded with an u4 in the classfile, but in practice, it's // unlikely to happen.
assert((length+1) > length, "Overflow checking"); char* sde = NEW_C_HEAP_ARRAY(char, (length + 1), mtClass); for (int i = 0; i < length; i++) {
sde[i] = array[i];
}
sde[length] = '\0';
_source_debug_extension = sde;
}
}
// Get the internal name as a c string constchar* src = (constchar*) (name()->as_C_string()); constint src_length = (int)strlen(src);
char* dest = NEW_RESOURCE_ARRAY(char, src_length + 3);
// Add L as type indicator int dest_index = 0;
dest[dest_index++] = JVM_SIGNATURE_CLASS;
// Add the actual class name for (int src_index = 0; src_index < src_length; ) {
dest[dest_index++] = src[src_index++];
}
if (is_hidden()) { // Replace the last '+' with a '.'. for (int index = (int)src_length; index > 0; index--) { if (dest[index] == '+') {
dest[index] = JVM_SIGNATURE_DOT; break;
}
}
}
// Add the semicolon and the NULL
dest[dest_index++] = JVM_SIGNATURE_ENDCLASS;
dest[dest_index] = '\0'; return dest;
}
ModuleEntry* InstanceKlass::module() const { if (is_hidden() &&
in_unnamed_package() &&
class_loader_data()->has_class_mirror_holder()) { // For a non-strong hidden class defined to an unnamed package, // its (class held) CLD will not have an unnamed module created for it. // Two choices to find the correct ModuleEntry: // 1. If hidden class is within a nest, use nest host's module // 2. Find the unnamed module off from the class loader // For now option #2 is used since a nest host is not set until // after the instance class is created in jvm_lookup_define_class(). if (class_loader_data()->is_boot_class_loader_data()) { return ClassLoaderData::the_null_class_loader_data()->unnamed_module();
} else {
oop module = java_lang_ClassLoader::unnamedModule(class_loader_data()->class_loader());
assert(java_lang_Module::is_instance(module), "Not an instance of java.lang.Module"); return java_lang_Module::module_entry(module);
}
}
// Class is in a named package if (!in_unnamed_package()) { return _package_entry->module();
}
// Class is in an unnamed package, return its loader's unnamed module return class_loader_data()->unnamed_module();
}
// ensure java/ packages only loaded by boot or platform builtin loaders // not needed for shared class since CDS does not archive prohibited classes. if (!is_shared()) {
check_prohibited_package(name(), loader_data, CHECK);
}
if (is_shared() && _package_entry != NULL) { if (MetaspaceShared::use_full_module_graph() && _package_entry == pkg_entry) { // we can use the saved package
assert(MetaspaceShared::is_in_shared_metaspace(_package_entry), "must be"); return;
} else {
_package_entry = NULL;
}
}
// ClassLoader::package_from_class_name has already incremented the refcount of the symbol // it returns, so we need to decrement it when the current function exits.
TempNewSymbol from_class_name =
(pkg_entry != NULL) ? NULL : ClassLoader::package_from_class_name(name());
// Find in class loader's package entry table.
_package_entry = pkg_entry != NULL ? pkg_entry : loader_data->packages()->lookup_only(pkg_name);
// If the package name is not found in the loader's package // entry table, it is an indication that the package has not // been defined. Consider it defined within the unnamed module. if (_package_entry == NULL) {
if (!ModuleEntryTable::javabase_defined()) { // Before java.base is defined during bootstrapping, define all packages in // the java.base module. If a non-java.base package is erroneously placed // in the java.base module it will be caught later when java.base // is defined by ModuleEntryTable::verify_javabase_packages check.
assert(ModuleEntryTable::javabase_moduleEntry() != NULL, JAVA_BASE_NAME " module is NULL");
_package_entry = loader_data->packages()->create_entry_if_absent(pkg_name, ModuleEntryTable::javabase_moduleEntry());
} else {
assert(loader_data->unnamed_module() != NULL, "unnamed module is NULL");
_package_entry = loader_data->packages()->create_entry_if_absent(pkg_name, loader_data->unnamed_module());
}
// A package should have been successfully created
DEBUG_ONLY(ResourceMark rm(THREAD));
assert(_package_entry != NULL, "Package entry for class %s not found, loader %s",
name()->as_C_string(), loader_data->loader_name_and_id());
}
// Function set_classpath_index ensures that for a non-null _package_entry // of the InstanceKlass, the entry is in the boot loader's package entry table. // It then sets the classpath_index in the package entry record. // // The classpath_index field is used to find the entry on the boot loader class // path for packages with classes loaded by the boot loader from -Xbootclasspath/a // in an unnamed module. It is also used to indicate (for all packages whose // classes are loaded by the boot loader) that at least one of the package's // classes has been loaded. void InstanceKlass::set_classpath_index(s2 path_index) { if (_package_entry != NULL) {
DEBUG_ONLY(PackageEntryTable* pkg_entry_tbl = ClassLoaderData::the_null_class_loader_data()->packages();)
assert(pkg_entry_tbl->lookup_only(_package_entry->name()) == _package_entry, "Should be same");
assert(path_index != -1, "Unexpected classpath_index");
_package_entry->set_classpath_index(path_index);
}
}
oop classloader2;
PackageEntry* classpkg2; if (class2->is_instance_klass()) {
classloader2 = class2->class_loader();
classpkg2 = class2->package();
} else {
assert(class2->is_typeArray_klass(), "should be type array");
classloader2 = NULL;
classpkg2 = NULL;
}
// Same package is determined by comparing class loader // and package entries. Both must be the same. This rule // applies even to classes that are defined in the unnamed // package, they still must have the same class loader. if ((classloader1 == classloader2) && (classpkg1 == classpkg2)) { returntrue;
}
returnfalse;
}
// return true if this class and other_class are in the same package. Classloader // and classname information is enough to determine a class's package bool InstanceKlass::is_same_class_package(oop other_class_loader, const Symbol* other_class_name) const { if (class_loader() != other_class_loader) { returnfalse;
} if (name()->fast_compare(other_class_name) == 0) { returntrue;
}
{
ResourceMark rm;
bool bad_class_name = false;
TempNewSymbol other_pkg = ClassLoader::package_from_class_name(other_class_name, &bad_class_name); if (bad_class_name) { returnfalse;
} // Check that package_from_class_name() returns NULL, not "", if there is no package.
assert(other_pkg == NULL || other_pkg->utf8_length() > 0, "package name is empty string");
if (this_package_name == NULL || other_pkg == NULL) { // One of the two doesn't have a package. Only return true if the other // one also doesn't have a package. return this_package_name == other_pkg;
}
// Check if package is identical return this_package_name->fast_compare(other_pkg) == 0;
}
}
// Only boot and platform class loaders can define classes in "java/" packages. void InstanceKlass::check_prohibited_package(Symbol* class_name,
ClassLoaderData* loader_data,
TRAPS) { if (!loader_data->is_boot_class_loader_data() &&
!loader_data->is_platform_class_loader_data() &&
class_name != NULL && class_name->utf8_length() >= 5) {
ResourceMark rm(THREAD); bool prohibited; const u1* base = class_name->base(); if ((base[0] | base[1] | base[2] | base[3] | base[4]) & 0x80) {
prohibited = is_prohibited_package_slow(class_name);
} else { char* name = class_name->as_C_string();
prohibited = (strncmp(name, JAVAPKG, JAVAPKG_LEN) == 0 && name[JAVAPKG_LEN] == '/');
} if (prohibited) {
TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name);
assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'"); char* name = pkg_name->as_C_string(); constchar* class_loader_name = loader_data->loader_name_and_id();
StringUtils::replace_no_expand(name, "/", "."); constchar* msg_text1 = "Class loader (instance of): "; constchar* msg_text2 = " tried to load prohibited package name: ";
size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(name) + 1; char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, name);
THROW_MSG(vmSymbols::java_lang_SecurityException(), message);
}
} return;
}
bool InstanceKlass::find_inner_classes_attr(int* ooff, int* noff, TRAPS) const {
constantPoolHandle i_cp(THREAD, constants()); for (InnerClassesIterator iter(this); !iter.done(); iter.next()) { int ioff = iter.inner_class_info_index(); if (ioff != 0) { // Check to see if the name matches the class we're looking for // before attempting to find the class. if (i_cp->klass_name_at_matches(this, ioff)) {
Klass* inner_klass = i_cp->klass_at(ioff, CHECK_false); if (this == inner_klass) {
*ooff = iter.outer_class_info_index();
*noff = iter.inner_name_index(); returntrue;
}
}
}
} returnfalse;
}
InstanceKlass* InstanceKlass::compute_enclosing_class(bool* inner_is_member, TRAPS) const {
InstanceKlass* outer_klass = NULL;
*inner_is_member = false; int ooff = 0, noff = 0; bool has_inner_classes_attr = find_inner_classes_attr(&ooff, &noff, THREAD); if (has_inner_classes_attr) {
constantPoolHandle i_cp(THREAD, constants()); if (ooff != 0) {
Klass* ok = i_cp->klass_at(ooff, CHECK_NULL); if (!ok->is_instance_klass()) { // If the outer class is not an instance klass then it cannot have // declared any inner classes.
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(), "%s and %s disagree on InnerClasses attribute",
ok->external_name(),
external_name()); return NULL;
}
outer_klass = InstanceKlass::cast(ok);
*inner_is_member = true;
} if (NULL == outer_klass) { // It may be a local class; try for that. int encl_method_class_idx = enclosing_method_class_index(); if (encl_method_class_idx != 0) {
Klass* ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL);
outer_klass = InstanceKlass::cast(ok);
*inner_is_member = false;
}
}
}
// If no inner class attribute found for this class. if (NULL == outer_klass) return NULL;
// Throws an exception if outer klass has not declared k as an inner klass // We need evidence that each klass knows about the other, or else // the system could allow a spoof of an inner class to gain access rights.
Reflection::check_for_inner_class(outer_klass, this, *inner_is_member, CHECK_NULL); return outer_klass;
}
// But check if it happens to be member class.
InnerClassesIterator iter(this); for (; !iter.done(); iter.next()) { int ioff = iter.inner_class_info_index(); // Inner class attribute can be zero, skip it. // Strange but true: JVM spec. allows null inner class refs. if (ioff == 0) continue;
// only look at classes that are already loaded // since we are looking for the flags for our self.
Symbol* inner_name = constants()->klass_name_at(ioff); if (name() == inner_name) { // This is really a member class.
access = iter.inner_access_flags(); break;
}
} // Remember to strip ACC_SUPER bit return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS;
}
jint InstanceKlass::jvmti_class_status() const {
jint result = 0;
if (is_linked()) {
result |= JVMTI_CLASS_STATUS_VERIFIED | JVMTI_CLASS_STATUS_PREPARED;
}
if (is_initialized()) {
assert(is_linked(), "Class status is not consistent");
result |= JVMTI_CLASS_STATUS_INITIALIZED;
} if (is_in_error_state()) {
result |= JVMTI_CLASS_STATUS_ERROR;
} return result;
}
Method* InstanceKlass::method_at_itable(InstanceKlass* holder, int index, TRAPS) { bool implements_interface; // initialized by method_at_itable_or_null
Method* m = method_at_itable_or_null(holder, index,
implements_interface); // out parameter if (m != NULL) {
assert(implements_interface, "sanity"); return m;
} elseif (implements_interface) { // Throw AbstractMethodError since corresponding itable slot is empty.
THROW_NULL(vmSymbols::java_lang_AbstractMethodError());
} else { // If the interface isn't implemented by the receiver class, // the VM should throw IncompatibleClassChangeError.
ResourceMark rm(THREAD);
stringStream ss; bool same_module = (module() == holder->module());
ss.print("Receiver class %s does not implement " "the interface %s defining the method to be called " "(%s%s%s)",
external_name(), holder->external_name(),
(same_module) ? joint_in_module_of_loader(holder) : class_in_module_of_loader(),
(same_module) ? "" : "; ",
(same_module) ? "" : holder->class_in_module_of_loader());
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
}
Method* InstanceKlass::method_at_itable_or_null(InstanceKlass* holder, int index, bool& implements_interface) {
klassItable itable(this); for (int i = 0; i < itable.size_offset_table(); i++) {
itableOffsetEntry* offset_entry = itable.offset_entry(i); if (offset_entry->interface_klass() == holder) {
implements_interface = true;
itableMethodEntry* ime = offset_entry->first_method_entry(this);
Method* m = ime[index].method(); return m;
}
}
implements_interface = false; return NULL; // offset entry not found
}
int InstanceKlass::vtable_index_of_interface_method(Method* intf_method) {
assert(is_linked(), "required");
assert(intf_method->method_holder()->is_interface(), "not an interface method");
assert(is_subtype_of(intf_method->method_holder()), "interface not implemented");
int vtable_index = Method::invalid_vtable_index;
Symbol* name = intf_method->name();
Symbol* signature = intf_method->signature();
// First check in default method array if (!intf_method->is_abstract() && default_methods() != NULL) { int index = find_method_index(default_methods(),
name, signature,
Klass::OverpassLookupMode::find,
Klass::StaticLookupMode::find,
Klass::PrivateLookupMode::find); if (index >= 0) {
vtable_index = default_vtable_indices()->at(index);
}
} if (vtable_index == Method::invalid_vtable_index) { // get vtable_index for miranda methods
klassVtable vt = vtable();
vtable_index = vt.index_of_miranda(name, signature);
} return vtable_index;
}
#if INCLUDE_JVMTI // update default_methods for redefineclasses for methods that are // not yet in the vtable due to concurrent subclass define and superinterface // redefinition // Note: those in the vtable, should have been updated via adjust_method_entries void InstanceKlass::adjust_default_methods(bool* trace_name_printed) { // search the default_methods for uses of either obsolete or EMCP methods if (default_methods() != NULL) { for (int index = 0; index < default_methods()->length(); index ++) {
Method* old_method = default_methods()->at(index); if (old_method == NULL || !old_method->is_old()) { continue; // skip uninteresting entries
}
assert(!old_method->is_deleted(), "default methods may not be deleted");
Method* new_method = old_method->get_new_method();
default_methods()->at_put(index, new_method);
// On-stack replacement stuff void InstanceKlass::add_osr_nmethod(nmethod* n) {
assert_lock_strong(CompiledMethod_lock); #ifndef PRODUCT
nmethod* prev = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), n->comp_level(), true);
assert(prev == NULL || !prev->is_in_use() COMPILER2_PRESENT(|| StressRecompilation), "redundant OSR recompilation detected. memory leak in CodeCache!"); #endif // only one compilation can be active
assert(n->is_osr_method(), "wrong kind of nmethod");
n->set_osr_link(osr_nmethods_head());
set_osr_nmethods_head(n); // Raise the highest osr level if necessary
n->method()->set_highest_osr_comp_level(MAX2(n->method()->highest_osr_comp_level(), n->comp_level()));
// Get rid of the osr methods for the same bci that have lower levels. for (int l = CompLevel_limited_profile; l < n->comp_level(); l++) {
nmethod *inv = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), l, true); if (inv != NULL && inv->is_in_use()) {
inv->make_not_entrant();
}
}
}
// Remove osr nmethod from the list. Return true if found and removed. bool InstanceKlass::remove_osr_nmethod(nmethod* n) { // This is a short non-blocking critical region, so the no safepoint check is ok.
MutexLocker ml(CompiledMethod_lock->owned_by_self() ? NULL : CompiledMethod_lock
, Mutex::_no_safepoint_check_flag);
assert(n->is_osr_method(), "wrong kind of nmethod");
nmethod* last = NULL;
nmethod* cur = osr_nmethods_head(); int max_level = CompLevel_none; // Find the max comp level excluding n
Method* m = n->method(); // Search for match bool found = false; while(cur != NULL && cur != n) { if (m == cur->method()) { // Find max level before n
max_level = MAX2(max_level, cur->comp_level());
}
last = cur;
cur = cur->osr_link();
}
nmethod* next = NULL; if (cur == n) {
found = true;
next = cur->osr_link(); if (last == NULL) { // Remove first element
set_osr_nmethods_head(next);
} else {
last->set_osr_link(next);
}
}
n->set_osr_link(NULL);
cur = next; while (cur != NULL) { // Find max level after n if (m == cur->method()) {
max_level = MAX2(max_level, cur->comp_level());
}
cur = cur->osr_link();
}
m->set_highest_osr_comp_level(max_level); return found;
}
int InstanceKlass::mark_osr_nmethods(const Method* m) {
MutexLocker ml(CompiledMethod_lock->owned_by_self() ? NULL : CompiledMethod_lock,
Mutex::_no_safepoint_check_flag);
nmethod* osr = osr_nmethods_head(); int found = 0; while (osr != NULL) {
assert(osr->is_osr_method(), "wrong kind of nmethod found in chain"); if (osr->method() == m) {
osr->mark_for_deoptimization();
found++;
}
osr = osr->osr_link();
} return found;
}
nmethod* InstanceKlass::lookup_osr_nmethod(const Method* m, int bci, int comp_level, bool match_level) const {
MutexLocker ml(CompiledMethod_lock->owned_by_self() ? NULL : CompiledMethod_lock,
Mutex::_no_safepoint_check_flag);
nmethod* osr = osr_nmethods_head();
nmethod* best = NULL; while (osr != NULL) {
assert(osr->is_osr_method(), "wrong kind of nmethod found in chain"); // There can be a time when a c1 osr method exists but we are waiting // for a c2 version. When c2 completes its osr nmethod we will trash // the c1 version and only be able to find the c2 version. However // while we overflow in the c1 code at back branches we don't want to // try and switch to the same code as we are already running
if (osr->method() == m &&
(bci == InvocationEntryBci || osr->osr_entry_bci() == bci)) { if (match_level) { if (osr->comp_level() == comp_level) { // Found a match - return it. return osr;
}
} else { if (best == NULL || (osr->comp_level() > best->comp_level())) { if (osr->comp_level() == CompilationPolicy::highest_compile_level()) { // Found the best possible - return it. return osr;
}
best = osr;
}
}
}
osr = osr->osr_link();
}
assert(match_level == false || best == NULL, "shouldn't pick up anything if match_level is set"); if (best != NULL && best->comp_level() >= comp_level) { return best;
} return NULL;
}
void InstanceKlass::verify_on(outputStream* st) { #ifndef PRODUCT // Avoid redundant verifies, this really should be in product. if (_verify_count == Universe::verify_count()) return;
_verify_count = Universe::verify_count(); #endif
// Verify Klass
Klass::verify_on(st);
// Verify that klass is present in ClassLoaderData
guarantee(class_loader_data()->contains_klass(this), "this class isn't found in class loader data");
// Verify vtables if (is_linked()) { // $$$ This used to be done only for m/s collections. Doing it // always seemed a valid generalization. (DLD -- 6/00)
vtable().verify(st);
}
// Verify first subklass if (subklass() != NULL) {
guarantee(subklass()->is_klass(), "should be klass");
}
// Verify siblings
Klass* super = this->super();
Klass* sib = next_sibling(); if (sib != NULL) { if (sib == this) {
fatal("subclass points to itself " PTR_FORMAT, p2i(sib));
}
guarantee(sib->is_klass(), "should be klass");
guarantee(sib->super() == super, "siblings should have same superklass");
}
// Verify local interfaces if (local_interfaces()) {
Array<InstanceKlass*>* local_interfaces = this->local_interfaces(); for (int j = 0; j < local_interfaces->length(); j++) {
InstanceKlass* e = local_interfaces->at(j);
guarantee(e->is_klass() && e->is_interface(), "invalid local interface");
}
}
// JNIid class for jfieldIDs only // Note to reviewers: // These JNI functions are just moved over to column 1 and not changed // in the compressed oops workspace.
JNIid::JNIid(Klass* holder, int offset, JNIid* next) {
_holder = holder;
_offset = offset;
_next = next;
debug_only(_is_static_field_id = false;)
}
JNIid* JNIid::find(int offset) {
JNIid* current = this; while (current != NULL) { if (current->offset() == offset) return current;
current = current->next();
} return NULL;
}
void JNIid::deallocate(JNIid* current) { while (current != NULL) {
JNIid* next = current->next(); delete current;
current = next;
}
}
void JNIid::verify(Klass* holder) { int first_field_offset = InstanceMirrorKlass::offset_of_static_fields(); int end_field_offset;
end_field_offset = first_field_offset + (InstanceKlass::cast(holder)->static_field_size() * wordSize);
JNIid* current = this; while (current != NULL) {
guarantee(current->holder() == holder, "Invalid klass in JNIid"); #ifdef ASSERT int o = current->offset(); if (current->is_static_field_id()) {
guarantee(o >= first_field_offset && o < end_field_offset, "Invalid static field offset in JNIid");
} #endif
current = current->next();
}
}
void InstanceKlass::set_init_state(ClassState state) { if (state > loaded) {
assert_lock_strong(_init_monitor);
} #ifdef ASSERT bool good_state = is_shared() ? (_init_state <= state)
: (_init_state < state); bool link_failed = _init_state == being_linked && state == loaded;
assert(good_state || state == allocated || link_failed, "illegal state transition"); #endif
assert(_init_thread == NULL, "should be cleared before state change");
_init_state = state;
}
#if INCLUDE_JVMTI
// RedefineClasses() support for previous versions
// Globally, there is at least one previous version of a class to walk // during class unloading, which is saved because old methods in the class // are still running. Otherwise the previous version list is cleaned up. bool InstanceKlass::_has_previous_versions = false;
// Returns true if there are previous versions of a class for class // unloading only. Also resets the flag to false. purge_previous_version // will set the flag to true if there are any left, i.e., if there's any // work to do for next time. This is to avoid the expensive code cache // walk in CLDG::clean_deallocate_lists(). bool InstanceKlass::has_previous_versions_and_reset() { bool ret = _has_previous_versions;
log_trace(redefine, class, iklass, purge)("Class unloading: has_previous_versions = %s",
ret ? "true" : "false");
_has_previous_versions = false; return ret;
}
// Purge previous versions before adding new previous versions of the class and // during class unloading. void InstanceKlass::purge_previous_version_list() {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
assert(has_been_redefined(), "Should only be called for main class");
// Quick exit. if (previous_versions() == NULL) { return;
}
// This klass has previous versions so see what we can cleanup // while it is safe to do so.
int deleted_count = 0; // leave debugging breadcrumbs int live_count = 0;
ClassLoaderData* loader_data = class_loader_data();
assert(loader_data != NULL, "should never be null");
// previous versions are linked together through the InstanceKlass
InstanceKlass* pv_node = previous_versions();
InstanceKlass* last = this; int version = 0;
// check the previous versions list for (; pv_node != NULL; ) {
if (!pvcp->on_stack()) { // If the constant pool isn't on stack, none of the methods // are executing. Unlink this previous_version. // The previous version InstanceKlass is on the ClassLoaderData deallocate list // so will be deallocated during the next phase of class unloading.
log_trace(redefine, class, iklass, purge)
("previous version " PTR_FORMAT " is dead.", p2i(pv_node)); // Unlink from previous version list.
assert(pv_node->class_loader_data() == loader_data, "wrong loader_data");
InstanceKlass* next = pv_node->previous_versions();
pv_node->link_previous_versions(NULL); // point next to NULL
last->link_previous_versions(next); // Delete this node directly. Nothing is referring to it and we don't // want it to increase the counter for metadata to delete in CLDG.
MetadataFactory::free_metadata(loader_data, pv_node);
pv_node = next;
deleted_count++;
version++; continue;
} else {
log_trace(redefine, class, iklass, purge)("previous version " PTR_FORMAT " is alive", p2i(pv_node));
assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
live_count++; // found a previous version for next time we do class unloading
_has_previous_versions = true;
}
// next previous version
last = pv_node;
pv_node = pv_node->previous_versions();
version++;
}
log_trace(redefine, class, iklass, purge)
("previous version stats: live=%d, deleted=%d", live_count, deleted_count);
}
void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods, int emcp_method_count) { int obsolete_method_count = old_methods->length() - emcp_method_count;
if (emcp_method_count != 0 && obsolete_method_count != 0 &&
_previous_versions != NULL) { // We have a mix of obsolete and EMCP methods so we have to // clear out any matching EMCP method entries the hard way. int local_count = 0; for (int i = 0; i < old_methods->length(); i++) {
Method* old_method = old_methods->at(i); if (old_method->is_obsolete()) { // only obsolete methods are interesting
Symbol* m_name = old_method->name();
Symbol* m_signature = old_method->signature();
// previous versions are linked together through the InstanceKlass int j = 0; for (InstanceKlass* prev_version = _previous_versions;
prev_version != NULL;
prev_version = prev_version->previous_versions(), j++) {
Array<Method*>* method_refs = prev_version->methods(); for (int k = 0; k < method_refs->length(); k++) {
Method* method = method_refs->at(k);
if (!method->is_obsolete() &&
method->name() == m_name &&
method->signature() == m_signature) { // The current RedefineClasses() call has made all EMCP // versions of this method obsolete so mark it as obsolete
log_trace(redefine, class, iklass, add)
("%s(%s): flush obsolete method @%d in version @%d",
m_name->as_C_string(), m_signature->as_C_string(), k, j);
method->set_is_obsolete(); break;
}
}
// The previous loop may not find a matching EMCP method, but // that doesn't mean that we can optimize and not go any // further back in the PreviousVersion generations. The EMCP // method for this generation could have already been made obsolete, // but there still may be an older EMCP method that has not // been made obsolete.
}
if (++local_count >= obsolete_method_count) { // no more obsolete methods so bail out now break;
}
}
}
}
}
// Save the scratch_class as the previous version if any of the methods are running. // The previous_versions are used to set breakpoints in EMCP methods and they are // also used to clean MethodData links to redefined methods that are no longer running. void InstanceKlass::add_previous_version(InstanceKlass* scratch_class, int emcp_method_count) {
assert(Thread::current()->is_VM_thread(), "only VMThread can add previous versions");
ResourceMark rm;
log_trace(redefine, class, iklass, add)
("adding previous version ref for %s, EMCP_cnt=%d", scratch_class->external_name(), emcp_method_count);
// Clean out old previous versions for this class
purge_previous_version_list();
// Mark newly obsolete methods in remaining previous versions. An EMCP method from // a previous redefinition may be made obsolete by this redefinition.
Array<Method*>* old_methods = scratch_class->methods();
mark_newly_obsolete_methods(old_methods, emcp_method_count);
// If the constant pool for this previous version of the class // is not marked as being on the stack, then none of the methods // in this previous version of the class are on the stack so // we don't need to add this as a previous version.
ConstantPool* cp_ref = scratch_class->constants(); if (!cp_ref->on_stack()) {
log_trace(redefine, class, iklass, add)("scratch class not added; no methods are running");
scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class); return;
}
// Add previous version if any methods are still running. // Set has_previous_version flag for processing during class unloading.
_has_previous_versions = true;
log_trace(redefine, class, iklass, add) ("scratch class added; one of its methods is on_stack.");
assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
scratch_class->link_previous_versions(previous_versions());
link_previous_versions(scratch_class);
} // end add_previous_version()
#endif// INCLUDE_JVMTI
Method* InstanceKlass::method_with_idnum(int idnum) {
Method* m = NULL; if (idnum < methods()->length()) {
m = methods()->at(idnum);
} if (m == NULL || m->method_idnum() != idnum) { for (int index = 0; index < methods()->length(); ++index) {
m = methods()->at(index); if (m->method_idnum() == idnum) { return m;
}
} // None found, return null for the caller to handle. return NULL;
} return m;
}
Method* InstanceKlass::method_with_orig_idnum(int idnum) { if (idnum >= methods()->length()) { return NULL;
}
Method* m = methods()->at(idnum); if (m != NULL && m->orig_method_idnum() == idnum) { return m;
} // Obsolete method idnum does not match the original idnum for (int index = 0; index < methods()->length(); ++index) {
m = methods()->at(index); if (m->orig_method_idnum() == idnum) { return m;
}
} // None found, return null for the caller to handle. return NULL;
}
Method* InstanceKlass::method_with_orig_idnum(int idnum, int version) {
InstanceKlass* holder = get_klass_version(version); if (holder == NULL) { return NULL; // The version of klass is gone, no method is found
}
Method* method = holder->method_with_orig_idnum(idnum); return method;
}
// Make a step iterating over the class hierarchy under the root class. // Skips subclasses if requested. void ClassHierarchyIterator::next() {
assert(_current != NULL, "required"); if (_visit_subclasses && _current->subklass() != NULL) {
_current = _current->subklass(); return; // visit next subclass
}
_visit_subclasses = true; // reset while (_current->next_sibling() == NULL && _current != _root) {
_current = _current->superklass(); // backtrack; no more sibling subclasses left
} if (_current == _root) { // Iteration is over (back at root after backtracking). Invalidate the iterator.
_current = NULL; return;
}
_current = _current->next_sibling(); return; // visit next sibling subclass
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.87 Sekunden
(vorverarbeitet am 2026-05-02)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.