8197844: JVMTI GetLoadedClasses should use the Access API
authorcoleenp
Wed, 21 Mar 2018 17:09:34 -0400
changeset 49479 5865398439d4
parent 49478 527a563046d0
child 49480 d7df2dd501ce
8197844: JVMTI GetLoadedClasses should use the Access API Summary: Make sure the holder of a class loader is accessed during iteration of CLDG Reviewed-by: eosterlund, rkennke
src/hotspot/share/classfile/classLoaderData.cpp
src/hotspot/share/classfile/classLoaderData.hpp
src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
--- a/src/hotspot/share/classfile/classLoaderData.cpp	Wed Mar 21 13:30:03 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.cpp	Wed Mar 21 17:09:34 2018 -0400
@@ -610,6 +610,21 @@
   return new Dictionary(this, size, resizable);
 }
 
+// Tell the GC to keep this klass alive while iterating ClassLoaderDataGraph
+oop ClassLoaderData::holder_phantom() {
+  // A klass that was previously considered dead can be looked up in the
+  // CLD/SD, and its _java_mirror or _class_loader can be stored in a root
+  // or a reachable object making it alive again. The SATB part of G1 needs
+  // to get notified about this potential resurrection, otherwise the marking
+  // might not find the object.
+  if (!keep_alive()) {
+    oop* o = is_anonymous() ? _klasses->java_mirror_handle().ptr_raw() : &_class_loader;
+    return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(o);
+  } else {
+    return NULL;
+  }
+}
+
 // Unloading support
 oop ClassLoaderData::keep_alive_object() const {
   assert_locked_or_safepoint(_metaspace_lock);
@@ -1048,26 +1063,34 @@
 }
 
 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());
     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());
     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());
     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());
     cld->modules_do(f);
   }
 }
@@ -1084,7 +1107,9 @@
 
 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());
     cld->packages_do(f);
   }
 }
@@ -1100,7 +1125,9 @@
 }
 
 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());
     cld->loaded_classes_do(klass_closure);
   }
 }
@@ -1121,21 +1148,27 @@
 // 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);
   }
 }
 
 // Walks all entries in the dictionary including entries initiated by this class loader.
 void ClassLoaderDataGraph::dictionary_all_entries_do(void f(InstanceKlass*, ClassLoaderData*)) {
+  Thread* thread = Thread::current();
   FOR_ALL_DICTIONARY(cld) {
+    Handle holder(thread, cld->holder_phantom());
     cld->dictionary()->all_entries_do(f);
   }
 }
--- a/src/hotspot/share/classfile/classLoaderData.hpp	Wed Mar 21 13:30:03 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.hpp	Wed Mar 21 17:09:34 2018 -0400
@@ -288,6 +288,7 @@
 
   void unload();
   bool keep_alive() const       { return _keep_alive > 0; }
+  oop  holder_phantom();
   void classes_do(void f(Klass*));
   void loaded_classes_do(KlassClosure* klass_closure);
   void classes_do(void f(InstanceKlass*));
--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp	Wed Mar 21 13:30:03 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp	Wed Mar 21 17:09:34 2018 -0400
@@ -30,10 +30,6 @@
 #include "runtime/jniHandles.inline.hpp"
 #include "runtime/thread.hpp"
 #include "utilities/stack.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#endif
-
 
 // The closure for GetLoadedClasses
 class LoadedClassesClosure : public KlassClosure {
@@ -42,20 +38,6 @@
   JvmtiEnv* _env;
   Thread*   _cur_thread;
 
-// Tell the GC to keep this klass alive
-static void ensure_klass_alive(oop o) {
-  // A klass that was previously considered dead can be looked up in the
-  // CLD/SD, and its _java_mirror or _class_loader can be stored in a root
-  // or a reachable object making it alive again. The SATB part of G1 needs
-  // to get notified about this potential resurrection, otherwise the marking
-  // might not find the object.
-#if INCLUDE_ALL_GCS
-  if (UseG1GC && o != NULL) {
-    G1BarrierSet::enqueue(o);
-  }
-#endif
-}
-
 public:
   LoadedClassesClosure(Thread* thread, JvmtiEnv* env) : _cur_thread(thread), _env(env) {
     assert(_cur_thread == Thread::current(), "must be current thread");
@@ -64,7 +46,6 @@
   void do_klass(Klass* k) {
     // Collect all jclasses
     _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror())));
-    ensure_klass_alive(k->java_mirror());
   }
 
   int extract(jclass* result_list) {