JBR-3459: Fix race condition in ClassLoaderDataGraph::classes_do

InstanceKlass in ClassLoaderData can be uninitialized when
ClassLoaderDataGraph::classes_do is called. Using
ClassLoaderDataGraph::dictionary_classes_do is safe but problem is still
persisting with anonymous classes.
This commit is contained in:
Vladimir Dvorak
2021-03-20 20:51:08 +01:00
committed by Vitaly Provodin
parent 9861d1cadf
commit 97e5abd8a1
3 changed files with 26 additions and 2 deletions

View File

@@ -361,6 +361,16 @@ void ClassLoaderDataGraph::classes_do(KlassClosure* klass_closure) {
}
}
void ClassLoaderDataGraph::anonymous_or_hidden_classes_do(KlassClosure* klass_closure) {
Thread* thread = Thread::current();
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
if (cld->has_class_mirror_holder()) {
Handle holder(thread, cld->holder_phantom());
cld->classes_do(klass_closure);
}
}
}
void ClassLoaderDataGraph::classes_do(void f(Klass* const)) {
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData* cld = iter.get_next()) {

View File

@@ -78,6 +78,10 @@ class ClassLoaderDataGraph : public AllStatic {
// for redefinition. These classes are removed during the next class unloading.
// Walking the ClassLoaderDataGraph also includes hidden classes.
static void classes_do(KlassClosure* klass_closure);
// Enhanced class redefinition
static void anonymous_or_hidden_classes_do(KlassClosure* klass_closure);
static void classes_do(void f(Klass* const));
static void methods_do(void f(Method*));
static void modules_do(void f(ModuleEntry*));

View File

@@ -2164,9 +2164,19 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
{
MutexLocker mcld(ClassLoaderDataGraph_lock);
ClassLoaderDataGraph::classes_do(&closure);
// 0. we can't use ClassLoaderDataGraph::classes_do since classes can be uninitialized in cld,
// fully initialized class is in system dictionary
// ClassLoaderDataGraph::classes_do(&closure);
// 1. Scan over dictionaries
ClassLoaderDataGraph::dictionary_classes_do(&closure);
// 2. Anonymous or hidden class is not in dictionary, we have to iterate anonymous cld directly, but there is race cond...
// TODO: review ... anonymous class is added to cld before InstanceKlass initialization,
// find out how to check if the InstanceKlass is initialized
ClassLoaderDataGraph::anonymous_or_hidden_classes_do(&closure);
}
//ClassLoaderDataGraph::dictionary_classes_do(&closure);
log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length());