8353597: Refactor handling VM options for AOT cache input and output

Reviewed-by: kvn, asmehra
This commit is contained in:
Ioi Lam 2025-04-09 15:03:38 +00:00
parent 4dc9e58906
commit 567c6885a3
15 changed files with 254 additions and 148 deletions

View File

@ -51,9 +51,10 @@ bool CDSConfig::_old_cds_flags_used = false;
bool CDSConfig::_new_aot_flags_used = false;
bool CDSConfig::_disable_heap_dumping = false;
char* CDSConfig::_default_archive_path = nullptr;
char* CDSConfig::_static_archive_path = nullptr;
char* CDSConfig::_dynamic_archive_path = nullptr;
const char* CDSConfig::_default_archive_path = nullptr;
const char* CDSConfig::_input_static_archive_path = nullptr;
const char* CDSConfig::_input_dynamic_archive_path = nullptr;
const char* CDSConfig::_output_archive_path = nullptr;
JavaThread* CDSConfig::_dumper_thread = nullptr;
@ -66,7 +67,11 @@ int CDSConfig::get_status() {
(is_using_archive() ? IS_USING_ARCHIVE : 0);
}
void CDSConfig::initialize() {
DEBUG_ONLY(static bool _cds_ergo_initialize_started = false);
void CDSConfig::ergo_initialize() {
DEBUG_ONLY(_cds_ergo_initialize_started = true);
if (is_dumping_static_archive() && !is_dumping_final_static_archive()) {
// Note: -Xshare and -XX:AOTMode flags are mutually exclusive.
// - Classic workflow: -Xshare:on and -Xshare:dump cannot take effect at the same time.
@ -83,10 +88,12 @@ void CDSConfig::initialize() {
// Initialize shared archive paths which could include both base and dynamic archive paths
// This must be after set_ergonomics_flags() called so flag UseCompressedOops is set properly.
//
// UseSharedSpaces may be disabled if -XX:SharedArchiveFile is invalid.
if (is_dumping_static_archive() || is_using_archive()) {
init_shared_archive_paths();
if (new_aot_flags_used()) {
ergo_init_aot_paths();
} else {
ergo_init_classic_archive_paths();
}
}
if (!is_dumping_heap()) {
@ -94,7 +101,10 @@ void CDSConfig::initialize() {
}
}
char* CDSConfig::default_archive_path() {
const char* CDSConfig::default_archive_path() {
// The path depends on UseCompressedOops, etc, which are set by GC ergonomics just
// before CDSConfig::ergo_initialize() is called.
assert(_cds_ergo_initialize_started, "sanity");
if (_default_archive_path == nullptr) {
stringStream tmp;
const char* subdir = WINDOWS_ONLY("bin") NOT_WINDOWS("lib");
@ -116,12 +126,12 @@ char* CDSConfig::default_archive_path() {
return _default_archive_path;
}
int CDSConfig::num_archives(const char* archive_path) {
if (archive_path == nullptr) {
int CDSConfig::num_archive_paths(const char* path_spec) {
if (path_spec == nullptr) {
return 0;
}
int npaths = 1;
char* p = (char*)archive_path;
char* p = (char*)path_spec;
while (*p != '\0') {
if (*p == os::path_separator()[0]) {
npaths++;
@ -131,9 +141,9 @@ int CDSConfig::num_archives(const char* archive_path) {
return npaths;
}
void CDSConfig::extract_shared_archive_paths(const char* archive_path,
char** base_archive_path,
char** top_archive_path) {
void CDSConfig::extract_archive_paths(const char* archive_path,
const char** base_archive_path,
const char** top_archive_path) {
char* begin_ptr = (char*)archive_path;
char* end_ptr = strchr((char*)archive_path, os::path_separator()[0]);
if (end_ptr == nullptr || end_ptr == begin_ptr) {
@ -157,7 +167,8 @@ void CDSConfig::extract_shared_archive_paths(const char* archive_path,
*top_archive_path = cur_path;
}
void CDSConfig::init_shared_archive_paths() {
void CDSConfig::ergo_init_classic_archive_paths() {
assert(_cds_ergo_initialize_started, "sanity");
if (ArchiveClassesAtExit != nullptr) {
assert(!RecordDynamicDumpInfo, "already checked");
if (is_dumping_static_archive()) {
@ -172,21 +183,24 @@ void CDSConfig::init_shared_archive_paths() {
}
if (SharedArchiveFile == nullptr) {
_static_archive_path = default_archive_path();
_input_static_archive_path = default_archive_path();
if (is_dumping_static_archive()) {
_output_archive_path = _input_static_archive_path;
}
} else {
int archives = num_archives(SharedArchiveFile);
assert(archives > 0, "must be");
int num_archives = num_archive_paths(SharedArchiveFile);
assert(num_archives > 0, "must be");
if (is_dumping_archive() && archives > 1) {
if (is_dumping_archive() && num_archives > 1) {
vm_exit_during_initialization(
"Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping");
}
if (is_dumping_static_archive()) {
assert(archives == 1, "must be");
assert(num_archives == 1, "just checked above");
// Static dump is simple: only one archive is allowed in SharedArchiveFile. This file
// will be overwritten no matter regardless of its contents
_static_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments);
// will be overwritten regardless of its contents
_output_archive_path = SharedArchiveFile;
} else {
// SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa
// is read from top.jsa
@ -197,48 +211,49 @@ void CDSConfig::init_shared_archive_paths() {
// However, if either RecordDynamicDumpInfo or ArchiveClassesAtExit is used, we do not
// allow cases (b) and (c). Case (b) is already checked above.
if (archives > 2) {
if (num_archives > 2) {
vm_exit_during_initialization(
"Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option");
}
if (archives == 1) {
char* base_archive_path = nullptr;
if (num_archives == 1) {
const char* base_archive_path = nullptr;
bool success =
FileMapInfo::get_base_archive_name_from_header(SharedArchiveFile, &base_archive_path);
if (!success) {
// If +AutoCreateSharedArchive and the specified shared archive does not exist,
// regenerate the dynamic archive base on default archive.
if (AutoCreateSharedArchive && !os::file_exists(SharedArchiveFile)) {
enable_dumping_dynamic_archive();
ArchiveClassesAtExit = const_cast<char *>(SharedArchiveFile);
_static_archive_path = default_archive_path();
SharedArchiveFile = nullptr;
} else {
enable_dumping_dynamic_archive(SharedArchiveFile);
FLAG_SET_ERGO(ArchiveClassesAtExit, SharedArchiveFile);
_input_static_archive_path = default_archive_path();
FLAG_SET_ERGO(SharedArchiveFile, nullptr);
} else {
if (AutoCreateSharedArchive) {
warning("-XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info.");
AutoCreateSharedArchive = false;
}
log_error(cds)("Not a valid %s (%s)", new_aot_flags_used() ? "AOT cache" : "archive", SharedArchiveFile);
log_error(cds)("Not a valid archive (%s)", SharedArchiveFile);
Arguments::no_shared_spaces("invalid archive");
}
} else if (base_archive_path == nullptr) {
// User has specified a single archive, which is a static archive.
_static_archive_path = const_cast<char *>(SharedArchiveFile);
_input_static_archive_path = SharedArchiveFile;
} else {
// User has specified a single archive, which is a dynamic archive.
_dynamic_archive_path = const_cast<char *>(SharedArchiveFile);
_static_archive_path = base_archive_path; // has been c-heap allocated.
_input_dynamic_archive_path = SharedArchiveFile;
_input_static_archive_path = base_archive_path; // has been c-heap allocated.
}
} else {
extract_shared_archive_paths((const char*)SharedArchiveFile,
&_static_archive_path, &_dynamic_archive_path);
if (_static_archive_path == nullptr) {
assert(_dynamic_archive_path == nullptr, "must be");
extract_archive_paths(SharedArchiveFile,
&_input_static_archive_path, &_input_dynamic_archive_path);
if (_input_static_archive_path == nullptr) {
assert(_input_dynamic_archive_path == nullptr, "must be");
Arguments::no_shared_spaces("invalid archive");
}
}
if (_dynamic_archive_path != nullptr) {
if (_input_dynamic_archive_path != nullptr) {
// Check for case (c)
if (RecordDynamicDumpInfo) {
vm_exit_during_initialization("-XX:+RecordDynamicDumpInfo is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile",
@ -353,14 +368,22 @@ bool CDSConfig::has_unsupported_runtime_module_options() {
return false;
}
#define CHECK_ALIAS(f) check_flag_alias(FLAG_IS_DEFAULT(f), #f)
#define CHECK_NEW_FLAG(f) check_new_flag(FLAG_IS_DEFAULT(f), #f)
void CDSConfig::check_flag_alias(bool alias_is_default, const char* alias_name) {
if (old_cds_flags_used() && !alias_is_default) {
void CDSConfig::check_new_flag(bool new_flag_is_default, const char* new_flag_name) {
if (old_cds_flags_used() && !new_flag_is_default) {
vm_exit_during_initialization(err_msg("Option %s cannot be used at the same time with "
"-Xshare:on, -Xshare:auto, -Xshare:off, -Xshare:dump, "
"DumpLoadedClassList, SharedClassListFile, or SharedArchiveFile",
alias_name));
new_flag_name));
}
}
#define CHECK_SINGLE_PATH(f) check_flag_single_path(#f, f)
void CDSConfig::check_flag_single_path(const char* flag_name, const char* value) {
if (value != nullptr && num_archive_paths(value) != 1) {
vm_exit_during_initialization(err_msg("Option %s must specify a single file name", flag_name));
}
}
@ -371,9 +394,13 @@ void CDSConfig::check_aot_flags() {
_old_cds_flags_used = true;
}
CHECK_ALIAS(AOTCache);
CHECK_ALIAS(AOTConfiguration);
CHECK_ALIAS(AOTMode);
// "New" AOT flags must not be mixed with "classic" flags such as -Xshare:dump
CHECK_NEW_FLAG(AOTCache);
CHECK_NEW_FLAG(AOTConfiguration);
CHECK_NEW_FLAG(AOTMode);
CHECK_SINGLE_PATH(AOTCache);
CHECK_SINGLE_PATH(AOTConfiguration);
if (FLAG_IS_DEFAULT(AOTCache) && FLAG_IS_DEFAULT(AOTConfiguration) && FLAG_IS_DEFAULT(AOTMode)) {
// AOTCache/AOTConfiguration/AOTMode not used.
@ -411,11 +438,6 @@ void CDSConfig::check_aotmode_auto_or_on() {
vm_exit_during_initialization("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create");
}
if (!FLAG_IS_DEFAULT(AOTCache)) {
assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked");
FLAG_SET_ERGO(SharedArchiveFile, AOTCache);
}
UseSharedSpaces = true;
if (FLAG_IS_DEFAULT(AOTMode) || (strcmp(AOTMode, "auto") == 0)) {
RequireSharedSpaces = false;
@ -430,10 +452,6 @@ void CDSConfig::check_aotmode_record() {
vm_exit_during_initialization("AOTCache must not be specified when using -XX:AOTMode=record");
}
assert(FLAG_IS_DEFAULT(DumpLoadedClassList), "already checked");
assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked");
FLAG_SET_ERGO(SharedArchiveFile, AOTConfiguration);
FLAG_SET_ERGO(DumpLoadedClassList, nullptr);
UseSharedSpaces = false;
RequireSharedSpaces = false;
_is_dumping_static_archive = true;
@ -449,10 +467,7 @@ void CDSConfig::check_aotmode_create() {
vm_exit_during_initialization("AOTCache must be specified when using -XX:AOTMode=create");
}
assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked");
_is_dumping_final_static_archive = true;
FLAG_SET_ERGO(SharedArchiveFile, AOTConfiguration);
UseSharedSpaces = true;
RequireSharedSpaces = true;
@ -463,7 +478,29 @@ void CDSConfig::check_aotmode_create() {
CDSConfig::enable_dumping_static_archive();
}
void CDSConfig::ergo_init_aot_paths() {
assert(_cds_ergo_initialize_started, "sanity");
if (is_dumping_static_archive()) {
if (is_dumping_preimage_static_archive()) {
_output_archive_path = AOTConfiguration;
} else {
assert(is_dumping_final_static_archive(), "must be");
_input_static_archive_path = AOTConfiguration;
_output_archive_path = AOTCache;
}
} else if (is_using_archive()) {
if (FLAG_IS_DEFAULT(AOTCache)) {
// Only -XX:AOTMode={auto,on} is specified
_input_static_archive_path = default_archive_path();
} else {
_input_static_archive_path = AOTCache;
}
}
}
bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) {
assert(!_cds_ergo_initialize_started, "This is called earlier than CDSConfig::ergo_initialize()");
check_aot_flags();
if (!FLAG_IS_DEFAULT(AOTMode)) {
@ -514,7 +551,7 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) {
disable_dumping_dynamic_archive();
} else {
enable_dumping_dynamic_archive();
enable_dumping_dynamic_archive(ArchiveClassesAtExit);
}
if (AutoCreateSharedArchive) {
@ -546,6 +583,34 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
return true;
}
void CDSConfig::prepare_for_dumping() {
assert(CDSConfig::is_dumping_archive(), "sanity");
if (is_dumping_dynamic_archive() && !is_using_archive()) {
assert(!is_dumping_static_archive(), "cannot be dumping both static and dynamic archives");
// This could happen if SharedArchiveFile has failed to load:
// - -Xshare:off was specified
// - SharedArchiveFile points to an non-existent file.
// - SharedArchiveFile points to an archive that has failed CRC check
// - SharedArchiveFile is not specified and the VM doesn't have a compatible default archive
#define __THEMSG " is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."
if (RecordDynamicDumpInfo) {
log_error(cds)("-XX:+RecordDynamicDumpInfo%s", __THEMSG);
MetaspaceShared::unrecoverable_loading_error();
} else {
assert(ArchiveClassesAtExit != nullptr, "sanity");
log_warning(cds)("-XX:ArchiveClassesAtExit" __THEMSG);
}
#undef __THEMSG
disable_dumping_dynamic_archive();
return;
}
check_unsupported_dumping_module_options();
}
bool CDSConfig::is_dumping_classic_static_archive() {
return _is_dumping_static_archive &&
!is_dumping_preimage_static_archive() &&
@ -560,6 +625,18 @@ bool CDSConfig::is_dumping_final_static_archive() {
return _is_dumping_final_static_archive;
}
void CDSConfig::enable_dumping_dynamic_archive(const char* output_path) {
_is_dumping_dynamic_archive = true;
if (output_path == nullptr) {
// output_path can be null when the VM is started with -XX:+RecordDynamicDumpInfo
// in anticipation of "jcmd VM.cds dynamic_dump", which will provide the actual
// output path.
_output_archive_path = nullptr;
} else {
_output_archive_path = os::strdup_check_oom(output_path, mtArguments);
}
}
bool CDSConfig::allow_only_single_java_thread() {
// See comments in JVM_StartThread()
return is_dumping_classic_static_archive() || is_dumping_final_static_archive();

View File

@ -42,9 +42,10 @@ class CDSConfig : public AllStatic {
static bool _is_using_full_module_graph;
static bool _has_aot_linked_classes;
static char* _default_archive_path;
static char* _static_archive_path;
static char* _dynamic_archive_path;
const static char* _default_archive_path;
const static char* _input_static_archive_path;
const static char* _input_dynamic_archive_path;
const static char* _output_archive_path;
static bool _old_cds_flags_used;
static bool _new_aot_flags_used;
@ -53,17 +54,24 @@ class CDSConfig : public AllStatic {
static JavaThread* _dumper_thread;
#endif
static void extract_shared_archive_paths(const char* archive_path,
char** base_archive_path,
char** top_archive_path);
static void init_shared_archive_paths();
static void extract_archive_paths(const char* archive_path,
const char** base_archive_path,
const char** top_archive_path);
static int num_archive_paths(const char* path_spec);
static void check_flag_single_path(const char* flag_name, const char* value);
static void check_flag_alias(bool alias_is_default, const char* alias_name);
// Checks before Arguments::apply_ergo()
static void check_new_flag(bool new_flag_is_default, const char* new_flag_name);
static void check_aot_flags();
static void check_aotmode_off();
static void check_aotmode_auto_or_on();
static void check_aotmode_record();
static void check_aotmode_create();
static void check_unsupported_dumping_module_options();
// Called after Arguments::apply_ergo() has started
static void ergo_init_classic_archive_paths();
static void ergo_init_aot_paths();
public:
// Used by jdk.internal.misc.CDS.getCDSConfigStatus();
@ -76,24 +84,25 @@ public:
static int get_status() NOT_CDS_RETURN_(0);
// Initialization and command-line checking
static void initialize() NOT_CDS_RETURN;
static void ergo_initialize() NOT_CDS_RETURN;
static void set_old_cds_flags_used() { CDS_ONLY(_old_cds_flags_used = true); }
static bool old_cds_flags_used() { return CDS_ONLY(_old_cds_flags_used) NOT_CDS(false); }
static bool new_aot_flags_used() { return CDS_ONLY(_new_aot_flags_used) NOT_CDS(false); }
static void check_internal_module_property(const char* key, const char* value) NOT_CDS_RETURN;
static void check_incompatible_property(const char* key, const char* value) NOT_CDS_RETURN;
static void check_unsupported_dumping_module_options() NOT_CDS_RETURN;
static bool has_unsupported_runtime_module_options() NOT_CDS_RETURN_(false);
static bool check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) NOT_CDS_RETURN_(true);
static const char* type_of_archive_being_loaded();
static const char* type_of_archive_being_written();
static void prepare_for_dumping();
// --- Basic CDS features
// archive(s) in general
static bool is_dumping_archive() { return is_dumping_static_archive() || is_dumping_dynamic_archive(); }
// input archive(s)
static bool is_using_archive() NOT_CDS_RETURN_(false);
static int num_archives(const char* archive_path) NOT_CDS_RETURN_(0);
// static_archive
static bool is_dumping_static_archive() { return CDS_ONLY(_is_dumping_static_archive) NOT_CDS(false); }
@ -125,7 +134,7 @@ public:
// dynamic_archive
static bool is_dumping_dynamic_archive() { return CDS_ONLY(_is_dumping_dynamic_archive) NOT_CDS(false); }
static void enable_dumping_dynamic_archive() { CDS_ONLY(_is_dumping_dynamic_archive = true); }
static void enable_dumping_dynamic_archive(const char* output_path) NOT_CDS_RETURN;
static void disable_dumping_dynamic_archive() { CDS_ONLY(_is_dumping_dynamic_archive = false); }
// Misc CDS features
@ -147,12 +156,11 @@ public:
// archive_path
// Points to the classes.jsa in $JAVA_HOME
static char* default_archive_path() NOT_CDS_RETURN_(nullptr);
// The actual static archive (if any) selected at runtime
static const char* static_archive_path() { return CDS_ONLY(_static_archive_path) NOT_CDS(nullptr); }
// The actual dynamic archive (if any) selected at runtime
static const char* dynamic_archive_path() { return CDS_ONLY(_dynamic_archive_path) NOT_CDS(nullptr); }
// Points to the classes.jsa in $JAVA_HOME (could be input or output)
static const char* default_archive_path() NOT_CDS_RETURN_(nullptr);
static const char* input_static_archive_path() { return CDS_ONLY(_input_static_archive_path) NOT_CDS(nullptr); }
static const char* input_dynamic_archive_path() { return CDS_ONLY(_input_dynamic_archive_path) NOT_CDS(nullptr); }
static const char* output_archive_path() { return CDS_ONLY(_output_archive_path) NOT_CDS(nullptr); }
// --- Archived java objects

View File

@ -97,8 +97,6 @@ public:
void gather_array_klasses();
public:
DynamicArchiveBuilder() : ArchiveBuilder() { }
// Do this before and after the archive dump to see if any corruption
// is caused by dynamic dumping.
void verify_universe(const char* info) {
@ -348,7 +346,7 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data, AOTClassLocatio
FileMapInfo* dynamic_info = FileMapInfo::dynamic_info();
assert(dynamic_info != nullptr, "Sanity");
dynamic_info->open_for_write();
dynamic_info->open_as_output();
ArchiveHeapInfo no_heap_for_dynamic_dump;
ArchiveBuilder::write_archive(dynamic_info, &no_heap_for_dynamic_dump);
@ -476,27 +474,6 @@ int DynamicArchive::num_array_klasses() {
return _array_klasses != nullptr ? _array_klasses->length() : 0;
}
void DynamicArchive::check_for_dynamic_dump() {
if (CDSConfig::is_dumping_dynamic_archive() && !CDSConfig::is_using_archive()) {
// This could happen if SharedArchiveFile has failed to load:
// - -Xshare:off was specified
// - SharedArchiveFile points to an non-existent file.
// - SharedArchiveFile points to an archive that has failed CRC check
// - SharedArchiveFile is not specified and the VM doesn't have a compatible default archive
#define __THEMSG " is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."
if (RecordDynamicDumpInfo) {
log_error(cds)("-XX:+RecordDynamicDumpInfo%s", __THEMSG);
MetaspaceShared::unrecoverable_loading_error();
} else {
assert(ArchiveClassesAtExit != nullptr, "sanity");
log_warning(cds)("-XX:ArchiveClassesAtExit" __THEMSG);
}
#undef __THEMSG
CDSConfig::disable_dumping_dynamic_archive();
}
}
void DynamicArchive::dump_impl(bool jcmd_request, const char* archive_name, TRAPS) {
MetaspaceShared::link_shared_classes(CHECK);
if (!jcmd_request && CDSConfig::is_dumping_regenerated_lambdaform_invokers()) {
@ -507,11 +484,12 @@ void DynamicArchive::dump_impl(bool jcmd_request, const char* archive_name, TRAP
VMThread::execute(&op);
}
void DynamicArchive::dump_at_exit(JavaThread* current, const char* archive_name) {
void DynamicArchive::dump_at_exit(JavaThread* current) {
ExceptionMark em(current);
ResourceMark rm(current);
CDSConfig::DumperThreadMark dumper_thread_mark(current);
const char* archive_name = CDSConfig::output_archive_path();
if (!CDSConfig::is_dumping_dynamic_archive() || archive_name == nullptr) {
return;
}

View File

@ -63,9 +63,8 @@ private:
static GrowableArray<ObjArrayKlass*>* _array_klasses;
static Array<ObjArrayKlass*>* _dynamic_archive_array_klasses;
public:
static void check_for_dynamic_dump();
static void dump_for_jcmd(const char* archive_name, TRAPS);
static void dump_at_exit(JavaThread* current, const char* archive_name);
static void dump_at_exit(JavaThread* current);
static void dump_impl(bool jcmd_request, const char* archive_name, TRAPS);
static bool is_mapped() { return FileMapInfo::dynamic_info() != nullptr; }
static bool validate(FileMapInfo* dynamic_info);

View File

@ -173,7 +173,7 @@ void FileMapInfo::populate_header(size_t core_region_alignment) {
header_size = c_header_size;
const char* default_base_archive_name = CDSConfig::default_archive_path();
const char* current_base_archive_name = CDSConfig::static_archive_path();
const char* current_base_archive_name = CDSConfig::input_static_archive_path();
if (!os::same_files(current_base_archive_name, default_base_archive_name)) {
base_archive_name_size = strlen(current_base_archive_name) + 1;
header_size += base_archive_name_size;
@ -209,7 +209,7 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment,
if (!info->is_static() && base_archive_name_size != 0) {
// copy base archive name
copy_base_archive_name(CDSConfig::static_archive_path());
copy_base_archive_name(CDSConfig::input_static_archive_path());
}
_core_region_alignment = core_region_alignment;
_obj_alignment = ObjectAlignmentInBytes;
@ -563,7 +563,7 @@ public:
// true && (*base_archive_name) != nullptr:
// <archive_name> is a valid dynamic archive.
bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name,
char** base_archive_name) {
const char** base_archive_name) {
FileHeaderHelper file_helper(archive_name, false);
*base_archive_name = nullptr;
@ -619,7 +619,7 @@ bool FileMapInfo::init_from_file(int fd) {
// Good
} else {
if (CDSConfig::new_aot_flags_used()) {
log_warning(cds)("Not a valid %s %s", file_type, _full_path);
log_warning(cds)("Not a valid %s (%s)", file_type, _full_path);
} else {
log_warning(cds)("Not a base shared archive: %s", _full_path);
}
@ -729,7 +729,7 @@ bool FileMapInfo::open_for_read() {
// Write the FileMapInfo information to the file.
void FileMapInfo::open_for_write() {
void FileMapInfo::open_as_output() {
LogMessage(cds) msg;
if (msg.is_info()) {
if (CDSConfig::is_dumping_preimage_static_archive()) {
@ -1759,7 +1759,7 @@ bool FileMapInfo::_memory_mapping_failed = false;
// [1] validate_header() - done here.
// [2] validate_shared_path_table - this is done later, because the table is in the RO
// region of the archive, which is not mapped yet.
bool FileMapInfo::initialize() {
bool FileMapInfo::open_as_input() {
assert(CDSConfig::is_using_archive(), "UseSharedSpaces expected.");
assert(Arguments::has_jimage(), "The shared archive file cannot be used with an exploded module build.");
@ -1774,13 +1774,12 @@ bool FileMapInfo::initialize() {
if (!open_for_read() || !init_from_file(_fd) || !validate_header()) {
if (_is_static) {
log_info(cds)("Initialize static archive failed.");
log_info(cds)("Loading static archive failed.");
return false;
} else {
log_info(cds)("Initialize dynamic archive failed.");
log_info(cds)("Loading dynamic archive failed.");
if (AutoCreateSharedArchive) {
CDSConfig::enable_dumping_dynamic_archive();
ArchiveClassesAtExit = CDSConfig::dynamic_archive_path();
CDSConfig::enable_dumping_dynamic_archive(_full_path);
}
return false;
}

View File

@ -268,7 +268,7 @@ private:
public:
FileMapHeader *header() const { return _header; }
static bool get_base_archive_name_from_header(const char* archive_name,
char** base_archive_name);
const char** base_archive_name);
static bool is_preimage_static_archive(const char* file);
bool init_from_file(int fd);
@ -346,9 +346,8 @@ public:
static void assert_mark(bool check);
// File manipulation.
bool initialize() NOT_CDS_RETURN_(false);
bool open_for_read();
void open_for_write();
bool open_as_input() NOT_CDS_RETURN_(false);
void open_as_output();
void write_header();
void write_region(int region, char* base, size_t size,
bool read_only, bool allow_exec);
@ -425,6 +424,7 @@ public:
}
private:
bool open_for_read();
void seek_to_position(size_t pos);
bool map_heap_region_impl() NOT_CDS_JAVA_HEAP_RETURN_(false);
void dealloc_heap_region() NOT_CDS_JAVA_HEAP_RETURN;

View File

@ -678,14 +678,11 @@ void VM_PopulateDumpSharedSpace::doit() {
CppVtables::zero_archived_vtables();
// Write the archive file
const char* static_archive;
if (CDSConfig::is_dumping_final_static_archive()) {
static_archive = AOTCache;
FileMapInfo::free_current_info();
} else {
static_archive = CDSConfig::static_archive_path();
FileMapInfo::free_current_info(); // FIXME: should not free current info
}
assert(static_archive != nullptr, "SharedArchiveFile not set?");
const char* static_archive = CDSConfig::output_archive_path();
assert(static_archive != nullptr, "sanity");
_map_info = new FileMapInfo(static_archive, true);
_map_info->populate_header(MetaspaceShared::core_region_alignment());
_map_info->set_early_serialized_data(early_serialized_data);
@ -789,11 +786,6 @@ void MetaspaceShared::link_shared_classes(TRAPS) {
}
}
void MetaspaceShared::prepare_for_dumping() {
assert(CDSConfig::is_dumping_archive(), "sanity");
CDSConfig::check_unsupported_dumping_module_options();
}
// Preload classes from a list, populate the shared spaces and dump to a
// file.
void MetaspaceShared::preload_and_dump(TRAPS) {
@ -1023,7 +1015,7 @@ bool MetaspaceShared::write_static_archive(ArchiveBuilder* builder, FileMapInfo*
// without runtime relocation.
builder->relocate_to_requested();
map_info->open_for_write();
map_info->open_as_output();
if (!map_info->is_open()) {
return false;
}
@ -1214,10 +1206,10 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
}
FileMapInfo* MetaspaceShared::open_static_archive() {
const char* static_archive = CDSConfig::static_archive_path();
const char* static_archive = CDSConfig::input_static_archive_path();
assert(static_archive != nullptr, "sanity");
FileMapInfo* mapinfo = new FileMapInfo(static_archive, true);
if (!mapinfo->initialize()) {
if (!mapinfo->open_as_input()) {
delete(mapinfo);
return nullptr;
}
@ -1228,13 +1220,13 @@ FileMapInfo* MetaspaceShared::open_dynamic_archive() {
if (CDSConfig::is_dumping_dynamic_archive()) {
return nullptr;
}
const char* dynamic_archive = CDSConfig::dynamic_archive_path();
const char* dynamic_archive = CDSConfig::input_dynamic_archive_path();
if (dynamic_archive == nullptr) {
return nullptr;
}
FileMapInfo* mapinfo = new FileMapInfo(dynamic_archive, false);
if (!mapinfo->initialize()) {
if (!mapinfo->open_as_input()) {
delete(mapinfo);
if (RequireSharedSpaces) {
MetaspaceShared::unrecoverable_loading_error("Failed to initialize dynamic archive");
@ -1817,7 +1809,7 @@ void MetaspaceShared::initialize_shared_spaces() {
if (PrintSharedArchiveAndExit) {
// Print archive names
if (dynamic_mapinfo != nullptr) {
tty->print_cr("\n\nBase archive name: %s", CDSConfig::static_archive_path());
tty->print_cr("\n\nBase archive name: %s", CDSConfig::input_static_archive_path());
tty->print_cr("Base archive version %d", static_mapinfo->version());
} else {
tty->print_cr("Static archive name: %s", static_mapinfo->full_path());

View File

@ -71,7 +71,6 @@ class MetaspaceShared : AllStatic {
n_regions = 4 // total number of regions
};
static void prepare_for_dumping() NOT_CDS_RETURN;
static void preload_and_dump(TRAPS) NOT_CDS_RETURN;
#ifdef _LP64
static void adjust_heap_sizes_for_dumping() NOT_CDS_JAVA_HEAP_RETURN;

View File

@ -897,14 +897,13 @@ jint universe_init() {
ClassLoaderData::init_null_class_loader_data();
#if INCLUDE_CDS
DynamicArchive::check_for_dynamic_dump();
if (CDSConfig::is_using_archive()) {
// Read the data structures supporting the shared spaces (shared
// system dictionary, symbol table, etc.)
MetaspaceShared::initialize_shared_spaces();
}
if (CDSConfig::is_dumping_archive()) {
MetaspaceShared::prepare_for_dumping();
CDSConfig::prepare_for_dumping();
}
#endif

View File

@ -3708,7 +3708,7 @@ jint Arguments::apply_ergo() {
CompressedKlassPointers::pre_initialize();
}
CDSConfig::initialize();
CDSConfig::ergo_initialize();
// Initialize Metaspace flags and alignments
Metaspace::ergo_initialize();

View File

@ -426,11 +426,10 @@ void before_exit(JavaThread* thread, bool halt) {
#if INCLUDE_CDS
// Dynamic CDS dumping must happen whilst we can still reliably
// run Java code.
DynamicArchive::dump_at_exit(thread, ArchiveClassesAtExit);
DynamicArchive::dump_at_exit(thread);
assert(!thread->has_pending_exception(), "must be");
#endif
// Actual shutdown logic begins here.
#if INCLUDE_JVMCI

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2025, 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
@ -265,7 +265,7 @@ bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t siz
#ifdef LINUX
// mangled name of CDSConfig::_static_archive_path
#define SHARED_ARCHIVE_PATH_SYM "_ZN9CDSConfig20_static_archive_pathE"
#define SHARED_ARCHIVE_PATH_SYM "_ZN9CDSConfig26_input_static_archive_pathE"
#define USE_SHARED_SPACES_SYM "UseSharedSpaces"
#define SHARED_BASE_ADDRESS_SYM "SharedBaseAddress"
#define LIBJVM_NAME "/libjvm.so"
@ -273,7 +273,7 @@ bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t siz
#ifdef __APPLE__
// mangled name of CDSConfig::_static_archive_path
#define SHARED_ARCHIVE_PATH_SYM "__ZN9CDSConfig20_static_archive_pathE"
#define SHARED_ARCHIVE_PATH_SYM "__ZN9CDSConfig26_input_static_archive_pathE"
#define USE_SHARED_SPACES_SYM "_UseSharedSpaces"
#define SHARED_BASE_ADDRESS_SYM "_SharedBaseAddress"
#define LIBJVM_NAME "/libjvm.dylib"

View File

@ -26,12 +26,14 @@
* @test
* @summary "AOT" aliases for traditional CDS command-line options
* @requires vm.cds
* @requires vm.flagless
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
* @build Hello
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar Hello
* @run driver AOTFlags
*/
import java.io.File;
import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.helpers.ClassFileInstaller;
import jdk.test.lib.process.OutputAnalyzer;
@ -298,6 +300,60 @@ public class AOTFlags {
"specified when the AOTConfiguration file was recorded");
out.shouldContain("Unable to use create AOT cache");
out.shouldHaveExitValue(1);
//----------------------------------------------------------------------
printTestCase("Cannot use multiple paths in AOTConfiguration");
pb = ProcessTools.createLimitedTestJavaProcessBuilder(
"-XX:AOTMode=record",
"-XX:AOTConfiguration=" + aotConfigFile + File.pathSeparator + "dummy",
"-cp", "noSuchJar.jar");
out = CDSTestUtils.executeAndLog(pb, "neg");
out.shouldContain("Option AOTConfiguration must specify a single file name");
out.shouldHaveExitValue(1);
//----------------------------------------------------------------------
printTestCase("Cannot use multiple paths in AOTCache");
pb = ProcessTools.createLimitedTestJavaProcessBuilder(
"-XX:AOTMode=create",
"-XX:AOTConfiguration=" + aotConfigFile,
"-XX:AOTCache=" + aotCacheFile + File.pathSeparator + "dummy",
"-cp", "noSuchJar.jar");
out = CDSTestUtils.executeAndLog(pb, "neg");
out.shouldContain("Option AOTCache must specify a single file name");
out.shouldHaveExitValue(1);
//----------------------------------------------------------------------
printTestCase("Cannot use a dynamic CDS archive for -XX:AOTCache");
String staticArchive = "static.jsa";
String dynamicArchive = "dynamic.jsa";
pb = ProcessTools.createLimitedTestJavaProcessBuilder(
"-Xshare:dump",
"-XX:SharedArchiveFile=" + staticArchive);
out = CDSTestUtils.executeAndLog(pb, "static");
out.shouldHaveExitValue(0);
pb = ProcessTools.createLimitedTestJavaProcessBuilder(
"-XX:SharedArchiveFile=" + staticArchive,
"-XX:ArchiveClassesAtExit=" + dynamicArchive,
"--version");
out = CDSTestUtils.executeAndLog(pb, "dynamic");
out.shouldHaveExitValue(0);
pb = ProcessTools.createLimitedTestJavaProcessBuilder(
"-Xlog:cds",
"-XX:AOTMode=on",
"-XX:AOTCache=" + dynamicArchive,
"--version");
out = CDSTestUtils.executeAndLog(pb, "neg");
out.shouldContain("Unable to use AOT cache.");
out.shouldContain("Not a valid AOT cache (dynamic.jsa)");
out.shouldHaveExitValue(1);
}
static int testNum = 0;

View File

@ -337,7 +337,7 @@ public class TestAutoCreateSharedArchive extends DynamicArchiveTestBase {
.shouldContain(HELLO_WORLD)
.shouldContain("The shared archive file version " + hex(version2) + " does not match the required version " + hex(currentCDSVersion))
.shouldContain("The shared archive file has the wrong version")
.shouldContain("Initialize dynamic archive failed")
.shouldContain("Loading dynamic archive failed")
.shouldContain("Dumping shared data to file");
});
ft2 = Files.getLastModifiedTime(Paths.get(modVersion));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, 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
@ -112,7 +112,7 @@ public class TestAutoCreateSharedArchiveNoDefaultArchive {
"-version");
TestCommon.executeAndLog(pb, "show-version")
.shouldHaveExitValue(0)
.shouldContain("Initialize static archive failed")
.shouldContain("Loading static archive failed")
.shouldContain("Unable to map shared spaces")
.shouldNotContain("sharing");
}
@ -132,7 +132,7 @@ public class TestAutoCreateSharedArchiveNoDefaultArchive {
mainClass);
TestCommon.executeAndLog(pb, "no-default-archive")
.shouldHaveExitValue(0)
.shouldContain("Initialize static archive failed")
.shouldContain("Loading static archive failed")
.shouldContain("Unable to map shared spaces")
.shouldNotContain("Dumping shared data to file");
if (jsaFile.exists()) {