--- old/src/hotspot/share/classfile/classLoaderData.cpp 2018-03-20 17:45:01.732060912 -0400 +++ new/src/hotspot/share/classfile/classLoaderData.cpp 2018-03-20 17:45:01.118004150 -0400 @@ -610,6 +610,21 @@ return new Dictionary(this, size, resizable); } +// Tell the GC to keep this klass alive while iterating ClassLoaderDataGraph +oop ClassLoaderData::ensure_loader_alive() { + // 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::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->ensure_loader_alive()); 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->ensure_loader_alive()); 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->ensure_loader_alive()); 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->ensure_loader_alive()); 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->ensure_loader_alive()); 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->ensure_loader_alive()); 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->ensure_loader_alive()); 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->ensure_loader_alive()); 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->ensure_loader_alive()); cld->dictionary()->all_entries_do(f); } } --- old/src/hotspot/share/classfile/classLoaderData.hpp 2018-03-20 17:45:02.498131725 -0400 +++ new/src/hotspot/share/classfile/classLoaderData.hpp 2018-03-20 17:45:01.880074594 -0400 @@ -288,6 +288,7 @@ void unload(); bool keep_alive() const { return _keep_alive > 0; } + oop ensure_loader_alive(); void classes_do(void f(Klass*)); void loaded_classes_do(KlassClosure* klass_closure); void classes_do(void f(InstanceKlass*)); --- old/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp 2018-03-20 17:45:03.191195791 -0400 +++ new/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp 2018-03-20 17:45:02.614142449 -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) {