1 /* 2 * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "cds/archiveHeapLoader.hpp" 27 #include "cds/cdsConfig.hpp" 28 #include "cds/heapShared.hpp" 29 #include "classfile/classLoaderDataShared.hpp" 30 #include "classfile/moduleEntry.hpp" 31 #include "include/jvm_io.h" 32 #include "logging/log.hpp" 33 #include "runtime/arguments.hpp" 34 #include "runtime/java.hpp" 35 #include "utilities/defaultStream.hpp" 36 37 bool CDSConfig::_is_dumping_static_archive = false; 38 bool CDSConfig::_is_dumping_dynamic_archive = false; 39 40 // The ability to dump the FMG depends on many factors checked by 41 // is_dumping_full_module_graph(), but can be unconditionally disabled by 42 // _dumping_full_module_graph_disabled. (Ditto for loading the FMG). 43 bool CDSConfig::_dumping_full_module_graph_disabled = false; 44 bool CDSConfig::_loading_full_module_graph_disabled = false; 45 46 char* CDSConfig::_default_archive_path = nullptr; 47 char* CDSConfig::_static_archive_path = nullptr; 48 char* CDSConfig::_dynamic_archive_path = nullptr; 49 50 void CDSConfig::initialize() { 51 if (is_dumping_static_archive()) { 52 if (RequireSharedSpaces) { 53 warning("Cannot dump shared archive while using shared archive"); 54 } 55 UseSharedSpaces = false; 56 } 57 58 // Initialize shared archive paths which could include both base and dynamic archive paths 59 // This must be after set_ergonomics_flags() called so flag UseCompressedOops is set properly. 60 // 61 // UseSharedSpaces may be disabled if -XX:SharedArchiveFile is invalid. 62 if (is_dumping_static_archive() || UseSharedSpaces) { 63 init_shared_archive_paths(); 64 } 65 } 66 67 char* CDSConfig::default_archive_path() { 68 if (_default_archive_path == nullptr) { 69 char jvm_path[JVM_MAXPATHLEN]; 70 os::jvm_path(jvm_path, sizeof(jvm_path)); 71 char *end = strrchr(jvm_path, *os::file_separator()); 72 if (end != nullptr) *end = '\0'; 73 size_t jvm_path_len = strlen(jvm_path); 74 size_t file_sep_len = strlen(os::file_separator()); 75 const size_t len = jvm_path_len + file_sep_len + 20; 76 _default_archive_path = NEW_C_HEAP_ARRAY(char, len, mtArguments); 77 jio_snprintf(_default_archive_path, len, 78 LP64_ONLY(!UseCompressedOops ? "%s%sclasses_nocoops.jsa":) "%s%sclasses.jsa", 79 jvm_path, os::file_separator()); 80 } 81 return _default_archive_path; 82 } 83 84 int CDSConfig::num_archives(const char* archive_path) { 85 if (archive_path == nullptr) { 86 return 0; 87 } 88 int npaths = 1; 89 char* p = (char*)archive_path; 90 while (*p != '\0') { 91 if (*p == os::path_separator()[0]) { 92 npaths++; 93 } 94 p++; 95 } 96 return npaths; 97 } 98 99 void CDSConfig::extract_shared_archive_paths(const char* archive_path, 100 char** base_archive_path, 101 char** top_archive_path) { 102 char* begin_ptr = (char*)archive_path; 103 char* end_ptr = strchr((char*)archive_path, os::path_separator()[0]); 104 if (end_ptr == nullptr || end_ptr == begin_ptr) { 105 vm_exit_during_initialization("Base archive was not specified", archive_path); 106 } 107 size_t len = end_ptr - begin_ptr; 108 char* cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); 109 strncpy(cur_path, begin_ptr, len); 110 cur_path[len] = '\0'; 111 *base_archive_path = cur_path; 112 113 begin_ptr = ++end_ptr; 114 if (*begin_ptr == '\0') { 115 vm_exit_during_initialization("Top archive was not specified", archive_path); 116 } 117 end_ptr = strchr(begin_ptr, '\0'); 118 assert(end_ptr != nullptr, "sanity"); 119 len = end_ptr - begin_ptr; 120 cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); 121 strncpy(cur_path, begin_ptr, len + 1); 122 *top_archive_path = cur_path; 123 } 124 125 void CDSConfig::init_shared_archive_paths() { 126 if (ArchiveClassesAtExit != nullptr) { 127 assert(!RecordDynamicDumpInfo, "already checked"); 128 if (is_dumping_static_archive()) { 129 vm_exit_during_initialization("-XX:ArchiveClassesAtExit cannot be used with -Xshare:dump"); 130 } 131 check_unsupported_dumping_properties(); 132 133 if (os::same_files(default_archive_path(), ArchiveClassesAtExit)) { 134 vm_exit_during_initialization( 135 "Cannot specify the default CDS archive for -XX:ArchiveClassesAtExit", default_archive_path()); 136 } 137 } 138 139 if (SharedArchiveFile == nullptr) { 140 _static_archive_path = default_archive_path(); 141 } else { 142 int archives = num_archives(SharedArchiveFile); 143 assert(archives > 0, "must be"); 144 145 if (is_dumping_archive() && archives > 1) { 146 vm_exit_during_initialization( 147 "Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping"); 148 } 149 150 if (is_dumping_static_archive()) { 151 assert(archives == 1, "must be"); 152 // Static dump is simple: only one archive is allowed in SharedArchiveFile. This file 153 // will be overwritten no matter regardless of its contents 154 _static_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments); 155 } else { 156 // SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa 157 // is read from top.jsa 158 // (a) 1 file: -XX:SharedArchiveFile=base.jsa 159 // (b) 2 files: -XX:SharedArchiveFile=base.jsa:top.jsa 160 // (c) 2 files: -XX:SharedArchiveFile=top.jsa 161 // 162 // However, if either RecordDynamicDumpInfo or ArchiveClassesAtExit is used, we do not 163 // allow cases (b) and (c). Case (b) is already checked above. 164 165 if (archives > 2) { 166 vm_exit_during_initialization( 167 "Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option"); 168 } 169 if (archives == 1) { 170 char* base_archive_path = nullptr; 171 bool success = 172 FileMapInfo::get_base_archive_name_from_header(SharedArchiveFile, &base_archive_path); 173 if (!success) { 174 // If +AutoCreateSharedArchive and the specified shared archive does not exist, 175 // regenerate the dynamic archive base on default archive. 176 if (AutoCreateSharedArchive && !os::file_exists(SharedArchiveFile)) { 177 enable_dumping_dynamic_archive(); 178 ArchiveClassesAtExit = const_cast<char *>(SharedArchiveFile); 179 _static_archive_path = default_archive_path(); 180 SharedArchiveFile = nullptr; 181 } else { 182 if (AutoCreateSharedArchive) { 183 warning("-XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."); 184 AutoCreateSharedArchive = false; 185 } 186 Arguments::no_shared_spaces("invalid archive"); 187 } 188 } else if (base_archive_path == nullptr) { 189 // User has specified a single archive, which is a static archive. 190 _static_archive_path = const_cast<char *>(SharedArchiveFile); 191 } else { 192 // User has specified a single archive, which is a dynamic archive. 193 _dynamic_archive_path = const_cast<char *>(SharedArchiveFile); 194 _static_archive_path = base_archive_path; // has been c-heap allocated. 195 } 196 } else { 197 extract_shared_archive_paths((const char*)SharedArchiveFile, 198 &_static_archive_path, &_dynamic_archive_path); 199 if (_static_archive_path == nullptr) { 200 assert(_dynamic_archive_path == nullptr, "must be"); 201 Arguments::no_shared_spaces("invalid archive"); 202 } 203 } 204 205 if (_dynamic_archive_path != nullptr) { 206 // Check for case (c) 207 if (RecordDynamicDumpInfo) { 208 vm_exit_during_initialization("-XX:+RecordDynamicDumpInfo is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile", 209 SharedArchiveFile); 210 } 211 if (ArchiveClassesAtExit != nullptr) { 212 vm_exit_during_initialization("-XX:ArchiveClassesAtExit is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile", 213 SharedArchiveFile); 214 } 215 } 216 217 if (ArchiveClassesAtExit != nullptr && os::same_files(SharedArchiveFile, ArchiveClassesAtExit)) { 218 vm_exit_during_initialization( 219 "Cannot have the same archive file specified for -XX:SharedArchiveFile and -XX:ArchiveClassesAtExit", 220 SharedArchiveFile); 221 } 222 } 223 } 224 } 225 226 void CDSConfig::check_system_property(const char* key, const char* value) { 227 if (Arguments::is_internal_module_property(key)) { 228 MetaspaceShared::disable_optimized_module_handling(); 229 log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value); 230 } 231 if (strcmp(key, "jdk.module.showModuleResolution") == 0 || 232 strcmp(key, "jdk.module.validation") == 0 || 233 strcmp(key, "java.system.class.loader") == 0) { 234 disable_loading_full_module_graph(); 235 disable_dumping_full_module_graph(); 236 log_info(cds)("full module graph: disabled due to incompatible property: %s=%s", key, value); 237 } 238 } 239 240 static const char* unsupported_properties[] = { 241 "jdk.module.limitmods", 242 "jdk.module.upgrade.path", 243 "jdk.module.patch.0" 244 }; 245 static const char* unsupported_options[] = { 246 "--limit-modules", 247 "--upgrade-module-path", 248 "--patch-module" 249 }; 250 251 void CDSConfig::check_unsupported_dumping_properties() { 252 assert(is_dumping_archive(), "this function is only used with CDS dump time"); 253 assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be"); 254 // If a vm option is found in the unsupported_options array, vm will exit with an error message. 255 SystemProperty* sp = Arguments::system_properties(); 256 while (sp != nullptr) { 257 for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) { 258 if (strcmp(sp->key(), unsupported_properties[i]) == 0) { 259 vm_exit_during_initialization( 260 "Cannot use the following option when dumping the shared archive", unsupported_options[i]); 261 } 262 } 263 sp = sp->next(); 264 } 265 266 // Check for an exploded module build in use with -Xshare:dump. 267 if (!Arguments::has_jimage()) { 268 vm_exit_during_initialization("Dumping the shared archive is not supported with an exploded module build"); 269 } 270 } 271 272 bool CDSConfig::check_unsupported_cds_runtime_properties() { 273 assert(UseSharedSpaces, "this function is only used with -Xshare:{on,auto}"); 274 assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be"); 275 if (ArchiveClassesAtExit != nullptr) { 276 // dynamic dumping, just return false for now. 277 // check_unsupported_dumping_properties() will be called later to check the same set of 278 // properties, and will exit the VM with the correct error message if the unsupported properties 279 // are used. 280 return false; 281 } 282 for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) { 283 if (Arguments::get_property(unsupported_properties[i]) != nullptr) { 284 if (RequireSharedSpaces) { 285 warning("CDS is disabled when the %s option is specified.", unsupported_options[i]); 286 } else { 287 log_info(cds)("CDS is disabled when the %s option is specified.", unsupported_options[i]); 288 } 289 return true; 290 } 291 } 292 return false; 293 } 294 295 bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) { 296 if (is_dumping_static_archive()) { 297 if (!mode_flag_cmd_line) { 298 // By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive. 299 // 300 // If your classlist is large and you don't care about deterministic dumping, you can use 301 // -Xshare:dump -Xmixed to improve dumping speed. 302 Arguments::set_mode_flags(Arguments::_int); 303 } else if (Arguments::mode() == Arguments::_comp) { 304 // -Xcomp may use excessive CPU for the test tiers. Also, -Xshare:dump runs a small and fixed set of 305 // Java code, so there's not much benefit in running -Xcomp. 306 log_info(cds)("reduced -Xcomp to -Xmixed for static dumping"); 307 Arguments::set_mode_flags(Arguments::_mixed); 308 } 309 310 // String deduplication may cause CDS to iterate the strings in different order from one 311 // run to another which resulting in non-determinstic CDS archives. 312 // Disable UseStringDeduplication while dumping CDS archive. 313 UseStringDeduplication = false; 314 } 315 316 // RecordDynamicDumpInfo is not compatible with ArchiveClassesAtExit 317 if (ArchiveClassesAtExit != nullptr && RecordDynamicDumpInfo) { 318 jio_fprintf(defaultStream::output_stream(), 319 "-XX:+RecordDynamicDumpInfo cannot be used with -XX:ArchiveClassesAtExit.\n"); 320 return false; 321 } 322 323 if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) { 324 disable_dumping_dynamic_archive(); 325 } else { 326 enable_dumping_dynamic_archive(); 327 } 328 329 if (AutoCreateSharedArchive) { 330 if (SharedArchiveFile == nullptr) { 331 log_warning(cds)("-XX:+AutoCreateSharedArchive requires -XX:SharedArchiveFile"); 332 return false; 333 } 334 if (ArchiveClassesAtExit != nullptr) { 335 log_warning(cds)("-XX:+AutoCreateSharedArchive does not work with ArchiveClassesAtExit"); 336 return false; 337 } 338 } 339 340 if (UseSharedSpaces && patch_mod_javabase) { 341 Arguments::no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched."); 342 } 343 if (UseSharedSpaces && check_unsupported_cds_runtime_properties()) { 344 UseSharedSpaces = false; 345 } 346 347 if (is_dumping_archive()) { 348 // Always verify non-system classes during CDS dump 349 if (!BytecodeVerificationRemote) { 350 BytecodeVerificationRemote = true; 351 log_info(cds)("All non-system classes will be verified (-Xverify:remote) during CDS dump time."); 352 } 353 } 354 355 return true; 356 } 357 358 #if INCLUDE_CDS_JAVA_HEAP 359 bool CDSConfig::is_dumping_heap() { 360 // heap dump is not supported in dynamic dump 361 return is_dumping_static_archive() && HeapShared::can_write(); 362 } 363 364 bool CDSConfig::is_dumping_full_module_graph() { 365 if (!_dumping_full_module_graph_disabled && 366 is_dumping_heap() && 367 MetaspaceShared::use_optimized_module_handling()) { 368 return true; 369 } else { 370 return false; 371 } 372 } 373 374 bool CDSConfig::is_loading_full_module_graph() { 375 if (ClassLoaderDataShared::is_full_module_graph_loaded()) { 376 return true; 377 } 378 379 if (!_loading_full_module_graph_disabled && 380 UseSharedSpaces && 381 ArchiveHeapLoader::can_use() && 382 MetaspaceShared::use_optimized_module_handling()) { 383 // Classes used by the archived full module graph are loaded in JVMTI early phase. 384 assert(!(JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()), 385 "CDS should be disabled if early class hooks are enabled"); 386 return true; 387 } else { 388 return false; 389 } 390 } 391 392 void CDSConfig::disable_dumping_full_module_graph(const char* reason) { 393 if (!_dumping_full_module_graph_disabled) { 394 _dumping_full_module_graph_disabled = true; 395 if (reason != nullptr) { 396 log_info(cds)("full module graph cannot be dumped: %s", reason); 397 } 398 } 399 } 400 401 void CDSConfig::disable_loading_full_module_graph(const char* reason) { 402 assert(!ClassLoaderDataShared::is_full_module_graph_loaded(), "you call this function too late!"); 403 if (!_loading_full_module_graph_disabled) { 404 _loading_full_module_graph_disabled = true; 405 if (reason != nullptr) { 406 log_info(cds)("full module graph cannot be loaded: %s", reason); 407 } 408 } 409 } 410 #endif // INCLUDE_CDS_JAVA_HEAP