8259839: SystemDictionary exports too much implementation

Reviewed-by: iklam, dholmes
This commit is contained in:
Coleen Phillimore 2021-02-02 13:29:16 +00:00
parent 189b65b2ca
commit a421bfad28
6 changed files with 199 additions and 259 deletions

View File

@ -966,7 +966,7 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
guarantee_property(unresolved_klass->char_at(0) != JVM_SIGNATURE_ARRAY, guarantee_property(unresolved_klass->char_at(0) != JVM_SIGNATURE_ARRAY,
"Bad interface name in class file %s", CHECK); "Bad interface name in class file %s", CHECK);
// Call resolve_super so classcircularity is checked // Call resolve_super so class circularity is checked
interf = SystemDictionary::resolve_super_or_fail( interf = SystemDictionary::resolve_super_or_fail(
_class_name, _class_name,
unresolved_klass, unresolved_klass,
@ -6206,7 +6206,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
CHECK); CHECK);
} }
// We check super class after class file is parsed and format is checked // We check super class after class file is parsed and format is checked
if (_super_class_index > 0 && NULL ==_super_klass) { if (_super_class_index > 0 && NULL == _super_klass) {
Symbol* const super_class_name = cp->klass_name_at(_super_class_index); Symbol* const super_class_name = cp->klass_name_at(_super_class_index);
if (_access_flags.is_interface()) { if (_access_flags.is_interface()) {
// Before attempting to resolve the superclass, check for class format // Before attempting to resolve the superclass, check for class format

View File

@ -88,7 +88,6 @@
#include "jfr/jfr.hpp" #include "jfr/jfr.hpp"
#endif #endif
PlaceholderTable* SystemDictionary::_placeholders = NULL;
LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL; LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL; ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL; SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
@ -98,9 +97,17 @@ OopHandle SystemDictionary::_java_system_loader;
OopHandle SystemDictionary::_java_platform_loader; OopHandle SystemDictionary::_java_platform_loader;
// Default ProtectionDomainCacheSize value // Default ProtectionDomainCacheSize value
const int defaultProtectionDomainCacheSize = 1009; const int defaultProtectionDomainCacheSize = 1009;
const int _loader_constraint_size = 107; // number of entries in constraint table
const int _resolution_error_size = 107; // number of entries in resolution error table
const int _invoke_method_size = 139; // number of entries in invoke method table
// Hashtable holding placeholders for classes being loaded.
const int _placeholder_table_size = 1009;
PlaceholderTable* _placeholders = NULL;
static PlaceholderTable* placeholders() { return _placeholders; }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Java-level SystemLoader and PlatformLoader // Java-level SystemLoader and PlatformLoader
oop SystemDictionary::java_system_loader() { oop SystemDictionary::java_system_loader() {
@ -211,55 +218,55 @@ Symbol* SystemDictionary::class_name_symbol(const char* name, Symbol* exception,
return SymbolTable::new_symbol(name); return SymbolTable::new_symbol(name);
} }
// Forwards to resolve_or_null #ifdef ASSERT
// Used to verify that class loading succeeded in adding k to the dictionary.
Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS) { void verify_dictionary_entry(Symbol* class_name, InstanceKlass* k) {
Klass* klass = resolve_or_null(class_name, class_loader, protection_domain, THREAD); MutexLocker mu(SystemDictionary_lock);
if (HAS_PENDING_EXCEPTION || klass == NULL) { ClassLoaderData* loader_data = k->class_loader_data();
// can return a null klass Dictionary* dictionary = loader_data->dictionary();
klass = handle_resolution_exception(class_name, throw_error, klass, THREAD); assert(class_name == k->name(), "Must be the same");
} unsigned int name_hash = dictionary->compute_hash(class_name);
return klass; InstanceKlass* kk = dictionary->find_class(name_hash, class_name);
assert(kk == k, "should be present in dictionary");
} }
#endif
Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name, static void handle_resolution_exception(Symbol* class_name, bool throw_error, TRAPS) {
bool throw_error,
Klass* klass, TRAPS) {
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
// If we have a pending exception we forward it to the caller, unless throw_error is true, // If we have a pending exception we forward it to the caller, unless throw_error is true,
// in which case we have to check whether the pending exception is a ClassNotFoundException, // in which case we have to check whether the pending exception is a ClassNotFoundException,
// and if so convert it to a NoClassDefFoundError // and convert it to a NoClassDefFoundError and chain the original ClassNotFoundException.
// And chain the original ClassNotFoundException
if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass())) { if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass())) {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
assert(klass == NULL, "Should not have result with exception pending");
Handle e(THREAD, PENDING_EXCEPTION); Handle e(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION;
THROW_MSG_CAUSE_NULL(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string(), e); THROW_MSG_CAUSE(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string(), e);
} else { } else {
return NULL; return; // the caller will throw the incoming exception
} }
} }
// Class not found, throw appropriate error or exception depending on value of throw_error // If the class is not found, ie, caller has checked that klass is NULL, throw the appropriate
if (klass == NULL) { // error or exception depending on the value of throw_error.
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
if (throw_error) { if (throw_error) {
THROW_MSG_NULL(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string()); THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string());
} else { } else {
THROW_MSG_NULL(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string()); THROW_MSG(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string());
} }
}
// Forwards to resolve_or_null
Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain,
bool throw_error, TRAPS) {
Klass* klass = resolve_or_null(class_name, class_loader, protection_domain, THREAD);
// Check for pending exception or null klass, and throw exception
if (HAS_PENDING_EXCEPTION || klass == NULL) {
handle_resolution_exception(class_name, throw_error, CHECK_NULL);
} }
return klass; return klass;
} }
Klass* SystemDictionary::resolve_or_fail(Symbol* class_name,
bool throw_error, TRAPS)
{
return resolve_or_fail(class_name, Handle(), Handle(), throw_error, THREAD);
}
// Forwards to resolve_array_class_or_null or resolve_instance_class_or_null // Forwards to resolve_array_class_or_null or resolve_instance_class_or_null
Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) { Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) {
@ -287,10 +294,6 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null_helper(Symbol* c
} }
} }
Klass* SystemDictionary::resolve_or_null(Symbol* class_name, TRAPS) {
return resolve_or_null(class_name, Handle(), Handle(), THREAD);
}
// Forwards to resolve_instance_class_or_null // Forwards to resolve_instance_class_or_null
Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name, Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
@ -323,9 +326,9 @@ Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
// Must be called for any super-class or super-interface resolution // Must be called for any super-class or super-interface resolution
// during class definition to allow class circularity checking // during class definition to allow class circularity checking
// super-interface callers: // super-interface callers:
// parse_interfaces - for defineClass & jvmtiRedefineClasses // parse_interfaces - for defineClass
// super-class callers: // super-class callers:
// ClassFileParser - for defineClass & jvmtiRedefineClasses // ClassFileParser - for defineClass
// load_shared_class - while loading a class from shared archive // load_shared_class - while loading a class from shared archive
// resolve_instance_class_or_null: // resolve_instance_class_or_null:
// via: handle_parallel_super_load // via: handle_parallel_super_load
@ -352,14 +355,11 @@ Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
// 4.2 resolve_instance_class_or_null Base, finds placeholder for Base (super Super) // 4.2 resolve_instance_class_or_null Base, finds placeholder for Base (super Super)
// 4.3 calls resolve_super_or_fail Super in parallel on own thread T2 // 4.3 calls resolve_super_or_fail Super in parallel on own thread T2
// 4.4 finds T2, Super -> throws class circularity // 4.4 finds T2, Super -> throws class circularity
// Must be called, even if superclass is null, since this is
// where the placeholder entry is created which claims this
// thread is loading this class/classloader.
// Be careful when modifying this code: once you have run // Be careful when modifying this code: once you have run
// placeholders()->find_and_add(PlaceholderTable::LOAD_SUPER), // placeholders()->find_and_add(PlaceholderTable::LOAD_SUPER),
// you need to find_and_remove it before returning. // you need to find_and_remove it before returning.
// So be careful to not exit with a CHECK_ macro betweeen these calls. // So be careful to not exit with a CHECK_ macro between these calls.
InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* child_name, InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name,
Symbol* super_name, Symbol* super_name,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
@ -369,7 +369,7 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
#if INCLUDE_CDS #if INCLUDE_CDS
if (DumpSharedSpaces) { if (DumpSharedSpaces) {
// Special processing for handling UNREGISTERED shared classes. // Special processing for handling UNREGISTERED shared classes.
InstanceKlass* k = SystemDictionaryShared::dump_time_resolve_super_or_fail(child_name, InstanceKlass* k = SystemDictionaryShared::dump_time_resolve_super_or_fail(class_name,
super_name, class_loader, protection_domain, is_superclass, CHECK_NULL); super_name, class_loader, protection_domain, is_superclass, CHECK_NULL);
if (k) { if (k) {
return k; return k;
@ -377,16 +377,16 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
} }
#endif // INCLUDE_CDS #endif // INCLUDE_CDS
// Double-check, if child class is already loaded, just return super-class,interface // Double-check, if klass is already loaded, just return super-class,interface
// Don't add a placedholder if already loaded, i.e. already in appropriate class loader // Don't add a placedholder if already loaded, i.e. already in appropriate class loader
// dictionary. // dictionary.
// Make sure there's a placeholder for the *child* before resolving. // Make sure there's a placeholder for the *klass* before resolving.
// Used as a claim that this thread is currently loading superclass/classloader // Used as a claim that this thread is currently loading superclass/classloader
// Used here for ClassCircularity checks and also for heap verification // Used here for ClassCircularity checks and also for heap verification
// (every InstanceKlass needs to be in its class loader dictionary or have a placeholder). // (every InstanceKlass needs to be in its class loader dictionary or have a placeholder).
// Must check ClassCircularity before checking if super class is already loaded. // Must check ClassCircularity before checking if super class is already loaded.
// //
// We might not already have a placeholder if this child_name was // We might not already have a placeholder if this class_name was
// first seen via resolve_from_stream (jni_DefineClass or JVM_DefineClass); // first seen via resolve_from_stream (jni_DefineClass or JVM_DefineClass);
// the name of the class might not be known until the stream is actually // the name of the class might not be known until the stream is actually
// parsed. // parsed.
@ -394,39 +394,36 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
ClassLoaderData* loader_data = class_loader_data(class_loader); ClassLoaderData* loader_data = class_loader_data(class_loader);
Dictionary* dictionary = loader_data->dictionary(); Dictionary* dictionary = loader_data->dictionary();
unsigned int name_hash = dictionary->compute_hash(child_name); unsigned int name_hash = dictionary->compute_hash(class_name);
assert(placeholders()->compute_hash(child_name) == name_hash, "they're the same hashcode"); assert(placeholders()->compute_hash(class_name) == name_hash, "they're the same hashcode");
// can't throw error holding a lock // can't throw error holding a lock
bool throw_circularity_error = false; bool throw_circularity_error = false;
{ {
MutexLocker mu(THREAD, SystemDictionary_lock); MutexLocker mu(THREAD, SystemDictionary_lock);
InstanceKlass* childk = dictionary->find_class(name_hash, child_name); InstanceKlass* klassk = dictionary->find_class(name_hash, class_name);
InstanceKlass* quicksuperk; InstanceKlass* quicksuperk;
// to support // loading: if child done loading, just return superclass // To support parallel loading: if class is done loading, just return the superclass
// if super_name, & class_loader don't match: // if the super_name matches class->super()->name() and if the class loaders match.
// if initial define, SD update will give LinkageError // Otherwise, a LinkageError will be thrown later.
// if redefine: compare_class_versions will give HIERARCHY_CHANGED if (klassk != NULL && is_superclass &&
// so we don't throw an exception here. ((quicksuperk = klassk->java_super()) != NULL) &&
// see: nsk redefclass014 & java.lang.instrument Instrument032
if ((childk != NULL ) && (is_superclass) &&
((quicksuperk = childk->java_super()) != NULL) &&
((quicksuperk->name() == super_name) && ((quicksuperk->name() == super_name) &&
(quicksuperk->class_loader() == class_loader()))) { (quicksuperk->class_loader() == class_loader()))) {
return quicksuperk; return quicksuperk;
} else { } else {
PlaceholderEntry* probe = placeholders()->get_entry(name_hash, child_name, loader_data); PlaceholderEntry* probe = placeholders()->get_entry(name_hash, class_name, loader_data);
if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER)) { if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER)) {
throw_circularity_error = true; throw_circularity_error = true;
} }
} }
if (!throw_circularity_error) { if (!throw_circularity_error) {
// Be careful not to exit resolve_super // Be careful not to exit resolve_super without removing this placeholder.
PlaceholderEntry* newprobe = placeholders()->find_and_add(name_hash, child_name, loader_data, PlaceholderTable::LOAD_SUPER, super_name, THREAD); PlaceholderEntry* newprobe = placeholders()->find_and_add(name_hash, class_name, loader_data, PlaceholderTable::LOAD_SUPER, super_name, THREAD);
} }
} }
if (throw_circularity_error) { if (throw_circularity_error) {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), child_name->as_C_string()); THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), class_name->as_C_string());
} }
// java.lang.Object should have been found above // java.lang.Object should have been found above
@ -446,16 +443,13 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
// the loader_data. parseClassFile adds the instanceKlass to loader_data. // the loader_data. parseClassFile adds the instanceKlass to loader_data.
{ {
MutexLocker mu(THREAD, SystemDictionary_lock); MutexLocker mu(THREAD, SystemDictionary_lock);
placeholders()->find_and_remove(name_hash, child_name, loader_data, PlaceholderTable::LOAD_SUPER, THREAD); placeholders()->find_and_remove(name_hash, class_name, loader_data, PlaceholderTable::LOAD_SUPER, THREAD);
SystemDictionary_lock->notify_all(); SystemDictionary_lock->notify_all();
} }
// Check for pending exception or null superk, and throw exception
if (HAS_PENDING_EXCEPTION || superk == NULL) { if (HAS_PENDING_EXCEPTION || superk == NULL) {
// can null superk handle_resolution_exception(super_name, true, CHECK_NULL);
Klass* k = handle_resolution_exception(super_name, true, superk, THREAD);
assert(k == NULL || k == superk, "must be");
if (k == NULL) {
superk = NULL;
}
} }
return superk; return superk;
@ -758,28 +752,25 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
if (!class_has_been_loaded) { if (!class_has_been_loaded) {
bool load_instance_added = false; bool load_instance_added = false;
// add placeholder entry to record loading instance class // Add placeholder entry to record loading instance class
// Five cases: // Three cases:
// All cases need to prevent modifying bootclasssearchpath // case 1. Bootstrap classloader
// in parallel with a classload of same classname // This classloader supports parallelism at the classloader level
// Redefineclasses uses existence of the placeholder for the duration // but only allows a single thread to load a class/classloader pair.
// of the class load to prevent concurrent redefinition of not completely // The LOAD_INSTANCE placeholder is the mechanism for mutual exclusion.
// defined classes. // case 2. parallelCapable user level classloaders
// case 1. traditional classloaders that rely on the classloader object lock // These class loaders don't lock the object until load_instance_class is
// - no other need for LOAD_INSTANCE // called after this placeholder is added.
// case 2. traditional classloaders that break the classloader object lock // Allow parallel classloading of a class/classloader pair where mutual
// as a deadlock workaround. Detection of this case requires that // exclusion is provided by this lock in the class loader Java code.
// case 3. traditional classloaders that rely on the classloader object lock
// There should be no need for need for LOAD_INSTANCE, except:
// case 4. traditional class loaders that break the classloader object lock
// as a legacy deadlock workaround. Detection of this case requires that
// this check is done while holding the classloader object lock, // this check is done while holding the classloader object lock,
// and that lock is still held when calling classloader's loadClass. // and that lock is still held when calling classloader's loadClass.
// For these classloaders, we ensure that the first requestor // For these classloaders, we ensure that the first requestor
// completes the load and other requestors wait for completion. // completes the load and other requestors wait for completion.
// case 3. Bootstrap classloader - don't own objectLocker
// This classloader supports parallelism at the classloader level,
// but only allows a single load of a class/classloader pair.
// No performance benefit and no deadlock issues.
// case 4. parallelCapable user level classloaders - without objectLocker
// Allow parallel classloading of a class/classloader pair
{ {
MutexLocker mu(THREAD, SystemDictionary_lock); MutexLocker mu(THREAD, SystemDictionary_lock);
if (class_loader.is_null() || !is_parallelCapable(class_loader)) { if (class_loader.is_null() || !is_parallelCapable(class_loader)) {
@ -790,15 +781,15 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
if (oldprobe->check_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE)) { if (oldprobe->check_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE)) {
throw_circularity_error = true; throw_circularity_error = true;
} else { } else {
// case 1: traditional: should never see load_in_progress. // case 3: traditional: should never see load_in_progress.
while (!class_has_been_loaded && oldprobe != NULL && oldprobe->instance_load_in_progress()) { while (!class_has_been_loaded && oldprobe != NULL && oldprobe->instance_load_in_progress()) {
// case 3: bootstrap classloader: prevent futile classloading, // case 1: bootstrap classloader: prevent futile classloading,
// wait on first requestor // wait on first requestor
if (class_loader.is_null()) { if (class_loader.is_null()) {
SystemDictionary_lock->wait(); SystemDictionary_lock->wait();
} else { } else {
// case 2: traditional with broken classloader lock. wait on first // case 4: traditional with broken classloader lock. wait on first
// requestor. // requestor.
double_lock_wait(THREAD, lockObject); double_lock_wait(THREAD, lockObject);
} }
@ -815,10 +806,8 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
} }
} }
} }
// All cases: add LOAD_INSTANCE holding SystemDictionary_lock
// case 4: parallelCapable: allow competing threads to try
// LOAD_INSTANCE in parallel
// All cases: add LOAD_INSTANCE while holding the SystemDictionary_lock
if (!throw_circularity_error && !class_has_been_loaded) { if (!throw_circularity_error && !class_has_been_loaded) {
PlaceholderEntry* newprobe = placeholders()->find_and_add(name_hash, name, loader_data, PlaceholderEntry* newprobe = placeholders()->find_and_add(name_hash, name, loader_data,
PlaceholderTable::LOAD_INSTANCE, NULL, THREAD); PlaceholderTable::LOAD_INSTANCE, NULL, THREAD);
@ -896,14 +885,9 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
if (class_load_start_event.should_commit()) { if (class_load_start_event.should_commit()) {
post_class_load_event(&class_load_start_event, loaded_class, loader_data); post_class_load_event(&class_load_start_event, loaded_class, loader_data);
} }
#ifdef ASSERT
{ // Make sure we have the right class in the dictionary
ClassLoaderData* loader_data = loaded_class->class_loader_data(); DEBUG_ONLY(verify_dictionary_entry(name, loaded_class));
MutexLocker mu(THREAD, SystemDictionary_lock);
InstanceKlass* kk = find_class(name, loader_data);
assert(kk == loaded_class, "should be present in dictionary");
}
#endif
// return if the protection domain in NULL // return if the protection domain in NULL
if (protection_domain() == NULL) return loaded_class; if (protection_domain() == NULL) return loaded_class;
@ -1118,33 +1102,23 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
// Add class just loaded // Add class just loaded
// If a class loader supports parallel classloading, handle parallel define requests. // If a class loader supports parallel classloading, handle parallel define requests.
// find_or_define_instance_class may return a different InstanceKlass // find_or_define_instance_class may return a different InstanceKlass,
// in which case the old k would be deallocated
if (is_parallelCapable(class_loader)) { if (is_parallelCapable(class_loader)) {
InstanceKlass* defined_k = find_or_define_instance_class(h_name, class_loader, k, THREAD); k = find_or_define_instance_class(h_name, class_loader, k, CHECK_NULL);
if (!HAS_PENDING_EXCEPTION && defined_k != k) {
// If a parallel capable class loader already defined this class, register 'k' for cleanup.
assert(defined_k != NULL, "Should have a klass if there's no exception");
loader_data->add_to_deallocate_list(k);
k = defined_k;
}
} else { } else {
define_instance_class(k, class_loader, THREAD); define_instance_class(k, class_loader, THREAD);
}
// If defining the class throws an exception register 'k' for cleanup. // If defining the class throws an exception register 'k' for cleanup.
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
assert(k != NULL, "Must have an instance klass here!"); assert(k != NULL, "Must have an instance klass here!");
loader_data->add_to_deallocate_list(k); loader_data->add_to_deallocate_list(k);
return NULL; return NULL;
}
} }
// Make sure we have an entry in the SystemDictionary on success // Make sure we have an entry in the SystemDictionary on success
debug_only( { DEBUG_ONLY(verify_dictionary_entry(h_name, k));
MutexLocker mu(THREAD, SystemDictionary_lock);
Klass* check = find_class(h_name, k->class_loader_data());
assert(check == k, "should be present in the dictionary");
} );
return k; return k;
} }
@ -1251,18 +1225,18 @@ bool SystemDictionary::is_shared_class_visible_impl(Symbol* class_name,
return visible; return visible;
} }
bool SystemDictionary::check_shared_class_super_type(InstanceKlass* child, InstanceKlass* super_type, bool SystemDictionary::check_shared_class_super_type(InstanceKlass* klass, InstanceKlass* super_type,
Handle class_loader, Handle protection_domain, Handle class_loader, Handle protection_domain,
bool is_superclass, TRAPS) { bool is_superclass, TRAPS) {
assert(super_type->is_shared(), "must be"); assert(super_type->is_shared(), "must be");
Klass *found = resolve_super_or_fail(child->name(), super_type->name(), Klass *found = resolve_super_or_fail(klass->name(), super_type->name(),
class_loader, protection_domain, is_superclass, CHECK_0); class_loader, protection_domain, is_superclass, CHECK_0);
if (found == super_type) { if (found == super_type) {
return true; return true;
} else { } else {
// The dynamically resolved super type is not the same as the one we used during dump time, // The dynamically resolved super type is not the same as the one we used during dump time,
// so we cannot use the child class. // so we cannot use the class.
return false; return false;
} }
} }
@ -1499,17 +1473,7 @@ InstanceKlass* SystemDictionary::load_instance_class(Symbol* class_name, Handle
// find_or_define_instance_class may return a different InstanceKlass // find_or_define_instance_class may return a different InstanceKlass
if (k != NULL) { if (k != NULL) {
InstanceKlass* defined_k = k = find_or_define_instance_class(class_name, class_loader, k, CHECK_NULL);
find_or_define_instance_class(class_name, class_loader, k, THREAD);
if (!HAS_PENDING_EXCEPTION && defined_k != k) {
// If a parallel capable class loader already defined this class, register 'k' for cleanup.
assert(defined_k != NULL, "Should have a klass if there's no exception");
loader_data->add_to_deallocate_list(k);
k = defined_k;
} else if (HAS_PENDING_EXCEPTION) {
loader_data->add_to_deallocate_list(k);
return NULL;
}
} }
return k; return k;
} else { } else {
@ -1578,8 +1542,8 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load
ClassLoaderData* loader_data = k->class_loader_data(); ClassLoaderData* loader_data = k->class_loader_data();
assert(loader_data->class_loader() == class_loader(), "they must be the same"); assert(loader_data->class_loader() == class_loader(), "they must be the same");
// Bootstrap and other parallel classloaders don't acquire lock, // Bootstrap and other parallel classloaders don't acquire a lock,
// they use a placeholder token instead. // they use placeholder token.
// If a parallelCapable class loader calls define_instance_class instead of // If a parallelCapable class loader calls define_instance_class instead of
// find_or_define_instance_class to get here, we have a timing // find_or_define_instance_class to get here, we have a timing
// hole with systemDictionary updates and check_constraints // hole with systemDictionary updates and check_constraints
@ -1656,8 +1620,8 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load
// placeholders()->find_and_add(PlaceholderTable::DEFINE_CLASS), // placeholders()->find_and_add(PlaceholderTable::DEFINE_CLASS),
// you need to find_and_remove it before returning. // you need to find_and_remove it before returning.
// So be careful to not exit with a CHECK_ macro between these calls. // So be careful to not exit with a CHECK_ macro between these calls.
InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_name, Handle class_loader, InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handle class_loader,
InstanceKlass* k, TRAPS) { InstanceKlass* k, TRAPS) {
Symbol* name_h = k->name(); // passed in class_name may be null Symbol* name_h = k->name(); // passed in class_name may be null
ClassLoaderData* loader_data = class_loader_data(class_loader); ClassLoaderData* loader_data = class_loader_data(class_loader);
@ -1719,38 +1683,24 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam
SystemDictionary_lock->notify_all(); SystemDictionary_lock->notify_all();
} }
return k; return HAS_PENDING_EXCEPTION ? NULL : k;
} }
// If a class loader supports parallel classloading handle parallel define requests.
// ---------------------------------------------------------------------------- // find_or_define_instance_class may return a different InstanceKlass
// Lookup InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_name, Handle class_loader,
InstanceKlass* k, TRAPS) {
// Basic find on classes in the midst of being loaded InstanceKlass* defined_k = find_or_define_helper(class_name, class_loader, k, THREAD);
Symbol* SystemDictionary::find_placeholder(Symbol* class_name, // Clean up original InstanceKlass if duplicate or error
ClassLoaderData* loader_data) { if (!HAS_PENDING_EXCEPTION && defined_k != k) {
assert_locked_or_safepoint(SystemDictionary_lock); // If a parallel capable class loader already defined this class, register 'k' for cleanup.
unsigned int name_hash = placeholders()->compute_hash(class_name); assert(defined_k != NULL, "Should have a klass if there's no exception");
return placeholders()->find_entry(name_hash, class_name, loader_data); k->class_loader_data()->add_to_deallocate_list(k);
} } else if (HAS_PENDING_EXCEPTION) {
assert(defined_k == NULL, "Should not have a klass if there's an exception");
k->class_loader_data()->add_to_deallocate_list(k);
// Used for assertions and verification only }
// Precalculating the hash and index is an optimization because there are many lookups return defined_k;
// before adding the class.
InstanceKlass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_data) {
assert_locked_or_safepoint(SystemDictionary_lock);
#ifndef ASSERT
guarantee(VerifyBeforeGC ||
VerifyDuringGC ||
VerifyBeforeExit ||
VerifyDuringStartup ||
VerifyAfterGC, "too expensive");
#endif
Dictionary* dictionary = loader_data->dictionary();
unsigned int name_hash = dictionary->compute_hash(class_name);
return dictionary->find_class(name_hash, class_name);
} }
@ -1849,6 +1799,17 @@ void SystemDictionary::initialize(TRAPS) {
} }
} }
#ifdef ASSERT
// Verify that this placeholder exists since this class is in the middle of loading.
void verify_placeholder(Symbol* class_name, ClassLoaderData* loader_data) {
// Only parallel capable class loaders use placeholder table for define class.
assert_locked_or_safepoint(SystemDictionary_lock);
unsigned int name_hash = placeholders()->compute_hash(class_name);
Symbol* ph_check = placeholders()->find_entry(name_hash, class_name, loader_data);
assert(ph_check != NULL, "This placeholder should exist");
}
#endif // ASSERT
// Constraints on class loaders. The details of the algorithm can be // Constraints on class loaders. The details of the algorithm can be
// found in the OOPSLA'98 paper "Dynamic Class Loading in the Java // found in the OOPSLA'98 paper "Dynamic Class Loading in the Java
// Virtual Machine" by Sheng Liang and Gilad Bracha. The basic idea is // Virtual Machine" by Sheng Liang and Gilad Bracha. The basic idea is
@ -1877,8 +1838,6 @@ void SystemDictionary::check_constraints(unsigned int name_hash,
// If different InstanceKlass - duplicate class definition, // If different InstanceKlass - duplicate class definition,
// else - ok, class loaded by a different thread in parallel. // else - ok, class loaded by a different thread in parallel.
// We should only have found it if it was done loading and ok to use. // We should only have found it if it was done loading and ok to use.
// The dictionary only holds instance classes, placeholders
// also hold array classes.
if ((defining == true) || (k != check)) { if ((defining == true) || (k != check)) {
throwException = true; throwException = true;
@ -1890,10 +1849,7 @@ void SystemDictionary::check_constraints(unsigned int name_hash,
} }
} }
#ifdef ASSERT DEBUG_ONLY(if (is_parallelCapable(class_loader)) verify_placeholder(name, loader_data));
Symbol* ph_check = find_placeholder(name, loader_data);
assert(ph_check == NULL || ph_check == name, "invalid symbol");
#endif
if (throwException == false) { if (throwException == false) {
if (constraints()->check_or_update(k, class_loader, name) == false) { if (constraints()->check_or_update(k, class_loader, name) == false) {
@ -1940,12 +1896,6 @@ void SystemDictionary::update_dictionary(unsigned int hash,
if (sd_check == NULL) { if (sd_check == NULL) {
dictionary->add_klass(hash, name, k); dictionary->add_klass(hash, name, k);
} }
#ifdef ASSERT
sd_check = dictionary->find_class(hash, name);
assert (sd_check != NULL, "should have entry in dictionary");
// Note: there may be a placeholder entry: for circularity testing
// or for parallel defines
#endif
SystemDictionary_lock->notify_all(); SystemDictionary_lock->notify_all();
} }
} }

View File

@ -74,7 +74,6 @@ class BootstrapInfo;
class ClassFileStream; class ClassFileStream;
class ClassLoadInfo; class ClassLoadInfo;
class Dictionary; class Dictionary;
class PlaceholderTable;
class LoaderConstraintTable; class LoaderConstraintTable;
template <MEMFLAGS F> class HashtableBucket; template <MEMFLAGS F> class HashtableBucket;
class ResolutionErrorTable; class ResolutionErrorTable;
@ -105,24 +104,23 @@ class SystemDictionary : public vmClasses {
static Klass* resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS); static Klass* resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS);
// Convenient call for null loader and protection domain. // Convenient call for null loader and protection domain.
static Klass* resolve_or_fail(Symbol* class_name, bool throw_error, TRAPS); static Klass* resolve_or_fail(Symbol* class_name, bool throw_error, TRAPS) {
protected: return resolve_or_fail(class_name, Handle(), Handle(), throw_error, THREAD);
// handle error translation for resolve_or_null results }
static Klass* handle_resolution_exception(Symbol* class_name, bool throw_error, Klass* klass, TRAPS);
public:
// Returns a class with a given class name and class loader. // Returns a class with a given class name and class loader.
// Loads the class if needed. If not found NULL is returned. // Loads the class if needed. If not found NULL is returned.
static Klass* resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS); static Klass* resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS);
// Version with null loader and protection domain // Version with null loader and protection domain
static Klass* resolve_or_null(Symbol* class_name, TRAPS); static Klass* resolve_or_null(Symbol* class_name, TRAPS) {
return resolve_or_null(class_name, Handle(), Handle(), THREAD);
}
// Resolve a superclass or superinterface. Called from ClassFileParser, // Resolve a superclass or superinterface. Called from ClassFileParser,
// parse_interfaces, resolve_instance_class_or_null, load_shared_class // parse_interfaces, resolve_instance_class_or_null, load_shared_class
// "child_name" is the class whose super class or interface is being resolved. // "class_name" is the class whose super class or interface is being resolved.
static InstanceKlass* resolve_super_or_fail(Symbol* child_name, static InstanceKlass* resolve_super_or_fail(Symbol* class_name,
Symbol* class_name, Symbol* super_name,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
bool is_superclass, bool is_superclass,
@ -151,9 +149,9 @@ public:
// Do not make any queries to class loaders; consult only the cache. // Do not make any queries to class loaders; consult only the cache.
// If not found NULL is returned. // If not found NULL is returned.
static Klass* find_instance_or_array_klass(Symbol* class_name, static Klass* find_instance_or_array_klass(Symbol* class_name,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
TRAPS); TRAPS);
// Lookup an instance or array class that has already been loaded // Lookup an instance or array class that has already been loaded
// either into the given class loader, or else into another class // either into the given class loader, or else into another class
@ -191,13 +189,9 @@ public:
// loaders. Returns "true" iff something was unloaded. // loaders. Returns "true" iff something was unloaded.
static bool do_unloading(GCTimer* gc_timer); static bool do_unloading(GCTimer* gc_timer);
// System loader lock
static oop system_loader_lock();
// Protection Domain Table // Protection Domain Table
static ProtectionDomainCacheTable* pd_cache_table() { return _pd_cache_table; } static ProtectionDomainCacheTable* pd_cache_table() { return _pd_cache_table; }
public:
// Printing // Printing
static void print(); static void print();
static void print_on(outputStream* st); static void print_on(outputStream* st);
@ -226,19 +220,8 @@ public:
// Register a new class loader // Register a new class loader
static ClassLoaderData* register_loader(Handle class_loader, bool create_mirror_cld = false); static ClassLoaderData* register_loader(Handle class_loader, bool create_mirror_cld = false);
protected:
// Mirrors for primitive classes (created eagerly)
static oop check_mirror(oop m) {
assert(m != NULL, "mirror not initialized");
return m;
}
public: public:
// Note: java_lang_Class::primitive_type is the inverse of java_mirror
// Check class loader constraints
static bool add_loader_constraint(Symbol* name, Klass* klass_being_linked, Handle loader1,
Handle loader2, TRAPS);
static Symbol* check_signature_loaders(Symbol* signature, Klass* klass_being_linked, static Symbol* check_signature_loaders(Symbol* signature, Klass* klass_being_linked,
Handle loader1, Handle loader2, bool is_method, TRAPS); Handle loader1, Handle loader2, bool is_method, TRAPS);
@ -312,21 +295,9 @@ public:
static ProtectionDomainCacheEntry* cache_get(Handle protection_domain); static ProtectionDomainCacheEntry* cache_get(Handle protection_domain);
protected: private:
enum Constants {
_loader_constraint_size = 107, // number of entries in constraint table
_resolution_error_size = 107, // number of entries in resolution error table
_invoke_method_size = 139, // number of entries in invoke method table
_placeholder_table_size = 1009 // number of entries in hash table for placeholders
};
// Static tables owned by the SystemDictionary // Static tables owned by the SystemDictionary
// Hashtable holding placeholders for classes being loaded.
static PlaceholderTable* _placeholders;
// Constraints on class loaders // Constraints on class loaders
static LoaderConstraintTable* _loader_constraints; static LoaderConstraintTable* _loader_constraints;
@ -340,35 +311,55 @@ public:
static ProtectionDomainCacheTable* _pd_cache_table; static ProtectionDomainCacheTable* _pd_cache_table;
protected: protected:
static InstanceKlass* _well_known_klasses[];
private:
// table of box klasses (int_klass, etc.)
static InstanceKlass* _box_klasses[T_VOID+1];
static OopHandle _java_system_loader;
static OopHandle _java_platform_loader;
static void validate_protection_domain(InstanceKlass* klass, static void validate_protection_domain(InstanceKlass* klass,
Handle class_loader, Handle class_loader,
Handle protection_domain, TRAPS); Handle protection_domain, TRAPS);
friend class VM_PopulateDumpSharedSpace; friend class VM_PopulateDumpSharedSpace;
friend class TraversePlaceholdersClosure;
static PlaceholderTable* placeholders() { return _placeholders; }
static LoaderConstraintTable* constraints() { return _loader_constraints; } static LoaderConstraintTable* constraints() { return _loader_constraints; }
static ResolutionErrorTable* resolution_errors() { return _resolution_errors; } static ResolutionErrorTable* resolution_errors() { return _resolution_errors; }
static SymbolPropertyTable* invoke_method_table() { return _invoke_method_table; } static SymbolPropertyTable* invoke_method_table() { return _invoke_method_table; }
static void post_class_load_event(EventClassLoad* event, const InstanceKlass* k, const ClassLoaderData* init_cld);
private:
// Basic loading operations // Basic loading operations
static InstanceKlass* resolve_instance_class_or_null_helper(Symbol* name, static InstanceKlass* resolve_instance_class_or_null_helper(Symbol* name,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
TRAPS); TRAPS);
static InstanceKlass* resolve_instance_class_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS); static InstanceKlass* resolve_instance_class_or_null(Symbol* class_name,
static Klass* resolve_array_class_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS); Handle class_loader,
static InstanceKlass* handle_parallel_super_load(Symbol* class_name, Symbol* supername, Handle class_loader, Handle protection_domain, Handle lockObject, TRAPS); Handle protection_domain, TRAPS);
static Klass* resolve_array_class_or_null(Symbol* class_name,
Handle class_loader,
Handle protection_domain, TRAPS);
static InstanceKlass* handle_parallel_super_load(Symbol* class_name,
Symbol* supername,
Handle class_loader,
Handle protection_domain,
Handle lockObject, TRAPS);
// Wait on SystemDictionary_lock; unlocks lockObject before // Wait on SystemDictionary_lock; unlocks lockObject before
// waiting; relocks lockObject with correct recursion count // waiting; relocks lockObject with correct recursion count
// after waiting, but before reentering SystemDictionary_lock // after waiting, but before reentering SystemDictionary_lock
// to preserve lock order semantics. // to preserve lock order semantics.
static void double_lock_wait(Thread* thread, Handle lockObject); static void double_lock_wait(Thread* thread, Handle lockObject);
static void define_instance_class(InstanceKlass* k, Handle class_loader, TRAPS); static void define_instance_class(InstanceKlass* k, Handle class_loader, TRAPS);
static InstanceKlass* find_or_define_instance_class(Symbol* class_name, static InstanceKlass* find_or_define_helper(Symbol* class_name,
Handle class_loader, Handle class_loader,
InstanceKlass* k, TRAPS); InstanceKlass* k, TRAPS);
static InstanceKlass* load_instance_class(Symbol* class_name, Handle class_loader, TRAPS);
static bool is_parallelDefine(Handle class_loader);
static Handle compute_loader_lock_object(Thread* thread, Handle class_loader);
static void check_loader_lock_contention(Thread* thread, Handle loader_lock);
static bool is_shared_class_visible(Symbol* class_name, InstanceKlass* ik, static bool is_shared_class_visible(Symbol* class_name, InstanceKlass* ik,
PackageEntry* pkg_entry, PackageEntry* pkg_entry,
Handle class_loader, TRAPS); Handle class_loader, TRAPS);
@ -376,11 +367,19 @@ protected:
InstanceKlass* ik, InstanceKlass* ik,
PackageEntry* pkg_entry, PackageEntry* pkg_entry,
Handle class_loader, TRAPS); Handle class_loader, TRAPS);
static bool check_shared_class_super_type(InstanceKlass* child, InstanceKlass* super, static bool check_shared_class_super_type(InstanceKlass* klass, InstanceKlass* super,
Handle class_loader, Handle protection_domain, Handle class_loader, Handle protection_domain,
bool is_superclass, TRAPS); bool is_superclass, TRAPS);
static bool check_shared_class_super_types(InstanceKlass* ik, Handle class_loader, static bool check_shared_class_super_types(InstanceKlass* ik, Handle class_loader,
Handle protection_domain, TRAPS); Handle protection_domain, TRAPS);
// Second part of load_shared_class
static void load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data, TRAPS) NOT_CDS_RETURN;
protected:
// Used by SystemDictionaryShared
static bool add_loader_constraint(Symbol* name, Klass* klass_being_linked, Handle loader1,
Handle loader2, TRAPS);
static void post_class_load_event(EventClassLoad* event, const InstanceKlass* k, const ClassLoaderData* init_cld);
static InstanceKlass* load_shared_lambda_proxy_class(InstanceKlass* ik, static InstanceKlass* load_shared_lambda_proxy_class(InstanceKlass* ik,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
@ -392,16 +391,13 @@ protected:
const ClassFileStream *cfs, const ClassFileStream *cfs,
PackageEntry* pkg_entry, PackageEntry* pkg_entry,
TRAPS); TRAPS);
// Second part of load_shared_class
static void load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data, TRAPS) NOT_CDS_RETURN;
static InstanceKlass* load_shared_boot_class(Symbol* class_name, static InstanceKlass* load_shared_boot_class(Symbol* class_name,
PackageEntry* pkg_entry, PackageEntry* pkg_entry,
TRAPS); TRAPS);
static InstanceKlass* load_instance_class(Symbol* class_name, Handle class_loader, TRAPS);
static Handle compute_loader_lock_object(Thread* thread, Handle class_loader);
static bool is_parallelCapable(Handle class_loader); static bool is_parallelCapable(Handle class_loader);
static bool is_parallelDefine(Handle class_loader); static InstanceKlass* find_or_define_instance_class(Symbol* class_name,
Handle class_loader,
InstanceKlass* k, TRAPS);
public: public:
static bool is_system_class_loader(oop class_loader); static bool is_system_class_loader(oop class_loader);
static bool is_platform_class_loader(oop class_loader); static bool is_platform_class_loader(oop class_loader);
@ -434,10 +430,6 @@ protected:
static void update_dictionary(unsigned int hash, static void update_dictionary(unsigned int hash,
InstanceKlass* k, Handle loader); InstanceKlass* k, Handle loader);
private:
static OopHandle _java_system_loader;
static OopHandle _java_platform_loader;
public: public:
static TableStatistics placeholders_statistics(); static TableStatistics placeholders_statistics();
static TableStatistics loader_constraints_statistics(); static TableStatistics loader_constraints_statistics();

