< prev index next >

src/hotspot/share/classfile/sharedPathsMiscInfo.cpp

Print this page

        

@@ -26,10 +26,11 @@
 #include "classfile/classLoader.hpp"
 #include "classfile/sharedPathsMiscInfo.hpp"
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
+#include "memory/filemap.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/os.inline.hpp"
 #include "utilities/ostream.hpp"

@@ -139,15 +140,80 @@
 
   return true;
 }
 
 bool SharedPathsMiscInfo::check(jint type, const char* path) {
+  assert(UseSharedSpaces, "runtime only");
   switch (type) {
   case BOOT_PATH:
-    // In the future we should perform the check based on the content of the mapped archive.
-    if (os::file_name_strcmp(path, Arguments::get_sysclasspath()) != 0) {
-      return fail("[BOOT classpath mismatch, actual =", Arguments::get_sysclasspath());
+    {
+      //
+      // - Archive contains boot classes only - relaxed boot path check:
+      //   Extra path elements appended to the boot path at runtime are allowed.
+      //
+      // - Archive contains application or platform classes - strict boot path check:
+      //   Validate the entire runtime boot path, which must be compactible
+      //   with the dump time boot path. Appending boot path at runtime is not
+      //   allowed.
+      //
+
+      bool relaxed_check = !FileMapInfo::current_info()->header()->has_platform_or_app_classes();
+      char* runtime_boot_path;
+      ResourceMark rm;
+      if (relaxed_check) {
+        // only check the begining portion of the runtime boot path, up to
+        // the length of the dump time boot path
+        size_t len = strlen(path);
+        runtime_boot_path = NEW_RESOURCE_ARRAY(char, len + 1);
+        strncpy(runtime_boot_path, Arguments::get_sysclasspath(), len);
+        runtime_boot_path[len] = '\0';
+      } else {
+        // check the full runtime boot path
+        runtime_boot_path = Arguments::get_sysclasspath();
+      }
+
+      // Do a quick check first with a simple
+      // strcmp(dump_time_boot_path, runtime_boot_path). If the paths are the
+      // same, the check has succeeded.
+      if (os::file_name_strcmp(path, runtime_boot_path) == 0) {
+        break; // ok
+      }
+
+      // The paths are different.
+      //
+      // - The first entry in boot path is the modules_image (guaranteed by
+      //   ClassLoader::setup_boot_search_path()). Skip the first entry. The
+      //   path of the runtime modules_image may be different from the dump
+      //   time path (e.g. the JDK image is copied to a different location
+      //   after generating the shared archive), which is acceptable. For most
+      //   common cases, the dump time boot path might contain modules_image only.
+      // - The rest of the 'runtime_boot_path' and 'dump_time_boot_path' strings
+      //   must be the same.
+      size_t path_sep_len = strlen(os::path_separator());
+      char* rp = strstr(runtime_boot_path, os::path_separator());
+      if (rp != NULL) {
+        rp += path_sep_len;
+      }
+
+      char* dp = strstr((char*)path, os::path_separator());
+      if (dp != NULL) {
+        dp += path_sep_len;
+      }
+
+      if (dp == NULL && rp == NULL) {
+        break;   // ok, both runtime and dump time boot paths have modules_images only
+      } else if (dp == NULL && rp != NULL && relaxed_check) {
+        break;   // ok, relaxed check, runtime has extra boot append path entries
+      } else if (dp != NULL && rp != NULL) {
+        if (os::file_name_strcmp(dp, rp) == 0) {
+          break; // ok, runtime and dump time paths match
+        }
+      }
+
+      // The paths are different
+      return fail("[BOOT classpath mismatch, actual =",
+                  Arguments::get_sysclasspath());
     }
     break;
   case NON_EXIST:
     {
       struct stat st;
< prev index next >