3535#include " oops/klass.inline.hpp"
3636#include " runtime/handles.inline.hpp"
3737#include " runtime/javaThread.hpp"
38+ #include " runtime/safepointVerifiers.hpp"
3839#include " utilities/stack.inline.hpp"
3940
4041static jobject empty_java_util_arraylist = nullptr ;
@@ -80,30 +81,25 @@ static bool is_allowed(const Klass* k) {
8081 return !(k->is_abstract () || k->should_be_initialized ());
8182}
8283
83- static void fill_klasses (GrowableArray<const void * >& event_subklasses, const InstanceKlass* event_klass, JavaThread* thread) {
84+ static void fill_klasses (GrowableArray<jclass >& event_subklasses, const InstanceKlass* event_klass, JavaThread* thread) {
8485 assert (event_subklasses.length () == 0 , " invariant" );
8586 assert (event_klass != nullptr , " invariant" );
8687 DEBUG_ONLY (JfrJavaSupport::check_java_thread_in_vm (thread));
88+ // Do not safepoint while walking the ClassHierarchy, keeping klasses alive and storing their mirrors in JNI handles.
89+ NoSafepointVerifier nsv;
8790
8891 for (ClassHierarchyIterator iter (const_cast <InstanceKlass*>(event_klass)); !iter.done (); iter.next ()) {
8992 Klass* subk = iter.klass ();
9093 if (is_allowed (subk)) {
91- event_subklasses.append (subk);
94+ // We are walking the class hierarchy and saving the relevant klasses in JNI handles.
95+ // To be allowed to store the java mirror, we must ensure that the klass and its oops are kept alive,
96+ // and perform the store before the next safepoint.
97+ subk->keep_alive ();
98+ event_subklasses.append ((jclass)JfrJavaSupport::local_jni_handle (subk->java_mirror (), thread));
9299 }
93100 }
94101}
95102
96- static void transform_klasses_to_local_jni_handles (GrowableArray<const void *>& event_subklasses, JavaThread* thread) {
97- assert (event_subklasses.is_nonempty (), " invariant" );
98- DEBUG_ONLY (JfrJavaSupport::check_java_thread_in_vm (thread));
99-
100- for (int i = 0 ; i < event_subklasses.length (); ++i) {
101- const InstanceKlass* k = static_cast <const InstanceKlass*>(event_subklasses.at (i));
102- assert (is_allowed (k), " invariant" );
103- event_subklasses.at_put (i, JfrJavaSupport::local_jni_handle (k->java_mirror (), thread));
104- }
105- }
106-
107103jobject JdkJfrEvent::get_all_klasses (TRAPS) {
108104 DEBUG_ONLY (JfrJavaSupport::check_java_thread_in_vm (THREAD));
109105 initialize (THREAD);
@@ -126,15 +122,13 @@ jobject JdkJfrEvent::get_all_klasses(TRAPS) {
126122 }
127123
128124 ResourceMark rm (THREAD);
129- GrowableArray<const void * > event_subklasses (initial_array_size);
125+ GrowableArray<jclass > event_subklasses (initial_array_size);
130126 fill_klasses (event_subklasses, InstanceKlass::cast (klass), THREAD);
131127
132128 if (event_subklasses.is_empty ()) {
133129 return empty_java_util_arraylist;
134130 }
135131
136- transform_klasses_to_local_jni_handles (event_subklasses, THREAD);
137-
138132 Handle h_array_list (THREAD, new_java_util_arraylist (THREAD));
139133 assert (h_array_list.not_null (), " invariant" );
140134
@@ -150,7 +144,7 @@ jobject JdkJfrEvent::get_all_klasses(TRAPS) {
150144
151145 JavaValue result (T_BOOLEAN);
152146 for (int i = 0 ; i < event_subklasses.length (); ++i) {
153- const jclass clazz = (jclass) event_subklasses.at (i);
147+ const jclass clazz = event_subklasses.at (i);
154148 assert (JdkJfrEvent::is_subklass (clazz), " invariant" );
155149 JfrJavaArguments args (&result, array_list_klass, add_method_sym, add_method_sig_sym);
156150 args.set_receiver (h_array_list ());
0 commit comments