Skip to content

Commit 789ead6

Browse files
committed
8364111: InstanceMirrorKlass iterators should handle CDS and hidden classes consistently
Backport-of: ebb7f5d39be8497fc89e25d0905335102e12c063
1 parent ab772dd commit 789ead6

File tree

2 files changed

+34
-32
lines changed

2 files changed

+34
-32
lines changed

src/hotspot/share/oops/instanceMirrorKlass.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ class InstanceMirrorKlass: public InstanceKlass {
5252

5353
InstanceMirrorKlass(const ClassFileParser& parser) : InstanceKlass(parser, Kind) {}
5454

55+
template <class OopClosureType>
56+
inline void do_metadata(oop obj, OopClosureType* closure);
57+
5558
public:
5659
InstanceMirrorKlass();
5760

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

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,38 +46,41 @@ void InstanceMirrorKlass::oop_oop_iterate_statics(oop obj, OopClosureType* closu
4646
}
4747
}
4848

49+
template <class OopClosureType>
50+
void InstanceMirrorKlass::do_metadata(oop obj, OopClosureType* closure) {
51+
Klass* klass = java_lang_Class::as_Klass(obj);
52+
if (klass != nullptr) {
53+
if (klass->class_loader_data() == nullptr) {
54+
// This is a mirror that belongs to a shared class that has not been loaded yet.
55+
assert(klass->is_shared(), "Must be");
56+
} else if (klass->is_instance_klass() && klass->class_loader_data()->has_class_mirror_holder()) {
57+
// A non-strong hidden class doesn't have its own class loader,
58+
// so when handling the java mirror for the class we need to make sure its class
59+
// loader data is claimed, this is done by calling do_cld explicitly.
60+
// For non-strong hidden classes the call to do_cld is made when the class
61+
// loader itself is handled.
62+
Devirtualizer::do_cld(closure, klass->class_loader_data());
63+
} else {
64+
Devirtualizer::do_klass(closure, klass);
65+
}
66+
} else {
67+
// Java mirror -> Klass* "nullptr" backlink means either:
68+
// 1. This is a Java mirror for a primitive class. We do not need to follow it,
69+
// these mirrors are always strong roots.
70+
// 2. This is a Java mirror for a newly allocated non-primitive class, and we
71+
// somehow managed to reach the newly allocated Java mirror with not yet
72+
// installed backlink. We cannot do anything here, this case would be handled
73+
// separately by GC, e.g. by keeping the relevant metadata alive during the GC.
74+
// Unfortunately, the existence of corner case (2) prevents us from asserting (1).
75+
}
76+
}
77+
4978
template <typename T, class OopClosureType>
5079
void InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
5180
InstanceKlass::oop_oop_iterate<T>(obj, closure);
5281

5382
if (Devirtualizer::do_metadata(closure)) {
54-
Klass* klass = java_lang_Class::as_Klass(obj);
55-
// We'll get null for primitive mirrors.
56-
if (klass != nullptr) {
57-
if (klass->class_loader_data() == nullptr) {
58-
// This is a mirror that belongs to a shared class that has not be loaded yet.
59-
assert(klass->is_shared(), "must be");
60-
} else if (klass->is_instance_klass() && klass->class_loader_data()->has_class_mirror_holder()) {
61-
// A non-strong hidden class doesn't have its own class loader,
62-
// so when handling the java mirror for the class we need to make sure its class
63-
// loader data is claimed, this is done by calling do_cld explicitly.
64-
// For non-strong hidden classes the call to do_cld is made when the class
65-
// loader itself is handled.
66-
Devirtualizer::do_cld(closure, klass->class_loader_data());
67-
} else {
68-
Devirtualizer::do_klass(closure, klass);
69-
}
70-
} else {
71-
// We would like to assert here (as below) that if klass has been null, then
72-
// this has been a mirror for a primitive type that we do not need to follow
73-
// as they are always strong roots.
74-
// However, we might get across a klass that just changed during CMS concurrent
75-
// marking if allocation occurred in the old generation.
76-
// This is benign here, as we keep alive all CLDs that were loaded during the
77-
// CMS concurrent phase in the class loading, i.e. they will be iterated over
78-
// and kept alive during remark.
79-
// assert(java_lang_Class::is_primitive(obj), "Sanity check");
80-
}
83+
do_metadata<OopClosureType>(obj, closure);
8184
}
8285

8386
oop_oop_iterate_statics<T>(obj, closure);
@@ -121,11 +124,7 @@ void InstanceMirrorKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closu
121124

122125
if (Devirtualizer::do_metadata(closure)) {
123126
if (mr.contains(obj)) {
124-
Klass* klass = java_lang_Class::as_Klass(obj);
125-
// We'll get null for primitive mirrors.
126-
if (klass != nullptr) {
127-
Devirtualizer::do_klass(closure, klass);
128-
}
127+
do_metadata<OopClosureType>(obj, closure);
129128
}
130129
}
131130

0 commit comments

Comments
 (0)