--- old/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp 2018-05-16 22:33:44.899208329 -0400 +++ new/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp 2018-05-16 22:33:43.175108468 -0400 @@ -28,6 +28,7 @@ #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" @@ -140,12 +141,66 @@ return true; } +char* skip_first_path_entry(const char* path) { + size_t path_sep_len = strlen(os::path_separator()); + char* p = strstr((char*)path, os::path_separator()); + if (p != NULL) { + p += path_sep_len; + } + return p; +} + 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. + // + + // 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. + char* runtime_boot_path = Arguments::get_sysclasspath(); + char* rp = skip_first_path_entry(runtime_boot_path); + char* dp = skip_first_path_entry(path); + + bool relaxed_check = !FileMapInfo::current_info()->header()->has_platform_or_app_classes(); + 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) { + ResourceMark rm; + char* checked_rp; + if (relaxed_check) { + // only check the leading entries in the runtime boot path, up to + // the length of the dump time boot path + size_t len = strlen(dp); + checked_rp = NEW_RESOURCE_ARRAY(char, len + 1); + strncpy(checked_rp, rp, len); + checked_rp[len] = '\0'; + } else { + checked_rp = rp; + } + + if (os::file_name_strcmp(dp, checked_rp) == 0) { + break; // ok, runtime and dump time paths match + } + } + + // The paths are different + return fail("[BOOT classpath mismatch, actual =", runtime_boot_path); } break; case NON_EXIST: