8213107: Make ClassLoaderDataGraph iterator skip unloaded CLDs
authorcoleenp
Wed, 31 Oct 2018 07:06:54 -0400
changeset 52344 55711b181dfc
parent 52343 b66b51c4e405
child 52345 418fb8bb5151
8213107: Make ClassLoaderDataGraph iterator skip unloaded CLDs Summary: with concurrent class unloading, the CLDG could contain unloaded CLDs while iterating in a safepoint Reviewed-by: lfoltan, eosterlund
src/hotspot/share/classfile/classLoaderDataGraph.cpp
--- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp	Wed Oct 31 11:36:07 2018 +0100
+++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp	Wed Oct 31 07:06:54 2018 -0400
@@ -287,54 +287,50 @@
   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();
+    ClassLoaderData* cld = _next;
+    // Skip already unloaded CLD for concurrent unloading.
+    while (cld != NULL && !cld->is_alive()) {
+      cld = cld->next();
     }
-    return next;
+    if (cld != NULL) {
+      // Keep cld that is being returned alive.
+      _holder = Handle(_thread, cld->holder_phantom());
+      _next = cld->next();
+    } else {
+      _next = NULL;
+    }
+    return cld;
   }
+
+
 };
 
 // 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) {
   ClassLoaderDataGraphIterator iter;
-  while (iter.repeat()) {
-    ClassLoaderData* cld = iter.get_next();
+  while (ClassLoaderData* cld = iter.get_next()) {
     cld->classes_do(klass_closure);
   }
 }
 
 void ClassLoaderDataGraph::classes_do(void f(Klass* const)) {
   ClassLoaderDataGraphIterator iter;
-  while (iter.repeat()) {
-    ClassLoaderData* cld = iter.get_next();
+  while (ClassLoaderData* cld = iter.get_next()) {
     cld->classes_do(f);
   }
 }
 
 void ClassLoaderDataGraph::methods_do(void f(Method*)) {
   ClassLoaderDataGraphIterator iter;
-  while (iter.repeat()) {
-    ClassLoaderData* cld = iter.get_next();
+  while (ClassLoaderData* cld = iter.get_next()) {
     cld->methods_do(f);
   }
 }
@@ -342,8 +338,7 @@
 void ClassLoaderDataGraph::modules_do(void f(ModuleEntry*)) {
   assert_locked_or_safepoint(Module_lock);
   ClassLoaderDataGraphIterator iter;
-  while (iter.repeat()) {
-    ClassLoaderData* cld = iter.get_next();
+  while (ClassLoaderData* cld = iter.get_next()) {
     cld->modules_do(f);
   }
 }
@@ -361,8 +356,7 @@
 void ClassLoaderDataGraph::packages_do(void f(PackageEntry*)) {
   assert_locked_or_safepoint(Module_lock);
   ClassLoaderDataGraphIterator iter;
-  while (iter.repeat()) {
-    ClassLoaderData* cld = iter.get_next();
+  while (ClassLoaderData* cld = iter.get_next()) {
     cld->packages_do(f);
   }
 }
@@ -379,8 +373,7 @@
 
 void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
   ClassLoaderDataGraphIterator iter;
-  while (iter.repeat()) {
-    ClassLoaderData* cld = iter.get_next();
+  while (ClassLoaderData* cld = iter.get_next()) {
     cld->loaded_classes_do(klass_closure);
   }
 }
@@ -404,8 +397,7 @@
 }
 
 #define FOR_ALL_DICTIONARY(X)   ClassLoaderDataGraphIterator iter; \
-                                ClassLoaderData* X; \
-                                while ((X = iter.get_next()) != NULL) \
+                                while (ClassLoaderData* X = iter.get_next()) \
                                   if (X->dictionary() != NULL)
 
 // Walk classes in the loaded class dictionaries in various forms.
@@ -696,16 +688,14 @@
 
 void ClassLoaderDataGraph::verify() {
   ClassLoaderDataGraphIterator iter;
-  while (iter.repeat()) {
-    ClassLoaderData* cld = iter.get_next();
+  while (ClassLoaderData* cld = iter.get_next()) {
     cld->verify();
   }
 }
 
 void ClassLoaderDataGraph::print_on(outputStream * const out) {
   ClassLoaderDataGraphIterator iter;
-  while (iter.repeat()) {
-    ClassLoaderData* cld = iter.get_next();
+  while (ClassLoaderData* cld = iter.get_next()) {
     cld->print_on(out);
   }
 }