8210155: Lock ClassLoaderDataGraph
authorcoleenp
Fri, 31 Aug 2018 07:03:46 -0400
changeset 51608 625a5bdde0c5
parent 51607 5eb48e9d607a
child 51609 48a95b70d4af
8210155: Lock ClassLoaderDataGraph Summary: In preparation for concurrent class unloading. Reviewed-by: hseigel, eosterlund
src/hotspot/share/classfile/classLoaderData.cpp
src/hotspot/share/classfile/classLoaderData.hpp
src/hotspot/share/classfile/systemDictionary.cpp
src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp
src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp
src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp
src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
src/hotspot/share/memory/heapInspection.cpp
src/hotspot/share/memory/heapInspection.hpp
src/hotspot/share/memory/metaspaceShared.cpp
src/hotspot/share/memory/universe.cpp
src/hotspot/share/oops/klassVtable.cpp
src/hotspot/share/prims/jvmtiEnvBase.cpp
src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
src/hotspot/share/prims/whitebox.cpp
src/hotspot/share/runtime/java.cpp
src/hotspot/share/runtime/mutexLocker.cpp
src/hotspot/share/runtime/mutexLocker.hpp
src/hotspot/share/services/heapDumper.cpp
--- a/src/hotspot/share/classfile/classLoaderData.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/classfile/classLoaderData.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -544,6 +544,7 @@
 static ClassLoaderDataGraphKlassIteratorStatic static_klass_iterator;
 
 InstanceKlass* ClassLoaderDataGraph::try_get_next_class() {
+  assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
   return static_klass_iterator.try_get_next_class();
 }
 
@@ -895,6 +896,7 @@
 }
 
 void ClassLoaderDataGraph::clean_deallocate_lists(bool walk_previous_versions) {
+  assert(SafepointSynchronize::is_at_safepoint(), "must only be called at safepoint");
   uint loaders_processed = 0;
   for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
     // is_alive check will be necessary for concurrent class unloading.
@@ -1065,43 +1067,43 @@
 // Add a new class loader data node to the list.  Assign the newly created
 // ClassLoaderData into the java/lang/ClassLoader object as a hidden field
 ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_unsafe_anonymous) {
-  NoSafepointVerifier no_safepoints; // we mustn't GC until we've installed the
-                                     // ClassLoaderData in the graph since the CLD
-                                     // contains oops in _handles that must be walked.
+
 
-  ClassLoaderData* cld = new ClassLoaderData(loader, is_unsafe_anonymous);
+  ClassLoaderData* cld;
+  {
+    NoSafepointVerifier no_safepoints; // we mustn't GC until we've installed the
+                                       // ClassLoaderData in the loader since the CLD
+                                       // contains oops in _handles that must be walked.
+                                       // GC will find the CLD through the loader after this.
 
-  if (!is_unsafe_anonymous) {
-    // First, Atomically set it
-    ClassLoaderData* old = java_lang_ClassLoader::cmpxchg_loader_data(cld, loader(), NULL);
-    if (old != NULL) {
-      delete cld;
-      // Returns the data.
-      return old;
+    cld = new ClassLoaderData(loader, is_unsafe_anonymous);
+
+    if (!is_unsafe_anonymous) {
+      // First, Atomically set it
+      ClassLoaderData* old = java_lang_ClassLoader::cmpxchg_loader_data(cld, loader(), NULL);
+      if (old != NULL) {
+        delete cld;
+        // Returns the data.
+        return old;
+      }
     }
   }
 
+  MutexLocker ml(ClassLoaderDataGraph_lock);
+
   // We won the race, and therefore the task of adding the data to the list of
   // class loader data
-  ClassLoaderData** list_head = &_head;
-  ClassLoaderData* next = _head;
-
-  do {
-    cld->set_next(next);
-    ClassLoaderData* exchanged = Atomic::cmpxchg(cld, list_head, next);
-    if (exchanged == next) {
-      LogTarget(Trace, class, loader, data) lt;
-      if (lt.is_enabled()) {
-        ResourceMark rm;
-        LogStream ls(lt);
-        ls.print("create ");
-        cld->print_value_on(&ls);
-        ls.cr();
-      }
-      return cld;
-    }
-    next = exchanged;
-  } while (true);
+  cld->set_next(_head);
+  _head = cld;
+  LogTarget(Trace, class, loader, data) lt;
+  if (lt.is_enabled()) {
+    ResourceMark rm;
+    LogStream ls(lt);
+    ls.print("create ");
+    cld->print_value_on(&ls);
+    ls.cr();
+  }
+  return cld;
 }
 
 ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_unsafe_anonymous) {
@@ -1115,13 +1117,14 @@
 }
 
 void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
-  for (ClassLoaderData* cld = _head; cl != NULL && cld != NULL; cld = cld->next()) {
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
+  for (ClassLoaderData* cld = _head;  cld != NULL; cld = cld->_next) {
     cl->do_cld(cld);
   }
 }
 
 void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
-  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
   // Only walk the head until any clds not purged from prior unloading
   // (CMS doesn't purge right away).
   for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
@@ -1131,6 +1134,7 @@
 }
 
 void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
   for (ClassLoaderData* cld = _head;  cld != NULL; cld = cld->_next) {
     CLDClosure* closure = cld->keep_alive() ? strong : weak;
     if (closure != NULL) {
@@ -1140,6 +1144,7 @@
 }
 
 void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) {
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
   if (ClassUnloading) {
     roots_cld_do(cl, NULL);
   } else {
@@ -1147,41 +1152,90 @@
   }
 }
 
