Skip to content

Commit a13b02c

Browse files
author
Ravi Reddy
committed
8340586: JdkJfrEvent::get_all_klasses stores non-strong oops in JNI handles
Backport-of: d620426
1 parent a7fbf37 commit a13b02c

File tree

3 files changed

+21
-17
lines changed

3 files changed

+21
-17
lines changed

src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
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

4041
static 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-
107103
jobject 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());

src/hotspot/share/oops/klass.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,8 @@ class Klass : public Metadata {
582582

583583
inline oop klass_holder() const;
584584

585+
inline void keep_alive() const;
586+
585587
protected:
586588

587589
// Error handling when length > max_length or length < 0

src/hotspot/share/oops/klass.inline.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ inline oop Klass::klass_holder() const {
3636
return class_loader_data()->holder();
3737
}
3838

39+
inline void Klass::keep_alive() const {
40+
// Resolving the holder (a WeakHandle) will keep the klass alive until the next safepoint.
41+
// Making the klass's CLD handle oops (e.g. the java_mirror), safe to store in the object
42+
// graph and its roots (e.g. Handles).
43+
static_cast<void>(klass_holder());
44+
}
45+
3946
inline bool Klass::is_non_strong_hidden() const {
4047
return access_flags().is_hidden_class() &&
4148
class_loader_data()->has_class_mirror_holder();
@@ -52,6 +59,7 @@ inline bool Klass::is_loader_alive() const {
5259
return class_loader_data()->is_alive();
5360
}
5461

62+
// Loading the java_mirror does not keep its holder alive. See Klass::keep_alive().
5563
inline oop Klass::java_mirror() const {
5664
return _java_mirror.resolve();
5765
}

0 commit comments

Comments
 (0)