< prev index next > src/hotspot/share/classfile/systemDictionary.cpp
Print this page
#include "memory/metaspaceClosure.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/access.inline.hpp"
+ #include "oops/fieldStreams.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.hpp"
#include "oops/oopHandle.hpp"
#include "oops/oopHandle.inline.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp"
+ #include "oops/inlineKlass.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
+ #include "runtime/os.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/signature.hpp"
#include "runtime/synchronizer.hpp"
#include "services/classLoadingService.hpp"
#include "services/diagnosticCommand.hpp"
return resolve_array_class_or_null(class_name, class_loader, protection_domain, THREAD);
} else {
assert(class_name != nullptr && !Signature::is_array(class_name), "must be");
if (Signature::has_envelope(class_name)) {
ResourceMark rm(THREAD);
- // Ignore wrapping L and ;.
+ // Ignore wrapping L and ; (and Q and ; for value types).
TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1,
class_name->utf8_length() - 2);
return resolve_instance_class_or_null(name, class_loader, protection_domain, THREAD);
} else {
return resolve_instance_class_or_null(class_name, class_loader, protection_domain, THREAD);
// a saved superclass [i.e. a defineClass is currently in progress]
// If another thread is trying to resolve the class, it must do
// superclass checks on its own thread to catch class circularity and
// to avoid deadlock.
//
- // resolve_super_or_fail adds a LOAD_SUPER placeholder to the placeholder table before calling
- // resolve_instance_class_or_null. ClassCircularityError is detected when a LOAD_SUPER or LOAD_INSTANCE
+ // resolve_with_circularity_detection_or_fail adds a DETECT_CIRCULARITY placeholder to the placeholder table before calling
+ // resolve_instance_class_or_null. ClassCircularityError is detected when a DETECT_CIRCULARITY or LOAD_INSTANCE
// placeholder for the same thread, class, classloader is found.
// This can be seen with logging option: -Xlog:class+load+placeholders=debug.
//
- InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name,
- Symbol* super_name,
+ InstanceKlass* SystemDictionary::resolve_with_circularity_detection_or_fail(Symbol* class_name,
+ Symbol* next_name,
Handle class_loader,
Handle protection_domain,
bool is_superclass,
TRAPS) {
- assert(super_name != nullptr, "null superclass for resolving");
- assert(!Signature::is_array(super_name), "invalid superclass name");
+ assert(next_name != nullptr, "null superclass for resolving");
+ assert(!Signature::is_array(next_name), "invalid superclass name");
#if INCLUDE_CDS
if (CDSConfig::is_dumping_static_archive()) {
// Special processing for handling UNREGISTERED shared classes.
InstanceKlass* k = SystemDictionaryShared::lookup_super_for_unregistered_class(class_name,
- super_name, is_superclass);
+ next_name, is_superclass);
if (k) {
return k;
}
}
#endif // INCLUDE_CDS
{
MutexLocker mu(THREAD, SystemDictionary_lock);
InstanceKlass* klassk = dictionary->find_class(THREAD, class_name);
InstanceKlass* quicksuperk;
// To support parallel loading: if class is done loading, just return the superclass
- // if the super_name matches class->super()->name() and if the class loaders match.
+ // if the next_name matches class->super()->name() and if the class loaders match.
// Otherwise, a LinkageError will be thrown later.
if (klassk != nullptr && is_superclass &&
((quicksuperk = klassk->java_super()) != nullptr) &&
- ((quicksuperk->name() == super_name) &&
+ ((quicksuperk->name() == next_name) &&
(quicksuperk->class_loader() == class_loader()))) {
return quicksuperk;
} else {
// Must check ClassCircularity before checking if superclass is already loaded.
PlaceholderEntry* probe = PlaceholderTable::get_entry(class_name, loader_data);
- if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER)) {
+ if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::DETECT_CIRCULARITY)) {
log_circularity_error(class_name, probe);
throw_circularity_error = true;
}
}
if (!throw_circularity_error) {
// Be careful not to exit resolve_super without removing this placeholder.
PlaceholderEntry* newprobe = PlaceholderTable::find_and_add(class_name,
loader_data,
- PlaceholderTable::LOAD_SUPER,
- super_name, THREAD);
+ PlaceholderTable::DETECT_CIRCULARITY,
+ next_name, THREAD);
}
}
if (throw_circularity_error) {
ResourceMark rm(THREAD);
THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), class_name->as_C_string());
}
// Resolve the superclass or superinterface, check results on return
InstanceKlass* superk =
- SystemDictionary::resolve_instance_class_or_null(super_name,
+ SystemDictionary::resolve_instance_class_or_null(next_name,
class_loader,
protection_domain,
THREAD);
// Clean up placeholder entry.
{
MutexLocker mu(THREAD, SystemDictionary_lock);
- PlaceholderTable::find_and_remove(class_name, loader_data, PlaceholderTable::LOAD_SUPER, THREAD);
+ PlaceholderTable::find_and_remove(class_name, loader_data, PlaceholderTable::DETECT_CIRCULARITY, THREAD);
SystemDictionary_lock->notify_all();
}
// Check for pending exception or null superk, and throw exception
if (HAS_PENDING_EXCEPTION || superk == nullptr) {
- handle_resolution_exception(super_name, true, CHECK_NULL);
+ handle_resolution_exception(next_name, true, CHECK_NULL);
}
return superk;
}
Symbol* superclassname,
Handle class_loader,
Handle protection_domain, TRAPS) {
// superk is not used; resolve_super_or_fail is called for circularity check only.
- Klass* superk = SystemDictionary::resolve_super_or_fail(name,
+ Klass* superk = SystemDictionary::resolve_with_circularity_detection_or_fail(name,
superclassname,
class_loader,
protection_domain,
- true,
+ false,
CHECK);
}
// Bootstrap and non-parallel capable class loaders use the LOAD_INSTANCE placeholder to
// wait for parallel class loading and/or to check for circularity error for Xcomp when loading.
return nullptr;
} else if (must_wait_for_class_loading) {
// Wait until the first thread has finished loading this class. Also wait until all the
// threads trying to load its superclass have removed their placeholders.
while (oldprobe != nullptr &&
- (oldprobe->instance_load_in_progress() || oldprobe->super_load_in_progress())) {
+ (oldprobe->instance_load_in_progress() || oldprobe->circularity_detection_in_progress())) {
// LOAD_INSTANCE placeholders are used to implement parallel capable class loading
// for the bootclass loader.
SystemDictionary_lock->wait();
Handle class_loader,
Handle protection_domain,
TRAPS) {
// name must be in the form of "java/lang/Object" -- cannot be "Ljava/lang/Object;"
assert(name != nullptr && !Signature::is_array(name) &&
- !Signature::has_envelope(name), "invalid class name");
+ !Signature::has_envelope(name), "invalid class name: %s", name == nullptr ? "nullptr" : name->as_C_string());
EventClassLoad class_load_start_event;
HandleMark hm(THREAD);
// ParallelCapable class loaders and the bootstrap classloader
// do not acquire lock here.
Handle lockObject = get_loader_lock_or_null(class_loader);
ObjectLocker ol(lockObject, THREAD);
- bool super_load_in_progress = false;
+ bool circularity_detection_in_progress = false;
InstanceKlass* loaded_class = nullptr;
SymbolHandle superclassname; // Keep alive while loading in parallel thread.
guarantee(THREAD->can_call_java(),
"can not load classes with compiler thread: class=%s, classloader=%s",
if (check != nullptr) {
// InstanceKlass is already loaded, but we still need to check protection domain below.
loaded_class = check;
} else {
PlaceholderEntry* placeholder = PlaceholderTable::get_entry(name, loader_data);
- if (placeholder != nullptr && placeholder->super_load_in_progress()) {
- super_load_in_progress = true;
- superclassname = placeholder->supername();
+ if (placeholder != nullptr && placeholder->circularity_detection_in_progress()) {
+ circularity_detection_in_progress = true;
+ superclassname = placeholder->next_klass_name();
assert(superclassname != nullptr, "superclass has to have a name");
}
}
}
// If the class is in the placeholder table with super_class set,
// handle superclass loading in progress.
- if (super_load_in_progress) {
+ if (circularity_detection_in_progress) {
handle_parallel_super_load(name, superclassname,
class_loader,
protection_domain,
CHECK_NULL);
}
// Check if a shared class can be loaded by the specific classloader.
bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
InstanceKlass* ik,
PackageEntry* pkg_entry,
Handle class_loader) {
- assert(!ModuleEntryTable::javabase_moduleEntry()->is_patched(),
- "Cannot use sharing if java.base is patched");
+ assert(!CDSConfig::module_patching_disables_cds(), "Cannot use CDS");
// (1) Check if we are loading into the same loader as in dump time.
if (ik->is_shared_boot_class()) {
if (class_loader() != nullptr) {
if (was_archived_from_named_module) {
if (should_be_in_named_module) {
// Is the module loaded from the same location as during dump time?
visible = mod_entry->shared_path_index() == scp_index;
if (visible) {
- assert(!mod_entry->is_patched(), "cannot load archived classes for patched module");
+ assert(!CDSConfig::module_patching_disables_cds(), "Cannot use CDS");
}
} else {
// During dump time, this class was in a named module, but at run time, this class should be
// in an unnamed module.
visible = false;
if (check == super_type) {
return true;
}
}
- Klass *found = resolve_super_or_fail(klass->name(), super_type->name(),
+ Klass *found = resolve_with_circularity_detection_or_fail(klass->name(), super_type->name(),
class_loader, protection_domain, is_superclass, CHECK_0);
if (found == super_type) {
return true;
} else {
// The dynamically resolved super type is not the same as the one we used during dump time,
if (!check_shared_class_super_types(ik, class_loader, protection_domain, THREAD)) {
return nullptr;
}
+ if (ik->has_inline_type_fields()) {
+ for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
+ if (fs.access_flags().is_static()) continue;
+ Symbol* sig = fs.signature();
+ if (fs.is_null_free_inline_type()) {
+ // Pre-load inline class
+ TempNewSymbol name = Signature::strip_envelope(sig);
+ Klass* real_k = SystemDictionary::resolve_with_circularity_detection_or_fail(ik->name(), name,
+ class_loader, protection_domain, false, CHECK_NULL);
+ Klass* k = ik->get_inline_type_field_klass_or_null(fs.index());
+ if (real_k != k) {
+ // oops, the app has substituted a different version of k!
+ return nullptr;
+ }
+ } else if (Signature::has_envelope(sig)) {
+ TempNewSymbol name = Signature::strip_envelope(sig);
+ if (name != ik->name() && ik->is_class_in_loadable_descriptors_attribute(name)) {
+ Klass* real_k = SystemDictionary::resolve_with_circularity_detection_or_fail(ik->name(), name,
+ class_loader, protection_domain, false, THREAD);
+ if (HAS_PENDING_EXCEPTION) {
+ CLEAR_PENDING_EXCEPTION;
+ }
+ Klass* k = ik->get_inline_type_field_klass_or_null(fs.index());
+ if (real_k != k) {
+ // oops, the app has substituted a different version of k!
+ return nullptr;
+ }
+ }
+ }
+ }
+ }
+
InstanceKlass* new_ik = nullptr;
// CFLH check is skipped for VM hidden classes (see KlassFactory::create_from_stream).
// It will be skipped for shared VM hidden lambda proxy classes.
if (!SystemDictionaryShared::is_hidden_lambda_proxy(ik)) {
new_ik = KlassFactory::check_shared_class_file_load_hook(
// restore_unshareable_info which calls ik->set_package()
ik->restore_unshareable_info(loader_data, protection_domain, pkg_entry, CHECK_NULL);
}
load_shared_class_misc(ik, loader_data);
+
return ik;
}
void SystemDictionary::load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data) {
ik->print_class_load_logging(loader_data, nullptr, nullptr);
< prev index next >