+// Closure for locking and iterating through classes.
+LockedClassesDo::LockedClassesDo(classes_do_func_t f) : _function(f) {
+  ClassLoaderDataGraph_lock->lock();
+}
+
+LockedClassesDo::LockedClassesDo() : _function(NULL) {
+  // callers provide their own do_klass
+  ClassLoaderDataGraph_lock->lock();
+}
+
+LockedClassesDo::~LockedClassesDo() { ClassLoaderDataGraph_lock->unlock(); }
+
+
+// Iterating over the CLDG needs to be locked because
+// unloading can remove entries concurrently soon.
+class ClassLoaderDataGraphIterator : public StackObj {
+  ClassLoaderData* _next;
+  HandleMark       _hm;  // clean up handles when this is done.
+  Handle           _holder;
+  Thread*          _thread;
+
+  void hold_next() {
+    if (_next != NULL) {
+      _holder = Handle(_thread, _next->holder_phantom());
+    }
+  }
+public:
+  ClassLoaderDataGraphIterator() : _next(ClassLoaderDataGraph::_head) {
+    _thread = Thread::current();
+    assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
+    hold_next();
+  }
+
+  bool repeat() const {
+    return _next != NULL;
+  }
+
+  ClassLoaderData* get_next() {
+    ClassLoaderData* next = _next;
+    if (_next != NULL) {
+      _next = _next->next();
+      hold_next();
+    }
+    return next;
+  }
+};
+
+// These functions assume that the caller has locked the ClassLoaderDataGraph_lock
+// if they are not calling the function from a safepoint.
 void ClassLoaderDataGraph::classes_do(KlassClosure* klass_closure) {
-  Thread* thread = Thread::current();
-  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
-    Handle holder(thread, cld->holder_phantom());
+  ClassLoaderDataGraphIterator iter;
+  while (iter.repeat()) {
+    ClassLoaderData* cld = iter.get_next();
     cld->classes_do(klass_closure);
   }
 }
 
 void ClassLoaderDataGraph::classes_do(void f(Klass* const)) {
-  Thread* thread = Thread::current();
-  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
-    Handle holder(thread, cld->holder_phantom());
+  ClassLoaderDataGraphIterator iter;
+  while (iter.repeat()) {
+    ClassLoaderData* cld = iter.get_next();
     cld->classes_do(f);
   }
 }
 
 void ClassLoaderDataGraph::methods_do(void f(Method*)) {
-  Thread* thread = Thread::current();
-  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
-    Handle holder(thread, cld->holder_phantom());
+  ClassLoaderDataGraphIterator iter;
+  while (iter.repeat()) {
+    ClassLoaderData* cld = iter.get_next();
     cld->methods_do(f);
   }
 }
 
 void ClassLoaderDataGraph::modules_do(void f(ModuleEntry*)) {
   assert_locked_or_safepoint(Module_lock);
-  Thread* thread = Thread::current();
-  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
-    Handle holder(thread, cld->holder_phantom());
+  ClassLoaderDataGraphIterator iter;
+  while (iter.repeat()) {
+    ClassLoaderData* cld = iter.get_next();
     cld->modules_do(f);
   }
 }
 
 void ClassLoaderDataGraph::modules_unloading_do(void f(ModuleEntry*)) {
-  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
   // Only walk the head until any clds not purged from prior unloading
   // (CMS doesn't purge right away).
   for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
@@ -1192,15 +1246,15 @@
 
 void ClassLoaderDataGraph::packages_do(void f(PackageEntry*)) {
   assert_locked_or_safepoint(Module_lock);
-  Thread* thread = Thread::current();
-  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
-    Handle holder(thread, cld->holder_phantom());
+  ClassLoaderDataGraphIterator iter;
+  while (iter.repeat()) {
+    ClassLoaderData* cld = iter.get_next();
     cld->packages_do(f);
   }
 }
 
 void ClassLoaderDataGraph::packages_unloading_do(void f(PackageEntry*)) {
-  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
   // Only walk the head until any clds not purged from prior unloading
   // (CMS doesn't purge right away).
   for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
@@ -1210,15 +1264,23 @@
 }
 
 void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
-  Thread* thread = Thread::current();
-  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
-    Handle holder(thread, cld->holder_phantom());
+  ClassLoaderDataGraphIterator iter;
+  while (iter.repeat()) {
+    ClassLoaderData* cld = iter.get_next();
     cld->loaded_classes_do(klass_closure);
   }
 }
 
