1 /* 2 * Copyright (c) 2023, 2024, 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/classListWriter.hpp" 29 #include "cds/heapShared.hpp" 30 #include "classfile/classLoaderDataShared.hpp" 31 #include "classfile/moduleEntry.hpp" 32 #include "include/jvm_io.h" 33 #include "logging/log.hpp" 34 #include "memory/universe.hpp" 35 #include "runtime/arguments.hpp" 36 #include "runtime/java.hpp" 37 #include "utilities/defaultStream.hpp" 38 39 bool CDSConfig::_is_dumping_static_archive = false; 40 bool CDSConfig::_is_dumping_dynamic_archive = false; 41 bool CDSConfig::_is_using_optimized_module_handling = true; 42 bool CDSConfig::_is_dumping_full_module_graph = true; 43 bool CDSConfig::_is_using_full_module_graph = true; 44 45 char* CDSConfig::_default_archive_path = nullptr; 46 char* CDSConfig::_static_archive_path = nullptr; 47 char* CDSConfig::_dynamic_archive_path = nullptr; 48 49 int CDSConfig::get_status() { 50 assert(Universe::is_fully_initialized(), "status is finalized only after Universe is initialized"); 51 return (is_dumping_archive() ? IS_DUMPING_ARCHIVE : 0) | 52 (is_dumping_static_archive() ? IS_DUMPING_STATIC_ARCHIVE : 0) | 53 (is_logging_lambda_form_invokers() ? IS_LOGGING_LAMBDA_FORM_INVOKERS : 0) | 54 (is_using_archive() ? IS_USING_ARCHIVE : 0); 55 } 56 57 58 void CDSConfig::initialize() { 59 if (is_dumping_static_archive()) { 60 if (RequireSharedSpaces) { 61 warning("Cannot dump shared archive while using shared archive"); 62 } 63 UseSharedSpaces = false; 64 } 65 66 // Initialize shared archive paths which could include both base and dynamic archive paths 67 // This must be after set_ergonomics_flags() called so flag UseCompressedOops is set properly. 68 // 69 // UseSharedSpaces may be disabled if -XX:SharedArchiveFile is invalid. 70 if (is_dumping_static_archive() || is_using_archive()) { 71 init_shared_archive_paths(); 72 } 73 74 if (!is_dumping_heap()) { 75 _is_dumping_full_module_graph = false; 76 } 77 } 78 79 char* CDSConfig::default_archive_path() { 80 if (_default_archive_path == nullptr) { 81 char jvm_path[JVM_MAXPATHLEN]; 82 os::jvm_path(jvm_path, sizeof(jvm_path)); 83 char *end = strrchr(jvm_path, *os::file_separator()); 84 if (end != nullptr) *end = '\0'; 85 stringStream tmp; 86 tmp.print("%s%sclasses", jvm_path, os::file_separator()); 87 #ifdef _LP64 88 if (!UseCompressedOops) { 89 tmp.print_raw("_nocoops"); 90 } 91 if (UseCompactObjectHeaders) { 92 // Note that generation of xxx_coh.jsa variants require 93 // --enable-cds-archive-coh at build time 94 tmp.print_raw("_coh"); 95 } 96 #endif 97 tmp.print_raw(".jsa"); 98 _default_archive_path = os::strdup(tmp.base()); 99 } 100 return _default_archive_path; 101 } 102 103 int CDSConfig::num_archives(const char* archive_path) { 104 if (archive_path == nullptr) { 105 return 0; 106 } 107 int npaths = 1; 108 char* p = (char*)archive_path; 109 while (*p != '\0') { 110 if (*p == os::path_separator()[0]) { 111 npaths++; 112 } 113 p++; 114 } 115 return npaths; 116 } 117 118 void CDSConfig::extract_shared_archive_paths(const char* archive_path, 119 char** base_archive_path, 120 char** top_archive_path) { 121 char* begin_ptr = (char*)archive_path; 122 char* end_ptr = strchr((char*)archive_path, os::path_separator()[0]); 123 if (end_ptr == nullptr || end_ptr == begin_ptr) { 124 vm_exit_during_initialization("Base archive was not specified", archive_path); 125 } 126 size_t len = end_ptr - begin_ptr; 127 char* cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); 128 strncpy(cur_path, begin_ptr, len); 129 cur_path[len] = '\0'; 130 *base_archive_path = cur_path; 131 132 begin_ptr = ++end_ptr; 133 if (*begin_ptr == '\0') { 134 vm_exit_during_initialization("Top archive was not specified", archive_path); 135 } 136 end_ptr = strchr(begin_ptr, '\0'); 137 assert(end_ptr != nullptr, "sanity"); 138 len = end_ptr - begin_ptr; 139 cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); 140 strncpy(cur_path, begin_ptr, len + 1); 141 *top_archive_path = cur_path; 142 } 143 144 void CDSConfig::init_shared_archive_paths() { 145 if (ArchiveClassesAtExit != nullptr) { 146 assert(!RecordDynamicDumpInfo, "already checked"); 147 if (is_dumping_static_archive()) { 148 vm_exit_during_initialization("-XX:ArchiveClassesAtExit cannot be used with -Xshare:dump"); 149 } 150 check_unsupported_dumping_module_options(); 151 152 if (os::same_files(default_archive_path(), ArchiveClassesAtExit)) { 153 vm_exit_during_initialization( 154 "Cannot specify the default CDS archive for -XX:ArchiveClassesAtExit", default_archive_path()); 155 } 156 } 157 158 if (SharedArchiveFile == nullptr) { 159 _static_archive_path = default_archive_path(); 160 } else { 161 int archives = num_archives(SharedArchiveFile); 162 assert(archives > 0, "must be"); 163 164 if (is_dumping_archive() && archives > 1) { 165 vm_exit_during_initialization( 166 "Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping"); 167 } 168 169 if (is_dumping_static_archive()) { 170 assert(archives == 1, "must be"); 171 // Static dump is simple: only one archive is allowed in SharedArchiveFile. This file 172 // will be overwritten no matter regardless of its contents 173 _static_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments); 174 } else { 175 // SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa 176 // is read from top.jsa 177 // (a) 1 file: -XX:SharedArchiveFile=base.jsa 178 // (b) 2 files: -XX:SharedArchiveFile=base.jsa:top.jsa 179 // (c) 2 files: -XX:SharedArchiveFile=top.jsa 180 // 181 // However, if either RecordDynamicDumpInfo or ArchiveClassesAtExit is used, we do not 182 // allow cases (b) and (c). Case (b) is already checked above. 183 184 if (archives > 2) { 185 vm_exit_during_initialization( 186 "Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option"); 187 } 188 if (archives == 1) { 189 char* base_archive_path = nullptr; 190 bool success = 191 FileMapInfo::get_base_archive_name_from_header(SharedArchiveFile, &base_archive_path); 192 if (!success) { 193 // If +AutoCreateSharedArchive and the specified shared archive does not exist, 194 // regenerate the dynamic archive base on default archive. 195 if (AutoCreateSharedArchive && !os::file_exists(SharedArchiveFile)) { 196 enable_dumping_dynamic_archive(); 197 ArchiveClassesAtExit = const_cast<char *>(SharedArchiveFile); 198 _static_archive_path = default_archive_path(); 199 SharedArchiveFile = nullptr; 200 } else { 201 if (AutoCreateSharedArchive) { 202 warning("-XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."); 203 AutoCreateSharedArchive = false; 204 } 205 Arguments::no_shared_spaces("invalid archive"); 206 } 207 } else if (base_archive_path == nullptr) { 208 // User has specified a single archive, which is a static archive. 209 _static_archive_path = const_cast<char *>(SharedArchiveFile); 210 } else { 211 // User has specified a single archive, which is a dynamic archive. 212 _dynamic_archive_path = const_cast<char *>(SharedArchiveFile); 213 _static_archive_path = base_archive_path; // has been c-heap allocated. 214 } 215 } else { 216 extract_shared_archive_paths((const char*)SharedArchiveFile, 217 &_static_archive_path, &_dynamic_archive_path); 218 if (_static_archive_path == nullptr) { 219 assert(_dynamic_archive_path == nullptr, "must be"); 220 Arguments::no_shared_spaces("invalid archive"); 221 } 222 } 223 224 if (_dynamic_archive_path != nullptr) { 225 // Check for case (c) 226 if (RecordDynamicDumpInfo) { 227 vm_exit_during_initialization("-XX:+RecordDynamicDumpInfo is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile", 228 SharedArchiveFile); 229 } 230 if (ArchiveClassesAtExit != nullptr) { 231 vm_exit_during_initialization("-XX:ArchiveClassesAtExit is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile", 232 SharedArchiveFile); 233 } 234 } 235 236 if (ArchiveClassesAtExit != nullptr && os::same_files(SharedArchiveFile, ArchiveClassesAtExit)) { 237 vm_exit_during_initialization( 238 "Cannot have the same archive file specified for -XX:SharedArchiveFile and -XX:ArchiveClassesAtExit", 239 SharedArchiveFile); 240 } 241 } 242 } 243 } 244 245 void CDSConfig::check_internal_module_property(const char* key, const char* value) { 246 if (Arguments::is_internal_module_property(key)) { 247 stop_using_optimized_module_handling(); 248 log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value); 249 } 250 } 251 252 void CDSConfig::check_incompatible_property(const char* key, const char* value) { 253 static const char* incompatible_properties[] = { 254 "java.system.class.loader", 255 "jdk.module.showModuleResolution", 256 "jdk.module.validation" 257 }; 258 259 for (const char* property : incompatible_properties) { 260 if (strcmp(key, property) == 0) { 261 stop_dumping_full_module_graph(); 262 stop_using_full_module_graph(); 263 log_info(cds)("full module graph: disabled due to incompatible property: %s=%s", key, value); 264 break; 265 } 266 } 267 268 } 269 270 // Returns any JVM command-line option, such as "--patch-module", that's not supported by CDS. 271 static const char* find_any_unsupported_module_option() { 272 // Note that arguments.cpp has translated the command-line options into properties. If we find an 273 // unsupported property, translate it back to its command-line option for better error reporting. 274 275 // The following properties are checked by Arguments::is_internal_module_property() and cannot be 276 // directly specified in the command-line. 277 static const char* unsupported_module_properties[] = { 278 "jdk.module.limitmods", 279 "jdk.module.upgrade.path", 280 "jdk.module.patch.0" 281 }; 282 static const char* unsupported_module_options[] = { 283 "--limit-modules", 284 "--upgrade-module-path", 285 "--patch-module" 286 }; 287 288 assert(ARRAY_SIZE(unsupported_module_properties) == ARRAY_SIZE(unsupported_module_options), "must be"); 289 SystemProperty* sp = Arguments::system_properties(); 290 while (sp != nullptr) { 291 for (uint i = 0; i < ARRAY_SIZE(unsupported_module_properties); i++) { 292 if (strcmp(sp->key(), unsupported_module_properties[i]) == 0) { 293 return unsupported_module_options[i]; 294 } 295 } 296 sp = sp->next(); 297 } 298 299 return nullptr; // not found 300 } 301 302 void CDSConfig::check_unsupported_dumping_module_options() { 303 assert(is_dumping_archive(), "this function is only used with CDS dump time"); 304 const char* option = find_any_unsupported_module_option(); 305 if (option != nullptr) { 306 vm_exit_during_initialization("Cannot use the following option when dumping the shared archive", option); 307 } 308 // Check for an exploded module build in use with -Xshare:dump. 309 if (!Arguments::has_jimage()) { 310 vm_exit_during_initialization("Dumping the shared archive is not supported with an exploded module build"); 311 } 312 } 313 314 bool CDSConfig::has_unsupported_runtime_module_options() { 315 assert(is_using_archive(), "this function is only used with -Xshare:{on,auto}"); 316 if (ArchiveClassesAtExit != nullptr) { 317 // dynamic dumping, just return false for now. 318 // check_unsupported_dumping_properties() will be called later to check the same set of 319 // properties, and will exit the VM with the correct error message if the unsupported properties 320 // are used. 321 return false; 322 } 323 const char* option = find_any_unsupported_module_option(); 324 if (option != nullptr) { 325 if (RequireSharedSpaces) { 326 warning("CDS is disabled when the %s option is specified.", option); 327 } else { 328 log_info(cds)("CDS is disabled when the %s option is specified.", option); 329 } 330 return true; 331 } 332 return false; 333 } 334 335 bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) { 336 if (is_dumping_static_archive()) { 337 if (!mode_flag_cmd_line) { 338 // By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive. 339 // 340 // If your classlist is large and you don't care about deterministic dumping, you can use 341 // -Xshare:dump -Xmixed to improve dumping speed. 342 Arguments::set_mode_flags(Arguments::_int); 343 } else if (Arguments::mode() == Arguments::_comp) { 344 // -Xcomp may use excessive CPU for the test tiers. Also, -Xshare:dump runs a small and fixed set of 345 // Java code, so there's not much benefit in running -Xcomp. 346 log_info(cds)("reduced -Xcomp to -Xmixed for static dumping"); 347 Arguments::set_mode_flags(Arguments::_mixed); 348 } 349 350 // String deduplication may cause CDS to iterate the strings in different order from one 351 // run to another which resulting in non-determinstic CDS archives. 352 // Disable UseStringDeduplication while dumping CDS archive. 353 UseStringDeduplication = false; 354 } 355 356 // RecordDynamicDumpInfo is not compatible with ArchiveClassesAtExit 357 if (ArchiveClassesAtExit != nullptr && RecordDynamicDumpInfo) { 358 jio_fprintf(defaultStream::output_stream(), 359 "-XX:+RecordDynamicDumpInfo cannot be used with -XX:ArchiveClassesAtExit.\n"); 360 return false; 361 } 362 363 if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) { 364 disable_dumping_dynamic_archive(); 365 } else { 366 enable_dumping_dynamic_archive(); 367 } 368 369 if (AutoCreateSharedArchive) { 370 if (SharedArchiveFile == nullptr) { 371 log_warning(cds)("-XX:+AutoCreateSharedArchive requires -XX:SharedArchiveFile"); 372 return false; 373 } 374 if (ArchiveClassesAtExit != nullptr) { 375 log_warning(cds)("-XX:+AutoCreateSharedArchive does not work with ArchiveClassesAtExit"); 376 return false; 377 } 378 } 379 380 if (is_using_archive() && patch_mod_javabase) { 381 Arguments::no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched."); 382 } 383 if (is_using_archive() && has_unsupported_runtime_module_options()) { 384 UseSharedSpaces = false; 385 } 386 387 if (is_dumping_archive()) { 388 // Always verify non-system classes during CDS dump 389 if (!BytecodeVerificationRemote) { 390 BytecodeVerificationRemote = true; 391 log_info(cds)("All non-system classes will be verified (-Xverify:remote) during CDS dump time."); 392 } 393 } 394 395 return true; 396 } 397 398 bool CDSConfig::is_using_archive() { 399 return UseSharedSpaces; 400 } 401 402 bool CDSConfig::is_logging_lambda_form_invokers() { 403 return ClassListWriter::is_enabled() || is_dumping_dynamic_archive(); 404 } 405 406 void CDSConfig::stop_using_optimized_module_handling() { 407 _is_using_optimized_module_handling = false; 408 _is_dumping_full_module_graph = false; // This requires is_using_optimized_module_handling() 409 _is_using_full_module_graph = false; // This requires is_using_optimized_module_handling() 410 } 411 412 #if INCLUDE_CDS_JAVA_HEAP 413 bool CDSConfig::is_dumping_heap() { 414 // heap dump is not supported in dynamic dump 415 return is_dumping_static_archive() && HeapShared::can_write(); 416 } 417 418 bool CDSConfig::is_using_full_module_graph() { 419 if (ClassLoaderDataShared::is_full_module_graph_loaded()) { 420 return true; 421 } 422 423 if (!_is_using_full_module_graph) { 424 return false; 425 } 426 427 if (is_using_archive() && ArchiveHeapLoader::can_use()) { 428 // Classes used by the archived full module graph are loaded in JVMTI early phase. 429 assert(!(JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()), 430 "CDS should be disabled if early class hooks are enabled"); 431 return true; 432 } else { 433 _is_using_full_module_graph = false; 434 return false; 435 } 436 } 437 438 void CDSConfig::stop_dumping_full_module_graph(const char* reason) { 439 if (_is_dumping_full_module_graph) { 440 _is_dumping_full_module_graph = false; 441 if (reason != nullptr) { 442 log_info(cds)("full module graph cannot be dumped: %s", reason); 443 } 444 } 445 } 446 447 void CDSConfig::stop_using_full_module_graph(const char* reason) { 448 assert(!ClassLoaderDataShared::is_full_module_graph_loaded(), "you call this function too late!"); 449 if (_is_using_full_module_graph) { 450 _is_using_full_module_graph = false; 451 if (reason != nullptr) { 452 log_info(cds)("full module graph cannot be loaded: %s", reason); 453 } 454 } 455 } 456 #endif // INCLUDE_CDS_JAVA_HEAP