1 /*
   2  * Copyright (c) 2003, 2026, 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 "cds/aotClassLocation.hpp"
  26 #include "cds/aotLogging.hpp"
  27 #include "cds/aotMetaspace.hpp"
  28 #include "cds/archiveBuilder.hpp"
  29 #include "cds/cdsConfig.hpp"
  30 #include "cds/dynamicArchive.hpp"
  31 #include "cds/filemap.hpp"
  32 #include "cds/serializeClosure.hpp"
  33 #include "classfile/classLoader.hpp"
  34 #include "classfile/classLoaderData.hpp"
  35 #include "classfile/javaClasses.hpp"
  36 #include "logging/log.hpp"
  37 #include "logging/logStream.hpp"
  38 #include "memory/metadataFactory.hpp"
  39 #include "memory/metaspaceClosure.hpp"
  40 #include "memory/resourceArea.hpp"
  41 #include "oops/array.hpp"
  42 #include "oops/objArrayKlass.hpp"
  43 #include "runtime/arguments.hpp"
  44 #include "utilities/classpathStream.hpp"
  45 #include "utilities/formatBuffer.hpp"
  46 #include "utilities/stringUtils.hpp"
  47 
  48 #include <errno.h>
  49 #include <sys/stat.h>
  50 
  51 Array<ClassPathZipEntry*>* AOTClassLocationConfig::_dumptime_jar_files = nullptr;
  52 AOTClassLocationConfig* AOTClassLocationConfig::_dumptime_instance = nullptr;
  53 const AOTClassLocationConfig* AOTClassLocationConfig::_runtime_instance = nullptr;
  54 
  55 // A ClassLocationStream represents a list of code locations, which can be iterated using
  56 // start() and has_next().
  57 class ClassLocationStream {
  58 protected:
  59   GrowableArray<const char*> _array;
  60   int _current;
  61 
  62   // Add one path to this stream.
  63   void add_one_path(const char* path) {
  64     _array.append(path);
  65   }
  66 
  67   // Add all paths specified in cp; cp must be from -classpath or -Xbootclasspath/a.
  68   void add_paths_in_classpath(const char* cp) {
  69     ClasspathStream cp_stream(cp);
  70     while (cp_stream.has_next()) {
  71       add_one_path(cp_stream.get_next());
  72     }
  73   }
  74 
  75 public:
  76   ClassLocationStream() : _array(), _current(0) {}
  77 
  78   void print(outputStream* st) const {
  79     const char* sep = "";
  80     for (int i = 0; i < _array.length(); i++) {
  81       st->print("%s%s", sep, _array.at(i));
  82       sep = os::path_separator();
  83     }
  84   }
  85 
  86   void add(ClassLocationStream& css) {
  87     for (css.start(); css.has_next();) {
  88       add_one_path(css.get_next());
  89     }
  90   }
  91 
  92   // Iteration
  93   void start() { _current = 0; }
  94   bool has_next() const { return _current < _array.length(); }
  95   const char* get_next() {
  96     return _array.at(_current++);
  97   }
  98 
  99   int current() const { return _current; }
 100   bool is_empty() const { return _array.length() == 0; }
 101 };
 102 
 103 class BootCpClassLocationStream : public ClassLocationStream {
 104 public:
 105   BootCpClassLocationStream() : ClassLocationStream() {
 106     // Arguments::get_boot_class_path() contains $JAVA_HOME/lib/modules, but we treat that separately
 107     for (const char* bootcp = Arguments::get_boot_class_path(); *bootcp != '\0'; ++bootcp) {
 108       if (*bootcp == *os::path_separator()) {
 109         ++bootcp;
 110         add_paths_in_classpath(bootcp);
 111         break;
 112       }
 113     }
 114   }
 115 };
 116 
 117 class AppCpClassLocationStream : public ClassLocationStream {
 118 public:
 119   AppCpClassLocationStream() : ClassLocationStream() {
 120     const char* appcp = Arguments::get_appclasspath();
 121     if (strcmp(appcp, ".") == 0) {
 122       appcp = "";
 123     }
 124     add_paths_in_classpath(appcp);
 125   }
 126 };
 127 
 128 class ModulePathClassLocationStream : public ClassLocationStream {
 129   bool _has_non_jar_modules;
 130 public:
 131   ModulePathClassLocationStream();
 132   bool has_non_jar_modules() { return _has_non_jar_modules; }
 133 };
 134 
 135 // AllClassLocationStreams is used to iterate over all the code locations that
 136 // are available to the application from -Xbootclasspath, -classpath and --module-path.
 137 // When creating an AOT cache, we store the contents from AllClassLocationStreams
 138 // into an array of AOTClassLocations. See AOTClassLocationConfig::dumptime_init_helper().
 139 // When loading the AOT cache in a production run, we compare the contents of the
 140 // stored AOTClassLocations against the current AllClassLocationStreams to determine whether
 141 // the AOT cache is compatible with the current JVM. See AOTClassLocationConfig::validate().
 142 class AllClassLocationStreams {
 143   BootCpClassLocationStream _boot_cp;          // Specified by -Xbootclasspath/a
 144   AppCpClassLocationStream _app_cp;            // Specified by -classpath
 145   ModulePathClassLocationStream _module_path;  // Specified by --module-path
 146   ClassLocationStream _boot_and_app_cp;        // Convenience for iterating over both _boot and _app
 147 public:
 148   BootCpClassLocationStream& boot_cp()             { return _boot_cp; }
 149   AppCpClassLocationStream& app_cp()               { return _app_cp; }
 150   ModulePathClassLocationStream& module_path()     { return _module_path; }
 151   ClassLocationStream& boot_and_app_cp()           { return _boot_and_app_cp; }
 152 
 153   AllClassLocationStreams() : _boot_cp(), _app_cp(), _module_path(), _boot_and_app_cp() {
 154     _boot_and_app_cp.add(_boot_cp);
 155     _boot_and_app_cp.add(_app_cp);
 156   }
 157 };
 158 
 159 static bool has_jar_suffix(const char* filename) {
 160   // In jdk.internal.module.ModulePath.readModule(), it checks for the ".jar" suffix.
 161   // Performing the same check here.
 162   const char* dot = strrchr(filename, '.');
 163   if (dot != nullptr && strcmp(dot + 1, "jar") == 0) {
 164     return true;
 165   }
 166   return false;
 167 }
 168 
 169 static int compare_module_path_by_name(const char** p1, const char** p2) {
 170   return strcmp(*p1, *p2);
 171 }
 172 
 173 ModulePathClassLocationStream::ModulePathClassLocationStream() : ClassLocationStream(), _has_non_jar_modules(false) {
 174   // Note: for handling of --module-path, see
 175   //   https://openjdk.org/jeps/261#Module-paths
 176   //   https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/module/ModuleFinder.html#of(java.nio.file.Path...)
 177 
 178   const char* jdk_module_path = Arguments::get_property("jdk.module.path");
 179   if (jdk_module_path == nullptr) {
 180     return;
 181   }
 182 
 183   ClasspathStream cp_stream(jdk_module_path);
 184   while (cp_stream.has_next()) {
 185     const char* path = cp_stream.get_next();
 186     DIR* dirp = os::opendir(path);
 187     if (dirp == nullptr && errno == ENOTDIR && has_jar_suffix(path)) {
 188       add_one_path(path);
 189     } else if (dirp != nullptr) {
 190       struct dirent* dentry;
 191       bool found_jar = false;
 192       while ((dentry = os::readdir(dirp)) != nullptr) {
 193         const char* file_name = dentry->d_name;
 194         if (has_jar_suffix(file_name)) {
 195           size_t full_name_len = strlen(path) + strlen(file_name) + strlen(os::file_separator()) + 1;
 196           char* full_name = NEW_RESOURCE_ARRAY(char, full_name_len);
 197           int n = os::snprintf(full_name, full_name_len, "%s%s%s", path, os::file_separator(), file_name);
 198           assert((size_t)n == full_name_len - 1, "Unexpected number of characters in string");
 199           add_one_path(full_name);
 200           found_jar = true;
 201         } else if (strcmp(file_name, ".") != 0 && strcmp(file_name, "..") != 0) {
 202           // Found some non jar entries
 203           _has_non_jar_modules = true;
 204           log_info(class, path)("Found non-jar path: '%s%s%s'", path, os::file_separator(), file_name);
 205         }
 206       }
 207       if (!found_jar) {
 208         log_info(class, path)("Found exploded module path: '%s'", path);
 209         _has_non_jar_modules = true;
 210       }
 211       os::closedir(dirp);
 212     } else {
 213       _has_non_jar_modules = true;
 214     }
 215   }
 216 
 217   _array.sort(compare_module_path_by_name);
 218 }
 219 
 220 AOTClassLocation* AOTClassLocation::allocate(JavaThread* current, const char* path, int index,
 221                                              Group group, bool from_cpattr, bool is_jrt) {
 222   size_t path_length = 0;
 223   size_t manifest_length = 0;
 224   bool check_time = false;
 225   time_t timestamp = 0;
 226   int64_t filesize = 0;
 227   FileType type = FileType::NORMAL;
 228   // Do not record the actual path of the jrt, as the entire JDK can be moved to a different
 229   // directory.
 230   const char* recorded_path = is_jrt ? "" : path;
 231   path_length = strlen(recorded_path);
 232 
 233   struct stat st;
 234   if (os::stat(path, &st) == 0) {
 235     if ((st.st_mode & S_IFMT) == S_IFDIR) {
 236       type = FileType::DIR;
 237     } else {
 238       timestamp = st.st_mtime;
 239       filesize = st.st_size;
 240 
 241       // The timestamp of $JAVA_HOME/lib/modules is not checked at runtime.
 242       check_time = !is_jrt;
 243     }
 244   } else if (errno == ENOENT) {
 245     // We allow the file to not exist, as long as it also doesn't exist during runtime.
 246     type = FileType::NOT_EXIST;
 247   } else {
 248     aot_log_error(aot)("Unable to open file %s.", path);
 249     AOTMetaspace::unrecoverable_loading_error();
 250   }
 251 
 252   ResourceMark rm(current);
 253   char* manifest = nullptr;
 254 
 255   if (!is_jrt && type == FileType::NORMAL) {
 256     manifest = read_manifest(current, path, manifest_length); // resource allocated
 257   }
 258 
 259   size_t cs_size = header_size() +
 260     + path_length + 1 /* nul-terminated */
 261     + manifest_length + 1; /* nul-terminated */
 262 
 263   AOTClassLocation* cs = (AOTClassLocation*)os::malloc(cs_size, mtClassShared);
 264   memset(cs, 0, cs_size);
 265   cs->_path_length = path_length;
 266   cs->_manifest_length = manifest_length;
 267   cs->_check_time = check_time;
 268   cs->_from_cpattr = from_cpattr;
 269   cs->_timestamp = check_time ? timestamp : 0;
 270   cs->_filesize = filesize;
 271   cs->_file_type = type;
 272   cs->_group = group;
 273   cs->_index = index;
 274 
 275   strcpy(((char*)cs) + cs->path_offset(), recorded_path);
 276   if (manifest_length > 0) {
 277     memcpy(((char*)cs) + cs->manifest_offset(), manifest, manifest_length);
 278   }
 279   assert(*(cs->manifest() + cs->manifest_length()) == '\0', "should be nul-terminated");
 280 
 281   if (strstr(cs->manifest(), "Multi-Release: true") != nullptr) {
 282     cs->_is_multi_release_jar = true;
 283   }
 284 
 285   if (strstr(cs->manifest(), "Extension-List:") != nullptr) {
 286     vm_exit_during_cds_dumping(err_msg("-Xshare:dump does not support Extension-List in JAR manifest: %s", path));
 287   }
 288 
 289   return cs;
 290 }
 291 
 292 char* AOTClassLocation::read_manifest(JavaThread* current, const char* path, size_t& manifest_length) {
 293   manifest_length = 0;
 294 
 295   struct stat st;
 296   if (os::stat(path, &st) != 0) {
 297     return nullptr;
 298   }
 299 
 300   ClassPathEntry* cpe = ClassLoader::create_class_path_entry(current, path, &st);
 301   if (cpe == nullptr) {
 302     // <path> is a file, but not a JAR file
 303     return nullptr;
 304   }
 305   assert(cpe->is_jar_file(), "should not be called with a directory");
 306 
 307   const char* name = "META-INF/MANIFEST.MF";
 308   char* manifest;
 309   jint size;
 310   manifest = (char*) ((ClassPathZipEntry*)cpe)->open_entry(current, name, &size, true);
 311 
 312   if (manifest == nullptr || size <= 0) { // No Manifest
 313     manifest_length = 0;
 314   } else {
 315     manifest_length = (size_t)size;
 316   }
 317 
 318   delete cpe;
 319   return manifest;
 320 }
 321 
 322 // The result is resource allocated.
 323 char* AOTClassLocation::get_cpattr() const {
 324   if (_manifest_length == 0) {
 325     return nullptr;
 326   }
 327 
 328   size_t buf_size = _manifest_length + 1;
 329   char* buf = NEW_RESOURCE_ARRAY(char, buf_size);
 330   memcpy(buf, manifest(), _manifest_length);
 331   buf[_manifest_length] = 0; // make sure it's 0-terminated
 332 
 333   // See http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#JAR%20Manifest
 334   // Replace all CR/LF and CR with LF
 335   StringUtils::replace_no_expand(buf, "\r\n", "\n");
 336   // Remove all new-line continuation (remove all "\n " substrings)
 337   StringUtils::replace_no_expand(buf, "\n ", "");
 338 
 339   const char* tag = "Class-Path: ";
 340   size_t tag_len = strlen(tag);
 341   char* found = nullptr;
 342   char* line_start = buf;
 343   char* end = buf + _manifest_length;
 344 
 345   assert(*end == 0, "must be nul-terminated");
 346 
 347   while (line_start < end) {
 348     char* line_end = strchr(line_start, '\n');
 349     if (line_end == nullptr) {
 350       // JAR spec require the manifest file to be terminated by a new line.
 351       break;
 352     }
 353     if (strncmp(tag, line_start, tag_len) == 0) {
 354       if (found != nullptr) {
 355         // Same behavior as jdk/src/share/classes/java/util/jar/Attributes.java
 356         // If duplicated entries are found, the last one is used.
 357         log_warning(aot)("Warning: Duplicate name in Manifest: %s.\n"
 358                          "Ensure that the manifest does not have duplicate entries, and\n"
 359                          "that blank lines separate individual sections in both your\n"
 360                          "manifest and in the META-INF/MANIFEST.MF entry in the jar file:\n%s\n", tag, path());
 361       }
 362       found = line_start + tag_len;
 363       assert(found <= line_end, "sanity");
 364       *line_end = '\0';
 365     }
 366     line_start = line_end + 1;
 367   }
 368 
 369   return found;
 370 }
 371 
 372 AOTClassLocation* AOTClassLocation::write_to_archive() const {
 373   AOTClassLocation* archived_copy = (AOTClassLocation*)ArchiveBuilder::ro_region_alloc(total_size());
 374   memcpy((char*)archived_copy, (char*)this, total_size());
 375   return archived_copy;
 376 }
 377 
 378 const char* AOTClassLocation::file_type_string() const {
 379   switch (_file_type) {
 380   case FileType::NORMAL: return "file";
 381   case FileType::DIR: return "dir";
 382   case FileType::NOT_EXIST: default: return "not-exist";
 383   }
 384 }
 385 
 386 bool AOTClassLocation::check(const char* runtime_path, bool has_aot_linked_classes) const {
 387   struct stat st;
 388   if (os::stat(runtime_path, &st) != 0) {
 389     if (_file_type != FileType::NOT_EXIST) {
 390       aot_log_warning(aot)("Required classpath entry does not exist: %s", runtime_path);
 391       return false;
 392     }
 393   } else if ((st.st_mode & S_IFMT) == S_IFDIR) {
 394     if (_file_type == FileType::NOT_EXIST) {
 395       aot_log_warning(aot)("'%s' must not exist", runtime_path);
 396       return false;
 397     }
 398     if (_file_type == FileType::NORMAL) {
 399       aot_log_warning(aot)("'%s' must be a file", runtime_path);
 400       return false;
 401     }
 402     if (!os::dir_is_empty(runtime_path)) {
 403       aot_log_warning(aot)("directory is not empty: '%s'", runtime_path);
 404       return false;
 405     }
 406   } else {
 407     if (_file_type == FileType::NOT_EXIST) {
 408       aot_log_warning(aot)("'%s' must not exist", runtime_path);
 409       if (has_aot_linked_classes) {
 410         aot_log_error(aot)("CDS archive has aot-linked classes. It cannot be used because the "
 411                        "file %s exists", runtime_path);
 412         return false;
 413       } else {
 414         aot_log_warning(aot)("Archived non-system classes are disabled because the "
 415                          "file %s exists", runtime_path);
 416         FileMapInfo::current_info()->set_has_platform_or_app_classes(false);
 417         if (DynamicArchive::is_mapped()) {
 418           FileMapInfo::dynamic_info()->set_has_platform_or_app_classes(false);
 419         }
 420       }
 421     }
 422     if (_file_type == FileType::DIR) {
 423       aot_log_warning(aot)("'%s' must be a directory", runtime_path);
 424       return false;
 425     }
 426     bool size_differs = _filesize != st.st_size;
 427     bool time_differs = _check_time && (_timestamp != st.st_mtime);
 428     if (size_differs || time_differs) {
 429       aot_log_warning(aot)("This file is not the one used while building the %s: '%s'%s%s",
 430                        CDSConfig::type_of_archive_being_loaded(),
 431                        runtime_path,
 432                        time_differs ? ", timestamp has changed" : "",
 433                        size_differs ? ", size has changed" : "");
 434       return false;
 435     }
 436   }
 437 
 438   log_info(class, path)("ok");
 439   return true;
 440 }
 441 
 442 void AOTClassLocationConfig::dumptime_init(JavaThread* current) {
 443   assert(CDSConfig::is_dumping_archive(), "");
 444   _dumptime_instance = NEW_C_HEAP_OBJ(AOTClassLocationConfig, mtClassShared);
 445   _dumptime_instance->dumptime_init_helper(current);
 446   if (current->has_pending_exception()) {
 447     // we can get an exception only when we run out of metaspace, but that
 448     // shouldn't happen this early in bootstrap.
 449     java_lang_Throwable::print(current->pending_exception(), tty);
 450     vm_exit_during_initialization("AOTClassLocationConfig::dumptime_init_helper() failed unexpectedly");
 451   }
 452 
 453   if (CDSConfig::is_dumping_final_static_archive()) {
 454     // The _max_used_index is usually updated by ClassLoader::record_result(). However,
 455     // when dumping the final archive, the classes are loaded from their images in
 456     // the AOT config file, so we don't go through ClassLoader::record_result().
 457     dumptime_update_max_used_index(runtime()->_max_used_index); // Same value as recorded in the training run.
 458   }
 459 }
 460 
 461 void AOTClassLocationConfig::dumptime_init_helper(TRAPS) {
 462   ResourceMark rm;
 463   GrowableClassLocationArray tmp_array;
 464   AllClassLocationStreams all_css;
 465 
 466   AOTClassLocation* jrt = AOTClassLocation::allocate(THREAD, ClassLoader::get_jrt_entry()->name(),
 467                                                0, Group::MODULES_IMAGE,
 468                                                /*from_cpattr*/false, /*is_jrt*/true);
 469   log_info(class, path)("path [%d] = (modules image)", tmp_array.length());
 470   tmp_array.append(jrt);
 471 
 472   parse(THREAD, tmp_array, all_css.boot_cp(), Group::BOOT_CLASSPATH, /*parse_manifest*/true);
 473   _boot_classpath_end = tmp_array.length();
 474 
 475   parse(THREAD, tmp_array, all_css.app_cp(), Group::APP_CLASSPATH, /*parse_manifest*/true);
 476   _app_classpath_end = tmp_array.length();
 477 
 478   parse(THREAD, tmp_array, all_css.module_path(), Group::MODULE_PATH, /*parse_manifest*/false);
 479   _module_end = tmp_array.length();
 480 
 481   _class_locations =  MetadataFactory::new_array<AOTClassLocation*>(ClassLoaderData::the_null_class_loader_data(),
 482                                                                tmp_array.length(), CHECK);
 483   for (int i = 0; i < tmp_array.length(); i++) {
 484     _class_locations->at_put(i, tmp_array.at(i));
 485   }
 486 
 487   _dumptime_jar_files = MetadataFactory::new_array<ClassPathZipEntry*>(ClassLoaderData::the_null_class_loader_data(),
 488                                                                        tmp_array.length(), CHECK);
 489   for (int i = 1; i < tmp_array.length(); i++) {
 490     ClassPathZipEntry* jar_file = ClassLoader::create_class_path_zip_entry(tmp_array.at(i)->path());
 491     _dumptime_jar_files->at_put(i, jar_file); // may be null if the path is not a valid JAR file
 492   }
 493 
 494   const char* lcp = find_lcp(all_css.boot_and_app_cp(), _dumptime_lcp_len);
 495   if (_dumptime_lcp_len > 0) {
 496     log_info(class, path)("Longest common prefix = %s (%zu chars)", lcp, _dumptime_lcp_len);
 497     os::free((void*)lcp);
 498   } else {
 499     assert(_dumptime_lcp_len == 0, "sanity");
 500     log_info(class, path)("Longest common prefix = <none> (0 chars)");
 501   }
 502 
 503   _has_non_jar_modules = all_css.module_path().has_non_jar_modules();
 504   _has_platform_classes = false;
 505   _has_app_classes = false;
 506   _max_used_index = 0;
 507 }
 508 
 509 // Find the longest common prefix of two paths, up to max_lcp_len.
 510 // E.g.   p1 = "/a/b/foo"
 511 //        p2 = "/a/b/bar"
 512 //        max_lcp_len = 3
 513 // -> returns 3
 514 static size_t find_lcp_of_two_paths(const char* p1, const char* p2, size_t max_lcp_len) {
 515   size_t lcp_len = 0;
 516   char sep = os::file_separator()[0];
 517   for (size_t i = 0; ; i++) {
 518     char c1 = *p1++;
 519     char c2 = *p2++;
 520     if (c1 == 0 || c2 == 0 || c1 != c2) {
 521       break;
 522     }
 523     if (c1 == sep) {
 524       lcp_len = i + 1;
 525       assert(lcp_len <= max_lcp_len, "sanity");
 526       if (lcp_len == max_lcp_len) {
 527         break;
 528       }
 529     }
 530   }
 531   return lcp_len;
 532 }
 533 
 534 // cheap-allocated if lcp_len > 0
 535 const char* AOTClassLocationConfig::find_lcp(ClassLocationStream& css, size_t& lcp_len) {
 536   const char* first_path = nullptr;
 537   char sep = os::file_separator()[0];
 538 
 539   for (css.start(); css.has_next(); ) {
 540     const char* path = css.get_next();
 541     if (first_path == nullptr) {
 542       first_path = path;
 543       const char* p = strrchr(first_path, sep);
 544       if (p == nullptr) {
 545         lcp_len = 0;
 546         return "";
 547       } else {
 548         lcp_len = p - first_path + 1;
 549       }
 550     } else {
 551       lcp_len = find_lcp_of_two_paths(first_path, path, lcp_len);
 552       if (lcp_len == 0) {
 553         return "";
 554       }
 555     }
 556   }
 557 
 558   if (first_path != nullptr && lcp_len > 0) {
 559     char* lcp = NEW_C_HEAP_ARRAY(char, lcp_len + 1, mtClassShared);
 560     lcp[0] = 0;
 561     strncat(lcp, first_path, lcp_len);
 562     return lcp;
 563   } else {
 564     lcp_len = 0;
 565     return "";
 566   }
 567 }
 568 
 569 void AOTClassLocationConfig::parse(JavaThread* current, GrowableClassLocationArray& tmp_array,
 570                                    ClassLocationStream& css, Group group, bool parse_manifest) {
 571   for (css.start(); css.has_next(); ) {
 572     add_class_location(current, tmp_array, css.get_next(), group, parse_manifest, /*from_cpattr*/false);
 573   }
 574 }
 575 
 576 void AOTClassLocationConfig::add_class_location(JavaThread* current, GrowableClassLocationArray& tmp_array,
 577                                                 const char* path, Group group, bool parse_manifest, bool from_cpattr) {
 578   AOTClassLocation* cs = AOTClassLocation::allocate(current, path, tmp_array.length(), group, from_cpattr);
 579   log_info(class, path)("path [%d] = %s%s", tmp_array.length(), path, from_cpattr ? " (from cpattr)" : "");
 580   tmp_array.append(cs);
 581 
 582   if (!parse_manifest) {
 583     // parse_manifest is true for -classpath and -Xbootclasspath/a, and false for --module-path.
 584     return;
 585   }
 586 
 587   ResourceMark rm;
 588   char* cp_attr = cs->get_cpattr(); // resource allocated
 589   if (cp_attr != nullptr && strlen(cp_attr) > 0) {
 590     //trace_class_path("found Class-Path: ", cp_attr); FIXME
 591 
 592     char sep = os::file_separator()[0];
 593     const char* dir_name = cs->path();
 594     const char* dir_tail = strrchr(dir_name, sep);
 595 #ifdef _WINDOWS
 596     // On Windows, we also support forward slash as the file separator when locating entries in the classpath entry.
 597     const char* dir_tail2 = strrchr(dir_name, '/');
 598     if (dir_tail == nullptr) {
 599       dir_tail = dir_tail2;
 600     } else if (dir_tail2 != nullptr && dir_tail2 > dir_tail) {
 601       dir_tail = dir_tail2;
 602     }
 603 #endif
 604     int dir_len;
 605     if (dir_tail == nullptr) {
 606       dir_len = 0;
 607     } else {
 608       dir_len = pointer_delta_as_int(dir_tail, dir_name) + 1;
 609     }
 610 
 611     // Split the cp_attr by spaces, and add each file
 612     char* file_start = cp_attr;
 613     char* end = file_start + strlen(file_start);
 614 
 615     while (file_start < end) {
 616       char* file_end = strchr(file_start, ' ');
 617       if (file_end != nullptr) {
 618         *file_end = 0;
 619         file_end += 1;
 620       } else {
 621         file_end = end;
 622       }
 623 
 624       size_t name_len = strlen(file_start);
 625       if (name_len > 0) {
 626         ResourceMark rm(current);
 627         size_t libname_len = dir_len + name_len;
 628         char* libname = NEW_RESOURCE_ARRAY(char, libname_len + 1);
 629         int n = os::snprintf(libname, libname_len + 1, "%.*s%s", dir_len, dir_name, file_start);
 630         assert((size_t)n == libname_len, "Unexpected number of characters in string");
 631 
 632         // Avoid infinite recursion when two JAR files refer to each
 633         // other via cpattr.
 634         bool found_duplicate = false;
 635         for (int i = boot_cp_start_index(); i < tmp_array.length(); i++) {
 636           if (strcmp(tmp_array.at(i)->path(), libname) == 0) {
 637             found_duplicate = true;
 638             break;
 639           }
 640         }
 641         if (!found_duplicate) {
 642           add_class_location(current, tmp_array, libname, group, parse_manifest, /*from_cpattr*/true);
 643         }
 644       }
 645 
 646       file_start = file_end;
 647     }
 648   }
 649 }
 650 
 651 AOTClassLocation const* AOTClassLocationConfig::class_location_at(int index) const {
 652   return _class_locations->at(index);
 653 }
 654 
 655 int AOTClassLocationConfig::get_module_shared_path_index(Symbol* location) const {
 656   if (location == nullptr) {
 657     return 0; // Used by java/lang/reflect/Proxy$ProxyBuilder
 658   }
 659 
 660   if (location->starts_with("jrt:", 4)) {
 661     assert(class_location_at(0)->is_modules_image(), "sanity");
 662     return 0;
 663   }
 664 
 665   if (num_module_paths() == 0) {
 666     // The archive(s) were created without --module-path option
 667     return -1;
 668   }
 669 
 670   if (!location->starts_with("file:", 5)) {
 671     return -1;
 672   }
 673 
 674   // skip_uri_protocol was also called during dump time -- see ClassLoaderExt::process_module_table()
 675   ResourceMark rm;
 676   const char* file = ClassLoader::uri_to_path(location->as_C_string());
 677   for (int i = module_path_start_index(); i < module_path_end_index(); i++) {
 678     const AOTClassLocation* cs = class_location_at(i);
 679     assert(!cs->has_unnamed_module(), "must be");
 680     bool same = os::same_files(file, cs->path());
 681     log_debug(class, path)("get_module_shared_path_index (%d) %s : %s = %s", i,
 682                            location->as_C_string(), cs->path(), same ? "same" : "different");
 683     if (same) {
 684       return i;
 685     }
 686   }
 687   return -1;
 688 }
 689 
 690 // We allow non-empty dirs as long as no classes have been loaded from them.
 691 void AOTClassLocationConfig::check_nonempty_dirs() const {
 692   assert(CDSConfig::is_dumping_archive(), "sanity");
 693 
 694   bool has_nonempty_dir = false;
 695   dumptime_iterate([&](AOTClassLocation* cs) {
 696     if (cs->index() > _max_used_index) {
 697       return false; // stop iterating
 698     }
 699     if (cs->is_dir()) {
 700       if (!os::dir_is_empty(cs->path())) {
 701         aot_log_error(aot)("Error: non-empty directory '%s'", cs->path());
 702         has_nonempty_dir = true;
 703       }
 704     }
 705     return true; // keep iterating
 706   });
 707 
 708   if (has_nonempty_dir) {
 709     vm_exit_during_cds_dumping("Cannot have non-empty directory in paths", nullptr);
 710   }
 711 }
 712 
 713 // It's possible to use reflection+setAccessible to call into ClassLoader::defineClass() to
 714 // pretend that a dynamically generated class comes from a JAR file in the classpath.
 715 // Detect such classes so that they can be excluded from the archive.
 716 bool AOTClassLocationConfig::is_valid_classpath_index(int classpath_index, InstanceKlass* ik) {
 717   if (1 <= classpath_index && classpath_index < length()) {
 718     ClassPathZipEntry *zip = _dumptime_jar_files->at(classpath_index);
 719     if (zip != nullptr) {
 720       JavaThread* current = JavaThread::current();
 721       ResourceMark rm(current);
 722       const char* const class_name = ik->name()->as_C_string();
 723       const char* const file_name = ClassLoader::file_name_for_class_name(class_name,
 724                                                                           ik->name()->utf8_length());
 725       if (!zip->has_entry(current, file_name)) {
 726         aot_log_warning(aot)("class %s cannot be archived because it was not defined from %s as claimed",
 727                          class_name, zip->name());
 728         return false;
 729       }
 730     }
 731   }
 732 
 733   return true;
 734 }
 735 
 736 AOTClassLocationConfig* AOTClassLocationConfig::write_to_archive() const {
 737   log_locations(CDSConfig::output_archive_path(), /*is_write=*/true);
 738 
 739   Array<AOTClassLocation*>* archived_copy = ArchiveBuilder::new_ro_array<AOTClassLocation*>(_class_locations->length());
 740   for (int i = 0; i < _class_locations->length(); i++) {
 741     archived_copy->at_put(i, _class_locations->at(i)->write_to_archive());
 742     ArchivePtrMarker::mark_pointer((address*)archived_copy->adr_at(i));
 743   }
 744 
 745   AOTClassLocationConfig* dumped = (AOTClassLocationConfig*)ArchiveBuilder::ro_region_alloc(sizeof(AOTClassLocationConfig));
 746   memcpy(dumped, this, sizeof(AOTClassLocationConfig));
 747   dumped->_class_locations = archived_copy;
 748   ArchivePtrMarker::mark_pointer(&dumped->_class_locations);
 749 
 750   return dumped;
 751 }
 752 
 753 bool AOTClassLocationConfig::check_classpaths(bool is_boot_classpath, bool has_aot_linked_classes,
 754                                               int index_start, int index_end,
 755                                               ClassLocationStream& runtime_css,
 756                                               bool use_lcp_match, const char* runtime_lcp,
 757                                               size_t runtime_lcp_len) const {
 758   if (index_start >= index_end && runtime_css.is_empty()) { // nothing to check
 759     return true;
 760   }
 761 
 762   ResourceMark rm;
 763   const char* which = is_boot_classpath ? "boot" : "app";
 764   LogTarget(Info, class, path) lt;
 765   if (lt.is_enabled()) {
 766     LogStream ls(lt);
 767     ls.print("Checking %s classpath", which);
 768     ls.print_cr("%s", use_lcp_match ? " (with longest common prefix substitution)" : "");
 769     ls.print("- expected : '");
 770     print_dumptime_classpath(ls, index_start, index_end, use_lcp_match, _dumptime_lcp_len, runtime_lcp, runtime_lcp_len);
 771     ls.print_cr("'");
 772     ls.print("- actual   : '");
 773     runtime_css.print(&ls);
 774     ls.print_cr("'");
 775   }
 776 
 777   runtime_css.start();
 778   for (int i = index_start; i < index_end; i++) {
 779     ResourceMark rm;
 780     const AOTClassLocation* cs = class_location_at(i);
 781     const char* effective_dumptime_path = cs->path();
 782     if (use_lcp_match && _dumptime_lcp_len > 0) {
 783       effective_dumptime_path = substitute(effective_dumptime_path, _dumptime_lcp_len, runtime_lcp, runtime_lcp_len);
 784     }
 785 
 786     log_info(class, path)("Checking [%d] '%s' %s%s", i, effective_dumptime_path, cs->file_type_string(),
 787                           cs->from_cpattr() ? " (from JAR manifest ClassPath attribute)" : "");
 788     if (!cs->from_cpattr() && file_exists(effective_dumptime_path)) {
 789       if (!runtime_css.has_next()) {
 790         aot_log_warning(aot)("%s classpath has fewer elements than expected", which);
 791         return false;
 792       }
 793       const char* runtime_path = runtime_css.get_next();
 794       while (!file_exists(runtime_path) && runtime_css.has_next()) {
 795         runtime_path = runtime_css.get_next();
 796       }
 797       if (!os::same_files(effective_dumptime_path, runtime_path)) {
 798         aot_log_warning(aot)("The name of %s classpath [%d] does not match: expected '%s', got '%s'",
 799                          which, runtime_css.current(), effective_dumptime_path, runtime_path);
 800         return false;
 801       }
 802     }
 803 
 804     if (!cs->check(effective_dumptime_path, has_aot_linked_classes)) {
 805       return false;
 806     }
 807   }
 808 
 809   // Check if the runtime boot classpath has more entries than the one stored in the archive and if the app classpath
 810   // or the module path requires validation.
 811   if (is_boot_classpath && runtime_css.has_next() && (need_to_check_app_classpath() || num_module_paths() > 0)) {
 812     // the check passes if all the extra runtime boot classpath entries are non-existent
 813     if (check_paths_existence(runtime_css)) {
 814       aot_log_warning(aot)("boot classpath is longer than expected");
 815       return false;
 816     }
 817   }
 818 
 819   return true;
 820 }
 821 
 822 bool AOTClassLocationConfig::file_exists(const char* filename) const{
 823   struct stat st;
 824   return (os::stat(filename, &st) == 0 && st.st_size > 0);
 825 }
 826 
 827 bool AOTClassLocationConfig::check_paths_existence(ClassLocationStream& runtime_css) const {
 828   bool exist = false;
 829   while (runtime_css.has_next()) {
 830     const char* path = runtime_css.get_next();
 831     if (file_exists(path)) {
 832       exist = true;
 833       break;
 834     }
 835   }
 836   return exist;
 837 }
 838 
 839 bool AOTClassLocationConfig::check_module_paths(bool has_aot_linked_classes, int index_start, int index_end,
 840                                                 ClassLocationStream& runtime_css,
 841                                                 bool* has_extra_module_paths) const {
 842   if (index_start >= index_end && runtime_css.is_empty()) { // nothing to check
 843     return true;
 844   }
 845 
 846   ResourceMark rm;
 847 
 848   LogTarget(Info, class, path) lt;
 849   if (lt.is_enabled()) {
 850     LogStream ls(lt);
 851     ls.print_cr("Checking module paths");
 852     ls.print("- expected : '");
 853     print_dumptime_classpath(ls, index_start, index_end, false, 0, nullptr, 0);
 854     ls.print_cr("'");
 855     ls.print("- actual   : '");
 856     runtime_css.print(&ls);
 857     ls.print_cr("'");
 858   }
 859 
 860   // Make sure all the dumptime module paths exist and are unchanged
 861   for (int i = index_start; i < index_end; i++) {
 862     const AOTClassLocation* cs = class_location_at(i);
 863     const char* dumptime_path = cs->path();
 864 
 865     assert(!cs->from_cpattr(), "not applicable for module path");
 866     log_info(class, path)("Checking '%s' %s", dumptime_path, cs->file_type_string());
 867 
 868     if (!cs->check(dumptime_path, has_aot_linked_classes)) {
 869       return false;
 870     }
 871   }
 872 
 873   // We allow runtime_css to be a superset of the module paths specified in dumptime. E.g.,
 874   // Dumptime:    A:C
 875   // Runtime:     A:B:C
 876   runtime_css.start();
 877   for (int i = index_start; i < index_end; i++) {
 878     const AOTClassLocation* cs = class_location_at(i);
 879     const char* dumptime_path = cs->path();
 880 
 881     while (true) {
 882       if (!runtime_css.has_next()) {
 883         aot_log_warning(aot)("module path has fewer elements than expected");
 884         *has_extra_module_paths = true;
 885         return true;
 886       }
 887       // Both this->class_locations() and runtime_css are alphabetically sorted. Skip
 888       // items in runtime_css until we see dumptime_path.
 889       const char* runtime_path = runtime_css.get_next();
 890       if (!os::same_files(dumptime_path, runtime_path)) {
 891         *has_extra_module_paths = true;
 892         return true;
 893       } else {
 894         break;
 895       }
 896     }
 897   }
 898 
 899   if (runtime_css.has_next()) {
 900     *has_extra_module_paths = true;
 901   }
 902 
 903   return true;
 904 }
 905 
 906 void AOTClassLocationConfig::print_dumptime_classpath(LogStream& ls, int index_start, int index_end,
 907                                                       bool do_substitute, size_t remove_prefix_len,
 908                                                       const char* prepend, size_t prepend_len) const {
 909   const char* sep = "";
 910   for (int i = index_start; i < index_end; i++) {
 911     ResourceMark rm;
 912     const AOTClassLocation* cs = class_location_at(i);
 913     const char* path = cs->path();
 914     if (!cs->from_cpattr()) {
 915       ls.print("%s", sep);
 916       if (do_substitute) {
 917         path = substitute(path, remove_prefix_len, prepend, prepend_len);
 918       }
 919       ls.print("%s", path);
 920       sep = os::path_separator();
 921     }
 922   }
 923 }
 924 
 925 // Returned path is resource-allocated
 926 const char* AOTClassLocationConfig::substitute(const char* path,         // start with this path (which was recorded from dump time)
 927                                                size_t remove_prefix_len, // remove this number of chars from the beginning
 928                                                const char* prepend,      // prepend this string
 929                                                size_t prepend_len) {     // length of the prepended string
 930   size_t len = strlen(path);
 931   assert(len > remove_prefix_len, "sanity");
 932   assert(prepend_len == strlen(prepend), "sanity");
 933   len -= remove_prefix_len;
 934   len += prepend_len;
 935 
 936   char* buf = NEW_RESOURCE_ARRAY(char, len + 1);
 937   int n = os::snprintf(buf, len + 1, "%s%s", prepend, path + remove_prefix_len);
 938   assert(size_t(n) == len, "sanity");
 939 
 940   return buf;
 941 }
 942 
 943 // For performance, we avoid using LCP match if there's at least one
 944 // AOTClassLocation can be matched exactly: this means all other AOTClassLocations must be
 945 // matched exactly.
 946 bool AOTClassLocationConfig::need_lcp_match(AllClassLocationStreams& all_css) const {
 947   if (app_cp_end_index() == boot_cp_start_index()) {
 948     // No need to use lcp-match when there are no boot/app paths.
 949     // TODO: LCP-match not yet supported for modules.
 950     return false;
 951   }
 952 
 953   if (need_lcp_match_helper(boot_cp_start_index(), boot_cp_end_index(), all_css.boot_cp()) &&
 954       need_lcp_match_helper(app_cp_start_index(), app_cp_end_index(), all_css.app_cp())) {
 955     return true;
 956   } else {
 957     return false;
 958   }
 959 }
 960 
 961 bool AOTClassLocationConfig::need_lcp_match_helper(int start, int end, ClassLocationStream& css) const {
 962   int i = start;
 963   for (css.start(); i < end && css.has_next(); ) {
 964     const AOTClassLocation* cs = class_location_at(i++);
 965     const char* runtime_path = css.get_next();
 966     if (cs->must_exist() && os::same_files(cs->path(), runtime_path)) {
 967       // Most likely, we will come to here at the first iteration.
 968       return false;
 969     }
 970   }
 971   return true;
 972 }
 973 
 974 bool AOTClassLocationConfig::validate(const char* cache_filename, bool has_aot_linked_classes, bool* has_extra_module_paths) const {
 975   ResourceMark rm;
 976   AllClassLocationStreams all_css;
 977 
 978   log_locations(cache_filename, /*is_write=*/false);
 979 
 980   const char* jrt = ClassLoader::get_jrt_entry()->name();
 981   log_info(class, path)("Checking [0] (modules image)");
 982   bool success = class_location_at(0)->check(jrt, has_aot_linked_classes);
 983   log_info(class, path)("Modules image %s validation: %s", jrt, success ? "passed" : "failed");
 984   if (!success) {
 985     return false;
 986   }
 987   if (class_locations()->length() == 1) {
 988     if ((module_path_start_index() >= module_path_end_index()) && Arguments::get_property("jdk.module.path") != nullptr) {
 989       *has_extra_module_paths = true;
 990     } else {
 991       *has_extra_module_paths = false;
 992     }
 993   } else {
 994     bool use_lcp_match = need_lcp_match(all_css);
 995     const char* runtime_lcp;
 996     size_t runtime_lcp_len;
 997 
 998     log_info(class, path)("Longest common prefix substitution in boot/app classpath matching: %s",
 999                           use_lcp_match ? "yes" : "no");
1000     if (use_lcp_match) {
1001       runtime_lcp = find_lcp(all_css.boot_and_app_cp(), runtime_lcp_len);
1002       log_info(class, path)("Longest common prefix: %s (%zu chars)", runtime_lcp, runtime_lcp_len);
1003     } else {
1004       runtime_lcp = nullptr;
1005       runtime_lcp_len = 0;
1006     }
1007 
1008     success = check_classpaths(true, has_aot_linked_classes, boot_cp_start_index(), boot_cp_end_index(), all_css.boot_cp(),
1009                                use_lcp_match, runtime_lcp, runtime_lcp_len);
1010     log_info(class, path)("Archived boot classpath validation: %s", success ? "passed" : "failed");
1011 
1012     if (success && need_to_check_app_classpath()) {
1013       success = check_classpaths(false, has_aot_linked_classes, app_cp_start_index(), app_cp_end_index(), all_css.app_cp(),
1014                                  use_lcp_match, runtime_lcp, runtime_lcp_len);
1015       log_info(class, path)("Archived app classpath validation: %s", success ? "passed" : "failed");
1016     }
1017 
1018     if (success) {
1019       success = check_module_paths(has_aot_linked_classes, module_path_start_index(), module_path_end_index(),
1020                                    all_css.module_path(), has_extra_module_paths);
1021       log_info(class, path)("Archived module path validation: %s%s", success ? "passed" : "failed",
1022                             (*has_extra_module_paths) ? " (extra module paths found)" : "");
1023     }
1024 
1025     if (runtime_lcp_len > 0) {
1026       os::free((void*)runtime_lcp);
1027     }
1028   }
1029 
1030   if (success) {
1031     _runtime_instance = this;
1032   } else {
1033     const char* mismatch_msg = "shared class paths mismatch";
1034     const char* hint_msg = log_is_enabled(Info, class, path) ?
1035         "" : " (hint: enable -Xlog:class+path=info to diagnose the failure)";
1036     if (RequireSharedSpaces && !PrintSharedArchiveAndExit) {
1037       if (CDSConfig::is_dumping_final_static_archive()) {
1038         aot_log_error(aot)("class path and/or module path are not compatible with the "
1039                        "ones specified when the AOTConfiguration file was recorded%s", hint_msg);
1040         vm_exit_during_initialization("Unable to use create AOT cache.", nullptr);
1041       } else {
1042         aot_log_error(aot)("%s%s", mismatch_msg, hint_msg);
1043         AOTMetaspace::unrecoverable_loading_error();
1044       }
1045     } else {
1046       AOTMetaspace::report_loading_error("%s%s", mismatch_msg, hint_msg);
1047     }
1048   }
1049   return success;
1050 }
1051 
1052 void AOTClassLocationConfig::log_locations(const char* cache_filename, bool is_write) const {
1053   if (log_is_enabled(Info, class, path)) {
1054     LogStreamHandle(Info, class, path) st;
1055     st.print_cr("%s classpath(s) %s %s (size = %d)",
1056                 is_write ? "Writing" : "Reading",
1057                 is_write ? "into" : "from",
1058                 cache_filename, class_locations()->length());
1059     print_on(&st);
1060   }
1061 }
1062 
1063 void AOTClassLocationConfig::print() {
1064   if (CDSConfig::is_dumping_archive()) {
1065     tty->print_cr("AOTClassLocationConfig::_dumptime_instance = %p", _dumptime_instance);
1066     if (_dumptime_instance != nullptr) {
1067       _dumptime_instance->print_on(tty);
1068     }
1069   }
1070   if (CDSConfig::is_using_archive()) {
1071     tty->print_cr("AOTClassLocationConfig::_runtime_instance = %p", _runtime_instance);
1072     if (_runtime_instance != nullptr) {
1073       _runtime_instance->print_on(tty);
1074     }
1075   }
1076 }
1077 
1078 void AOTClassLocationConfig::print_on(outputStream* st) const {
1079   const char* type = "boot";
1080   int n = class_locations()->length();
1081   for (int i = 0; i < n; i++) {
1082     if (i >= boot_cp_end_index()) {
1083       type = "app";
1084     }
1085     if (i >= app_cp_end_index()) {
1086       type = "module";
1087     }
1088     const AOTClassLocation* cs = class_location_at(i);
1089     const char* path;
1090     if (i == 0) {
1091       path = ClassLoader::get_jrt_entry()->name();
1092     } else {
1093       path = cs->path();
1094     }
1095     st->print_cr("(%-6s) [%d] = %s", type, i, path);
1096   }
1097 }