+// This case can block but cannot do unloading (called from CDS)
+void ClassLoaderDataGraph::unlocked_loaded_classes_do(KlassClosure* klass_closure) {
+  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
+    cld->loaded_classes_do(klass_closure);
+  }
+}
+
+
 void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) {
-  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
   // Only walk the head until any clds not purged from prior unloading
   // (CMS doesn't purge right away).
   for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
@@ -1227,24 +1289,22 @@
   }
 }
 
-#define FOR_ALL_DICTIONARY(X) for (ClassLoaderData* X = _head; X != NULL; X = X->next()) \
-                                if (X->dictionary() != NULL)
+#define FOR_ALL_DICTIONARY(X)   ClassLoaderDataGraphIterator iter; \
+                                ClassLoaderData* X; \
+                                while ((X = iter.get_next()) != 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*)) {
-  Thread* thread = Thread::current();
   FOR_ALL_DICTIONARY(cld) {
-    Handle holder(thread, cld->holder_phantom());
     cld->dictionary()->classes_do(f);
   }
 }
 
 // Only walks the classes defined in this class loader.
 void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS) {
-  Thread* thread = Thread::current();
   FOR_ALL_DICTIONARY(cld) {
-    Handle holder(thread, cld->holder_phantom());
     cld->dictionary()->classes_do(f, CHECK);
   }
 }
