< 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 >