8367475: Incorrect lock usage in LambdaFormInvokers::regenerate_holder_classes

Reviewed-by: dholmes, matsaave, liach
This commit is contained in:
Ioi Lam 2025-09-13 20:43:40 +00:00
parent ef291d2d5d
commit c85c5cb50e
3 changed files with 32 additions and 17 deletions

View File

@ -862,7 +862,11 @@ CDSConfig::DumperThreadMark::~DumperThreadMark() {
bool CDSConfig::current_thread_is_vm_or_dumper() {
Thread* t = Thread::current();
return t != nullptr && (t->is_VM_thread() || t == _dumper_thread);
return t->is_VM_thread() || t == _dumper_thread;
}
bool CDSConfig::current_thread_is_dumper() {
return Thread::current() == _dumper_thread;
}
const char* CDSConfig::type_of_archive_being_loaded() {

View File

@ -216,6 +216,7 @@ public:
~DumperThreadMark();
};
static bool current_thread_is_dumper() NOT_CDS_RETURN_(false);
static bool current_thread_is_vm_or_dumper() NOT_CDS_RETURN_(false);
};

View File

@ -53,6 +53,7 @@
GrowableArrayCHeap<char*, mtClassShared>* LambdaFormInvokers::_lambdaform_lines = nullptr;
Array<u4>* LambdaFormInvokers::_static_archive_invokers = nullptr;
static bool _stop_appending = false;
#define NUM_FILTER 4
static const char* filter[NUM_FILTER] = {"java.lang.invoke.Invokers$Holder",
@ -71,7 +72,12 @@ static bool should_be_archived(char* line) {
#undef NUM_FILTER
void LambdaFormInvokers::append(char* line) {
// This function can be called by concurrent Java threads, even after
// LambdaFormInvokers::regenerate_holder_classes() has been called.
MutexLocker ml(Thread::current(), LambdaFormInvokers_lock);
if (_stop_appending) {
return;
}
if (_lambdaform_lines == nullptr) {
_lambdaform_lines = new GrowableArrayCHeap<char*, mtClassShared>(150);
}
@ -112,12 +118,6 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) {
return;
}
PrintLambdaFormMessage plm;
if (_lambdaform_lines == nullptr || _lambdaform_lines->length() == 0) {
log_info(aot)("Nothing to regenerate for holder classes");
return;
}
ResourceMark rm(THREAD);
// Filter out AOT tooling classes like java.lang.invoke.GenerateJLIClassesHelper, etc.
@ -127,18 +127,27 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) {
Klass* cds_klass = SystemDictionary::resolve_or_null(cds_name, THREAD);
guarantee(cds_klass != nullptr, "jdk/internal/misc/CDS must exist!");
assert(CDSConfig::current_thread_is_dumper(), "not supposed to be called from other threads");
{
// Stop other threads from recording into _lambdaform_lines.
MutexLocker ml(Thread::current(), LambdaFormInvokers_lock);
_stop_appending = true;
}
PrintLambdaFormMessage plm;
if (_lambdaform_lines == nullptr || _lambdaform_lines->length() == 0) {
log_info(aot)("Nothing to regenerate for lambda form holder classes");
return;
}
HandleMark hm(THREAD);
int len = _lambdaform_lines->length();
objArrayHandle list_lines;
{
MutexLocker ml(Thread::current(), LambdaFormInvokers_lock);
list_lines = oopFactory::new_objArray_handle(vmClasses::String_klass(), len, CHECK);
for (int i = 0; i < len; i++) {
Handle h_line = java_lang_String::create_from_str(_lambdaform_lines->at(i), CHECK);
list_lines->obj_at_put(i, h_line());
}
} // Before calling into java, release vm lock.
//
objArrayHandle list_lines = oopFactory::new_objArray_handle(vmClasses::String_klass(), len, CHECK);
for (int i = 0; i < len; i++) {
Handle h_line = java_lang_String::create_from_str(_lambdaform_lines->at(i), CHECK);
list_lines->obj_at_put(i, h_line());
}
// Object[] CDS.generateLambdaFormHolderClasses(String[] lines)
// the returned Object[] layout:
// name, byte[], name, byte[] ....
@ -232,6 +241,7 @@ void LambdaFormInvokers::regenerate_class(char* class_name, ClassFileStream& st,
}
void LambdaFormInvokers::dump_static_archive_invokers() {
assert(SafepointSynchronize::is_at_safepoint(), "no concurrent update to _lambdaform_lines");
if (_lambdaform_lines != nullptr && _lambdaform_lines->length() > 0) {
int count = 0;
int len = _lambdaform_lines->length();