diff --git a/src/hotspot/share/classfile/classLoaderData.hpp b/src/hotspot/share/classfile/classLoaderData.hpp index 8c1fed3..39e16c3 100644 --- a/src/hotspot/share/classfile/classLoaderData.hpp +++ b/src/hotspot/share/classfile/classLoaderData.hpp @@ -230,6 +230,7 @@ class ClassLoaderData : public CHeapObj { friend class ClassLoaderDataGraphKlassIteratorStatic; friend class ClassLoaderDataGraphMetaspaceIterator; friend class InstanceKlass; + friend class Klass; friend class MetaDataFactory; friend class Method; diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 50d744d..a6961ec 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -51,6 +51,7 @@ #include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" +#include "oops/access.inline.hpp" #include "oops/fieldStreams.hpp" #include "oops/instanceClassLoaderKlass.hpp" #include "oops/instanceKlass.inline.hpp" @@ -3416,13 +3417,12 @@ void JNIid::verify(Klass* holder) { } oop InstanceKlass::klass_holder_phantom() { - oop* addr; if (is_anonymous()) { - addr = _java_mirror.ptr_raw(); + oop* addr = _java_mirror.ptr_raw(); + return RootAccess::oop_load(addr); } else { - addr = &class_loader_data()->_class_loader; + return Klass::klass_holder_phantom(); } - return RootAccess::oop_load(addr); } #ifdef ASSERT diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 82c5723..c5aad77 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -35,6 +35,7 @@ #include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" +#include "oops/access.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/oop.inline.hpp" @@ -54,6 +55,18 @@ oop Klass::java_mirror() const { return _java_mirror.resolve(); } +oop Klass::java_mirror_phantom() { + // Loading the klass_holder as a phantom oop ref keeps the class alive. + // After the holder has been kept alive, it is safe to return the mirror. + (void)klass_holder_phantom(); + return java_mirror(); +} + +oop Klass::klass_holder_phantom() { + oop* addr = &class_loader_data()->_class_loader; + return RootAccess::oop_load(addr); +} + bool Klass::is_cloneable() const { return _access_flags.is_cloneable_fast() || is_subtype_of(SystemDictionary::Cloneable_klass()); diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index d8fe5de..956a6c4 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -227,6 +227,11 @@ protected: // java mirror oop java_mirror() const; + // Load the java_mirror as a phantom. This is useful when a weak Klass + // pointer has been "peeked" and then must be kept alive before it may + // be used safely. The Klass will be kept alive and not be unloaded due + // to concurrent marking. + virtual oop java_mirror_phantom(); void set_java_mirror(Handle m); // Temporary mirror switch used by RedefineClasses @@ -454,6 +459,11 @@ protected: oop class_loader() const; virtual oop klass_holder() const { return class_loader(); } + // Load the klass_holder as a phantom. This is useful when a weak Klass + // pointer has been "peeked" and then must be kept alive before it may + // be used safely. The Klass will be kept alive and not be unloaded due + // to concurrent marking. + virtual oop klass_holder_phantom(); protected: virtual Klass* array_klass_impl(bool or_null, int rank, TRAPS); diff --git a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp index cc78e64..bc52721 100644 --- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp +++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp @@ -29,9 +29,6 @@ #include "prims/jvmtiGetLoadedClasses.hpp" #include "runtime/thread.hpp" #include "utilities/stack.inline.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif // The closure for GetLoadedClasses @@ -41,20 +38,6 @@ private: 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) { - G1SATBCardTableModRefBS::enqueue(o); - } -#endif -} - public: LoadedClassesClosure(Thread* thread, JvmtiEnv* env) : _cur_thread(thread), _env(env) { assert(_cur_thread == Thread::current(), "must be current thread"); @@ -62,8 +45,9 @@ public: 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()); + oop mirror = k->java_mirror_phantom(); // make sure the class is not unloaded during + // concurrent marking by using the phantom getter. + _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, mirror))); } int extract(jclass* result_list) {