View File

@ -1046,7 +1046,7 @@ InstanceKlass* SystemDictionaryShared::find_or_load_shared_class(
k = load_shared_class_for_builtin_loader(name, class_loader, THREAD); k = load_shared_class_for_builtin_loader(name, class_loader, THREAD);
if (k != NULL) { if (k != NULL) {
define_instance_class(k, class_loader, CHECK_NULL); k = find_or_define_instance_class(name, class_loader, k, CHECK_NULL);
} }
} }
} }
@ -1219,14 +1219,14 @@ bool SystemDictionaryShared::add_unregistered_class(InstanceKlass* k, TRAPS) {
} }
// This function is called to resolve the super/interfaces of shared classes for // This function is called to resolve the super/interfaces of shared classes for
// non-built-in loaders. E.g., ChildClass in the below example // non-built-in loaders. E.g., SharedClass in the below example
// where "super:" (and optionally "interface:") have been specified. // where "super:" (and optionally "interface:") have been specified.
// //
// java/lang/Object id: 0 // java/lang/Object id: 0
// Interface id: 2 super: 0 source: cust.jar // Interface id: 2 super: 0 source: cust.jar
// ChildClass id: 4 super: 0 interfaces: 2 source: cust.jar // SharedClass id: 4 super: 0 interfaces: 2 source: cust.jar
InstanceKlass* SystemDictionaryShared::dump_time_resolve_super_or_fail( InstanceKlass* SystemDictionaryShared::dump_time_resolve_super_or_fail(
Symbol* child_name, Symbol* class_name, Handle class_loader, Symbol* class_name, Symbol* super_name, Handle class_loader,
Handle protection_domain, bool is_superclass, TRAPS) { Handle protection_domain, bool is_superclass, TRAPS) {
assert(DumpSharedSpaces, "only when dumping"); assert(DumpSharedSpaces, "only when dumping");
@ -1236,13 +1236,13 @@ InstanceKlass* SystemDictionaryShared::dump_time_resolve_super_or_fail(
// We're still loading the well-known classes, before the ClassListParser is created. // We're still loading the well-known classes, before the ClassListParser is created.
return NULL; return NULL;
} }
if (child_name->equals(parser->current_class_name())) { if (class_name->equals(parser->current_class_name())) {
// When this function is called, all the numbered super and interface types // When this function is called, all the numbered super and interface types
// must have already been loaded. Hence this function is never recursively called. // must have already been loaded. Hence this function is never recursively called.
if (is_superclass) { if (is_superclass) {
return parser->lookup_super_for_current_class(class_name); return parser->lookup_super_for_current_class(super_name);
} else { } else {
return parser->lookup_interface_for_current_class(class_name); return parser->lookup_interface_for_current_class(super_name);
} }
} else { } else {
// The VM is not trying to resolve a super type of parser->current_class_name(). // The VM is not trying to resolve a super type of parser->current_class_name().

View File

@ -246,8 +246,8 @@ public:
static bool is_sharing_possible(ClassLoaderData* loader_data); static bool is_sharing_possible(ClassLoaderData* loader_data);
static bool add_unregistered_class(InstanceKlass* k, TRAPS); static bool add_unregistered_class(InstanceKlass* k, TRAPS);
static InstanceKlass* dump_time_resolve_super_or_fail(Symbol* child_name, static InstanceKlass* dump_time_resolve_super_or_fail(Symbol* class_name,
Symbol* class_name, Symbol* super_name,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
bool is_superclass, bool is_superclass,

View File

@ -726,8 +726,6 @@ void VM_PopulateDumpSharedSpace::doit() {
// shared classes at runtime, where constraints were previously created. // shared classes at runtime, where constraints were previously created.
guarantee(SystemDictionary::constraints()->number_of_entries() == 0, guarantee(SystemDictionary::constraints()->number_of_entries() == 0,
"loader constraints are not saved"); "loader constraints are not saved");
guarantee(SystemDictionary::placeholders()->number_of_entries() == 0,
"placeholders are not saved");
// At this point, many classes have been loaded. // At this point, many classes have been loaded.
// Gather systemDictionary classes in a global array and do everything to // Gather systemDictionary classes in a global array and do everything to