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,
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
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 &&
|
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/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/globals.hpp"
35 #include "runtime/java.hpp"
36 #include "utilities/defaultStream.hpp"
37
38 bool CDSConfig::_is_dumping_static_archive = false;
39 bool CDSConfig::_is_dumping_dynamic_archive = false;
40
41 // The ability to dump the FMG depends on many factors checked by
42 // is_dumping_full_module_graph(), but can be unconditionally disabled by
43 // _dumping_full_module_graph_disabled. (Ditto for loading the FMG).
44 bool CDSConfig::_dumping_full_module_graph_disabled = false;
45 bool CDSConfig::_loading_full_module_graph_disabled = false;
46
47 bool CDSConfig::_module_patching_disables_cds = false;
48 bool CDSConfig::_java_base_module_patching_disables_cds = false;
49
50 bool CDSConfig::is_valhalla_preview() {
51 return Arguments::enable_preview() && EnableValhalla;
52 }
53
54
55 char* CDSConfig::_default_archive_path = nullptr;
56 char* CDSConfig::_static_archive_path = nullptr;
57 char* CDSConfig::_dynamic_archive_path = nullptr;
58
59 void CDSConfig::initialize() {
60 if (is_dumping_static_archive()) {
61 if (RequireSharedSpaces) {
62 warning("Cannot dump shared archive while using shared archive");
63 }
64 UseSharedSpaces = false;
65 }
66
67 // Initialize shared archive paths which could include both base and dynamic archive paths
68 // This must be after set_ergonomics_flags() called so flag UseCompressedOops is set properly.
69 //
70 // UseSharedSpaces may be disabled if -XX:SharedArchiveFile is invalid.
71 if (is_dumping_static_archive() || UseSharedSpaces) {
72 init_shared_archive_paths();
73 }
74 }
75
76 char* CDSConfig::default_archive_path() {
77 if (_default_archive_path == nullptr) {
78 char jvm_path[JVM_MAXPATHLEN];
79 os::jvm_path(jvm_path, sizeof(jvm_path));
80 char *end = strrchr(jvm_path, *os::file_separator());
81 if (end != nullptr) *end = '\0';
82 size_t jvm_path_len = strlen(jvm_path);
83 size_t file_sep_len = strlen(os::file_separator());
84 const size_t len = jvm_path_len + file_sep_len + strlen("classes_nocoops_valhalla.jsa") + 1;
85 _default_archive_path = NEW_C_HEAP_ARRAY(char, len, mtArguments);
86 LP64_ONLY(bool nocoops = !UseCompressedOops);
87 NOT_LP64(bool nocoops = false);
88 bool valhalla = is_valhalla_preview();
89 jio_snprintf(_default_archive_path, len, "%s%sclasses%s%s.jsa",
90 jvm_path, os::file_separator(),
91 nocoops ? "_nocoops" : "",
92 valhalla ? "_valhalla" : "");
93 }
94 return _default_archive_path;
95 }
96
97 int CDSConfig::num_archives(const char* archive_path) {
98 if (archive_path == nullptr) {
99 return 0;
100 }
101 int npaths = 1;
102 char* p = (char*)archive_path;
103 while (*p != '\0') {
104 if (*p == os::path_separator()[0]) {
105 npaths++;
106 }
107 p++;
108 }
109 return npaths;
110 }
111
112 void CDSConfig::extract_shared_archive_paths(const char* archive_path,
236 }
237 }
238
239 void CDSConfig::check_system_property(const char* key, const char* value) {
240 if (Arguments::is_internal_module_property(key)) {
241 MetaspaceShared::disable_optimized_module_handling();
242 log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value);
243 }
244 if (strcmp(key, "jdk.module.showModuleResolution") == 0 ||
245 strcmp(key, "jdk.module.validation") == 0 ||
246 strcmp(key, "java.system.class.loader") == 0) {
247 disable_loading_full_module_graph();
248 disable_dumping_full_module_graph();
249 log_info(cds)("full module graph: disabled due to incompatible property: %s=%s", key, value);
250 }
251 }
252
253 static const char* unsupported_properties[] = {
254 "jdk.module.limitmods",
255 "jdk.module.upgrade.path",
256 };
257 static const char* unsupported_options[] = {
258 "--limit-modules",
259 "--upgrade-module-path",
260 };
261
262 void CDSConfig::check_unsupported_dumping_properties() {
263 assert(is_dumping_archive(), "this function is only used with CDS dump time");
264 assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be");
265 // If a vm option is found in the unsupported_options array, vm will exit with an error message.
266 SystemProperty* sp = Arguments::system_properties();
267 while (sp != nullptr) {
268 for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) {
269 if (strcmp(sp->key(), unsupported_properties[i]) == 0) {
270 vm_exit_during_initialization(
271 "Cannot use the following option when dumping the shared archive", unsupported_options[i]);
272 }
273 }
274 sp = sp->next();
275 }
276
277 if (module_patching_disables_cds()) {
278 vm_exit_during_initialization(
279 "Cannot use the following option when dumping the shared archive", "--patch-module");
280 }
281
282
283 // Check for an exploded module build in use with -Xshare:dump.
284 if (!Arguments::has_jimage()) {
285 vm_exit_during_initialization("Dumping the shared archive is not supported with an exploded module build");
286 }
287 }
288
289 bool CDSConfig::check_unsupported_cds_runtime_properties() {
290 assert(UseSharedSpaces, "this function is only used with -Xshare:{on,auto}");
291 assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be");
292 if (ArchiveClassesAtExit != nullptr) {
293 // dynamic dumping, just return false for now.
294 // check_unsupported_dumping_properties() will be called later to check the same set of
295 // properties, and will exit the VM with the correct error message if the unsupported properties
296 // are used.
297 return false;
298 }
299 for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) {
300 if (Arguments::get_property(unsupported_properties[i]) != nullptr) {
301 if (RequireSharedSpaces) {
302 warning("CDS is disabled when the %s option is specified.", unsupported_options[i]);
303 } else {
304 log_info(cds)("CDS is disabled when the %s option is specified.", unsupported_options[i]);
305 }
306 return true;
307 }
308 }
309
310 if (module_patching_disables_cds()) {
311 if (RequireSharedSpaces) {
312 warning("CDS is disabled when the %s option is specified.", "--patch-module");
313 } else {
314 log_info(cds)("CDS is disabled when the %s option is specified.", "--patch-module");
315 }
316 return true;
317 }
318
319 return false;
320 }
321
322 bool CDSConfig::check_vm_args_consistency(bool mode_flag_cmd_line) {
323 if (is_dumping_static_archive()) {
324 if (!mode_flag_cmd_line) {
325 // By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive.
326 //
327 // If your classlist is large and you don't care about deterministic dumping, you can use
328 // -Xshare:dump -Xmixed to improve dumping speed.
329 Arguments::set_mode_flags(Arguments::_int);
330 } else if (Arguments::mode() == Arguments::_comp) {
331 // -Xcomp may use excessive CPU for the test tiers. Also, -Xshare:dump runs a small and fixed set of
332 // Java code, so there's not much benefit in running -Xcomp.
333 log_info(cds)("reduced -Xcomp to -Xmixed for static dumping");
334 Arguments::set_mode_flags(Arguments::_mixed);
335 }
336
337 // String deduplication may cause CDS to iterate the strings in different order from one
338 // run to another which resulting in non-determinstic CDS archives.
339 // Disable UseStringDeduplication while dumping CDS archive.
340 UseStringDeduplication = false;
341 }
342
347 return false;
348 }
349
350 if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) {
351 disable_dumping_dynamic_archive();
352 } else {
353 enable_dumping_dynamic_archive();
354 }
355
356 if (AutoCreateSharedArchive) {
357 if (SharedArchiveFile == nullptr) {
358 log_warning(cds)("-XX:+AutoCreateSharedArchive requires -XX:SharedArchiveFile");
359 return false;
360 }
361 if (ArchiveClassesAtExit != nullptr) {
362 log_warning(cds)("-XX:+AutoCreateSharedArchive does not work with ArchiveClassesAtExit");
363 return false;
364 }
365 }
366
367 if (UseSharedSpaces && java_base_module_patching_disables_cds() && module_patching_disables_cds()) {
368 Arguments::no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched.");
369 }
370 if (UseSharedSpaces && check_unsupported_cds_runtime_properties()) {
371 UseSharedSpaces = false;
372 }
373
374 if (is_dumping_archive()) {
375 // Always verify non-system classes during CDS dump
376 if (!BytecodeVerificationRemote) {
377 BytecodeVerificationRemote = true;
378 log_info(cds)("All non-system classes will be verified (-Xverify:remote) during CDS dump time.");
379 }
380 }
381
382 return true;
383 }
384
385 #if INCLUDE_CDS_JAVA_HEAP
386 bool CDSConfig::is_dumping_heap() {
387 if (is_valhalla_preview()) {
388 // Not working yet -- e.g., HeapShared::oop_hash() needs to be implemented for value oops
389 return false;
390 }
391 // heap dump is not supported in dynamic dump
392 return is_dumping_static_archive() && HeapShared::can_write();
393 }
394
395 bool CDSConfig::is_dumping_full_module_graph() {
396 if (!_dumping_full_module_graph_disabled &&
397 is_dumping_heap() &&
398 MetaspaceShared::use_optimized_module_handling()) {
399 return true;
400 } else {
401 return false;
402 }
403 }
404
405 bool CDSConfig::is_loading_full_module_graph() {
406 if (ClassLoaderDataShared::is_full_module_graph_loaded()) {
407 return true;
408 }
409
410 if (!_loading_full_module_graph_disabled &&
|