mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
6893504: LinkageError for bootstrap duplicate class definitions
Reviewed-by: kamg, xlu
This commit is contained in:
parent
a3b18775c7
commit
47748afed5
2 changed files with 23 additions and 8 deletions
|
@ -99,6 +99,15 @@ bool SystemDictionary::is_parallelCapable(Handle class_loader) {
|
||||||
return java_lang_Class::parallelCapable(class_loader());
|
return java_lang_Class::parallelCapable(class_loader());
|
||||||
}
|
}
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
// ParallelDefineClass flag does not apply to bootclass loader
|
||||||
|
bool SystemDictionary::is_parallelDefine(Handle class_loader) {
|
||||||
|
if (class_loader.is_null()) return false;
|
||||||
|
if (AllowParallelDefineClass && java_lang_Class::parallelCapable(class_loader())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
// Resolving of classes
|
// Resolving of classes
|
||||||
|
|
||||||
// Forwards to resolve_or_null
|
// Forwards to resolve_or_null
|
||||||
|
@ -724,13 +733,13 @@ klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_nam
|
||||||
// Do actual loading
|
// Do actual loading
|
||||||
k = load_instance_class(name, class_loader, THREAD);
|
k = load_instance_class(name, class_loader, THREAD);
|
||||||
|
|
||||||
// For UnsyncloadClass and AllowParallelDefineClass only:
|
// For UnsyncloadClass only
|
||||||
// If they got a linkageError, check if a parallel class load succeeded.
|
// If they got a linkageError, check if a parallel class load succeeded.
|
||||||
// If it did, then for bytecode resolution the specification requires
|
// If it did, then for bytecode resolution the specification requires
|
||||||
// that we return the same result we did for the other thread, i.e. the
|
// that we return the same result we did for the other thread, i.e. the
|
||||||
// successfully loaded instanceKlass
|
// successfully loaded instanceKlass
|
||||||
// Should not get here for classloaders that support parallelism
|
// Should not get here for classloaders that support parallelism
|
||||||
// with the new cleaner mechanism
|
// with the new cleaner mechanism, even with AllowParallelDefineClass
|
||||||
// Bootstrap goes through here to allow for an extra guarantee check
|
// Bootstrap goes through here to allow for an extra guarantee check
|
||||||
if (UnsyncloadClass || (class_loader.is_null())) {
|
if (UnsyncloadClass || (class_loader.is_null())) {
|
||||||
if (k.is_null() && HAS_PENDING_EXCEPTION
|
if (k.is_null() && HAS_PENDING_EXCEPTION
|
||||||
|
@ -1483,14 +1492,17 @@ void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support parallel classloading
|
// Support parallel classloading
|
||||||
// Initial implementation for bootstrap classloader
|
// All parallel class loaders, including bootstrap classloader
|
||||||
// For custom class loaders that support parallel classloading,
|
// lock a placeholder entry for this class/class_loader pair
|
||||||
|
// to allow parallel defines of different classes for this class loader
|
||||||
// With AllowParallelDefine flag==true, in case they do not synchronize around
|
// With AllowParallelDefine flag==true, in case they do not synchronize around
|
||||||
// FindLoadedClass/DefineClass, calls, we check for parallel
|
// FindLoadedClass/DefineClass, calls, we check for parallel
|
||||||
// loading for them, wait if a defineClass is in progress
|
// loading for them, wait if a defineClass is in progress
|
||||||
// and return the initial requestor's results
|
// and return the initial requestor's results
|
||||||
|
// This flag does not apply to the bootstrap classloader.
|
||||||
// With AllowParallelDefine flag==false, call through to define_instance_class
|
// With AllowParallelDefine flag==false, call through to define_instance_class
|
||||||
// which will throw LinkageError: duplicate class definition.
|
// which will throw LinkageError: duplicate class definition.
|
||||||
|
// False is the requested default.
|
||||||
// For better performance, the class loaders should synchronize
|
// For better performance, the class loaders should synchronize
|
||||||
// findClass(), i.e. FindLoadedClass/DefineClassIfAbsent or they
|
// findClass(), i.e. FindLoadedClass/DefineClassIfAbsent or they
|
||||||
// potentially waste time reading and parsing the bytestream.
|
// potentially waste time reading and parsing the bytestream.
|
||||||
|
@ -1511,10 +1523,12 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(symbolHandle
|
||||||
{
|
{
|
||||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||||
// First check if class already defined
|
// First check if class already defined
|
||||||
|
if (UnsyncloadClass || (is_parallelDefine(class_loader))) {
|
||||||
klassOop check = find_class(d_index, d_hash, name_h, class_loader);
|
klassOop check = find_class(d_index, d_hash, name_h, class_loader);
|
||||||
if (check != NULL) {
|
if (check != NULL) {
|
||||||
return(instanceKlassHandle(THREAD, check));
|
return(instanceKlassHandle(THREAD, check));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Acquire define token for this class/classloader
|
// Acquire define token for this class/classloader
|
||||||
symbolHandle nullsymbolHandle;
|
symbolHandle nullsymbolHandle;
|
||||||
|
@ -1529,7 +1543,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(symbolHandle
|
||||||
// Only special cases allow parallel defines and can use other thread's results
|
// Only special cases allow parallel defines and can use other thread's results
|
||||||
// Other cases fall through, and may run into duplicate defines
|
// Other cases fall through, and may run into duplicate defines
|
||||||
// caught by finding an entry in the SystemDictionary
|
// caught by finding an entry in the SystemDictionary
|
||||||
if ((UnsyncloadClass || AllowParallelDefineClass) && (probe->instanceKlass() != NULL)) {
|
if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->instanceKlass() != NULL)) {
|
||||||
probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS);
|
probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS);
|
||||||
placeholders()->find_and_remove(p_index, p_hash, name_h, class_loader, THREAD);
|
placeholders()->find_and_remove(p_index, p_hash, name_h, class_loader, THREAD);
|
||||||
SystemDictionary_lock->notify_all();
|
SystemDictionary_lock->notify_all();
|
||||||
|
|
|
@ -578,6 +578,7 @@ private:
|
||||||
static Handle compute_loader_lock_object(Handle class_loader, TRAPS);
|
static Handle compute_loader_lock_object(Handle class_loader, TRAPS);
|
||||||
static void check_loader_lock_contention(Handle loader_lock, TRAPS);
|
static void check_loader_lock_contention(Handle loader_lock, TRAPS);
|
||||||
static bool is_parallelCapable(Handle class_loader);
|
static bool is_parallelCapable(Handle class_loader);
|
||||||
|
static bool is_parallelDefine(Handle class_loader);
|
||||||
|
|
||||||
static klassOop find_shared_class(symbolHandle class_name);
|
static klassOop find_shared_class(symbolHandle class_name);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue