--- old/src/share/vm/classfile/classLoaderData.cpp 2017-07-19 11:07:20.450964223 -0400 +++ new/src/share/vm/classfile/classLoaderData.cpp 2017-07-19 11:07:20.076759222 -0400 @@ -114,6 +114,12 @@ } else { _unnamed_module = NULL; } + + if (!is_anonymous) { + _dictionary = create_dictionary(); + } else { + _dictionary = NULL; + } TRACE_INIT_ID(this); } @@ -453,10 +459,12 @@ // Class iterator used by the compiler. It gets some number of classes at // a safepoint to decay invocation counters on the methods. class ClassLoaderDataGraphKlassIteratorStatic { - ClassLoaderData* _current_loader_data = NULL; - Klass* _current_class_entry = NULL; + ClassLoaderData* _current_loader_data; + Klass* _current_class_entry; public: + ClassLoaderDataGraphKlassIteratorStatic() : _current_loader_data(NULL), _current_class_entry(NULL) {} + InstanceKlass* try_get_next_class() { assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); while (true) { @@ -612,34 +620,17 @@ return newsize; } -Dictionary* ClassLoaderData::dictionary_or_null() { - return load_ptr_acquire(&_dictionary); -} - -Dictionary* ClassLoaderData::dictionary() { +Dictionary* ClassLoaderData::create_dictionary() { assert(!is_anonymous(), "anonymous class loader data do not have a dictionary"); - // Lazily create the dictionary, in the same way of lazily creating modules. - // Lock-free access requires load_ptr_acquire. - Dictionary* dictionary = load_ptr_acquire(&_dictionary); - if (dictionary == NULL) { - MutexLocker m1(SystemDictionary_lock); - // Check if _dictionary got allocated while we were waiting for this lock. - if ((dictionary = _dictionary) == NULL) { - int size; - if (this == the_null_class_loader_data()) { - size = _boot_loader_dictionary_size; - } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) { - size = 1; // there's only one class in relection class loader and no initiated classes - } else { - size = calculate_dictionary_size(PredictedLoadedClassCount); - } - dictionary = new Dictionary(this, size); - // Ensure _dictionary is stable, since it is examined without a lock. - // Don't need metaspace_lock since SystemDictionary_lock is held. - OrderAccess::release_store_ptr(&_dictionary, dictionary); - } + int size; + if (_the_null_class_loader_data == NULL) { + size = _boot_loader_dictionary_size; + } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) { + size = 1; // there's only one class in relection class loader and no initiated classes + } else { + size = calculate_dictionary_size(PredictedLoadedClassCount); } - return dictionary; + return new Dictionary(this, size); } // Unloading support @@ -1109,21 +1100,24 @@ } #define FOR_ALL_DICTIONARY(X) for (ClassLoaderData* X = _head; X != NULL; X = X->next()) \ - if (X->dictionary_or_null() != NULL) + if (X->dictionary() != NULL) // Walk classes in the loaded class dictionaries in various forms. +// Only walks the classes defined in this class loader. void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*)) { FOR_ALL_DICTIONARY(cld) { cld->dictionary()->classes_do(f); } } +// Only walks the classes defined in this class loader. void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS) { FOR_ALL_DICTIONARY(cld) { cld->dictionary()->classes_do(f, CHECK); } } +// Walks all entries in the dictionary including entries initiated by this class loader. void ClassLoaderDataGraph::dictionary_all_entries_do(void f(InstanceKlass*, ClassLoaderData*)) { FOR_ALL_DICTIONARY(cld) { cld->dictionary()->all_entries_do(f); @@ -1245,17 +1239,19 @@ } if (seen_dead_loader) { - // Walk a Dictionary, ModuleEntry's reads, and a PackageEntry's exports - // lists to determine if there are modules on those lists that are now - // dead and should be removed. A module's life cycle is equivalent - // to its defining class loader's life cycle. Since a module is - // considered dead if its class loader is dead, these walks must - // occur after each class loader's aliveness is determined. data = _head; while (data != NULL) { - if (data->dictionary_or_null() != NULL) { + // Remove entries in the dictionary of live class loader that have + // initiated loading classes in a dead class loader. + if (data->dictionary() != NULL) { data->dictionary()->do_unloading(); } + // Walk a ModuleEntry's reads, and a PackageEntry's exports + // lists to determine if there are modules on those lists that are now + // dead and should be removed. A module's life cycle is equivalent + // to its defining class loader's life cycle. Since a module is + // considered dead if its class loader is dead, these walks must + // occur after each class loader's aliveness is determined. if (data->packages() != NULL) { data->packages()->purge_all_package_exports(); } --- old/src/share/vm/classfile/classLoaderData.hpp 2017-07-19 11:07:29.087960740 -0400 +++ new/src/share/vm/classfile/classLoaderData.hpp 2017-07-19 11:07:28.855707934 -0400 @@ -46,9 +46,8 @@ // used by the dynamic linker to allocate the runtime representation of all // the types it defines. // -// ClassLoaderData are stored in the runtime representation of classes and the -// system dictionary, are roots of garbage collection, and provides iterators -// for root tracing and other GC operations. +// ClassLoaderData are stored in the runtime representation of classes, +// and provides iterators for root tracing and other GC operations. class ClassLoaderData; class JNIMethodBlock; @@ -241,9 +240,9 @@ Klass* volatile _klasses; // The classes defined by the class loader. PackageEntryTable* volatile _packages; // The packages defined by the class loader. + ModuleEntryTable* volatile _modules; // The modules defined by the class loader. ModuleEntry* _unnamed_module; // This class loader's unnamed module. - ModuleEntryTable* volatile _modules; // The modules defined by the class loader. - Dictionary* volatile _dictionary; // The loaded InstanceKlasses, including initiated by this class loader + Dictionary* _dictionary; // The loaded InstanceKlasses, including initiated by this class loader // These method IDs are created for the class loader and set to NULL when the // class loader is unloaded. They are rarely freed, only for redefine classes @@ -290,6 +289,7 @@ // Allocate out of this class loader data MetaWord* allocate(size_t size); + Dictionary* create_dictionary(); public: bool is_alive(BoolObjectClosure* is_alive_closure) const; @@ -358,7 +358,7 @@ void print() { print_on(tty); } void print_on(outputStream* out) const; - void print_value() { print_value_on(tty); } + void print_value() { print_value_on(tty); } void print_value_on(outputStream* out) const; void dump(outputStream * const out) PRODUCT_RETURN; void verify(); @@ -377,8 +377,7 @@ bool modules_defined() { return (_modules != NULL); } // Loaded class dictionary - Dictionary* dictionary(); - Dictionary* dictionary_or_null(); + Dictionary* dictionary() const { return _dictionary; } void add_to_deallocate_list(Metadata* m); --- old/src/share/vm/classfile/dictionary.cpp 2017-07-19 11:07:37.131454600 -0400 +++ new/src/share/vm/classfile/dictionary.cpp 2017-07-19 11:07:36.880450020 -0400 @@ -95,7 +95,7 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const { #ifdef ASSERT - if (protection_domain == klass()->protection_domain()) { + if (protection_domain == instance_klass()->protection_domain()) { // Ensure this doesn't show up in the pd_set (invariant) bool in_pd_set = false; for (ProtectionDomainEntry* current = _pd_set; @@ -113,7 +113,7 @@ } #endif /* ASSERT */ - if (protection_domain == klass()->protection_domain()) { + if (protection_domain == instance_klass()->protection_domain()) { // Succeeds trivially return true; } @@ -160,7 +160,7 @@ for (int index = 0; index < table_size(); index++) { for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) { probe = *p; - InstanceKlass* ik = probe->klass(); + InstanceKlass* ik = probe->instance_klass(); ClassLoaderData* k_def_class_loader_data = ik->class_loader_data(); // If the klass that this loader initiated is dead, @@ -169,10 +169,10 @@ if (k_def_class_loader_data->is_unloading()) { assert(k_def_class_loader_data != loader_data(), "cannot have live defining loader and unreachable klass"); - *p = probe->next(); - free_entry(probe); - continue; - } + *p = probe->next(); + free_entry(probe); + continue; + } p = probe->next_addr(); } } @@ -184,7 +184,7 @@ for (int index = 0; index < table_size(); index++) { for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) { probe = *p; - InstanceKlass* ik = probe->klass(); + InstanceKlass* ik = probe->instance_klass(); if (ik->is_in_error_state()) { // purge this entry *p = probe->next(); free_entry(probe); @@ -204,7 +204,7 @@ for (DictionaryEntry* probe = bucket(index); probe != NULL; probe = probe->next()) { - InstanceKlass* k = probe->klass(); + InstanceKlass* k = probe->instance_klass(); if (loader_data() == k->class_loader_data()) { f(k); } @@ -219,7 +219,7 @@ for (DictionaryEntry* probe = bucket(index); probe != NULL; probe = probe->next()) { - InstanceKlass* k = probe->klass(); + InstanceKlass* k = probe->instance_klass(); if (loader_data() == k->class_loader_data()) { f(k, CHECK); } @@ -233,14 +233,14 @@ for (DictionaryEntry* probe = bucket(index); probe != NULL; probe = probe->next()) { - InstanceKlass* k = probe->klass(); + InstanceKlass* k = probe->instance_klass(); f(k, loader_data()); } } } -// Add a loaded class to the system dictionary. +// Add a loaded class to the dictionary. // Readers of the SystemDictionary aren't always locked, so _buckets // is volatile. The store of the next field in the constructor is // also cast to volatile; we do this to ensure store order is maintained @@ -257,7 +257,7 @@ } -// This routine does not lock the system dictionary. +// This routine does not lock the dictionary. // // Since readers don't hold a lock, we must make sure that system // dictionary entries are only removed at a safepoint (when only one @@ -285,7 +285,7 @@ Handle protection_domain) { DictionaryEntry* entry = get_entry(index, hash, name); if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) { - return entry->klass(); + return entry->instance_klass(); } else { return NULL; } @@ -298,7 +298,7 @@ assert (index == index_for(name), "incorrect index?"); DictionaryEntry* entry = get_entry(index, hash, name); - return (entry != NULL) ? entry->klass() : NULL; + return (entry != NULL) ? entry->instance_klass() : NULL; } @@ -310,7 +310,7 @@ assert (index == index_for(name), "incorrect index?"); DictionaryEntry* entry = get_entry(index, hash, name); - return (entry != NULL) ? entry->klass() : NULL; + return (entry != NULL) ? entry->instance_klass() : NULL; } @@ -362,7 +362,7 @@ DictionaryEntry* p = master_list; master_list = master_list->next(); p->set_next(NULL); - Symbol* class_name = p->klass()->name(); + Symbol* class_name = p->instance_klass()->name(); // Since the null class loader data isn't copied to the CDS archive, // compute the hash with NULL for loader data. unsigned int hash = compute_hash(class_name); @@ -436,8 +436,9 @@ void Dictionary::print(bool details) { ResourceMark rm; + assert(loader_data() != NULL, "loader data should not be null"); if (details) { - tty->print_cr("Java system dictionary (table_size=%d, classes=%d)", + tty->print_cr("Java dictionary (table_size=%d, classes=%d)", table_size(), number_of_entries()); tty->print_cr("^ indicates that initiating loader is different from " "defining loader"); @@ -447,7 +448,7 @@ for (DictionaryEntry* probe = bucket(index); probe != NULL; probe = probe->next()) { - Klass* e = probe->klass(); + Klass* e = probe->instance_klass(); bool is_defining_class = (loader_data() == e->class_loader_data()); if (details) { @@ -467,15 +468,14 @@ } void DictionaryEntry::verify() { - Klass* e = klass(); - guarantee(e->is_instance_klass(), - "Verify of system dictionary failed"); + Klass* e = instance_klass(); + guarantee(e->is_instance_klass(), "Verify of dictionary failed"); e->verify(); verify_protection_domain_set(); } void Dictionary::verify() { - guarantee(number_of_entries() >= 0, "Verify of system dictionary failed"); + guarantee(number_of_entries() >= 0, "Verify of dictionary failed"); ClassLoaderData* cld = loader_data(); // class loader must be present; a null class loader is the --- old/src/share/vm/classfile/dictionary.hpp 2017-07-19 11:07:44.975858549 -0400 +++ new/src/share/vm/classfile/dictionary.hpp 2017-07-19 11:07:44.744005554 -0400 @@ -36,7 +36,7 @@ class BoolObjectClosure; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// The data structure for the system dictionary (and the shared system +// The data structure for the class loader data dictionaries (and the shared system // dictionary). class Dictionary : public Hashtable { @@ -110,14 +110,14 @@ void verify(); }; -// An entry in the system dictionary, this describes a class as -// { InstanceKlass*, loader, protection_domain }. +// An entry in the class loader data dictionaries, this describes a class as +// { InstanceKlass*, protection_domain }. class DictionaryEntry : public HashtableEntry { friend class VMStructs; private: // Contains the set of approved protection domains that can access - // this system dictionary entry. + // this dictionary entry. // // This protection domain set is a set of tuples: // @@ -144,7 +144,7 @@ // Adds a protection domain to the approved set. void add_protection_domain(Dictionary* dict, Handle protection_domain); - InstanceKlass* klass() const { return (InstanceKlass*)literal(); } + InstanceKlass* instance_klass() const { return literal(); } DictionaryEntry* next() const { return (DictionaryEntry*)HashtableEntry::next(); @@ -157,7 +157,7 @@ ProtectionDomainEntry* pd_set() const { return _pd_set; } void set_pd_set(ProtectionDomainEntry* pd_set) { _pd_set = pd_set; } - // Tells whether the initiating class' protection can access the this _klass + // Tells whether the initiating class' protection domain can access the klass in this entry bool is_valid_protection_domain(Handle protection_domain) { if (!ProtectionDomainVerification) return true; if (!SystemDictionary::has_checkPackageAccess()) return true; --- old/src/share/vm/classfile/loaderConstraints.cpp 2017-07-19 11:07:53.577011377 -0400 +++ new/src/share/vm/classfile/loaderConstraints.cpp 2017-07-19 11:07:53.347573001 -0400 @@ -441,17 +441,16 @@ guarantee(ik->name() == probe->name(), "name should match"); Symbol* name = ik->name(); ClassLoaderData* loader_data = ik->class_loader_data(); - Dictionary* dictionary = loader_data->dictionary_or_null(); - assert(dictionary != NULL, "no dictionary for this loader constraint entry?"); + Dictionary* dictionary = loader_data->dictionary(); unsigned int d_hash = dictionary->compute_hash(name); int d_index = dictionary->hash_to_index(d_hash); InstanceKlass* k = dictionary->find_class(d_index, d_hash, name); if (k != NULL) { - // We found the class in the system dictionary, so we should + // We found the class in the dictionary, so we should // make sure that the Klass* matches what we already have. guarantee(k == probe->klass(), "klass should be in dictionary"); } else { - // If we don't find the class in the system dictionary, it + // If we don't find the class in the dictionary, it // has to be in the placeholders table. unsigned int p_hash = placeholders->compute_hash(name); int p_index = placeholders->hash_to_index(p_hash); --- old/src/share/vm/classfile/protectionDomainCache.hpp 2017-07-19 11:08:01.403499136 -0400 +++ new/src/share/vm/classfile/protectionDomainCache.hpp 2017-07-19 11:08:01.173728377 -0400 @@ -33,7 +33,7 @@ // Dictionary entry pd_set point to entries in this hashtable. Please refer // to dictionary.hpp pd_set for more information about how protection domain entries // are used. -// This table is walked during GC, rather than the entire system dictionary +// This table is walked during GC, rather than the class loader data graph dictionaries. class ProtectionDomainCacheEntry : public HashtableEntry { friend class VMStructs; public: @@ -55,7 +55,7 @@ void verify(); }; -// The ProtectionDomainCacheTable contains all protection domain oops. The system +// The ProtectionDomainCacheTable contains all protection domain oops. The // dictionary entries reference its entries instead of having references to oops // directly. // This is used to speed up system dictionary iteration: the oops in the --- old/src/share/vm/classfile/systemDictionary.cpp 2017-07-19 11:08:09.332308965 -0400 +++ new/src/share/vm/classfile/systemDictionary.cpp 2017-07-19 11:08:09.052407908 -0400 @@ -342,13 +342,13 @@ #endif // INCLUDE_CDS // Double-check, if child class is already loaded, just return super-class,interface - // Don't add a placedholder if already loaded, i.e. already in system dictionary + // Don't add a placedholder if already loaded, i.e. already in appropriate class loader + // dictionary. // Make sure there's a placeholder for the *child* before resolving. // Used as a claim that this thread is currently loading superclass/classloader // Used here for ClassCircularity checks and also for heap verification - // (every InstanceKlass in the heap needs to be in the system dictionary - // or have a placeholder). - // Must check ClassCircularity before checking if super class is already loaded + // (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. // // We might not already have a placeholder if this child_name was // first seen via resolve_from_stream (jni_DefineClass or JVM_DefineClass); @@ -445,6 +445,7 @@ // This handle and the class_loader handle passed in keeps this class from // being unloaded through several GC points. + // The class_loader handle passed in is the initiating loader. Handle mirror(THREAD, klass->java_mirror()); InstanceKlass* system_loader = SystemDictionary::ClassLoader_klass(); @@ -479,7 +480,6 @@ dictionary->add_protection_domain(d_index, d_hash, klass, protection_domain, THREAD); } -} // We only get here if this thread finds that another thread // has already claimed the placeholder token for the current operation, @@ -952,12 +952,7 @@ return NULL; } - Dictionary* dictionary = loader_data->dictionary_or_null(); - // If ClassLoaderData has no dictionary, the class won't be found in it - if (dictionary == NULL) { - return NULL; - } - + Dictionary* dictionary = loader_data->dictionary(); unsigned int d_hash = dictionary->compute_hash(class_name); int d_index = dictionary->hash_to_index(d_hash); return dictionary->find(d_index, d_hash, class_name, @@ -1045,7 +1040,7 @@ // deoptimizations. add_to_hierarchy(k, CHECK_NULL); // No exception, but can block - // But, do not add to system dictionary. + // But, do not add to dictionary. // compiled code dependencies need to be validated anyway notice_modification(); @@ -1818,10 +1813,7 @@ VerifyAfterGC, "too expensive"); #endif - Dictionary* dictionary = loader_data->dictionary_or_null(); - if (dictionary == NULL) { - return NULL; - } + Dictionary* dictionary = loader_data->dictionary(); unsigned int d_hash = dictionary->compute_hash(class_name); int d_index = dictionary->hash_to_index(d_hash); return find_class(d_index, d_hash, class_name, dictionary); @@ -1851,14 +1843,6 @@ // ---------------------------------------------------------------------------- // GC support -// Following roots during mark-sweep is separated in two phases. -// -// The first phase follows preloaded classes and all other system -// classes, since these will never get unloaded anyway. -// -// The second phase removes (unloads) unreachable classes from the -// system dictionary and follows the remaining classes' contents. - void SystemDictionary::always_strong_oops_do(OopClosure* blk) { roots_oops_do(blk, NULL); } @@ -1871,7 +1855,7 @@ template void do_oop_work(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); - guarantee(_is_alive->do_object_b(obj), "Oop in system dictionary must be live"); + guarantee(_is_alive->do_object_b(obj), "Oop in protection domain cache table must be live"); } public: @@ -1906,7 +1890,7 @@ { GCTraceTime(Debug, gc, phases) t("ProtectionDomainCacheTable", gc_timer); - // Oops referenced by the system dictionary may get unreachable independently + // Oops referenced by the protection domain cache table may get unreachable independently // of the class loader (eg. cached protection domain oops). So we need to // explicitly unlink them here. _pd_cache_table->unlink(is_alive); @@ -1930,7 +1914,6 @@ strong->do_oop(&_system_loader_lock_obj); CDS_ONLY(SystemDictionaryShared::roots_oops_do(strong);) - // Adjust dictionary // Do strong roots marking if the closures are the same. if (strong == weak || !ClassUnloading) { // Only the protection domain oops contain references into the heap. Iterate @@ -2156,9 +2139,9 @@ // Constraints on class loaders. The details of the algorithm can be // found in the OOPSLA'98 paper "Dynamic Class Loading in the Java // Virtual Machine" by Sheng Liang and Gilad Bracha. The basic idea is -// that the system dictionary needs to maintain a set of contraints that +// that the dictionary needs to maintain a set of contraints that // must be satisfied by all classes in the dictionary. -// if defining is true, then LinkageError if already in systemDictionary +// if defining is true, then LinkageError if already in dictionary // if initiating loader, then ok if InstanceKlass matches existing entry void SystemDictionary::check_constraints(int d_index, unsigned int d_hash, @@ -2178,7 +2161,7 @@ // if different InstanceKlass - duplicate class definition, // 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 - // system dictionary only holds instance classes, placeholders + // dictionary only holds instance classes, placeholders // also holds array classes assert(check->is_instance_klass(), "noninstance in systemdictionary"); @@ -2219,7 +2202,7 @@ } -// Update system dictionary - done after check_constraint and add_to_hierachy +// Update class loader data dictionary - done after check_constraint and add_to_hierachy // have been called. void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash, int p_index, unsigned int p_hash, @@ -2254,19 +2237,19 @@ } } - // Make a new system dictionary entry. + // Make a new dictionary entry. Dictionary* dictionary = loader_data->dictionary(); InstanceKlass* sd_check = find_class(d_index, d_hash, name, dictionary); if (sd_check == NULL) { dictionary->add_klass(d_index, d_hash, name, k); notice_modification(); } - #ifdef ASSERT +#ifdef ASSERT sd_check = find_class(d_index, d_hash, name, dictionary); - assert (sd_check != NULL, "should have entry in system dictionary"); + assert (sd_check != NULL, "should have entry in dictionary"); // Note: there may be a placeholder entry: for circularity testing // or for parallel defines - #endif +#endif SystemDictionary_lock->notify_all(); } } @@ -2853,7 +2836,7 @@ guarantee(constraints() != NULL, "Verify of loader constraints failed"); guarantee(placeholders()->number_of_entries() >= 0, - "Verify of system dictionary failed"); + "Verify of placeholders failed"); // Verify dictionary ClassLoaderDataGraph::verify_dictionary(); --- old/src/share/vm/classfile/systemDictionary.hpp 2017-07-19 11:08:17.240336966 -0400 +++ new/src/share/vm/classfile/systemDictionary.hpp 2017-07-19 11:08:17.008502388 -0400 @@ -35,31 +35,34 @@ #include "utilities/hashtable.hpp" #include "utilities/hashtable.inline.hpp" -// The system dictionary stores all loaded classes and maps: +// The dictionary in each ClassLoaderData stores all loaded classes, either +// initiatied by its class loader or defined by its class loader: // -// [class name,class loader] -> class i.e. [Symbol*,oop] -> Klass* +// class loader -> ClassLoaderData -> [class, protection domain set] // // Classes are loaded lazily. The default VM class loader is // represented as NULL. -// The underlying data structure is an open hash table with a fixed number -// of buckets. During loading the loader object is locked, (for the VM loader -// a private lock object is used). Class loading can thus be done concurrently, -// but only by different loaders. +// The underlying data structure is an open hash table (Dictionary) per +// ClassLoaderData with a fixed number of buckets. During loading the +// class loader object is locked, (for the VM loader a private lock object is used). +// The global SystemDictionary_lock is held for all additions into the ClassLoaderData +// dictionaries. TODO: fix lock granularity so that class loading can +// be done concurrently, but only by different loaders. // // During loading a placeholder (name, loader) is temporarily placed in // a side data structure, and is used to detect ClassCircularityErrors // and to perform verification during GC. A GC can occur in the midst // of class loading, as we call out to Java, have to take locks, etc. // -// When class loading is finished, a new entry is added to the system -// dictionary and the place holder is removed. Note that the protection -// domain field of the system dictionary has not yet been filled in when -// the "real" system dictionary entry is created. +// When class loading is finished, a new entry is added to the dictionary +// of the class loader and the placeholder is removed. Note that the protection +// domain field of the dictionary entry has not yet been filled in when +// the "real" dictionary entry is created. // // Clients of this class who are interested in finding if a class has // been completely loaded -- not classes in the process of being loaded -- -// can read the SystemDictionary unlocked. This is safe because +// can read the dictionary unlocked. This is safe because // - entries are only deleted at safepoints // - readers cannot come to a safepoint while actively examining // an entry (an entry cannot be deleted from under a reader) @@ -283,7 +286,7 @@ bool is_superclass, TRAPS); - // Parse new stream. This won't update the system dictionary or + // Parse new stream. This won't update the dictionary or // class hierarchy, simply parse the stream. Used by JVMTI RedefineClasses. // Also used by Unsafe_DefineAnonymousClass static InstanceKlass* parse_stream(Symbol* class_name, --- old/src/share/vm/prims/jvmtiGetLoadedClasses.cpp 2017-07-19 11:08:25.623996169 -0400 +++ new/src/share/vm/prims/jvmtiGetLoadedClasses.cpp 2017-07-19 11:08:25.257808727 -0400 @@ -292,10 +292,10 @@ { // To get a consistent list of classes we need MultiArray_lock to ensure // array classes aren't created, and SystemDictionary_lock to ensure that - // classes aren't added to the system dictionary, + // classes aren't added to the class loader data dictionaries. MutexLocker ma(MultiArray_lock); MutexLocker sd(SystemDictionary_lock); - // First, count the classes in the system dictionary which have this loader recorded + // First, count the classes in the class loader data dictionaries which have this loader recorded // as an initiating loader. For basic type arrays this information is not recorded // so GetClassLoaderClasses will return all of the basic type arrays. This is okay // because the defining loader for basic type arrays is always the boot class loader --- old/src/share/vm/runtime/biasedLocking.cpp 2017-07-19 11:08:33.960317869 -0400 +++ new/src/share/vm/runtime/biasedLocking.cpp 2017-07-19 11:08:33.638169635 -0400 @@ -56,8 +56,8 @@ bool is_cheap_allocated() const { return _is_cheap_allocated; } void doit() { - // Iterate the system dictionary enabling biased locking for all - // currently loaded classes + // Iterate the class loader data dictionaries enabling biased locking for all + // currently loaded classes. ClassLoaderDataGraph::dictionary_classes_do(enable_biased_locking); // Indicate that future instances should enable it as well _biased_locking_enabled = true; --- old/src/share/vm/utilities/hashtable.hpp 2017-07-19 11:08:42.110769998 -0400 +++ new/src/share/vm/utilities/hashtable.hpp 2017-07-19 11:08:41.793948030 -0400 @@ -265,7 +265,7 @@ // Table entry management HashtableEntry* new_entry(unsigned int hashValue, T obj); - // Don't create and use freelist + // Don't create and use freelist of HashtableEntry. HashtableEntry* allocate_new_entry(unsigned int hashValue, T obj); // The following method is MT-safe and may be used with caution.