mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-14 18:03:44 +00:00
8336919: Cleanup and rename tags in placeholders code
Co-authored-by: Frederic Parain <fparain@openjdk.org> Reviewed-by: iklam, fparain, dholmes
This commit is contained in:
parent
e4c7850c17
commit
8f039b5629
@ -835,14 +835,12 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
|
||||
guarantee_property(unresolved_klass->char_at(0) != JVM_SIGNATURE_ARRAY,
|
||||
"Bad interface name in class file %s", CHECK);
|
||||
|
||||
// Call resolve_super so class circularity is checked
|
||||
interf = SystemDictionary::resolve_super_or_fail(
|
||||
_class_name,
|
||||
unresolved_klass,
|
||||
Handle(THREAD, _loader_data->class_loader()),
|
||||
_protection_domain,
|
||||
false,
|
||||
CHECK);
|
||||
// Call resolve on the interface class name with class circularity checking
|
||||
interf = SystemDictionary::resolve_super_or_fail(_class_name,
|
||||
unresolved_klass,
|
||||
Handle(THREAD, _loader_data->class_loader()),
|
||||
_protection_domain,
|
||||
false, CHECK);
|
||||
}
|
||||
|
||||
if (!interf->is_interface()) {
|
||||
|
||||
@ -95,8 +95,8 @@ SeenThread* PlaceholderEntry::actionToQueue(PlaceholderTable::classloadAction ac
|
||||
case PlaceholderTable::LOAD_INSTANCE:
|
||||
queuehead = _loadInstanceThreadQ;
|
||||
break;
|
||||
case PlaceholderTable::LOAD_SUPER:
|
||||
queuehead = _superThreadQ;
|
||||
case PlaceholderTable::DETECT_CIRCULARITY:
|
||||
queuehead = _circularityThreadQ;
|
||||
break;
|
||||
case PlaceholderTable::DEFINE_CLASS:
|
||||
queuehead = _defineThreadQ;
|
||||
@ -111,8 +111,8 @@ void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::cla
|
||||
case PlaceholderTable::LOAD_INSTANCE:
|
||||
_loadInstanceThreadQ = seenthread;
|
||||
break;
|
||||
case PlaceholderTable::LOAD_SUPER:
|
||||
_superThreadQ = seenthread;
|
||||
case PlaceholderTable::DETECT_CIRCULARITY:
|
||||
_circularityThreadQ = seenthread;
|
||||
break;
|
||||
case PlaceholderTable::DEFINE_CLASS:
|
||||
_defineThreadQ = seenthread;
|
||||
@ -188,10 +188,10 @@ bool PlaceholderEntry::remove_seen_thread(JavaThread* thread, PlaceholderTable::
|
||||
}
|
||||
|
||||
|
||||
void PlaceholderEntry::set_supername(Symbol* supername) {
|
||||
void PlaceholderEntry::set_next_klass_name(Symbol* next_klass_name) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
assert(_supername == nullptr || _supername->refcount() > 1, "must be referenced also by the loader");
|
||||
_supername = supername;
|
||||
assert(_next_klass_name == nullptr || _next_klass_name->refcount() > 1, "must be referenced also by the loader");
|
||||
_next_klass_name = next_klass_name;
|
||||
}
|
||||
|
||||
// Placeholder objects represent classes currently being loaded.
|
||||
@ -199,12 +199,12 @@ void PlaceholderEntry::set_supername(Symbol* supername) {
|
||||
// SystemDictionary_lock, so we don't need special precautions
|
||||
// on store ordering here.
|
||||
static PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
|
||||
Symbol* supername){
|
||||
Symbol* next_klass_name){
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
assert(class_name != nullptr, "adding nullptr obj");
|
||||
|
||||
PlaceholderEntry entry;
|
||||
entry.set_supername(supername);
|
||||
entry.set_next_klass_name(next_klass_name);
|
||||
PlaceholderKey key(class_name, loader_data);
|
||||
bool created;
|
||||
PlaceholderEntry* table_copy = _placeholders->put_if_absent(key, entry, &created);
|
||||
@ -230,7 +230,7 @@ PlaceholderEntry* PlaceholderTable::get_entry(Symbol* class_name, ClassLoaderDat
|
||||
static const char* action_to_string(PlaceholderTable::classloadAction action) {
|
||||
switch (action) {
|
||||
case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
|
||||
case PlaceholderTable::LOAD_SUPER: return "LOAD_SUPER";
|
||||
case PlaceholderTable::DETECT_CIRCULARITY: return "DETECT_CIRCULARITY";
|
||||
case PlaceholderTable::DEFINE_CLASS: return "DEFINE_CLASS";
|
||||
}
|
||||
return "";
|
||||
@ -250,20 +250,21 @@ inline void log(Symbol* name, PlaceholderEntry* entry, const char* function, Pla
|
||||
// If no entry exists, add a placeholder entry
|
||||
// If entry exists, reuse entry
|
||||
// For both, push SeenThread for classloadAction
|
||||
// If LOAD_SUPER, this is used for circularity detection for instanceklass loading.
|
||||
// If DETECT_CIRCULARITY, this is used for circularity detection for instanceklass loading.
|
||||
PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
|
||||
ClassLoaderData* loader_data,
|
||||
classloadAction action,
|
||||
Symbol* supername,
|
||||
Symbol* next_klass_name,
|
||||
JavaThread* thread) {
|
||||
assert(action != LOAD_SUPER || supername != nullptr, "must have a super class name");
|
||||
assert(action != DETECT_CIRCULARITY || next_klass_name != nullptr,
|
||||
"must have a class name for the next step in the class resolution recursion");
|
||||
PlaceholderEntry* probe = get_entry(name, loader_data);
|
||||
if (probe == nullptr) {
|
||||
// Nothing found, add place holder
|
||||
probe = add_entry(name, loader_data, supername);
|
||||
probe = add_entry(name, loader_data, next_klass_name);
|
||||
} else {
|
||||
if (action == LOAD_SUPER) {
|
||||
probe->set_supername(supername);
|
||||
if (action == DETECT_CIRCULARITY) {
|
||||
probe->set_next_klass_name(next_klass_name);
|
||||
}
|
||||
}
|
||||
probe->add_seen_thread(thread, action);
|
||||
@ -295,11 +296,11 @@ void PlaceholderTable::find_and_remove(Symbol* name, ClassLoaderData* loader_dat
|
||||
assert(probe != nullptr, "must find an entry");
|
||||
log(name, probe, "find_and_remove", action);
|
||||
probe->remove_seen_thread(thread, action);
|
||||
if (probe->superThreadQ() == nullptr) {
|
||||
probe->set_supername(nullptr);
|
||||
if (probe->circularityThreadQ() == nullptr) {
|
||||
probe->set_next_klass_name(nullptr);
|
||||
}
|
||||
// If no other threads using this entry, and this thread is not using this entry for other states
|
||||
if ((probe->superThreadQ() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
|
||||
if ((probe->circularityThreadQ() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
|
||||
&& (probe->defineThreadQ() == nullptr) && (probe->definer() == nullptr)) {
|
||||
remove_entry(name, loader_data);
|
||||
}
|
||||
@ -312,9 +313,9 @@ void PlaceholderKey::print_on(outputStream* st) const {
|
||||
}
|
||||
|
||||
void PlaceholderEntry::print_on(outputStream* st) const {
|
||||
if (supername() != nullptr) {
|
||||
st->print(", supername ");
|
||||
supername()->print_value_on(st);
|
||||
if (next_klass_name() != nullptr) {
|
||||
st->print(", next_klass_name ");
|
||||
next_klass_name()->print_value_on(st);
|
||||
}
|
||||
if (definer() != nullptr) {
|
||||
st->print(", definer ");
|
||||
@ -328,8 +329,8 @@ void PlaceholderEntry::print_on(outputStream* st) const {
|
||||
st->print("loadInstanceThreadQ threads:");
|
||||
SeenThread::print_action_queue(loadInstanceThreadQ(), st);
|
||||
st->cr();
|
||||
st->print("superThreadQ threads:");
|
||||
SeenThread::print_action_queue(superThreadQ(), st);
|
||||
st->print("circularityThreadQ threads:");
|
||||
SeenThread::print_action_queue(circularityThreadQ(), st);
|
||||
st->cr();
|
||||
st->print("defineThreadQ threads:");
|
||||
SeenThread::print_action_queue(defineThreadQ(), st);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -41,15 +41,15 @@ class PlaceholderTable : public AllStatic {
|
||||
// caller claims ownership of that action
|
||||
// For parallel classloading:
|
||||
// multiple LOAD_INSTANCE threads can proceed in parallel
|
||||
// multiple LOAD_SUPER threads can proceed in parallel
|
||||
// LOAD_SUPER needed to check for class circularity
|
||||
// multiple DETECT_CIRCULARITY threads can proceed in parallel
|
||||
// DETECT_CIRCULARITY needed to check for class circularity
|
||||
// DEFINE_CLASS: ultimately define class must be single threaded
|
||||
// on a class/classloader basis
|
||||
// so the head of that queue owns the token
|
||||
// and the rest of the threads return the result the first thread gets
|
||||
enum classloadAction {
|
||||
LOAD_INSTANCE = 1, // calling load_instance_class
|
||||
LOAD_SUPER = 2, // loading superclass for this class
|
||||
DETECT_CIRCULARITY = 2, // loading while detecting class circularity
|
||||
DEFINE_CLASS = 3 // find_or_define class
|
||||
};
|
||||
static void initialize();
|
||||
@ -81,13 +81,13 @@ class SeenThread;
|
||||
class PlaceholderEntry {
|
||||
friend class PlaceholderTable;
|
||||
private:
|
||||
SymbolHandle _supername;
|
||||
JavaThread* _definer; // owner of define token
|
||||
InstanceKlass* _instanceKlass; // InstanceKlass from successful define
|
||||
SeenThread* _superThreadQ; // doubly-linked queue of Threads loading a superclass for this class
|
||||
SeenThread* _loadInstanceThreadQ; // loadInstance thread
|
||||
// This can't be multiple threads since class loading waits for
|
||||
// this token to be removed.
|
||||
SymbolHandle _next_klass_name; // next step in the recursive process of class loading
|
||||
JavaThread* _definer; // owner of define token
|
||||
InstanceKlass* _instanceKlass; // InstanceKlass from successful define
|
||||
SeenThread* _circularityThreadQ; // doubly-linked queue of Threads loading with circularity detection
|
||||
SeenThread* _loadInstanceThreadQ; // loadInstance thread
|
||||
// This can't be multiple threads since class loading
|
||||
// waits for this token to be removed.
|
||||
|
||||
SeenThread* _defineThreadQ; // queue of Threads trying to define this class
|
||||
// including _definer
|
||||
@ -99,8 +99,8 @@ class PlaceholderEntry {
|
||||
void add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
|
||||
bool remove_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
|
||||
|
||||
SeenThread* superThreadQ() const { return _superThreadQ; }
|
||||
void set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; }
|
||||
SeenThread* circularityThreadQ() const { return _circularityThreadQ; }
|
||||
void set_circularityThreadQ(SeenThread* SeenThread) { _circularityThreadQ = SeenThread; }
|
||||
|
||||
SeenThread* loadInstanceThreadQ() const { return _loadInstanceThreadQ; }
|
||||
void set_loadInstanceThreadQ(SeenThread* SeenThread) { _loadInstanceThreadQ = SeenThread; }
|
||||
@ -110,10 +110,10 @@ class PlaceholderEntry {
|
||||
public:
|
||||
PlaceholderEntry() :
|
||||
_definer(nullptr), _instanceKlass(nullptr),
|
||||
_superThreadQ(nullptr), _loadInstanceThreadQ(nullptr), _defineThreadQ(nullptr) { }
|
||||
_circularityThreadQ(nullptr), _loadInstanceThreadQ(nullptr), _defineThreadQ(nullptr) { }
|
||||
|
||||
Symbol* supername() const { return _supername; }
|
||||
void set_supername(Symbol* supername);
|
||||
Symbol* next_klass_name() const { return _next_klass_name; }
|
||||
void set_next_klass_name(Symbol* next_klass_name);
|
||||
|
||||
JavaThread* definer() const {return _definer; }
|
||||
void set_definer(JavaThread* definer) { _definer = definer; }
|
||||
@ -121,8 +121,8 @@ class PlaceholderEntry {
|
||||
InstanceKlass* instance_klass() const {return _instanceKlass; }
|
||||
void set_instance_klass(InstanceKlass* ik) { _instanceKlass = ik; }
|
||||
|
||||
bool super_load_in_progress() {
|
||||
return (_superThreadQ != nullptr);
|
||||
bool circularity_detection_in_progress() {
|
||||
return (_circularityThreadQ != nullptr);
|
||||
}
|
||||
|
||||
bool instance_load_in_progress() {
|
||||
|
||||
@ -399,32 +399,32 @@ static inline void log_circularity_error(Symbol* name, PlaceholderEntry* probe)
|
||||
// superclass checks on its own thread to catch class circularity and
|
||||
// to avoid deadlock.
|
||||
//
|
||||
// resolve_super_or_fail adds a LOAD_SUPER placeholder to the placeholder table before calling
|
||||
// resolve_instance_class_or_null. ClassCircularityError is detected when a LOAD_SUPER or LOAD_INSTANCE
|
||||
// resolve_with_circularity_detection adds a DETECT_CIRCULARITY placeholder to the placeholder table before calling
|
||||
// resolve_instance_class_or_null. ClassCircularityError is detected when a DETECT_CIRCULARITY or LOAD_INSTANCE
|
||||
// placeholder for the same thread, class, classloader is found.
|
||||
// This can be seen with logging option: -Xlog:class+load+placeholders=debug.
|
||||
//
|
||||
InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name,
|
||||
Symbol* super_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
bool is_superclass,
|
||||
TRAPS) {
|
||||
InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* class_name,
|
||||
Symbol* next_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
bool is_superclass,
|
||||
TRAPS) {
|
||||
|
||||
assert(super_name != nullptr, "null superclass for resolving");
|
||||
assert(!Signature::is_array(super_name), "invalid superclass name");
|
||||
assert(next_name != nullptr, "null superclass for resolving");
|
||||
assert(!Signature::is_array(next_name), "invalid superclass name");
|
||||
#if INCLUDE_CDS
|
||||
if (CDSConfig::is_dumping_static_archive()) {
|
||||
// Special processing for handling UNREGISTERED shared classes.
|
||||
InstanceKlass* k = SystemDictionaryShared::lookup_super_for_unregistered_class(class_name,
|
||||
super_name, is_superclass);
|
||||
next_name, is_superclass);
|
||||
if (k) {
|
||||
return k;
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_CDS
|
||||
|
||||
// If klass is already loaded, just return the superclass or superinterface.
|
||||
// If class_name is already loaded, just return the superclass or superinterface.
|
||||
// Make sure there's a placeholder for the class_name before resolving.
|
||||
// This is used as a claim that this thread is currently loading superclass/classloader
|
||||
// and for ClassCircularity checks.
|
||||
@ -439,28 +439,27 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name,
|
||||
InstanceKlass* klassk = dictionary->find_class(THREAD, class_name);
|
||||
InstanceKlass* quicksuperk;
|
||||
// To support parallel loading: if class is done loading, just return the superclass
|
||||
// if the super_name matches class->super()->name() and if the class loaders match.
|
||||
// Otherwise, a LinkageError will be thrown later.
|
||||
// if the next_name matches class->super()->name() and if the class loaders match.
|
||||
if (klassk != nullptr && is_superclass &&
|
||||
((quicksuperk = klassk->java_super()) != nullptr) &&
|
||||
((quicksuperk->name() == super_name) &&
|
||||
(quicksuperk->class_loader() == class_loader()))) {
|
||||
return quicksuperk;
|
||||
((quicksuperk = klassk->java_super()) != nullptr) &&
|
||||
((quicksuperk->name() == next_name) &&
|
||||
(quicksuperk->class_loader() == class_loader()))) {
|
||||
return quicksuperk;
|
||||
} else {
|
||||
// Must check ClassCircularity before checking if superclass is already loaded.
|
||||
PlaceholderEntry* probe = PlaceholderTable::get_entry(class_name, loader_data);
|
||||
if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER)) {
|
||||
if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::DETECT_CIRCULARITY)) {
|
||||
log_circularity_error(class_name, probe);
|
||||
throw_circularity_error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!throw_circularity_error) {
|
||||
// Be careful not to exit resolve_super without removing this placeholder.
|
||||
// Be careful not to exit resolve_with_circularity_detection without removing this placeholder.
|
||||
PlaceholderEntry* newprobe = PlaceholderTable::find_and_add(class_name,
|
||||
loader_data,
|
||||
PlaceholderTable::LOAD_SUPER,
|
||||
super_name, THREAD);
|
||||
PlaceholderTable::DETECT_CIRCULARITY,
|
||||
next_name, THREAD);
|
||||
}
|
||||
}
|
||||
|
||||
@ -471,7 +470,7 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name,
|
||||
|
||||
// Resolve the superclass or superinterface, check results on return
|
||||
InstanceKlass* superk =
|
||||
SystemDictionary::resolve_instance_class_or_null(super_name,
|
||||
SystemDictionary::resolve_instance_class_or_null(next_name,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
THREAD);
|
||||
@ -479,13 +478,13 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name,
|
||||
// Clean up placeholder entry.
|
||||
{
|
||||
MutexLocker mu(THREAD, SystemDictionary_lock);
|
||||
PlaceholderTable::find_and_remove(class_name, loader_data, PlaceholderTable::LOAD_SUPER, THREAD);
|
||||
PlaceholderTable::find_and_remove(class_name, loader_data, PlaceholderTable::DETECT_CIRCULARITY, THREAD);
|
||||
SystemDictionary_lock->notify_all();
|
||||
}
|
||||
|
||||
// Check for pending exception or null superk, and throw exception
|
||||
if (HAS_PENDING_EXCEPTION || superk == nullptr) {
|
||||
handle_resolution_exception(super_name, true, CHECK_NULL);
|
||||
handle_resolution_exception(next_name, true, CHECK_NULL);
|
||||
}
|
||||
|
||||
return superk;
|
||||
@ -502,13 +501,15 @@ static void handle_parallel_super_load(Symbol* name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain, TRAPS) {
|
||||
|
||||
// superk is not used; resolve_super_or_fail is called for circularity check only.
|
||||
Klass* superk = SystemDictionary::resolve_super_or_fail(name,
|
||||
superclassname,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
true,
|
||||
CHECK);
|
||||
// The result superk is not used; resolve_with_circularity_detection is called for circularity check only.
|
||||
// This passes true to is_superclass even though it might not be the super class in order to perform the
|
||||
// optimization anyway.
|
||||
Klass* superk = SystemDictionary::resolve_with_circularity_detection(name,
|
||||
superclassname,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
true,
|
||||
CHECK);
|
||||
}
|
||||
|
||||
// Bootstrap and non-parallel capable class loaders use the LOAD_INSTANCE placeholder to
|
||||
@ -536,7 +537,7 @@ static InstanceKlass* handle_parallel_loading(JavaThread* current,
|
||||
// Wait until the first thread has finished loading this class. Also wait until all the
|
||||
// threads trying to load its superclass have removed their placeholders.
|
||||
while (oldprobe != nullptr &&
|
||||
(oldprobe->instance_load_in_progress() || oldprobe->super_load_in_progress())) {
|
||||
(oldprobe->instance_load_in_progress() || oldprobe->circularity_detection_in_progress())) {
|
||||
|
||||
// LOAD_INSTANCE placeholders are used to implement parallel capable class loading
|
||||
// for the bootclass loader.
|
||||
@ -575,8 +576,9 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
Handle protection_domain,
|
||||
TRAPS) {
|
||||
// name must be in the form of "java/lang/Object" -- cannot be "Ljava/lang/Object;"
|
||||
DEBUG_ONLY(ResourceMark rm(THREAD));
|
||||
assert(name != nullptr && !Signature::is_array(name) &&
|
||||
!Signature::has_envelope(name), "invalid class name");
|
||||
!Signature::has_envelope(name), "invalid class name: %s", name == nullptr ? "nullptr" : name->as_C_string());
|
||||
|
||||
EventClassLoad class_load_start_event;
|
||||
|
||||
@ -607,7 +609,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
Handle lockObject = get_loader_lock_or_null(class_loader);
|
||||
ObjectLocker ol(lockObject, THREAD);
|
||||
|
||||
bool super_load_in_progress = false;
|
||||
bool circularity_detection_in_progress = false;
|
||||
InstanceKlass* loaded_class = nullptr;
|
||||
SymbolHandle superclassname; // Keep alive while loading in parallel thread.
|
||||
|
||||
@ -625,9 +627,9 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
loaded_class = check;
|
||||
} else {
|
||||
PlaceholderEntry* placeholder = PlaceholderTable::get_entry(name, loader_data);
|
||||
if (placeholder != nullptr && placeholder->super_load_in_progress()) {
|
||||
super_load_in_progress = true;
|
||||
superclassname = placeholder->supername();
|
||||
if (placeholder != nullptr && placeholder->circularity_detection_in_progress()) {
|
||||
circularity_detection_in_progress = true;
|
||||
superclassname = placeholder->next_klass_name();
|
||||
assert(superclassname != nullptr, "superclass has to have a name");
|
||||
}
|
||||
}
|
||||
@ -635,7 +637,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
|
||||
// If the class is in the placeholder table with super_class set,
|
||||
// handle superclass loading in progress.
|
||||
if (super_load_in_progress) {
|
||||
if (circularity_detection_in_progress) {
|
||||
handle_parallel_super_load(name, superclassname,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
@ -1052,8 +1054,8 @@ bool SystemDictionary::check_shared_class_super_type(InstanceKlass* klass, Insta
|
||||
}
|
||||
}
|
||||
|
||||
Klass *found = resolve_super_or_fail(klass->name(), super_type->name(),
|
||||
class_loader, protection_domain, is_superclass, CHECK_0);
|
||||
Klass *found = resolve_with_circularity_detection(klass->name(), super_type->name(),
|
||||
class_loader, protection_domain, is_superclass, CHECK_0);
|
||||
if (found == super_type) {
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -102,15 +102,23 @@ class SystemDictionary : AllStatic {
|
||||
return resolve_or_null(class_name, Handle(), Handle(), THREAD);
|
||||
}
|
||||
|
||||
static InstanceKlass* resolve_with_circularity_detection(Symbol* class_name,
|
||||
Symbol* next_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
bool is_superclass,
|
||||
TRAPS);
|
||||
|
||||
// Resolve a superclass or superinterface. Called from ClassFileParser,
|
||||
// parse_interfaces, resolve_instance_class_or_null, load_shared_class
|
||||
// "class_name" is the class whose super class or interface is being resolved.
|
||||
static InstanceKlass* resolve_super_or_fail(Symbol* class_name,
|
||||
Symbol* super_name,
|
||||
static InstanceKlass* resolve_super_or_fail(Symbol* class_name, Symbol* super_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
bool is_superclass,
|
||||
TRAPS);
|
||||
Handle protection_domain, bool is_superclass, TRAPS) {
|
||||
return resolve_with_circularity_detection(class_name, super_name, class_loader, protection_domain,
|
||||
is_superclass, THREAD);
|
||||
}
|
||||
|
||||
private:
|
||||
// Parse the stream to create a hidden class.
|
||||
// Used by jvm_lookup_define_class.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -49,7 +49,7 @@ TEST_VM(PlaceholderTable, supername) {
|
||||
{
|
||||
MutexLocker ml(THREAD, SystemDictionary_lock);
|
||||
|
||||
PlaceholderTable::classloadAction super_action = PlaceholderTable::LOAD_SUPER;
|
||||
PlaceholderTable::classloadAction super_action = PlaceholderTable::DETECT_CIRCULARITY;
|
||||
PlaceholderTable::classloadAction define_action = PlaceholderTable::DEFINE_CLASS;
|
||||
|
||||
// DefineClass A and D
|
||||
@ -71,7 +71,7 @@ TEST_VM(PlaceholderTable, supername) {
|
||||
|
||||
// Another thread comes in and finds A loading Super
|
||||
PlaceholderEntry* placeholder = PlaceholderTable::get_entry(A, loader_data);
|
||||
SymbolHandle supername = placeholder->supername();
|
||||
SymbolHandle supername = placeholder->next_klass_name();
|
||||
|
||||
// Other thread is done before handle_parallel_super_load
|
||||
PlaceholderTable::find_and_remove(A, loader_data, super_action, THREAD);
|
||||
@ -86,7 +86,7 @@ TEST_VM(PlaceholderTable, supername) {
|
||||
// Refcount should be 3: one in table for class A, one in table for class D
|
||||
// and one locally with SymbolHandle keeping it alive
|
||||
placeholder = PlaceholderTable::get_entry(A, loader_data);
|
||||
supername = placeholder->supername();
|
||||
supername = placeholder->next_klass_name();
|
||||
EXPECT_EQ(super->refcount(), 3) << "super class name refcount should be 3";
|
||||
|
||||
// Second thread's done too
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user