Skip to content

Commit d330421

Browse files
committed
8337548: Parallel class loading can pass is_superclass true for interfaces
Reviewed-by: iklam
1 parent 3f1d9b5 commit d330421

File tree

2 files changed

+28
-26
lines changed

2 files changed

+28
-26
lines changed

src/hotspot/share/classfile/systemDictionary.cpp

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -424,36 +424,39 @@ InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* clas
424424
assert(next_name != nullptr, "null superclass for resolving");
425425
assert(!Signature::is_array(next_name), "invalid superclass name");
426426

427-
// If class_name is already loaded, just return the superclass or superinterface.
428-
// Make sure there's a placeholder for the class_name before resolving.
429-
// This is used as a claim that this thread is currently loading superclass/classloader
430-
// and for ClassCircularity checks.
431-
432427
ClassLoaderData* loader_data = class_loader_data(class_loader);
433-
Dictionary* dictionary = loader_data->dictionary();
428+
429+
if (is_superclass) {
430+
InstanceKlass* klassk = loader_data->dictionary()->find_class(THREAD, class_name);
431+
if (klassk != nullptr) {
432+
// We can come here for two reasons:
433+
// (a) RedefineClasses -- the class is already loaded
434+
// (b) Rarely, the class might have been loaded by a parallel thread
435+
// We can do a quick check against the already assigned superclass's name and loader.
436+
InstanceKlass* superk = klassk->java_super();
437+
if (superk != nullptr &&
438+
superk->name() == next_name &&
439+
superk->class_loader() == class_loader()) {
440+
return superk;
441+
}
442+
}
443+
}
434444

435445
// can't throw error holding a lock
436446
bool throw_circularity_error = false;
437447
{
438448
MutexLocker mu(THREAD, SystemDictionary_lock);
439-
InstanceKlass* klassk = dictionary->find_class(THREAD, class_name);
440-
InstanceKlass* quicksuperk;
441-
// To support parallel loading: if class is done loading, just return the superclass
442-
// if the next_name matches class->super()->name() and if the class loaders match.
443-
if (klassk != nullptr && is_superclass &&
444-
((quicksuperk = klassk->java_super()) != nullptr) &&
445-
((quicksuperk->name() == next_name) &&
446-
(quicksuperk->class_loader() == class_loader()))) {
447-
return quicksuperk;
448-
} else {
449-
// Must check ClassCircularity before checking if superclass is already loaded.
450-
PlaceholderEntry* probe = PlaceholderTable::get_entry(class_name, loader_data);
451-
if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::DETECT_CIRCULARITY)) {
452-
log_circularity_error(class_name, probe);
453-
throw_circularity_error = true;
454-
}
449+
450+
// Must check ClassCircularity before resolving next_name (superclass or interface).
451+
PlaceholderEntry* probe = PlaceholderTable::get_entry(class_name, loader_data);
452+
if (probe != nullptr && probe->check_seen_thread(THREAD, PlaceholderTable::DETECT_CIRCULARITY)) {
453+
log_circularity_error(class_name, probe);
454+
throw_circularity_error = true;
455455
}
456456

457+
// Make sure there's a placeholder for the class_name before resolving.
458+
// This is used as a claim that this thread is currently loading superclass/classloader
459+
// and for ClassCircularity checks.
457460
if (!throw_circularity_error) {
458461
// Be careful not to exit resolve_with_circularity_detection without removing this placeholder.
459462
PlaceholderEntry* newprobe = PlaceholderTable::find_and_add(class_name,
@@ -501,12 +504,11 @@ static void handle_parallel_super_load(Symbol* name,
501504
TRAPS) {
502505

503506
// The result superk is not used; resolve_with_circularity_detection is called for circularity check only.
504-
// This passes true to is_superclass even though it might not be the super class in order to perform the
505-
// optimization anyway.
507+
// This passes false to is_superclass to skip doing the unlikely optimization.
506508
Klass* superk = SystemDictionary::resolve_with_circularity_detection(name,
507509
superclassname,
508510
class_loader,
509-
true,
511+
false,
510512
CHECK);
511513
}
512514

src/hotspot/share/classfile/systemDictionary.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it

0 commit comments

Comments
 (0)