diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index d3048b9ee7a..0505ae20a78 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -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() { diff --git a/src/hotspot/share/cds/cdsConfig.hpp b/src/hotspot/share/cds/cdsConfig.hpp index 8361cf052db..cfa846f2b41 100644 --- a/src/hotspot/share/cds/cdsConfig.hpp +++ b/src/hotspot/share/cds/cdsConfig.hpp @@ -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); }; diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index e8900f43d43..946599dddbf 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -53,6 +53,7 @@ GrowableArrayCHeap* LambdaFormInvokers::_lambdaform_lines = nullptr; Array* 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(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();