diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index 6261321fc1fe0..818b92efe70d9 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -27,7 +27,12 @@ #include "cds/cdsConfig.hpp" #include "cds/heapShared.hpp" #include "classfile/classLoaderDataShared.hpp" +#include "classfile/moduleEntry.hpp" +#include "include/jvm_io.h" #include "logging/log.hpp" +#include "runtime/arguments.hpp" +#include "runtime/java.hpp" +#include "utilities/defaultStream.hpp" bool CDSConfig::_is_dumping_static_archive = false; bool CDSConfig::_is_dumping_dynamic_archive = false; @@ -38,6 +43,318 @@ bool CDSConfig::_is_dumping_dynamic_archive = false; bool CDSConfig::_dumping_full_module_graph_disabled = false; bool CDSConfig::_loading_full_module_graph_disabled = false; +char* CDSConfig::_default_archive_path = nullptr; +char* CDSConfig::_static_archive_path = nullptr; +char* CDSConfig::_dynamic_archive_path = nullptr; + +void CDSConfig::initialize() { + if (is_dumping_static_archive()) { + if (RequireSharedSpaces) { + warning("Cannot dump shared archive while using shared archive"); + } + UseSharedSpaces = false; + } + + // 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() || UseSharedSpaces) { + init_shared_archive_paths(); + } +} + +char* CDSConfig::default_archive_path() { + if (_default_archive_path == nullptr) { + char jvm_path[JVM_MAXPATHLEN]; + os::jvm_path(jvm_path, sizeof(jvm_path)); + char *end = strrchr(jvm_path, *os::file_separator()); + if (end != nullptr) *end = '\0'; + size_t jvm_path_len = strlen(jvm_path); + size_t file_sep_len = strlen(os::file_separator()); + const size_t len = jvm_path_len + file_sep_len + 20; + _default_archive_path = NEW_C_HEAP_ARRAY(char, len, mtArguments); + jio_snprintf(_default_archive_path, len, + LP64_ONLY(!UseCompressedOops ? "%s%sclasses_nocoops.jsa":) "%s%sclasses.jsa", + jvm_path, os::file_separator()); + } + return _default_archive_path; +} + +int CDSConfig::num_archives(const char* archive_path) { + if (archive_path == nullptr) { + return 0; + } + int npaths = 1; + char* p = (char*)archive_path; + while (*p != '\0') { + if (*p == os::path_separator()[0]) { + npaths++; + } + p++; + } + return npaths; +} + +void CDSConfig::extract_shared_archive_paths(const char* archive_path, + char** base_archive_path, + 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) { + vm_exit_during_initialization("Base archive was not specified", archive_path); + } + size_t len = end_ptr - begin_ptr; + char* cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); + strncpy(cur_path, begin_ptr, len); + cur_path[len] = '\0'; + *base_archive_path = cur_path; + + begin_ptr = ++end_ptr; + if (*begin_ptr == '\0') { + vm_exit_during_initialization("Top archive was not specified", archive_path); + } + end_ptr = strchr(begin_ptr, '\0'); + assert(end_ptr != nullptr, "sanity"); + len = end_ptr - begin_ptr; + cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); + strncpy(cur_path, begin_ptr, len + 1); + *top_archive_path = cur_path; +} + +void CDSConfig::init_shared_archive_paths() { + if (ArchiveClassesAtExit != nullptr) { + assert(!RecordDynamicDumpInfo, "already checked"); + if (is_dumping_static_archive()) { + vm_exit_during_initialization("-XX:ArchiveClassesAtExit cannot be used with -Xshare:dump"); + } + check_unsupported_dumping_properties(); + + if (os::same_files(default_archive_path(), ArchiveClassesAtExit)) { + vm_exit_during_initialization( + "Cannot specify the default CDS archive for -XX:ArchiveClassesAtExit", default_archive_path()); + } + } + + if (SharedArchiveFile == nullptr) { + _static_archive_path = default_archive_path(); + } else { + int archives = num_archives(SharedArchiveFile); + assert(archives > 0, "must be"); + + if (is_dumping_archive() && 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"); + // 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); + } else { + // SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa + // is read from top.jsa + // (a) 1 file: -XX:SharedArchiveFile=base.jsa + // (b) 2 files: -XX:SharedArchiveFile=base.jsa:top.jsa + // (c) 2 files: -XX:SharedArchiveFile=top.jsa + // + // 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) { + 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; + 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 { + if (AutoCreateSharedArchive) { + warning("-XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."); + AutoCreateSharedArchive = false; + } + 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); + } 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. + } + } 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"); + Arguments::no_shared_spaces("invalid archive"); + } + } + + if (_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", + SharedArchiveFile); + } + if (ArchiveClassesAtExit != nullptr) { + vm_exit_during_initialization("-XX:ArchiveClassesAtExit is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile", + SharedArchiveFile); + } + } + + if (ArchiveClassesAtExit != nullptr && os::same_files(SharedArchiveFile, ArchiveClassesAtExit)) { + vm_exit_during_initialization( + "Cannot have the same archive file specified for -XX:SharedArchiveFile and -XX:ArchiveClassesAtExit", + SharedArchiveFile); + } + } + } +} + +void CDSConfig::check_system_property(const char* key, const char* value) { + if (Arguments::is_internal_module_property(key)) { + MetaspaceShared::disable_optimized_module_handling(); + log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value); + } + if (strcmp(key, "jdk.module.showModuleResolution") == 0 || + strcmp(key, "jdk.module.validation") == 0 || + strcmp(key, "java.system.class.loader") == 0) { + disable_loading_full_module_graph(); + disable_dumping_full_module_graph(); + log_info(cds)("full module graph: disabled due to incompatible property: %s=%s", key, value); + } +} + +static const char* unsupported_properties[] = { + "jdk.module.limitmods", + "jdk.module.upgrade.path", + "jdk.module.patch.0" +}; +static const char* unsupported_options[] = { + "--limit-modules", + "--upgrade-module-path", + "--patch-module" +}; + +void CDSConfig::check_unsupported_dumping_properties() { + assert(is_dumping_archive(), "this function is only used with CDS dump time"); + assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be"); + // If a vm option is found in the unsupported_options array, vm will exit with an error message. + SystemProperty* sp = Arguments::system_properties(); + while (sp != nullptr) { + for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) { + if (strcmp(sp->key(), unsupported_properties[i]) == 0) { + vm_exit_during_initialization( + "Cannot use the following option when dumping the shared archive", unsupported_options[i]); + } + } + sp = sp->next(); + } + + // Check for an exploded module build in use with -Xshare:dump. + if (!Arguments::has_jimage()) { + vm_exit_during_initialization("Dumping the shared archive is not supported with an exploded module build"); + } +} + +bool CDSConfig::check_unsupported_cds_runtime_properties() { + assert(UseSharedSpaces, "this function is only used with -Xshare:{on,auto}"); + assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be"); + if (ArchiveClassesAtExit != nullptr) { + // dynamic dumping, just return false for now. + // check_unsupported_dumping_properties() will be called later to check the same set of + // properties, and will exit the VM with the correct error message if the unsupported properties + // are used. + return false; + } + for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) { + if (Arguments::get_property(unsupported_properties[i]) != nullptr) { + if (RequireSharedSpaces) { + warning("CDS is disabled when the %s option is specified.", unsupported_options[i]); + } else { + log_info(cds)("CDS is disabled when the %s option is specified.", unsupported_options[i]); + } + return true; + } + } + return false; +} + +bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) { + if (is_dumping_static_archive()) { + if (!mode_flag_cmd_line) { + // By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive. + // + // If your classlist is large and you don't care about deterministic dumping, you can use + // -Xshare:dump -Xmixed to improve dumping speed. + Arguments::set_mode_flags(Arguments::_int); + } else if (Arguments::mode() == Arguments::_comp) { + // -Xcomp may use excessive CPU for the test tiers. Also, -Xshare:dump runs a small and fixed set of + // Java code, so there's not much benefit in running -Xcomp. + log_info(cds)("reduced -Xcomp to -Xmixed for static dumping"); + Arguments::set_mode_flags(Arguments::_mixed); + } + + // String deduplication may cause CDS to iterate the strings in different order from one + // run to another which resulting in non-determinstic CDS archives. + // Disable UseStringDeduplication while dumping CDS archive. + UseStringDeduplication = false; + } + + // RecordDynamicDumpInfo is not compatible with ArchiveClassesAtExit + if (ArchiveClassesAtExit != nullptr && RecordDynamicDumpInfo) { + jio_fprintf(defaultStream::output_stream(), + "-XX:+RecordDynamicDumpInfo cannot be used with -XX:ArchiveClassesAtExit.\n"); + return false; + } + + if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) { + disable_dumping_dynamic_archive(); + } else { + enable_dumping_dynamic_archive(); + } + + if (AutoCreateSharedArchive) { + if (SharedArchiveFile == nullptr) { + log_warning(cds)("-XX:+AutoCreateSharedArchive requires -XX:SharedArchiveFile"); + return false; + } + if (ArchiveClassesAtExit != nullptr) { + log_warning(cds)("-XX:+AutoCreateSharedArchive does not work with ArchiveClassesAtExit"); + return false; + } + } + + if (UseSharedSpaces && patch_mod_javabase) { + Arguments::no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched."); + } + if (UseSharedSpaces && check_unsupported_cds_runtime_properties()) { + UseSharedSpaces = false; + } + + if (is_dumping_archive()) { + // Always verify non-system classes during CDS dump + if (!BytecodeVerificationRemote) { + BytecodeVerificationRemote = true; + log_info(cds)("All non-system classes will be verified (-Xverify:remote) during CDS dump time."); + } + } + + return true; +} + #if INCLUDE_CDS_JAVA_HEAP bool CDSConfig::is_dumping_heap() { // heap dump is not supported in dynamic dump diff --git a/src/hotspot/share/cds/cdsConfig.hpp b/src/hotspot/share/cds/cdsConfig.hpp index cc3c5556d0abe..d7de147d20cf5 100644 --- a/src/hotspot/share/cds/cdsConfig.hpp +++ b/src/hotspot/share/cds/cdsConfig.hpp @@ -26,6 +26,7 @@ #define SHARE_CDS_CDSCONFIG_HPP #include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" class CDSConfig : public AllStatic { @@ -34,9 +35,25 @@ class CDSConfig : public AllStatic { static bool _is_dumping_dynamic_archive; static bool _dumping_full_module_graph_disabled; static bool _loading_full_module_graph_disabled; + + static char* _default_archive_path; + static char* _static_archive_path; + static char* _dynamic_archive_path; #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 bool check_unsupported_cds_runtime_properties(); + public: + // Initialization and command-line checking + static void initialize() NOT_CDS_RETURN; + static void check_system_property(const char* key, const char* value) NOT_CDS_RETURN; + static void check_unsupported_dumping_properties() NOT_CDS_RETURN; + static bool check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) NOT_CDS_RETURN_(false); + // Basic CDS features static bool is_dumping_archive() { return is_dumping_static_archive() || is_dumping_dynamic_archive(); } static bool is_dumping_static_archive() { return CDS_ONLY(_is_dumping_static_archive) NOT_CDS(false); } @@ -45,6 +62,17 @@ class CDSConfig : public AllStatic { static void enable_dumping_dynamic_archive() { CDS_ONLY(_is_dumping_dynamic_archive = true); } static void disable_dumping_dynamic_archive() { CDS_ONLY(_is_dumping_dynamic_archive = false); } + // Archive paths + // 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); } + + static int num_archives(const char* archive_path) NOT_CDS_RETURN_(0); + + // CDS archived heap static bool is_dumping_heap() NOT_CDS_JAVA_HEAP_RETURN_(false); static void disable_dumping_full_module_graph(const char* reason = nullptr) NOT_CDS_JAVA_HEAP_RETURN; diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 0810c17c00a75..99acbb4ace8f2 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -162,8 +162,8 @@ void FileMapInfo::populate_header(size_t core_region_alignment) { c_header_size = sizeof(DynamicArchiveHeader); header_size = c_header_size; - const char* default_base_archive_name = Arguments::get_default_shared_archive_path(); - const char* current_base_archive_name = Arguments::GetSharedArchivePath(); + const char* default_base_archive_name = CDSConfig::default_archive_path(); + const char* current_base_archive_name = CDSConfig::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; @@ -199,7 +199,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(Arguments::GetSharedArchivePath()); + copy_base_archive_name(CDSConfig::static_archive_path()); } _core_region_alignment = core_region_alignment; _obj_alignment = ObjectAlignmentInBytes; @@ -918,7 +918,7 @@ void FileMapInfo::log_paths(const char* msg, int start_idx, int end_idx) { bool FileMapInfo::check_module_paths() { const char* rp = Arguments::get_property("jdk.module.path"); - int num_paths = Arguments::num_archives(rp); + int num_paths = CDSConfig::num_archives(rp); if (num_paths != header()->num_module_paths()) { return false; } @@ -1250,7 +1250,7 @@ bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name, const char* base = file_helper.base_archive_name(); if (base == nullptr) { - *base_archive_name = Arguments::get_default_shared_archive_path(); + *base_archive_name = CDSConfig::default_archive_path(); } else { *base_archive_name = os::strdup_check_oom(base); } @@ -2275,7 +2275,7 @@ bool FileMapInfo::initialize() { log_info(cds)("Initialize dynamic archive failed."); if (AutoCreateSharedArchive) { CDSConfig::enable_dumping_dynamic_archive(); - ArchiveClassesAtExit = Arguments::GetSharedDynamicArchivePath(); + ArchiveClassesAtExit = CDSConfig::dynamic_archive_path(); } return false; } diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index dedd7cb85ee5d..fedbc5841b682 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -539,7 +539,7 @@ void VM_PopulateDumpSharedSpace::doit() { builder.relocate_to_requested(); // Write the archive file - const char* static_archive = Arguments::GetSharedArchivePath(); + const char* static_archive = CDSConfig::static_archive_path(); assert(static_archive != nullptr, "SharedArchiveFile not set?"); FileMapInfo* mapinfo = new FileMapInfo(static_archive, true); mapinfo->populate_header(MetaspaceShared::core_region_alignment()); @@ -651,8 +651,7 @@ void MetaspaceShared::link_shared_classes(bool jcmd_request, TRAPS) { void MetaspaceShared::prepare_for_dumping() { assert(CDSConfig::is_dumping_archive(), "sanity"); - Arguments::check_unsupported_dumping_properties(); - + CDSConfig::check_unsupported_dumping_properties(); ClassLoader::initialize_shared_path(JavaThread::current()); } @@ -987,8 +986,8 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() { } FileMapInfo* MetaspaceShared::open_static_archive() { - const char* static_archive = Arguments::GetSharedArchivePath(); - assert(static_archive != nullptr, "SharedArchivePath is nullptr"); + const char* static_archive = CDSConfig::static_archive_path(); + assert(static_archive != nullptr, "sanity"); FileMapInfo* mapinfo = new FileMapInfo(static_archive, true); if (!mapinfo->initialize()) { delete(mapinfo); @@ -1001,7 +1000,7 @@ FileMapInfo* MetaspaceShared::open_dynamic_archive() { if (CDSConfig::is_dumping_dynamic_archive()) { return nullptr; } - const char* dynamic_archive = Arguments::GetSharedDynamicArchivePath(); + const char* dynamic_archive = CDSConfig::dynamic_archive_path(); if (dynamic_archive == nullptr) { return nullptr; } @@ -1494,7 +1493,7 @@ void MetaspaceShared::initialize_shared_spaces() { if (PrintSharedArchiveAndExit) { // Print archive names if (dynamic_mapinfo != nullptr) { - tty->print_cr("\n\nBase archive name: %s", Arguments::GetSharedArchivePath()); + tty->print_cr("\n\nBase archive name: %s", CDSConfig::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()); diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 230129ea2df31..d70c775937fd0 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -2043,7 +2043,7 @@ WB_ENTRY(jobject, WB_GetMethodStringOption(JNIEnv* env, jobject wb, jobject meth WB_END WB_ENTRY(jobject, WB_GetDefaultArchivePath(JNIEnv* env, jobject wb)) - const char* p = Arguments::get_default_shared_archive_path(); + const char* p = CDSConfig::default_archive_path(); ThreadToNativeFromVM ttn(thread); jstring path_string = env->NewStringUTF(p); diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 477a1ebe8d110..fd8f155af420e 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -101,10 +101,6 @@ size_t Arguments::_default_SharedBaseAddress = SharedBaseAddress; bool Arguments::_enable_preview = false; -char* Arguments::_default_shared_archive_path = nullptr; -char* Arguments::SharedArchivePath = nullptr; -char* Arguments::SharedDynamicArchivePath = nullptr; - LegacyGCLogging Arguments::_legacyGCLogging = { 0, 0 }; // These are not set by the JDK's built-in launchers, but they can be set by @@ -1263,19 +1259,7 @@ bool Arguments::add_property(const char* prop, PropertyWriteable writeable, Prop value = &prop[key_len + 1]; } -#if INCLUDE_CDS - if (is_internal_module_property(key)) { - MetaspaceShared::disable_optimized_module_handling(); - log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value); - } - if (strcmp(key, "jdk.module.showModuleResolution") == 0 || - strcmp(key, "jdk.module.validation") == 0 || - strcmp(key, "java.system.class.loader") == 0) { - CDSConfig::disable_loading_full_module_graph(); - CDSConfig::disable_dumping_full_module_graph(); - log_info(cds)("full module graph: disabled due to incompatible property: %s=%s", key, value); - } -#endif + CDSConfig::check_system_property(key, value); if (strcmp(key, "java.compiler") == 0) { // we no longer support java.compiler system property, log a warning and let it get @@ -1329,60 +1313,6 @@ bool Arguments::add_property(const char* prop, PropertyWriteable writeable, Prop return true; } -#if INCLUDE_CDS -const char* unsupported_properties[] = { "jdk.module.limitmods", - "jdk.module.upgrade.path", - "jdk.module.patch.0" }; -const char* unsupported_options[] = { "--limit-modules", - "--upgrade-module-path", - "--patch-module" - }; -void Arguments::check_unsupported_dumping_properties() { - assert(CDSConfig::is_dumping_archive(), - "this function is only used with CDS dump time"); - assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be"); - // If a vm option is found in the unsupported_options array, vm will exit with an error message. - SystemProperty* sp = system_properties(); - while (sp != nullptr) { - for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) { - if (strcmp(sp->key(), unsupported_properties[i]) == 0) { - vm_exit_during_initialization( - "Cannot use the following option when dumping the shared archive", unsupported_options[i]); - } - } - sp = sp->next(); - } - - // Check for an exploded module build in use with -Xshare:dump. - if (!has_jimage()) { - vm_exit_during_initialization("Dumping the shared archive is not supported with an exploded module build"); - } -} - -bool Arguments::check_unsupported_cds_runtime_properties() { - assert(UseSharedSpaces, "this function is only used with -Xshare:{on,auto}"); - assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be"); - if (ArchiveClassesAtExit != nullptr) { - // dynamic dumping, just return false for now. - // check_unsupported_dumping_properties() will be called later to check the same set of - // properties, and will exit the VM with the correct error message if the unsupported properties - // are used. - return false; - } - for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) { - if (get_property(unsupported_properties[i]) != nullptr) { - if (RequireSharedSpaces) { - warning("CDS is disabled when the %s option is specified.", unsupported_options[i]); - } else { - log_info(cds)("CDS is disabled when the %s option is specified.", unsupported_options[i]); - } - return true; - } - } - return false; -} -#endif - //=========================================================================================================== // Setting int/mixed/comp mode flags @@ -1432,7 +1362,7 @@ void Arguments::set_mode_flags(Mode mode) { // Conflict: required to use shared spaces (-Xshare:on), but // incompatible command line options were chosen. -static void no_shared_spaces(const char* message) { +void Arguments::no_shared_spaces(const char* message) { if (RequireSharedSpaces) { jio_fprintf(defaultStream::error_stream(), "Class data sharing is inconsistent with other specified options.\n"); @@ -3037,67 +2967,10 @@ jint Arguments::finalize_vm_init_args(bool patch_mod_javabase) { return JNI_ERR; } -#if INCLUDE_CDS - if (CDSConfig::is_dumping_static_archive()) { - if (!mode_flag_cmd_line) { - // By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive. - // - // If your classlist is large and you don't care about deterministic dumping, you can use - // -Xshare:dump -Xmixed to improve dumping speed. - set_mode_flags(_int); - } else if (_mode == _comp) { - // -Xcomp may use excessive CPU for the test tiers. Also, -Xshare:dump runs a small and fixed set of - // Java code, so there's not much benefit in running -Xcomp. - log_info(cds)("reduced -Xcomp to -Xmixed for static dumping"); - set_mode_flags(_mixed); - } - - // String deduplication may cause CDS to iterate the strings in different order from one - // run to another which resulting in non-determinstic CDS archives. - // Disable UseStringDeduplication while dumping CDS archive. - UseStringDeduplication = false; - } - - // RecordDynamicDumpInfo is not compatible with ArchiveClassesAtExit - if (ArchiveClassesAtExit != nullptr && RecordDynamicDumpInfo) { - jio_fprintf(defaultStream::output_stream(), - "-XX:+RecordDynamicDumpInfo cannot be used with -XX:ArchiveClassesAtExit.\n"); + if (!CDSConfig::check_vm_args_consistency(patch_mod_javabase, mode_flag_cmd_line)) { return JNI_ERR; } - if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) { - CDSConfig::disable_dumping_dynamic_archive(); - } else { - CDSConfig::enable_dumping_dynamic_archive(); - } - - if (AutoCreateSharedArchive) { - if (SharedArchiveFile == nullptr) { - log_warning(cds)("-XX:+AutoCreateSharedArchive requires -XX:SharedArchiveFile"); - return JNI_ERR; - } - if (ArchiveClassesAtExit != nullptr) { - log_warning(cds)("-XX:+AutoCreateSharedArchive does not work with ArchiveClassesAtExit"); - return JNI_ERR; - } - } - - if (UseSharedSpaces && patch_mod_javabase) { - no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched."); - } - if (UseSharedSpaces && check_unsupported_cds_runtime_properties()) { - UseSharedSpaces = false; - } - - if (CDSConfig::is_dumping_archive()) { - // Always verify non-system classes during CDS dump - if (!BytecodeVerificationRemote) { - BytecodeVerificationRemote = true; - log_info(cds)("All non-system classes will be verified (-Xverify:remote) during CDS dump time."); - } - } -#endif - #ifndef CAN_SHOW_REGISTERS_ON_ASSERT UNSUPPORTED_OPTION(ShowRegistersOnAssert); #endif // CAN_SHOW_REGISTERS_ON_ASSERT @@ -3365,187 +3238,6 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_ return vm_args->set_args(&options); } -void Arguments::set_shared_spaces_flags_and_archive_paths() { - if (CDSConfig::is_dumping_static_archive()) { - if (RequireSharedSpaces) { - warning("Cannot dump shared archive while using shared archive"); - } - UseSharedSpaces = false; - } -#if INCLUDE_CDS - // 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 (CDSConfig::is_dumping_static_archive() || UseSharedSpaces) { - init_shared_archive_paths(); - } -#endif // INCLUDE_CDS -} - -#if INCLUDE_CDS -// Sharing support -// Construct the path to the archive -char* Arguments::get_default_shared_archive_path() { - if (_default_shared_archive_path == nullptr) { - char jvm_path[JVM_MAXPATHLEN]; - os::jvm_path(jvm_path, sizeof(jvm_path)); - char *end = strrchr(jvm_path, *os::file_separator()); - if (end != nullptr) *end = '\0'; - size_t jvm_path_len = strlen(jvm_path); - size_t file_sep_len = strlen(os::file_separator()); - const size_t len = jvm_path_len + file_sep_len + 20; - _default_shared_archive_path = NEW_C_HEAP_ARRAY(char, len, mtArguments); - jio_snprintf(_default_shared_archive_path, len, - LP64_ONLY(!UseCompressedOops ? "%s%sclasses_nocoops.jsa":) "%s%sclasses.jsa", - jvm_path, os::file_separator()); - } - return _default_shared_archive_path; -} - -int Arguments::num_archives(const char* archive_path) { - if (archive_path == nullptr) { - return 0; - } - int npaths = 1; - char* p = (char*)archive_path; - while (*p != '\0') { - if (*p == os::path_separator()[0]) { - npaths++; - } - p++; - } - return npaths; -} - -void Arguments::extract_shared_archive_paths(const char* archive_path, - char** base_archive_path, - 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) { - vm_exit_during_initialization("Base archive was not specified", archive_path); - } - size_t len = end_ptr - begin_ptr; - char* cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); - strncpy(cur_path, begin_ptr, len); - cur_path[len] = '\0'; - *base_archive_path = cur_path; - - begin_ptr = ++end_ptr; - if (*begin_ptr == '\0') { - vm_exit_during_initialization("Top archive was not specified", archive_path); - } - end_ptr = strchr(begin_ptr, '\0'); - assert(end_ptr != nullptr, "sanity"); - len = end_ptr - begin_ptr; - cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); - strncpy(cur_path, begin_ptr, len + 1); - *top_archive_path = cur_path; -} - -void Arguments::init_shared_archive_paths() { - if (ArchiveClassesAtExit != nullptr) { - assert(!RecordDynamicDumpInfo, "already checked"); - if (CDSConfig::is_dumping_static_archive()) { - vm_exit_during_initialization("-XX:ArchiveClassesAtExit cannot be used with -Xshare:dump"); - } - check_unsupported_dumping_properties(); - - if (os::same_files(get_default_shared_archive_path(), ArchiveClassesAtExit)) { - vm_exit_during_initialization( - "Cannot specify the default CDS archive for -XX:ArchiveClassesAtExit", get_default_shared_archive_path()); - } - } - - if (SharedArchiveFile == nullptr) { - SharedArchivePath = get_default_shared_archive_path(); - } else { - int archives = num_archives(SharedArchiveFile); - assert(archives > 0, "must be"); - - if (CDSConfig::is_dumping_archive() && archives > 1) { - vm_exit_during_initialization( - "Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping"); - } - - if (CDSConfig::is_dumping_static_archive()) { - assert(archives == 1, "must be"); - // Static dump is simple: only one archive is allowed in SharedArchiveFile. This file - // will be overwritten no matter regardless of its contents - SharedArchivePath = os::strdup_check_oom(SharedArchiveFile, mtArguments); - } else { - // SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa - // is read from top.jsa - // (a) 1 file: -XX:SharedArchiveFile=base.jsa - // (b) 2 files: -XX:SharedArchiveFile=base.jsa:top.jsa - // (c) 2 files: -XX:SharedArchiveFile=top.jsa - // - // 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) { - 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; - 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)) { - CDSConfig::enable_dumping_dynamic_archive(); - ArchiveClassesAtExit = const_cast<char *>(SharedArchiveFile); - SharedArchivePath = get_default_shared_archive_path(); - 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; - } - no_shared_spaces("invalid archive"); - } - } else if (base_archive_path == nullptr) { - // User has specified a single archive, which is a static archive. - SharedArchivePath = const_cast<char *>(SharedArchiveFile); - } else { - // User has specified a single archive, which is a dynamic archive. - SharedDynamicArchivePath = const_cast<char *>(SharedArchiveFile); - SharedArchivePath = base_archive_path; // has been c-heap allocated. - } - } else { - extract_shared_archive_paths((const char*)SharedArchiveFile, - &SharedArchivePath, &SharedDynamicArchivePath); - if (SharedArchivePath == nullptr) { - assert(SharedDynamicArchivePath == nullptr, "must be"); - no_shared_spaces("invalid archive"); - } - } - - if (SharedDynamicArchivePath != 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", - SharedArchiveFile); - } - if (ArchiveClassesAtExit != nullptr) { - vm_exit_during_initialization("-XX:ArchiveClassesAtExit is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile", - SharedArchiveFile); - } - } - - if (ArchiveClassesAtExit != nullptr && os::same_files(SharedArchiveFile, ArchiveClassesAtExit)) { - vm_exit_during_initialization( - "Cannot have the same archive file specified for -XX:SharedArchiveFile and -XX:ArchiveClassesAtExit", - SharedArchiveFile); - } - } - } -} -#endif // INCLUDE_CDS - #ifndef PRODUCT // Determine whether LogVMOutput should be implicitly turned on. static bool use_vm_log() { @@ -3990,7 +3682,7 @@ jint Arguments::apply_ergo() { GCConfig::arguments()->initialize(); - set_shared_spaces_flags_and_archive_paths(); + CDSConfig::initialize(); // Initialize Metaspace flags and alignments Metaspace::ergo_initialize(); diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index 2b871fdc0c96c..8251db3d0d59a 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -248,7 +248,6 @@ class Arguments : AllStatic { // Operation modi static Mode _mode; - static void set_mode_flags(Mode mode); // preview features static bool _enable_preview; @@ -264,7 +263,6 @@ class Arguments : AllStatic { static void set_use_compressed_oops(); static void set_use_compressed_klass_ptrs(); static jint set_ergonomics_flags(); - static void set_shared_spaces_flags_and_archive_paths(); // Limits the given heap size by the maximum amount of virtual // memory this process is currently allowed to use. It also takes // the virtual-to-physical ratio of the current GC into account. @@ -363,17 +361,9 @@ class Arguments : AllStatic { // Return the "real" name for option arg if arg is an alias, and print a warning if arg is deprecated. // Return nullptr if the arg has expired. static const char* handle_aliases_and_deprecation(const char* arg); - - static char* _default_shared_archive_path; - static char* SharedArchivePath; - static char* SharedDynamicArchivePath; static size_t _default_SharedBaseAddress; // The default value specified in globals.hpp - static void extract_shared_archive_paths(const char* archive_path, - char** base_archive_path, - char** top_archive_path) NOT_CDS_RETURN; public: - static int num_archives(const char* archive_path) NOT_CDS_RETURN_(0); // Parses the arguments, first phase static jint parse(const JavaVMInitArgs* args); // Parse a string for a unsigned integer. Returns true if value @@ -441,8 +431,7 @@ class Arguments : AllStatic { static exit_hook_t exit_hook() { return _exit_hook; } static vfprintf_hook_t vfprintf_hook() { return _vfprintf_hook; } - static const char* GetSharedArchivePath() { return SharedArchivePath; } - static const char* GetSharedDynamicArchivePath() { return SharedDynamicArchivePath; } + static void no_shared_spaces(const char* message); static size_t default_SharedBaseAddress() { return _default_SharedBaseAddress; } // Java launcher properties static void process_sun_java_launcher_properties(JavaVMInitArgs* args); @@ -501,11 +490,9 @@ class Arguments : AllStatic { static char* get_appclasspath() { return _java_class_path->value(); } static void fix_appclasspath(); - static char* get_default_shared_archive_path() NOT_CDS_RETURN_(nullptr); - static void init_shared_archive_paths() NOT_CDS_RETURN; - // Operation modi static Mode mode() { return _mode; } + static void set_mode_flags(Mode mode); static bool is_interpreter_only() { return mode() == _int; } static bool is_compiler_only() { return mode() == _comp; } @@ -517,10 +504,6 @@ class Arguments : AllStatic { // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid. static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen); - static void check_unsupported_dumping_properties() NOT_CDS_RETURN; - - static bool check_unsupported_cds_runtime_properties() NOT_CDS_RETURN0; - static bool atojulong(const char *s, julong* result); static bool has_jfr_option() NOT_JFR_RETURN_(false); diff --git a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c index 3912332662ae1..bcce23f12216a 100644 --- a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c +++ b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2023, 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 @@ -264,16 +264,16 @@ bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t siz } #ifdef LINUX -// mangled name of Arguments::SharedArchivePath -#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE" +// mangled name of CDSConfig::_static_archive_path +#define SHARED_ARCHIVE_PATH_SYM "_ZN9CDSConfig20_static_archive_pathE" #define USE_SHARED_SPACES_SYM "UseSharedSpaces" #define SHARED_BASE_ADDRESS_SYM "SharedBaseAddress" #define LIBJVM_NAME "/libjvm.so" #endif #ifdef __APPLE__ -// mangled name of Arguments::SharedArchivePath -#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE" +// mangled name of CDSConfig::_static_archive_path +#define SHARED_ARCHIVE_PATH_SYM "__ZN9CDSConfig20_static_archive_pathE" #define USE_SHARED_SPACES_SYM "_UseSharedSpaces" #define SHARED_BASE_ADDRESS_SYM "_SharedBaseAddress" #define LIBJVM_NAME "/libjvm.dylib"