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,
113                                              char** base_archive_path,
114                                              char** top_archive_path) {
115   char* begin_ptr = (char*)archive_path;
116   char* end_ptr = strchr((char*)archive_path, os::path_separator()[0]);
117   if (end_ptr == nullptr || end_ptr == begin_ptr) {
118     vm_exit_during_initialization("Base archive was not specified", archive_path);
119   }
120   size_t len = end_ptr - begin_ptr;
121   char* cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
122   strncpy(cur_path, begin_ptr, len);
123   cur_path[len] = '\0';
124   *base_archive_path = cur_path;
125 
126   begin_ptr = ++end_ptr;
127   if (*begin_ptr == '\0') {
128     vm_exit_during_initialization("Top archive was not specified", archive_path);
129   }
130   end_ptr = strchr(begin_ptr, '\0');
131   assert(end_ptr != nullptr, "sanity");
132   len = end_ptr - begin_ptr;
133   cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
134   strncpy(cur_path, begin_ptr, len + 1);
135   *top_archive_path = cur_path;
136 }
137 
138 void CDSConfig::init_shared_archive_paths() {
139   if (ArchiveClassesAtExit != nullptr) {
140     assert(!RecordDynamicDumpInfo, "already checked");
141     if (is_dumping_static_archive()) {
142       vm_exit_during_initialization("-XX:ArchiveClassesAtExit cannot be used with -Xshare:dump");
143     }
144     check_unsupported_dumping_properties();
145 
146     if (os::same_files(default_archive_path(), ArchiveClassesAtExit)) {
147       vm_exit_during_initialization(
148         "Cannot specify the default CDS archive for -XX:ArchiveClassesAtExit", default_archive_path());
149     }
150   }
151 
152   if (SharedArchiveFile == nullptr) {
153     _static_archive_path = default_archive_path();
154   } else {
155     int archives = num_archives(SharedArchiveFile);
156     assert(archives > 0, "must be");
157 
158     if (is_dumping_archive() && archives > 1) {
159       vm_exit_during_initialization(
160         "Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping");
161     }
162 
163     if (is_dumping_static_archive()) {
164       assert(archives == 1, "must be");
165       // Static dump is simple: only one archive is allowed in SharedArchiveFile. This file
166       // will be overwritten no matter regardless of its contents
167       _static_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments);
168     } else {
169       // SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa
170       // is read from top.jsa
171       //    (a) 1 file:  -XX:SharedArchiveFile=base.jsa
172       //    (b) 2 files: -XX:SharedArchiveFile=base.jsa:top.jsa
173       //    (c) 2 files: -XX:SharedArchiveFile=top.jsa
174       //
175       // However, if either RecordDynamicDumpInfo or ArchiveClassesAtExit is used, we do not
176       // allow cases (b) and (c). Case (b) is already checked above.
177 
178       if (archives > 2) {
179         vm_exit_during_initialization(
180           "Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option");
181       }
182       if (archives == 1) {
183         char* base_archive_path = nullptr;
184         bool success =
185           FileMapInfo::get_base_archive_name_from_header(SharedArchiveFile, &base_archive_path);
186         if (!success) {
187           // If +AutoCreateSharedArchive and the specified shared archive does not exist,
188           // regenerate the dynamic archive base on default archive.
189           if (AutoCreateSharedArchive && !os::file_exists(SharedArchiveFile)) {
190             enable_dumping_dynamic_archive();
191             ArchiveClassesAtExit = const_cast<char *>(SharedArchiveFile);
192             _static_archive_path = default_archive_path();
193             SharedArchiveFile = nullptr;
194           } else {
195             if (AutoCreateSharedArchive) {
196               warning("-XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info.");
197               AutoCreateSharedArchive = false;
198             }
199             Arguments::no_shared_spaces("invalid archive");
200           }
201         } else if (base_archive_path == nullptr) {
202           // User has specified a single archive, which is a static archive.
203           _static_archive_path = const_cast<char *>(SharedArchiveFile);
204         } else {
205           // User has specified a single archive, which is a dynamic archive.
206           _dynamic_archive_path = const_cast<char *>(SharedArchiveFile);
207           _static_archive_path = base_archive_path; // has been c-heap allocated.
208         }
209       } else {
210         extract_shared_archive_paths((const char*)SharedArchiveFile,
211                                       &_static_archive_path, &_dynamic_archive_path);
212         if (_static_archive_path == nullptr) {
213           assert(_dynamic_archive_path == nullptr, "must be");
214           Arguments::no_shared_spaces("invalid archive");
215         }
216       }
217 
218       if (_dynamic_archive_path != nullptr) {
219         // Check for case (c)
220         if (RecordDynamicDumpInfo) {
221           vm_exit_during_initialization("-XX:+RecordDynamicDumpInfo is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile",
222                                         SharedArchiveFile);
223         }
224         if (ArchiveClassesAtExit != nullptr) {
225           vm_exit_during_initialization("-XX:ArchiveClassesAtExit is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile",
226                                         SharedArchiveFile);
227         }
228       }
229 
230       if (ArchiveClassesAtExit != nullptr && os::same_files(SharedArchiveFile, ArchiveClassesAtExit)) {
231           vm_exit_during_initialization(
232             "Cannot have the same archive file specified for -XX:SharedArchiveFile and -XX:ArchiveClassesAtExit",
233             SharedArchiveFile);
234       }
235     }
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 
343   // RecordDynamicDumpInfo is not compatible with ArchiveClassesAtExit
344   if (ArchiveClassesAtExit != nullptr && RecordDynamicDumpInfo) {
345     jio_fprintf(defaultStream::output_stream(),
346                 "-XX:+RecordDynamicDumpInfo cannot be used with -XX:ArchiveClassesAtExit.\n");
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 &&
411       UseSharedSpaces &&
412       ArchiveHeapLoader::can_use() &&
413       MetaspaceShared::use_optimized_module_handling()) {
414     // Classes used by the archived full module graph are loaded in JVMTI early phase.
415     assert(!(JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()),
416            "CDS should be disabled if early class hooks are enabled");
417     return true;
418   } else {
419     return false;
420   }
421 }
422 
423 void CDSConfig::disable_dumping_full_module_graph(const char* reason) {
424   if (!_dumping_full_module_graph_disabled) {
425     _dumping_full_module_graph_disabled = true;
426     if (reason != nullptr) {
427       log_info(cds)("full module graph cannot be dumped: %s", reason);
428     }
429   }
430 }
431 
432 void CDSConfig::disable_loading_full_module_graph(const char* reason) {
433   assert(!ClassLoaderDataShared::is_full_module_graph_loaded(), "you call this function too late!");
434   if (!_loading_full_module_graph_disabled) {
435     _loading_full_module_graph_disabled = true;
436     if (reason != nullptr) {
437       log_info(cds)("full module graph cannot be loaded: %s", reason);
438     }
439   }
440 }
441 #endif // INCLUDE_CDS_JAVA_HEAP