@@ -1275,6 +1335,7 @@
 }
 
 GrowableArray<ClassLoaderData*>* ClassLoaderDataGraph::new_clds() {
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
   assert(_head == NULL || _saved_head != NULL, "remember_new_clds(true) not called?");
 
   GrowableArray<ClassLoaderData*>* array = new GrowableArray<ClassLoaderData*>();
@@ -1301,6 +1362,7 @@
 
 #ifndef PRODUCT
 bool ClassLoaderDataGraph::contains_loader_data(ClassLoaderData* loader_data) {
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
   for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
     if (loader_data == data) {
       return true;
@@ -1314,6 +1376,7 @@
 // Move class loader data from main list to the unloaded list for unloading
 // and deallocation later.
 bool ClassLoaderDataGraph::do_unloading(bool do_cleaning) {
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
 
   // Indicate whether safepoint cleanup is needed.
   _safepoint_cleanup_needed |= do_cleaning;
@@ -1362,6 +1425,8 @@
 // There's at least one dead class loader.  Purge refererences of healthy module
 // reads lists and package export lists to modules belonging to dead loaders.
 void ClassLoaderDataGraph::clean_module_and_package_info() {
+  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
+
   ClassLoaderData* data = _head;
   while (data != NULL) {
     // Remove entries in the dictionary of live class loader that have
@@ -1418,6 +1483,7 @@
 
 ClassLoaderDataGraphKlassIteratorAtomic::ClassLoaderDataGraphKlassIteratorAtomic()
     : _next_klass(NULL) {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
   ClassLoaderData* cld = ClassLoaderDataGraph::_head;
   Klass* klass = NULL;
 
@@ -1474,6 +1540,7 @@
 }
 
 ClassLoaderDataGraphMetaspaceIterator::ClassLoaderDataGraphMetaspaceIterator() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
   _data = ClassLoaderDataGraph::_head;
 }
 
@@ -1488,14 +1555,18 @@
 }
 
 void ClassLoaderDataGraph::verify() {
-  for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
-    data->verify();
+  ClassLoaderDataGraphIterator iter;
+  while (iter.repeat()) {
+    ClassLoaderData* cld = iter.get_next();
+    cld->verify();
   }
 }
 
 void ClassLoaderDataGraph::print_on(outputStream * const out) {
-  for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
-    data->print_on(out);
+  ClassLoaderDataGraphIterator iter;
+  while (iter.repeat()) {
+    ClassLoaderData* cld = iter.get_next();
+    cld->print_on(out);
   }
 }
 #endif // PRODUCT
--- a/src/hotspot/share/classfile/classLoaderData.hpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/classfile/classLoaderData.hpp	Fri Aug 31 07:03:46 2018 -0400
@@ -70,6 +70,7 @@
   friend class ClassLoaderDataGraphMetaspaceIterator;
   friend class ClassLoaderDataGraphKlassIteratorAtomic;
   friend class ClassLoaderDataGraphKlassIteratorStatic;
+  friend class ClassLoaderDataGraphIterator;
   friend class VMStructs;
  private:
   // All CLDs (except the null CLD) can be reached by walking _head->_next->...
@@ -118,6 +119,7 @@
   static void packages_do(void f(PackageEntry*));
   static void packages_unloading_do(void f(PackageEntry*));
   static void loaded_classes_do(KlassClosure* klass_closure);
+  static void unlocked_loaded_classes_do(KlassClosure* klass_closure);
   static void classes_unloading_do(void f(Klass* const));
   static bool do_unloading(bool do_cleaning);
 
@@ -177,6 +179,20 @@
 #endif
 };
 
+class LockedClassesDo : public KlassClosure {
+  typedef void (*classes_do_func_t)(Klass*);
+  classes_do_func_t _function;
+public:
+  LockedClassesDo();  // For callers who provide their own do_klass
+  LockedClassesDo(classes_do_func_t function);
+  ~LockedClassesDo();
+
+  void do_klass(Klass* k) {
+    (*_function)(k);
+  }
+};
+
+
 // ClassLoaderData class
 
 class ClassLoaderData : public CHeapObj<mtClass> {
@@ -213,6 +229,7 @@
   };
 
   friend class ClassLoaderDataGraph;
+  friend class ClassLoaderDataGraphIterator;
   friend class ClassLoaderDataGraphKlassIteratorAtomic;
   friend class ClassLoaderDataGraphKlassIteratorStatic;
   friend class ClassLoaderDataGraphMetaspaceIterator;
--- a/src/hotspot/share/classfile/systemDictionary.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -1919,6 +1919,7 @@
 
 void SystemDictionary::methods_do(void f(Method*)) {
   // Walk methods in loaded classes
+  MutexLocker ml(ClassLoaderDataGraph_lock);
   ClassLoaderDataGraph::methods_do(f);
   // Walk method handle intrinsics
   invoke_method_table()->methods_do(f);
@@ -1936,6 +1937,7 @@
 void SystemDictionary::remove_classes_in_error_state() {
   ClassLoaderData::the_null_class_loader_data()->dictionary()->remove_classes_in_error_state();
   RemoveClassesClosure rcc;
+  MutexLocker ml(ClassLoaderDataGraph_lock);
   ClassLoaderDataGraph::cld_do(&rcc);
 }
 
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -4074,6 +4074,8 @@
 
 // The freelist lock is needed to prevent asserts, is it really needed?
 void CMSCollector::preclean_cld(MarkRefsIntoAndScanClosure* cl, Mutex* freelistLock) {
+  // Needed to walk CLDG
+  MutexLocker ml(ClassLoaderDataGraph_lock);
 
   cl->set_freelistLock(freelistLock);
 
--- a/src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -121,12 +121,14 @@
 
 void JfrModuleEvent::generate_module_dependency_events() {
   invocation_time = JfrTicks::now();
-  MutexLockerEx module_lock(Module_lock);
+  MutexLocker cld_lock(ClassLoaderDataGraph_lock);
+  MutexLocker module_lock(Module_lock);
   ClassLoaderDataGraph::modules_do(&module_dependency_event_callback);
 }
 
 void JfrModuleEvent::generate_module_export_events() {
   invocation_time = JfrTicks::now();
-  MutexLockerEx module_lock(Module_lock);
+  MutexLocker cld_lock(ClassLoaderDataGraph_lock);
+  MutexLocker module_lock(Module_lock);
   ClassLoaderDataGraph::packages_do(&module_export_event_callback);
 }
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -149,7 +149,9 @@
 
 void JfrTypeManager::write_type_set() {
   // can safepoint here because of Module_lock
+  MutexLockerEx cld_lock(SafepointSynchronize::is_at_safepoint() ? NULL : ClassLoaderDataGraph_lock);
   MutexLockerEx lock(SafepointSynchronize::is_at_safepoint() ? NULL : Module_lock);
+
   JfrCheckpointWriter writer(true, true, Thread::current());
   TypeSet set;
   set.serialize(writer);
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -74,6 +74,10 @@
     Module_lock->unlock();
   }
 
+  if (ClassLoaderDataGraph_lock->owned_by_self()) {
+    ClassLoaderDataGraph_lock->unlock();
+  }
+
   if (Heap_lock->owned_by_self()) {
     Heap_lock->unlock();
   }
--- a/src/hotspot/share/memory/heapInspection.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/memory/heapInspection.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -153,11 +153,17 @@
   }
 }
 
-void KlassInfoTable::AllClassesFinder::do_klass(Klass* k) {
-  // This has the SIDE EFFECT of creating a KlassInfoEntry
-  // for <k>, if one doesn't exist yet.
-  _table->lookup(k);
-}
+class KlassInfoTable::AllClassesFinder : public LockedClassesDo {
+  KlassInfoTable *_table;
+public:
+  AllClassesFinder(KlassInfoTable* table) : _table(table) {}
+  virtual void do_klass(Klass* k) {
+    // This has the SIDE EFFECT of creating a KlassInfoEntry
+    // for <k>, if one doesn't exist yet.
+    _table->lookup(k);
+  }
+};
+
 
 KlassInfoTable::KlassInfoTable(bool add_all_classes) {
   _size_of_instances_in_words = 0;
--- a/src/hotspot/share/memory/heapInspection.hpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/memory/heapInspection.hpp	Fri Aug 31 07:03:46 2018 -0400
@@ -247,12 +247,7 @@
   uint hash(const Klass* p);
   KlassInfoEntry* lookup(Klass* k); // allocates if not found!
 
-  class AllClassesFinder : public KlassClosure {
-    KlassInfoTable *_table;
-   public:
-    AllClassesFinder(KlassInfoTable* table) : _table(table) {}
-    virtual void do_klass(Klass* k);
-  };
+  class AllClassesFinder;
 
  public:
   KlassInfoTable(bool add_all_classes);
--- a/src/hotspot/share/memory/metaspaceShared.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/memory/metaspaceShared.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -1619,7 +1619,7 @@
   LinkSharedClassesClosure link_closure(THREAD);
   do {
     link_closure.reset();
-    ClassLoaderDataGraph::loaded_classes_do(&link_closure);
+    ClassLoaderDataGraph::unlocked_loaded_classes_do(&link_closure);
     guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class");
   } while (link_closure.made_progress());
 
@@ -1631,7 +1631,7 @@
       // we should come here only if there are unverifiable classes, which
       // shouldn't happen in normal cases. So better safe than sorry.
       check_closure.reset();
-      ClassLoaderDataGraph::loaded_classes_do(&check_closure);
+      ClassLoaderDataGraph::unlocked_loaded_classes_do(&check_closure);
     } while (check_closure.made_progress());
 
     if (IgnoreUnverifiableClassesDuringDump) {
--- a/src/hotspot/share/memory/universe.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/memory/universe.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -545,6 +545,7 @@
 
 
 void Universe::reinitialize_itables(TRAPS) {
+  MutexLocker mcld(ClassLoaderDataGraph_lock);
   ClassLoaderDataGraph::dictionary_classes_do(initialize_itable_for_klass, CHECK);
 }
 
--- a/src/hotspot/share/oops/klassVtable.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/oops/klassVtable.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -1595,7 +1595,8 @@
   }
 
   static void compute() {
-    ClassLoaderDataGraph::classes_do(do_class);
+    LockedClassesDo locked_do_class(&do_class);
+    ClassLoaderDataGraph::classes_do(&locked_do_class);
     fixed  = no_klasses * oopSize;      // vtable length
     // filler size is a conservative approximation
     filler = oopSize * (no_klasses - no_instance_klasses) * (sizeof(InstanceKlass) - sizeof(ArrayKlass) - 1);
--- a/src/hotspot/share/prims/jvmtiEnvBase.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -1489,6 +1489,7 @@
 jvmtiError
 JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr) {
   ResourceMark rm;
+  MutexLocker mcld(ClassLoaderDataGraph_lock);
   MutexLocker ml(Module_lock);
 
   _tbl = new GrowableArray<OopHandle>(77);
--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -107,6 +107,7 @@
 
     // Iterate through all classes in ClassLoaderDataGraph
     // and collect them using the LoadedClassesClosure
+    MutexLocker mcld(ClassLoaderDataGraph_lock);
     ClassLoaderDataGraph::loaded_classes_do(&closure);
   }
 
--- a/src/hotspot/share/prims/whitebox.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/prims/whitebox.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -146,7 +146,7 @@
   return os::large_page_size();
 WB_END
 
-class WBIsKlassAliveClosure : public KlassClosure {
+class WBIsKlassAliveClosure : public LockedClassesDo {
     Symbol* _name;
     bool _found;
 public:
--- a/src/hotspot/share/runtime/java.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/runtime/java.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -346,6 +346,7 @@
 
   if (PrintSystemDictionaryAtExit) {
     ResourceMark rm;
+    MutexLocker mcld(ClassLoaderDataGraph_lock);
     SystemDictionary::print();
     ClassLoaderDataGraph::print();
   }
@@ -494,6 +495,7 @@
     Universe::print_on(&ls_info);
     if (log.is_trace()) {
       LogStream ls_trace(log.trace());
+      MutexLocker mcld(ClassLoaderDataGraph_lock);
       ClassLoaderDataGraph::print_on(&ls_trace);
     }
   }
--- a/src/hotspot/share/runtime/mutexLocker.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/runtime/mutexLocker.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -147,6 +147,7 @@
 Monitor* CodeHeapStateAnalytics_lock  = NULL;
 
 Mutex*   MetaspaceExpand_lock         = NULL;
+Mutex*   ClassLoaderDataGraph_lock    = NULL;
 
 #define MAX_NUM_MUTEX 128
 static Monitor * _mutex_array[MAX_NUM_MUTEX];
@@ -224,6 +225,7 @@
   def(OopMapCacheAlloc_lock        , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always);     // used for oop_map_cache allocation.
 
   def(MetaspaceExpand_lock         , PaddedMutex  , leaf-1,      true,  Monitor::_safepoint_check_never);
+  def(ClassLoaderDataGraph_lock    , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_always);
 
   def(Patching_lock                , PaddedMutex  , special,     true,  Monitor::_safepoint_check_never);      // used for safepointing and code patching.
   def(Service_lock                 , PaddedMonitor, special,     true,  Monitor::_safepoint_check_never);      // used for service thread operations
--- a/src/hotspot/share/runtime/mutexLocker.hpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/runtime/mutexLocker.hpp	Fri Aug 31 07:03:46 2018 -0400
@@ -145,6 +145,7 @@
 #endif
 
 extern Mutex*   MetaspaceExpand_lock;            // protects Metaspace virtualspace and chunk expansions
+extern Mutex*   ClassLoaderDataGraph_lock;       // protects CLDG list, needed for concurrent unloading
 
 
 extern Monitor* CodeHeapStateAnalytics_lock;     // lock print functions against concurrent analyze functions.
--- a/src/hotspot/share/services/heapDumper.cpp	Fri Aug 31 12:41:00 2018 +0200
+++ b/src/hotspot/share/services/heapDumper.cpp	Fri Aug 31 07:03:46 2018 -0400
@@ -1464,6 +1464,7 @@
   bool skip_operation() const;
 
   // writes a HPROF_LOAD_CLASS record
+  class ClassesDo;
   static void do_load_class(Klass* k);
 
   // writes a HPROF_GC_CLASS_DUMP record for the given class
@@ -1821,7 +1822,10 @@
   SymbolTable::symbols_do(&sym_dumper);
 
   // write HPROF_LOAD_CLASS records
-  ClassLoaderDataGraph::classes_do(&do_load_class);
+  {
+    LockedClassesDo locked_load_classes(&do_load_class);
+    ClassLoaderDataGraph::classes_do(&locked_load_classes);
+  }
   Universe::basic_type_classes_do(&do_load_class);
 
   // write HPROF_FRAME and HPROF_TRACE records
@@ -1832,7 +1836,10 @@
   DumperSupport::write_dump_header(writer());
 
   // Writes HPROF_GC_CLASS_DUMP records
-  ClassLoaderDataGraph::classes_do(&do_class_dump);
+  {
+    LockedClassesDo locked_dump_class(&do_class_dump);
+    ClassLoaderDataGraph::classes_do(&locked_dump_class);
+  }
   Universe::basic_type_classes_do(&do_basic_type_array_class_dump);
   check_segment_length();