Skip to content

Commit 5909d54

Browse files
committed
8326820: Metadata artificially kept alive
Reviewed-by: eosterlund, stefank, coleenp
1 parent d5375c7 commit 5909d54

File tree

6 files changed

+55
-49
lines changed

6 files changed

+55
-49
lines changed

src/hotspot/share/classfile/classLoaderDataGraph.cpp

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -241,22 +241,23 @@ LockedClassesDo::~LockedClassesDo() {
241241

242242

243243
// Iterating over the CLDG needs to be locked because
244-
// unloading can remove entries concurrently soon.
245-
template <bool keep_alive = true>
246-
class ClassLoaderDataGraphIteratorBase : public StackObj {
244+
// unloading can remove entries concurrently.
245+
// This iterator does not keep the CLD alive.
246+
// Any CLD OopHandles (modules, mirrors, resolved refs)
247+
// resolved must be treated as no keepalive. And requires
248+
// that its CLD's holder is kept alive if they escape the
249+
// caller's safepoint or ClassLoaderDataGraph_lock
250+
// critical section.
251+
class ClassLoaderDataGraph::ClassLoaderDataGraphIterator : public StackObj {
247252
ClassLoaderData* _next;
248253
Thread* _thread;
249254
HandleMark _hm; // clean up handles when this is done.
250255
NoSafepointVerifier _nsv; // No safepoints allowed in this scope
251256
// unless verifying at a safepoint.
252257

253258
public:
254-
ClassLoaderDataGraphIteratorBase() : _next(ClassLoaderDataGraph::_head), _thread(Thread::current()), _hm(_thread) {
255-
if (keep_alive) {
256-
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
257-
} else {
258-
assert_at_safepoint();
259-
}
259+
ClassLoaderDataGraphIterator() : _next(ClassLoaderDataGraph::_head), _thread(Thread::current()), _hm(_thread) {
260+
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
260261
}
261262

262263
ClassLoaderData* get_next() {
@@ -266,10 +267,6 @@ class ClassLoaderDataGraphIteratorBase : public StackObj {
266267
cld = cld->next();
267268
}
268269
if (cld != nullptr) {
269-
if (keep_alive) {
270-
// Keep cld that is being returned alive.
271-
Handle(_thread, cld->holder());
272-
}
273270
_next = cld->next();
274271
} else {
275272
_next = nullptr;
@@ -278,23 +275,13 @@ class ClassLoaderDataGraphIteratorBase : public StackObj {
278275
}
279276
};
280277

281-
using ClassLoaderDataGraphIterator = ClassLoaderDataGraphIteratorBase<true /* keep_alive */>;
282-
using ClassLoaderDataGraphIteratorNoKeepAlive = ClassLoaderDataGraphIteratorBase<false /* keep_alive */>;
283-
284278
void ClassLoaderDataGraph::loaded_cld_do(CLDClosure* cl) {
285279
ClassLoaderDataGraphIterator iter;
286280
while (ClassLoaderData* cld = iter.get_next()) {
287281
cl->do_cld(cld);
288282
}
289283
}
290284

291-
void ClassLoaderDataGraph::loaded_cld_do_no_keepalive(CLDClosure* cl) {
292-
ClassLoaderDataGraphIteratorNoKeepAlive iter;
293-
while (ClassLoaderData* cld = iter.get_next()) {
294-
cl->do_cld(cld);
295-
}
296-
}
297-
298285
// These functions assume that the caller has locked the ClassLoaderDataGraph_lock
299286
// if they are not calling the function from a safepoint.
300287
void ClassLoaderDataGraph::classes_do(KlassClosure* klass_closure) {
@@ -318,6 +305,16 @@ void ClassLoaderDataGraph::methods_do(void f(Method*)) {
318305
}
319306
}
320307

308+
void ClassLoaderDataGraph::modules_do_keepalive(void f(ModuleEntry*)) {
309+
assert_locked_or_safepoint(Module_lock);
310+
ClassLoaderDataGraphIterator iter;
311+
while (ClassLoaderData* cld = iter.get_next()) {
312+
// Keep the holder alive.
313+
(void)cld->holder();
314+
cld->modules_do(f);
315+
}
316+
}
317+
321318
void ClassLoaderDataGraph::modules_do(void f(ModuleEntry*)) {
322319
assert_locked_or_safepoint(Module_lock);
323320
ClassLoaderDataGraphIterator iter;
@@ -334,9 +331,11 @@ void ClassLoaderDataGraph::packages_do(void f(PackageEntry*)) {
334331
}
335332
}
336333

337-
void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
334+
void ClassLoaderDataGraph::loaded_classes_do_keepalive(KlassClosure* klass_closure) {
338335
ClassLoaderDataGraphIterator iter;
339336
while (ClassLoaderData* cld = iter.get_next()) {
337+
// Keep the holder alive.
338+
(void)cld->holder();
340339
cld->loaded_classes_do(klass_closure);
341340
}
342341
}
@@ -346,34 +345,36 @@ void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) {
346345
}
347346

348347
void ClassLoaderDataGraph::verify_dictionary() {
349-
ClassLoaderDataGraphIteratorNoKeepAlive iter;
348+
ClassLoaderDataGraphIterator iter;
350349
while (ClassLoaderData* cld = iter.get_next()) {
351350
if (cld->dictionary() != nullptr) {
352351
cld->dictionary()->verify();
353352
}
354353
}
355354
}
356355

357-
#define FOR_ALL_DICTIONARY(X) ClassLoaderDataGraphIterator iter; \
358-
while (ClassLoaderData* X = iter.get_next()) \
359-
if (X->dictionary() != nullptr)
360-
361356
void ClassLoaderDataGraph::print_dictionary(outputStream* st) {
362-
FOR_ALL_DICTIONARY(cld) {
363-
st->print("Dictionary for ");
364-
cld->print_value_on(st);
365-
st->cr();
366-
cld->dictionary()->print_on(st);
367-
st->cr();
357+
ClassLoaderDataGraphIterator iter;
358+
while (ClassLoaderData *cld = iter.get_next()) {
359+
if (cld->dictionary() != nullptr) {
360+
st->print("Dictionary for ");
361+
cld->print_value_on(st);
362+
st->cr();
363+
cld->dictionary()->print_on(st);
364+
st->cr();
365+
}
368366
}
369367
}
370368

371369
void ClassLoaderDataGraph::print_table_statistics(outputStream* st) {
372-
FOR_ALL_DICTIONARY(cld) {
373-
ResourceMark rm; // loader_name_and_id
374-
stringStream tempst;
375-
tempst.print("System Dictionary for %s class loader", cld->loader_name_and_id());
376-
cld->dictionary()->print_table_statistics(st, tempst.freeze());
370+
ClassLoaderDataGraphIterator iter;
371+
while (ClassLoaderData *cld = iter.get_next()) {
372+
if (cld->dictionary() != nullptr) {
373+
ResourceMark rm; // loader_name_and_id
374+
stringStream tempst;
375+
tempst.print("System Dictionary for %s class loader", cld->loader_name_and_id());
376+
cld->dictionary()->print_table_statistics(st, tempst.freeze());
377+
}
377378
}
378379
}
379380

@@ -550,7 +551,7 @@ Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass() {
550551
}
551552

552553
void ClassLoaderDataGraph::verify() {
553-
ClassLoaderDataGraphIteratorNoKeepAlive iter;
554+
ClassLoaderDataGraphIterator iter;
554555
while (ClassLoaderData* cld = iter.get_next()) {
555556
cld->verify();
556557
}

src/hotspot/share/classfile/classLoaderDataGraph.hpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ class ClassLoaderDataGraph : public AllStatic {
3737
friend class ClassLoaderDataGraphMetaspaceIterator;
3838
friend class ClassLoaderDataGraphKlassIteratorAtomic;
3939
friend class ClassLoaderDataGraphKlassIteratorStatic;
40-
template <bool keep_alive>
41-
friend class ClassLoaderDataGraphIteratorBase;
4240
friend class VMStructs;
4341
private:
42+
class ClassLoaderDataGraphIterator;
43+
4444
// All CLDs (except unlinked CLDs) can be reached by walking _head->_next->...
4545
static ClassLoaderData* volatile _head;
4646

@@ -71,8 +71,12 @@ class ClassLoaderDataGraph : public AllStatic {
7171
static void roots_cld_do(CLDClosure* strong, CLDClosure* weak);
7272
static void always_strong_cld_do(CLDClosure* cl);
7373
// Iteration through CLDG not by GC.
74+
// All the do suffixed functions do not keep the CLD alive. Any CLD OopHandles
75+
// (modules, mirrors, resolved refs) resolved must be treated as no keepalive.
76+
// And requires that its CLD's holder is kept alive if they escape the
77+
// caller's safepoint or ClassLoaderDataGraph_lock critical section.
78+
// The do_keepalive suffixed functions will keep all CLDs alive.
7479
static void loaded_cld_do(CLDClosure* cl);
75-
static void loaded_cld_do_no_keepalive(CLDClosure* cl);
7680
// klass do
7781
// Walking classes through the ClassLoaderDataGraph include array classes. It also includes
7882
// classes that are allocated but not loaded, classes that have errors, and scratch classes
@@ -81,9 +85,10 @@ class ClassLoaderDataGraph : public AllStatic {
8185
static void classes_do(KlassClosure* klass_closure);
8286
static void classes_do(void f(Klass* const));
8387
static void methods_do(void f(Method*));
88+
static void modules_do_keepalive(void f(ModuleEntry*));
8489
static void modules_do(void f(ModuleEntry*));
8590
static void packages_do(void f(PackageEntry*));
86-
static void loaded_classes_do(KlassClosure* klass_closure);
91+
static void loaded_classes_do_keepalive(KlassClosure* klass_closure);
8792
static void classes_unloading_do(void f(Klass* const));
8893
static bool do_unloading();
8994

src/hotspot/share/classfile/classLoaderStats.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ void ClassLoaderStatsClosure::addEmptyParents(oop cl) {
165165

166166
void ClassLoaderStatsVMOperation::doit() {
167167
ClassLoaderStatsClosure clsc (_out);
168-
ClassLoaderDataGraph::loaded_cld_do_no_keepalive(&clsc);
168+
ClassLoaderDataGraph::loaded_cld_do(&clsc);
169169
clsc.print();
170170
}
171171

src/hotspot/share/classfile/systemDictionary.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ class SystemDictionary : AllStatic {
177177

178178
static void classes_do(MetaspaceClosure* it);
179179
// Iterate over all methods in all klasses
180-
180+
// Will not keep metadata alive. See ClassLoaderDataGraph::methods_do.
181181
static void methods_do(void f(Method*));
182182

183183
// Garbage collection support

src/hotspot/share/prims/jvmtiEnvBase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2339,7 +2339,7 @@ JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobje
23392339
}
23402340

23412341
// Iterate over all the modules loaded to the system.
2342-
ClassLoaderDataGraph::modules_do(&do_module);
2342+
ClassLoaderDataGraph::modules_do_keepalive(&do_module);
23432343

23442344
jint len = _tbl->length();
23452345
guarantee(len > 0, "at least one module must be present");

src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jcla
105105
// Iterate through all classes in ClassLoaderDataGraph
106106
// and collect them using the LoadedClassesClosure
107107
MutexLocker mcld(ClassLoaderDataGraph_lock);
108-
ClassLoaderDataGraph::loaded_classes_do(&closure);
108+
ClassLoaderDataGraph::loaded_classes_do_keepalive(&closure);
109109
}
110110

111111
return closure.get_result(env, classCountPtr, classesPtr);

0 commit comments

Comments
 (0)