< prev index next >
src/hotspot/share/classfile/systemDictionary.cpp
Print this page
*** 1,7 ****
/*
! * Copyright (c) 1997, 2017, 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.
--- 1,7 ----
/*
! * Copyright (c) 1997, 2018, 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.
*** 157,167 ****
// ----------------------------------------------------------------------------
// Parallel class loading check
bool SystemDictionary::is_parallelCapable(Handle class_loader) {
! if (UnsyncloadClass || class_loader.is_null()) return true;
if (AlwaysLockClassLoader) return false;
return java_lang_ClassLoader::parallelCapable(class_loader());
}
// ----------------------------------------------------------------------------
// ParallelDefineClass flag does not apply to bootclass loader
--- 157,167 ----
// ----------------------------------------------------------------------------
// Parallel class loading check
bool SystemDictionary::is_parallelCapable(Handle class_loader) {
! if (class_loader.is_null()) return true;
if (AlwaysLockClassLoader) return false;
return java_lang_ClassLoader::parallelCapable(class_loader());
}
// ----------------------------------------------------------------------------
// ParallelDefineClass flag does not apply to bootclass loader
*** 501,512 ****
// Waits on SystemDictionary_lock to indicate placeholder table updated
// On return, caller must recheck placeholder table state
//
// We only get here if
// 1) custom classLoader, i.e. not bootstrap classloader
! // 2) UnsyncloadClass not set
! // 3) custom classLoader has broken the class loader objectLock
// so another thread got here in parallel
//
// lockObject must be held.
// Complicated dance due to lock ordering:
// Must first release the classloader object lock to
--- 501,511 ----
// Waits on SystemDictionary_lock to indicate placeholder table updated
// On return, caller must recheck placeholder table state
//
// We only get here if
// 1) custom classLoader, i.e. not bootstrap classloader
! // 2) custom classLoader has broken the class loader objectLock
// so another thread got here in parallel
//
// lockObject must be held.
// Complicated dance due to lock ordering:
// Must first release the classloader object lock to
*** 592,602 ****
// Klass is already loaded, so just return it
return check;
} else {
placeholder = placeholders()->get_entry(p_index, p_hash, name, loader_data);
if (placeholder && placeholder->super_load_in_progress() ){
- // Before UnsyncloadClass:
// We only get here if the application has released the
// classloader lock when another thread was in the middle of loading a
// superclass/superinterface for this class, and now
// this thread is also trying to load this class.
// To minimize surprises, the first thread that started to
--- 591,600 ----
*** 685,697 ****
// define via jvm/jni_DefineClass which will acquire the
// class loader object lock to protect against multiple threads
// defining the class in parallel by accident.
// This lock must be acquired here so the waiter will find
// any successful result in the SystemDictionary and not attempt
! // the define
! // ParallelCapable Classloaders and the bootstrap classloader,
! // or all classloaders with UnsyncloadClass do not acquire lock here
bool DoObjectLock = true;
if (is_parallelCapable(class_loader)) {
DoObjectLock = false;
}
--- 683,695 ----
// define via jvm/jni_DefineClass which will acquire the
// class loader object lock to protect against multiple threads
// defining the class in parallel by accident.
// This lock must be acquired here so the waiter will find
// any successful result in the SystemDictionary and not attempt
! // the define.
! // ParallelCapable Classloaders and the bootstrap classloader
! // do not acquire lock here.
bool DoObjectLock = true;
if (is_parallelCapable(class_loader)) {
DoObjectLock = false;
}
*** 763,780 ****
// as a deadlock workaround. Detection of this case requires that
// this check is done while holding the classloader object lock,
// and that lock is still held when calling classloader's loadClass.
// For these classloaders, we ensure that the first requestor
// completes the load and other requestors wait for completion.
! // case 3. UnsyncloadClass - don't use objectLocker
! // With this flag, we allow parallel classloading of a
! // class/classloader pair
! // case4. 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 5. parallelCapable user level classloaders - without objectLocker
// Allow parallel classloading of a class/classloader pair
{
MutexLocker mu(SystemDictionary_lock, THREAD);
if (class_loader.is_null() || !is_parallelCapable(class_loader)) {
--- 761,775 ----
// as a deadlock workaround. Detection of this case requires that
// this check is done while holding the classloader object lock,
// and that lock is still held when calling classloader's loadClass.
// For these classloaders, we ensure that the first requestor
// 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(SystemDictionary_lock, THREAD);
if (class_loader.is_null() || !is_parallelCapable(class_loader)) {
*** 809,819 ****
}
}
}
}
// All cases: add LOAD_INSTANCE holding SystemDictionary_lock
! // case 3: UnsyncloadClass || case 5: parallelCapable: allow competing threads to try
// LOAD_INSTANCE in parallel
if (!throw_circularity_error && !class_has_been_loaded) {
PlaceholderEntry* newprobe = placeholders()->find_and_add(p_index, p_hash, name, loader_data, PlaceholderTable::LOAD_INSTANCE, NULL, THREAD);
load_instance_added = true;
--- 804,814 ----
}
}
}
}
// All cases: add LOAD_INSTANCE holding SystemDictionary_lock
! // case 4: parallelCapable: allow competing threads to try
// LOAD_INSTANCE in parallel
if (!throw_circularity_error && !class_has_been_loaded) {
PlaceholderEntry* newprobe = placeholders()->find_and_add(p_index, p_hash, name, loader_data, PlaceholderTable::LOAD_INSTANCE, NULL, THREAD);
load_instance_added = true;
*** 842,860 ****
if (!class_has_been_loaded) {
// Do actual loading
k = load_instance_class(name, class_loader, THREAD);
- // For UnsyncloadClass only
// If they got a linkageError, check if a parallel class load succeeded.
// 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
// successfully loaded InstanceKlass
// Should not get here for classloaders that support parallelism
// with the new cleaner mechanism, even with AllowParallelDefineClass
// Bootstrap goes through here to allow for an extra guarantee check
! if (UnsyncloadClass || (class_loader.is_null())) {
if (k == NULL && HAS_PENDING_EXCEPTION
&& PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
MutexLocker mu(SystemDictionary_lock, THREAD);
InstanceKlass* check = find_class(d_hash, name, dictionary);
if (check != NULL) {
--- 837,854 ----
if (!class_has_been_loaded) {
// Do actual loading
k = load_instance_class(name, class_loader, THREAD);
// If they got a linkageError, check if a parallel class load succeeded.
// 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
// successfully loaded InstanceKlass
// Should not get here for classloaders that support parallelism
// with the new cleaner mechanism, even with AllowParallelDefineClass
// Bootstrap goes through here to allow for an extra guarantee check
! if ((class_loader.is_null())) {
if (k == NULL && HAS_PENDING_EXCEPTION
&& PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
MutexLocker mu(SystemDictionary_lock, THREAD);
InstanceKlass* check = find_class(d_hash, name, dictionary);
if (check != NULL) {
*** 1095,1105 ****
#endif
HandleMark hm(THREAD);
// Classloaders that support parallelism, e.g. bootstrap classloader,
! // or all classloaders with UnsyncloadClass do not acquire lock here
bool DoObjectLock = true;
if (is_parallelCapable(class_loader)) {
DoObjectLock = false;
}
--- 1089,1099 ----
#endif
HandleMark hm(THREAD);
// Classloaders that support parallelism, e.g. bootstrap classloader,
! // do not acquire lock here
bool DoObjectLock = true;
if (is_parallelCapable(class_loader)) {
DoObjectLock = false;
}
*** 1559,1597 ****
// Call public unsynchronized loadClass(String) directly for all class loaders
// for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will
// acquire a class-name based lock rather than the class loader object lock.
// JDK < 7 already acquire the class loader lock in loadClass(String, boolean),
// so the call to loadClassInternal() was not required.
- //
- // UnsyncloadClass flag means both call loadClass(String) and do
- // not acquire the class loader lock even for class loaders that are
- // not parallelCapable. This was a risky transitional
- // flag for diagnostic purposes only. It is risky to call
- // custom class loaders without synchronization.
- // WARNING If a custom class loader does NOT synchronizer findClass, or callers of
- // findClass, the UnsyncloadClass flag risks unexpected timing bugs in the field.
- // Do NOT assume this will be supported in future releases.
- //
- // Added MustCallLoadClassInternal in case we discover in the field
- // a customer that counts on this call
- if (MustCallLoadClassInternal && has_loadClassInternal()) {
- JavaCalls::call_special(&result,
- class_loader,
- spec_klass,
- vmSymbols::loadClassInternal_name(),
- vmSymbols::string_class_signature(),
- string,
- CHECK_NULL);
- } else {
JavaCalls::call_virtual(&result,
class_loader,
spec_klass,
vmSymbols::loadClass_name(),
vmSymbols::string_class_signature(),
string,
CHECK_NULL);
- }
assert(result.get_type() == T_OBJECT, "just checking");
oop obj = (oop) result.get_jobject();
// Primitive classes return null since forName() can not be
--- 1553,1569 ----
*** 1716,1726 ****
PlaceholderEntry* probe;
{
MutexLocker mu(SystemDictionary_lock, THREAD);
// First check if class already defined
! if (UnsyncloadClass || (is_parallelDefine(class_loader))) {
InstanceKlass* check = find_class(d_hash, name_h, dictionary);
if (check != NULL) {
return check;
}
}
--- 1688,1698 ----
PlaceholderEntry* probe;
{
MutexLocker mu(SystemDictionary_lock, THREAD);
// First check if class already defined
! if (is_parallelDefine(class_loader)) {
InstanceKlass* check = find_class(d_hash, name_h, dictionary);
if (check != NULL) {
return check;
}
}
*** 1735,1745 ****
SystemDictionary_lock->wait();
}
// Only special cases allow parallel defines and can use other thread's results
// Other cases fall through, and may run into duplicate defines
// caught by finding an entry in the SystemDictionary
! if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->instance_klass() != NULL)) {
placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD);
SystemDictionary_lock->notify_all();
#ifdef ASSERT
InstanceKlass* check = find_class(d_hash, name_h, dictionary);
assert(check != NULL, "definer missed recording success");
--- 1707,1717 ----
SystemDictionary_lock->wait();
}
// Only special cases allow parallel defines and can use other thread's results
// Other cases fall through, and may run into duplicate defines
// caught by finding an entry in the SystemDictionary
! if (is_parallelDefine(class_loader) && (probe->instance_klass() != NULL)) {
placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD);
SystemDictionary_lock->notify_all();
#ifdef ASSERT
InstanceKlass* check = find_class(d_hash, name_h, dictionary);
assert(check != NULL, "definer missed recording success");
< prev index next >