src/hotspot/share/memory/filemap.cpp
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54927 1512d88b24c6
child 58679 9c3209ff7550
--- a/src/hotspot/share/memory/filemap.cpp	Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/memory/filemap.cpp	Thu Oct 17 20:53:35 2019 +0100
@@ -55,6 +55,7 @@
 #include "runtime/vm_version.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/align.hpp"
+#include "utilities/classpathStream.hpp"
 #include "utilities/defaultStream.hpp"
 #if INCLUDE_G1GC
 #include "gc/g1/g1CollectedHeap.hpp"
@@ -75,7 +76,7 @@
 // an archive file should stop the process.  Unrecoverable errors during
 // the reading of the archive file should stop the process.
 
-static void fail(const char *msg, va_list ap) {
+static void fail_exit(const char *msg, va_list ap) {
   // This occurs very early during initialization: tty is not initialized.
   jio_fprintf(defaultStream::error_stream(),
               "An error has occurred while processing the"
@@ -90,7 +91,7 @@
 void FileMapInfo::fail_stop(const char *msg, ...) {
         va_list ap;
   va_start(ap, msg);
-  fail(msg, ap);        // Never returns.
+  fail_exit(msg, ap);   // Never returns.
   va_end(ap);           // for completeness.
 }
 
@@ -118,7 +119,7 @@
     tty->print_cr("]");
   } else {
     if (RequireSharedSpaces) {
-      fail(msg, ap);
+      fail_exit(msg, ap);
     } else {
       if (log_is_enabled(Info, cds)) {
         ResourceMark rm;
@@ -155,6 +156,8 @@
   const char *vm_version = VM_Version::internal_vm_info_string();
   const int version_len = (int)strlen(vm_version);
 
+  memset(header_version, 0, JVM_IDENT_MAX);
+
   if (version_len < (JVM_IDENT_MAX-1)) {
     strcpy(header_version, vm_version);
 
@@ -170,6 +173,8 @@
     sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash);
     header_version[JVM_IDENT_MAX-1] = 0;  // Null terminate.
   }
+
+  assert(header_version[JVM_IDENT_MAX-1] == 0, "must be");
 }
 
 FileMapInfo::FileMapInfo(bool is_static) {
@@ -187,9 +192,9 @@
   }
   _header = (FileMapHeader*)os::malloc(header_size, mtInternal);
   memset((void*)_header, 0, header_size);
-  _header->_header_size = header_size;
-  _header->_version = INVALID_CDS_ARCHIVE_VERSION;
-  _header->_has_platform_or_app_classes = true;
+  _header->set_header_size(header_size);
+  _header->set_version(INVALID_CDS_ARCHIVE_VERSION);
+  _header->set_has_platform_or_app_classes(true);
   _file_offset = 0;
   _file_open = false;
 }
@@ -205,7 +210,7 @@
 }
 
 void FileMapInfo::populate_header(size_t alignment) {
-  _header->populate(this, alignment);
+  header()->populate(this, alignment);
 }
 
 void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
@@ -226,7 +231,7 @@
   _narrow_klass_shift = CompressedKlassPointers::shift();
   _shared_path_table = mapinfo->_shared_path_table;
   if (HeapShared::is_heap_object_archiving_allowed()) {
-    _heap_reserved = Universe::heap()->reserved_region();
+    _heap_end = CompressedOops::end();
   }
 
   // The following fields are for sanity checks for whether this archive
@@ -236,7 +241,6 @@
   // JVM version string ... changes on each build.
   get_header_version(_jvm_ident);
 
-  ClassLoaderExt::finalize_shared_paths_misc_info();
   _app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index();
   _app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index();
   _num_module_paths = ClassLoader::num_module_path_entries();
@@ -252,13 +256,20 @@
   _base_archive_is_default = false;
 }
 
-void SharedClassPathEntry::init(const char* name, bool is_modules_image, TRAPS) {
-  assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
+void SharedClassPathEntry::init_as_non_existent(const char* path, TRAPS) {
+  _type = non_existent_entry;
+  set_name(path, THREAD);
+}
+
+void SharedClassPathEntry::init(bool is_modules_image,
+                                ClassPathEntry* cpe, TRAPS) {
+  Arguments::assert_is_dumping_archive();
   _timestamp = 0;
   _filesize  = 0;
+  _from_class_path_attr = false;
 
   struct stat st;
-  if (os::stat(name, &st) == 0) {
+  if (os::stat(cpe->name(), &st) == 0) {
     if ((st.st_mode & S_IFMT) == S_IFDIR) {
       _type = dir_entry;
     } else {
@@ -268,6 +279,7 @@
       } else {
         _type = jar_entry;
         _timestamp = st.st_mtime;
+        _from_class_path_attr = cpe->from_class_path_attr();
       }
       _filesize = st.st_size;
     }
@@ -277,29 +289,38 @@
     //
     // If we can't access a jar file in the boot path, then we can't
     // make assumptions about where classes get loaded from.
-    FileMapInfo::fail_stop("Unable to open file %s.", name);
+    FileMapInfo::fail_stop("Unable to open file %s.", cpe->name());
   }
 
+  // No need to save the name of the module file, as it will be computed at run time
+  // to allow relocation of the JDK directory.
+  const char* name = is_modules_image  ? "" : cpe->name();
+  set_name(name, THREAD);
+}
+
+void SharedClassPathEntry::set_name(const char* name, TRAPS) {
   size_t len = strlen(name) + 1;
   _name = MetadataFactory::new_array<char>(ClassLoaderData::the_null_class_loader_data(), (int)len, THREAD);
   strcpy(_name->data(), name);
 }
 
-bool SharedClassPathEntry::validate(bool is_class_path) {
+const char* SharedClassPathEntry::name() const {
+  if (UseSharedSpaces && is_modules_image()) {
+    // In order to validate the runtime modules image file size against the archived
+    // size information, we need to obtain the runtime modules image path. The recorded
+    // dump time modules image path in the archive may be different from the runtime path
+    // if the JDK image has beed moved after generating the archive.
+    return ClassLoader::get_jrt_entry()->name();
+  } else {
+    return _name->data();
+  }
+}
+
+bool SharedClassPathEntry::validate(bool is_class_path) const {
   assert(UseSharedSpaces, "runtime only");
 
   struct stat st;
-  const char* name;
-
-  // In order to validate the runtime modules image file size against the archived
-  // size information, we need to obtain the runtime modules image path. The recorded
-  // dump time modules image path in the archive may be different from the runtime path
-  // if the JDK image has beed moved after generating the archive.
-  if (is_modules_image()) {
-    name = ClassLoader::get_jrt_entry()->name();
-  } else {
-    name = this->name();
-  }
+  const char* name = this->name();
 
   bool ok = true;
   log_info(class, path)("checking shared classpath entry: %s", name);
@@ -337,6 +358,19 @@
   return ok;
 }
 
+bool SharedClassPathEntry::check_non_existent() const {
+  assert(_type == non_existent_entry, "must be");
+  log_info(class, path)("should be non-existent: %s", name());
+  struct stat st;
+  if (os::stat(name(), &st) != 0) {
+    log_info(class, path)("ok");
+    return true; // file doesn't exist
+  } else {
+    return false;
+  }
+}
+
+
 void SharedClassPathEntry::metaspace_pointers_do(MetaspaceClosure* it) {
   it->push(&_name);
   it->push(&_manifest);
@@ -351,10 +385,11 @@
 
 void SharedPathTable::dumptime_init(ClassLoaderData* loader_data, Thread* THREAD) {
   size_t entry_size = sizeof(SharedClassPathEntry);
-  int num_boot_classpath_entries = ClassLoader::num_boot_classpath_entries();
-  int num_app_classpath_entries = ClassLoader::num_app_classpath_entries();
-  int num_module_path_entries = ClassLoader::num_module_path_entries();
-  int num_entries = num_boot_classpath_entries + num_app_classpath_entries + num_module_path_entries;
+  int num_entries = 0;
+  num_entries += ClassLoader::num_boot_classpath_entries();
+  num_entries += ClassLoader::num_app_classpath_entries();
+  num_entries += ClassLoader::num_module_path_entries();
+  num_entries += FileMapInfo::num_non_existent_class_paths();
   size_t bytes = entry_size * num_entries;
 
   _table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD);
@@ -362,9 +397,9 @@
 }
 
 void FileMapInfo::allocate_shared_path_table() {
-  assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "Sanity");
+  Arguments::assert_is_dumping_archive();
 
-  Thread* THREAD = Thread::current();
+  EXCEPTION_MARK; // The following calls should never throw, but would exit VM on error.
   ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
   ClassPathEntry* jrt = ClassLoader::get_jrt_entry();
 
@@ -375,51 +410,41 @@
 
   // 1. boot class path
   int i = 0;
-  ClassPathEntry* cpe = jrt;
+  i = add_shared_classpaths(i, "boot",   jrt, THREAD);
+  i = add_shared_classpaths(i, "app",    ClassLoader::app_classpath_entries(), THREAD);
+  i = add_shared_classpaths(i, "module", ClassLoader::module_path_entries(), THREAD);
+
+  for (int x = 0; x < num_non_existent_class_paths(); x++, i++) {
+    const char* path = _non_existent_class_paths->at(x);
+    shared_path(i)->init_as_non_existent(path, THREAD);
+  }
+
+  assert(i == _shared_path_table.size(), "number of shared path entry mismatch");
+}
+
+int FileMapInfo::add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS) {
   while (cpe != NULL) {
-    bool is_jrt = (cpe == jrt);
+    bool is_jrt = (cpe == ClassLoader::get_jrt_entry());
     const char* type = (is_jrt ? "jrt" : (cpe->is_jar_file() ? "jar" : "dir"));
-    log_info(class, path)("add main shared path (%s) %s", type, cpe->name());
+    log_info(class, path)("add %s shared path (%s) %s", which, type, cpe->name());
     SharedClassPathEntry* ent = shared_path(i);
-    ent->init(cpe->name(), is_jrt, THREAD);
-    if (!is_jrt) {    // No need to do the modules image.
-      EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
-      update_shared_classpath(cpe, ent, THREAD);
+    ent->init(is_jrt, cpe, THREAD);
+    if (cpe->is_jar_file()) {
+      update_jar_manifest(cpe, ent, THREAD);
     }
-    cpe = ClassLoader::get_next_boot_classpath_entry(cpe);
-    i++;
-  }
-  assert(i == ClassLoader::num_boot_classpath_entries(),
-         "number of boot class path entry mismatch");
-
-  // 2. app class path
-  ClassPathEntry *acpe = ClassLoader::app_classpath_entries();
-  while (acpe != NULL) {
-    log_info(class, path)("add app shared path %s", acpe->name());
-    SharedClassPathEntry* ent = shared_path(i);
-    ent->init(acpe->name(), false, THREAD);
-    EXCEPTION_MARK;
-    update_shared_classpath(acpe, ent, THREAD);
-    acpe = acpe->next();
+    if (is_jrt) {
+      cpe = ClassLoader::get_next_boot_classpath_entry(cpe);
+    } else {
+      cpe = cpe->next();
+    }
     i++;
   }
 
-  // 3. module path
-  ClassPathEntry *mpe = ClassLoader::module_path_entries();
-  while (mpe != NULL) {
-    log_info(class, path)("add module path %s",mpe->name());
-    SharedClassPathEntry* ent = shared_path(i);
-    ent->init(mpe->name(), false, THREAD);
-    EXCEPTION_MARK;
-    update_shared_classpath(mpe, ent, THREAD);
-    mpe = mpe->next();
-    i++;
-  }
-  assert(i == _shared_path_table.size(), "number of shared path entry mismatch");
+  return i;
 }
 
 void FileMapInfo::check_nonempty_dir_in_shared_path_table() {
-  assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
+  Arguments::assert_is_dumping_archive();
 
   bool has_nonempty_dir = false;
 
@@ -434,7 +459,7 @@
     if (e->is_dir()) {
       const char* path = e->name();
       if (!os::dir_is_empty(path)) {
-        tty->print_cr("Error: non-empty directory '%s'", path);
+        log_error(cds)("Error: non-empty directory '%s'", path);
         has_nonempty_dir = true;
       }
     }
@@ -445,6 +470,24 @@
   }
 }
 
+void FileMapInfo::record_non_existent_class_path_entry(const char* path) {
+  Arguments::assert_is_dumping_archive();
+  log_info(class, path)("non-existent Class-Path entry %s", path);
+  if (_non_existent_class_paths == NULL) {
+    _non_existent_class_paths = new (ResourceObj::C_HEAP, mtInternal)GrowableArray<const char*>(10, true);
+  }
+  _non_existent_class_paths->append(os::strdup(path));
+}
+
+int FileMapInfo::num_non_existent_class_paths() {
+  Arguments::assert_is_dumping_archive();
+  if (_non_existent_class_paths != NULL) {
+    return _non_existent_class_paths->length();
+  } else {
+    return 0;
+  }
+}
+
 class ManifestStream: public ResourceObj {
   private:
   u1*   _buffer_start; // Buffer bottom
@@ -493,33 +536,215 @@
   }
 };
 
-void FileMapInfo::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS) {
+void FileMapInfo::update_jar_manifest(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS) {
   ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
   ResourceMark rm(THREAD);
   jint manifest_size;
 
-  if (cpe->is_jar_file()) {
-    assert(ent->is_jar(), "the shared class path entry is not a JAR file");
-    char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK);
-    if (manifest != NULL) {
-      ManifestStream* stream = new ManifestStream((u1*)manifest,
-                                                  manifest_size);
-      if (stream->check_is_signed()) {
-        ent->set_is_signed();
-      } else {
-        // Copy the manifest into the shared archive
-        manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK);
-        Array<u1>* buf = MetadataFactory::new_array<u1>(loader_data,
-                                                        manifest_size,
-                                                        THREAD);
-        char* p = (char*)(buf->data());
-        memcpy(p, manifest, manifest_size);
-        ent->set_manifest(buf);
-      }
+  assert(cpe->is_jar_file() && ent->is_jar(), "the shared class path entry is not a JAR file");
+  char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK);
+  if (manifest != NULL) {
+    ManifestStream* stream = new ManifestStream((u1*)manifest,
+                                                manifest_size);
+    if (stream->check_is_signed()) {
+      ent->set_is_signed();
+    } else {
+      // Copy the manifest into the shared archive
+      manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK);
+      Array<u1>* buf = MetadataFactory::new_array<u1>(loader_data,
+                                                      manifest_size,
+                                                      THREAD);
+      char* p = (char*)(buf->data());
+      memcpy(p, manifest, manifest_size);
+      ent->set_manifest(buf);
     }
   }
 }
 
+char* FileMapInfo::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) {
+    debug_only( {
+      size_t image_name_len = strlen(MODULES_IMAGE_NAME);
+      assert(strncmp(p - image_name_len, MODULES_IMAGE_NAME, image_name_len) == 0,
+             "first entry must be the modules image");
+    } );
+    p += path_sep_len;
+  } else {
+    debug_only( {
+      assert(ClassLoader::string_ends_with(path, MODULES_IMAGE_NAME),
+             "first entry must be the modules image");
+    } );
+  }
+  return p;
+}
+
+int FileMapInfo::num_paths(const char* path) {
+  if (path == NULL) {
+    return 0;
+  }
+  int npaths = 1;
+  char* p = (char*)path;
+  while (p != NULL) {
+    char* prev = p;
+    p = strstr((char*)p, os::path_separator());
+    if (p != NULL) {
+      p++;
+      // don't count empty path
+      if ((p - prev) > 1) {
+       npaths++;
+      }
+    }
+  }
+  return npaths;
+}
+
+GrowableArray<const char*>* FileMapInfo::create_path_array(const char* paths) {
+  GrowableArray<const char*>* path_array =  new(ResourceObj::RESOURCE_AREA, mtInternal)
+      GrowableArray<const char*>(10);
+
+  ClasspathStream cp_stream(paths);
+  while (cp_stream.has_next()) {
+    const char* path = cp_stream.get_next();
+    struct stat st;
+    if (os::stat(path, &st) == 0) {
+      path_array->append(path);
+    }
+  }
+  return path_array;
+}
+
+bool FileMapInfo::fail(const char* msg, const char* name) {
+  ClassLoader::trace_class_path(msg, name);
+  MetaspaceShared::set_archive_loading_failed();
+  return false;
+}
+
+bool FileMapInfo::check_paths(int shared_path_start_idx, int num_paths, GrowableArray<const char*>* rp_array) {
+  int i = 0;
+  int j = shared_path_start_idx;
+  bool mismatch = false;
+  while (i < num_paths && !mismatch) {
+    while (shared_path(j)->from_class_path_attr()) {
+      // shared_path(j) was expanded from the JAR file attribute "Class-Path:"
+      // during dump time. It's not included in the -classpath VM argument.
+      j++;
+    }
+    if (!os::same_files(shared_path(j)->name(), rp_array->at(i))) {
+      mismatch = true;
+    }
+    i++;
+    j++;
+  }
+  return mismatch;
+}
+
+bool FileMapInfo::validate_boot_class_paths() {
+  //
+  // - 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 compatible
+  //   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);
+  assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
+  int dp_len = header()->app_class_paths_start_index() - 1; // ignore the first path to the module image
+  bool mismatch = false;
+
+  bool relaxed_check = !header()->has_platform_or_app_classes();
+  if (dp_len == 0 && rp == NULL) {
+    return true;   // ok, both runtime and dump time boot paths have modules_images only
+  } else if (dp_len == 0 && rp != NULL) {
+    if (relaxed_check) {
+      return true;   // ok, relaxed check, runtime has extra boot append path entries
+    } else {
+      mismatch = true;
+    }
+  } else if (dp_len > 0 && rp != NULL) {
+    int num;
+    ResourceMark rm;
+    GrowableArray<const char*>* rp_array = create_path_array(rp);
+    int rp_len = rp_array->length();
+    if (rp_len >= dp_len) {
+      if (relaxed_check) {
+        // only check the leading entries in the runtime boot path, up to
+        // the length of the dump time boot path
+        num = dp_len;
+      } else {
+        // check the full runtime boot path, must match with dump time
+        num = rp_len;
+      }
+      mismatch = check_paths(1, num, rp_array);
+    }
+  }
+
+  if (mismatch) {
+    // The paths are different
+    return fail("[BOOT classpath mismatch, actual =", runtime_boot_path);
+  }
+  return true;
+}
+
+bool FileMapInfo::validate_app_class_paths(int shared_app_paths_len) {
+  const char *appcp = Arguments::get_appclasspath();
+  assert(appcp != NULL, "NULL app classpath");
+  int rp_len = num_paths(appcp);
+  bool mismatch = false;
+  if (rp_len < shared_app_paths_len) {
+    return fail("Run time APP classpath is shorter than the one at dump time: ", appcp);
+  }
+  if (shared_app_paths_len != 0 && rp_len != 0) {
+    // Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar.
+    ResourceMark rm;
+    GrowableArray<const char*>* rp_array = create_path_array(appcp);
+    if (rp_array->length() == 0) {
+      // None of the jar file specified in the runtime -cp exists.
+      return fail("None of the jar file specified in the runtime -cp exists: -Djava.class.path=", appcp);
+    }
+
+    // Handling of non-existent entries in the classpath: we eliminate all the non-existent
+    // entries from both the dump time classpath (ClassLoader::update_class_path_entry_list)
+    // and the runtime classpath (FileMapInfo::create_path_array), and check the remaining
+    // entries. E.g.:
+    //
+    // dump : -cp a.jar:NE1:NE2:b.jar  -> a.jar:b.jar -> recorded in archive.
+    // run 1: -cp NE3:a.jar:NE4:b.jar  -> a.jar:b.jar -> matched
+    // run 2: -cp x.jar:NE4:b.jar      -> x.jar:b.jar -> mismatched
+
+    int j = header()->app_class_paths_start_index();
+    mismatch = check_paths(j, shared_app_paths_len, rp_array);
+    if (mismatch) {
+      return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
+    }
+  }
+  return true;
+}
+
+void FileMapInfo::log_paths(const char* msg, int start_idx, int end_idx) {
+  LogTarget(Info, class, path) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    ls.print("%s", msg);
+    const char* prefix = "";
+    for (int i = start_idx; i < end_idx; i++) {
+      ls.print("%s%s", prefix, shared_path(i)->name());
+      prefix = os::path_separator();
+    }
+    ls.cr();
+  }
+}
 
 bool FileMapInfo::validate_shared_path_table() {
   assert(UseSharedSpaces, "runtime only");
@@ -527,7 +752,7 @@
   _validating_shared_path_table = true;
 
   // Load the shared path table info from the archive header
-  _shared_path_table = _header->_shared_path_table;
+  _shared_path_table = header()->shared_path_table();
   if (DynamicDumpSharedSpaces) {
     // Only support dynamic dumping with the usage of the default CDS archive
     // or a simple base archive.
@@ -537,24 +762,32 @@
     // When dynamic archiving is enabled, the _shared_path_table is overwritten
     // to include the application path and stored in the top layer archive.
     assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
-    if (_header->_app_class_paths_start_index > 1) {
+    if (header()->app_class_paths_start_index() > 1) {
       DynamicDumpSharedSpaces = false;
       warning(
         "Dynamic archiving is disabled because base layer archive has appended boot classpath");
     }
-    if (_header->_num_module_paths > 0) {
+    if (header()->num_module_paths() > 0) {
       DynamicDumpSharedSpaces = false;
       warning(
         "Dynamic archiving is disabled because base layer archive has module path");
     }
   }
 
-  int module_paths_start_index = _header->_app_module_paths_start_index;
+  log_paths("Expecting BOOT path=", 0, header()->app_class_paths_start_index());
+  log_paths("Expecting -Djava.class.path=", header()->app_class_paths_start_index(), header()->app_module_paths_start_index());
+
+  int module_paths_start_index = header()->app_module_paths_start_index();
+  int shared_app_paths_len = 0;
 
   // validate the path entries up to the _max_used_path_index
-  for (int i=0; i < _header->_max_used_path_index + 1; i++) {
+  for (int i=0; i < header()->max_used_path_index() + 1; i++) {
     if (i < module_paths_start_index) {
       if (shared_path(i)->validate()) {
+        // Only count the app class paths not from the "Class-path" attribute of a jar manifest.
+        if (!shared_path(i)->from_class_path_attr() && i >= header()->app_class_paths_start_index()) {
+          shared_app_paths_len++;
+        }
         log_info(class, path)("ok");
       } else {
         if (_dynamic_archive_info != NULL && _dynamic_archive_info->_is_static) {
@@ -574,6 +807,18 @@
     }
   }
 
+  if (header()->max_used_path_index() == 0) {
+    // default archive only contains the module image in the bootclasspath
+    assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
+  } else {
+    if (!validate_boot_class_paths() || !validate_app_class_paths(shared_app_paths_len)) {
+      fail_continue("shared class paths mismatch (hint: enable -Xlog:class+path=info to diagnose the failure)");
+      return false;
+    }
+  }
+
+  validate_non_existent_class_paths();
+
   _validating_shared_path_table = false;
 
 #if INCLUDE_JVMTI
@@ -588,37 +833,24 @@
   return true;
 }
 
-bool FileMapInfo::same_files(const char* file1, const char* file2) {
-  if (strcmp(file1, file2) == 0) {
-    return true;
-  }
+void FileMapInfo::validate_non_existent_class_paths() {
+  // All of the recorded non-existent paths came from the Class-Path: attribute from the JAR
+  // files on the app classpath. If any of these are found to exist during runtime,
+  // it will change how classes are loading for the app loader. For safety, disable
+  // loading of archived platform/app classes (currently there's no way to disable just the
+  // app classes).
 
-  bool is_same = false;
-  // if the two paths diff only in case
-  struct stat st1;
-  struct stat st2;
-  int ret1;
-  int ret2;
-  ret1 = os::stat(file1, &st1);
-  ret2 = os::stat(file2, &st2);
-  if (ret1 < 0 || ret2 < 0) {
-    // one of the files is invalid. So they are not the same.
-    is_same = false;
-  } else if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
-    // different files
-    is_same = false;
-#ifndef _WINDOWS
-  } else if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) {
-    // same files
-    is_same = true;
-#else
-  } else if ((st1.st_size == st2.st_size) && (st1.st_ctime == st2.st_ctime) &&
-             (st1.st_mtime == st2.st_mtime)) {
-    // same files
-    is_same = true;
-#endif
+  assert(UseSharedSpaces, "runtime only");
+  for (int i = header()->app_module_paths_start_index() + header()->num_module_paths();
+       i < get_number_of_shared_paths();
+       i++) {
+    SharedClassPathEntry* ent = shared_path(i);
+    if (!ent->check_non_existent()) {
+      warning("Archived non-system classes are disabled because the "
+              "file %s exists", ent->name());
+      header()->set_has_platform_or_app_classes(false);
+    }
   }
-  return is_same;
 }
 
 bool FileMapInfo::check_archive(const char* archive_name, bool is_static) {
@@ -642,7 +874,7 @@
   }
   if (is_static) {
     FileMapHeader* static_header = (FileMapHeader*)header;
-    if (static_header->_magic != CDS_ARCHIVE_MAGIC) {
+    if (static_header->magic() != CDS_ARCHIVE_MAGIC) {
       os::free(header);
       os::close(fd);
       vm_exit_during_initialization("Not a base shared archive", archive_name);
@@ -650,7 +882,7 @@
     }
   } else {
     DynamicArchiveHeader* dynamic_header = (DynamicArchiveHeader*)header;
-    if (dynamic_header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) {
+    if (dynamic_header->magic() != CDS_DYNAMIC_ARCHIVE_MAGIC) {
       os::free(header);
       os::close(fd);
       vm_exit_during_initialization("Not a top shared archive", archive_name);
@@ -680,21 +912,18 @@
     os::close(fd);
     return false;
   }
-  if (dynamic_header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) {
+  if (dynamic_header->magic() != CDS_DYNAMIC_ARCHIVE_MAGIC) {
     // Not a dynamic header, no need to proceed further.
     *size = 0;
     os::free(dynamic_header);
     os::close(fd);
     return false;
   }
-  if (dynamic_header->_base_archive_is_default) {
+  if (dynamic_header->base_archive_is_default()) {
     *base_archive_name = Arguments::get_default_shared_archive_path();
   } else {
-    // skip over the _paths_misc_info
-    sz = dynamic_header->_paths_misc_info_size;
-    lseek(fd, (long)sz, SEEK_CUR);
     // read the base archive name
-    size_t name_size = dynamic_header->_base_archive_name_size;
+    size_t name_size = dynamic_header->base_archive_name_size();
     if (name_size == 0) {
       os::free(dynamic_header);
       os::close(fd);
@@ -718,56 +947,97 @@
 }
 
 void FileMapInfo::restore_shared_path_table() {
-  _shared_path_table = _current_info->_header->_shared_path_table;
+  _shared_path_table = _current_info->header()->shared_path_table();
 }
 
 // Read the FileMapInfo information from the file.
 
 bool FileMapInfo::init_from_file(int fd, bool is_static) {
   size_t sz = is_static ? sizeof(FileMapHeader) : sizeof(DynamicArchiveHeader);
-  size_t n = os::read(fd, _header, (unsigned int)sz);
+  size_t n = os::read(fd, header(), (unsigned int)sz);
   if (n != sz) {
     fail_continue("Unable to read the file header.");
     return false;
   }
-  if (_header->_version != CURRENT_CDS_ARCHIVE_VERSION) {
+
+  if (!Arguments::has_jimage()) {
+    FileMapInfo::fail_continue("The shared archive file cannot be used with an exploded module build.");
+    return false;
+  }
+
+  unsigned int expected_magic = is_static ? CDS_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC;
+  if (header()->magic() != expected_magic) {
+    log_info(cds)("_magic expected: 0x%08x", expected_magic);
+    log_info(cds)("         actual: 0x%08x", header()->magic());
+    FileMapInfo::fail_continue("The shared archive file has a bad magic number.");
+    return false;
+  }
+
+  if (header()->version() != CURRENT_CDS_ARCHIVE_VERSION) {
+    log_info(cds)("_version expected: %d", CURRENT_CDS_ARCHIVE_VERSION);
+    log_info(cds)("           actual: %d", header()->version());
     fail_continue("The shared archive file has the wrong version.");
     return false;
   }
-  _file_offset = n;
 
-  size_t info_size = _header->_paths_misc_info_size;
-  _paths_misc_info = NEW_C_HEAP_ARRAY(char, info_size, mtClass);
-  n = os::read(fd, _paths_misc_info, (unsigned int)info_size);
-  if (n != info_size) {
-    fail_continue("Unable to read the shared path info header.");
-    FREE_C_HEAP_ARRAY(char, _paths_misc_info);
-    _paths_misc_info = NULL;
+  if (header()->header_size() != sz) {
+    log_info(cds)("_header_size expected: " SIZE_FORMAT, sz);
+    log_info(cds)("               actual: " SIZE_FORMAT, header()->header_size());
+    FileMapInfo::fail_continue("The shared archive file has an incorrect header size.");
+    return false;
+  }
+
+  const char* actual_ident = header()->jvm_ident();
+
+  if (actual_ident[JVM_IDENT_MAX-1] != 0) {
+    FileMapInfo::fail_continue("JVM version identifier is corrupted.");
     return false;
   }
-  _file_offset += n + _header->_base_archive_name_size; // accounts for the size of _base_archive_name
+
+  char expected_ident[JVM_IDENT_MAX];
+  get_header_version(expected_ident);
+  if (strncmp(actual_ident, expected_ident, JVM_IDENT_MAX-1) != 0) {
+    log_info(cds)("_jvm_ident expected: %s", expected_ident);
+    log_info(cds)("             actual: %s", actual_ident);
+    FileMapInfo::fail_continue("The shared archive file was created by a different"
+                  " version or build of HotSpot");
+    return false;
+  }
+
+  if (VerifySharedSpaces) {
+    int expected_crc = header()->compute_crc();
+    if (expected_crc != header()->crc()) {
+      log_info(cds)("_crc expected: %d", expected_crc);
+      log_info(cds)("       actual: %d", header()->crc());
+      FileMapInfo::fail_continue("Header checksum verification failed.");
+      return false;
+    }
+  }
+
+  _file_offset = n + header()->base_archive_name_size(); // accounts for the size of _base_archive_name
 
   if (is_static) {
-    if (_header->_magic != CDS_ARCHIVE_MAGIC) {
-      fail_continue("Incorrect static archive magic number");
-      return false;
-    }
     // just checking the last region is sufficient since the archive is written
     // in sequential order
     size_t len = lseek(fd, 0, SEEK_END);
-    CDSFileMapRegion* si = space_at(MetaspaceShared::last_valid_region);
+    FileMapRegion* si = space_at(MetaspaceShared::last_valid_region);
     // The last space might be empty
-    if (si->_file_offset > len || len - si->_file_offset < si->_used) {
+    if (si->file_offset() > len || len - si->file_offset() < si->used()) {
       fail_continue("The shared archive file has been truncated.");
       return false;
     }
 
-    SharedBaseAddress = _header->_shared_base_address;
+    SharedBaseAddress = header()->shared_base_address();
   }
 
   return true;
 }
 
+void FileMapInfo::seek_to_position(size_t pos) {
+  if (lseek(_fd, (long)pos, SEEK_SET) < 0) {
+    fail_stop("Unable to seek to position " SIZE_FORMAT, pos);
+  }
+}
 
 // Read the FileMapInfo information from the file.
 bool FileMapInfo::open_for_read(const char* path) {
@@ -823,72 +1093,80 @@
               os::strerror(errno));
   }
   _fd = fd;
-  _file_offset = 0;
   _file_open = true;
+
+  // Seek past the header. We will write the header after all regions are written
+  // and their CRCs computed.
+  size_t header_bytes = header()->header_size();
+  if (header()->magic() == CDS_DYNAMIC_ARCHIVE_MAGIC) {
+    header_bytes += strlen(Arguments::GetSharedArchivePath()) + 1;
+  }
+
+  header_bytes = align_up(header_bytes, os::vm_allocation_granularity());
+  _file_offset = header_bytes;
+  seek_to_position(_file_offset);
 }
 
 
 // Write the header to the file, seek to the next allocation boundary.
 
 void FileMapInfo::write_header() {
-  int info_size = ClassLoader::get_shared_paths_misc_info_size();
-
-  _header->_paths_misc_info_size = info_size;
-
+  _file_offset = 0;
+  seek_to_position(_file_offset);
   char* base_archive_name = NULL;
-  if (_header->_magic == CDS_DYNAMIC_ARCHIVE_MAGIC) {
+  if (header()->magic() == CDS_DYNAMIC_ARCHIVE_MAGIC) {
     base_archive_name = (char*)Arguments::GetSharedArchivePath();
-    _header->_base_archive_name_size = (int)strlen(base_archive_name) + 1;
-    _header->_base_archive_is_default = FLAG_IS_DEFAULT(SharedArchiveFile);
+    header()->set_base_archive_name_size(strlen(base_archive_name) + 1);
+    header()->set_base_archive_is_default(FLAG_IS_DEFAULT(SharedArchiveFile));
   }
 
   assert(is_file_position_aligned(), "must be");
-  write_bytes(_header, _header->_header_size);
-  write_bytes(ClassLoader::get_shared_paths_misc_info(), (size_t)info_size);
+  write_bytes(header(), header()->header_size());
   if (base_archive_name != NULL) {
-    write_bytes(base_archive_name, (size_t)_header->_base_archive_name_size);
+    write_bytes(base_archive_name, header()->base_archive_name_size());
   }
-  align_file_position();
 }
 
-// Dump region to file.
-// This is called twice for each region during archiving, once before
-// the archive file is open (_file_open is false) and once after.
+void FileMapRegion::init(bool is_heap_region, char* base, size_t size, bool read_only,
+                         bool allow_exec, int crc) {
+  _is_heap_region = is_heap_region;
+
+  if (is_heap_region) {
+    assert(!DynamicDumpSharedSpaces, "must be");
+    assert((base - (char*)CompressedKlassPointers::base()) % HeapWordSize == 0, "Sanity");
+    if (base != NULL) {
+      _addr._offset = (intx)CompressedOops::encode_not_null((oop)base);
+    } else {
+      _addr._offset = 0;
+    }
+  } else {
+    _addr._base = base;
+  }
+  _used = size;
+  _read_only = read_only;
+  _allow_exec = allow_exec;
+  _crc = crc;
+}
+
 void FileMapInfo::write_region(int region, char* base, size_t size,
                                bool read_only, bool allow_exec) {
-  assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "Dump time only");
+  Arguments::assert_is_dumping_archive();
 
-  CDSFileMapRegion* si = space_at(region);
+  FileMapRegion* si = space_at(region);
   char* target_base = base;
   if (DynamicDumpSharedSpaces) {
+    assert(!HeapShared::is_heap_region(region), "dynamic archive doesn't support heap regions");
     target_base = DynamicArchive::buffer_to_target(base);
   }
 
-  if (_file_open) {
-    guarantee(si->_file_offset == _file_offset, "file offset mismatch.");
-    log_info(cds)("Shared file region %d: " SIZE_FORMAT_HEX_W(08)
-                  " bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08),
-                  region, size, p2i(target_base), _file_offset);
-  } else {
-    si->_file_offset = _file_offset;
-  }
+  si->set_file_offset(_file_offset);
+  log_info(cds)("Shared file region %d: " SIZE_FORMAT_HEX_W(08)
+                " bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08),
+                region, size, p2i(target_base), _file_offset);
 
-  if (HeapShared::is_heap_region(region)) {
-    assert((target_base - (char*)CompressedKlassPointers::base()) % HeapWordSize == 0, "Sanity");
-    if (target_base != NULL) {
-      si->_addr._offset = (intx)CompressedOops::encode_not_null((oop)target_base);
-    } else {
-      si->_addr._offset = 0;
-    }
-  } else {
-    si->_addr._base = target_base;
-  }
-  si->_used = size;
-  si->_read_only = read_only;
-  si->_allow_exec = allow_exec;
+  int crc = ClassLoader::crc32(0, base, (jint)size);
+  si->init(HeapShared::is_heap_region(region), target_base, size, read_only, allow_exec, crc);
 
-  // Use the current 'base' when computing the CRC value and writing out data
-  si->_crc = ClassLoader::crc32(0, base, (jint)size);
   if (base != NULL) {
     write_bytes_aligned(base, size);
   }
@@ -927,8 +1205,7 @@
 //             +-- gap
 size_t FileMapInfo::write_archive_heap_regions(GrowableArray<MemRegion> *heap_mem,
                                                GrowableArray<ArchiveHeapOopmapInfo> *oopmaps,
-                                               int first_region_id, int max_num_regions,
-                                               bool print_log) {
+                                               int first_region_id, int max_num_regions) {
   assert(max_num_regions <= 2, "Only support maximum 2 memory regions");
 
   int arr_len = heap_mem == NULL ? 0 : heap_mem->length();
@@ -952,14 +1229,12 @@
       total_size += size;
     }
 
-    if (print_log) {
-      log_info(cds)("Archive heap region %d " INTPTR_FORMAT " - " INTPTR_FORMAT " = " SIZE_FORMAT_W(8) " bytes",
-                    i, p2i(start), p2i(start + size), size);
-    }
+    log_info(cds)("Archive heap region %d " INTPTR_FORMAT " - " INTPTR_FORMAT " = " SIZE_FORMAT_W(8) " bytes",
+                  i, p2i(start), p2i(start + size), size);
     write_region(i, start, size, false, false);
     if (size > 0) {
-      space_at(i)->_oopmap = oopmaps->at(arr_idx)._oopmap;
-      space_at(i)->_oopmap_size_in_bits = oopmaps->at(arr_idx)._oopmap_size_in_bits;
+      space_at(i)->init_oopmap(oopmaps->at(arr_idx)._oopmap,
+                               oopmaps->at(arr_idx)._oopmap_size_in_bits);
     }
   }
   return total_size;
@@ -968,14 +1243,13 @@
 // Dump bytes to file -- at the current file position.
 
 void FileMapInfo::write_bytes(const void* buffer, size_t nbytes) {
-  if (_file_open) {
-    size_t n = os::write(_fd, buffer, (unsigned int)nbytes);
-    if (n != nbytes) {
-      // If the shared archive is corrupted, close it and remove it.
-      close();
-      remove(_full_path);
-      fail_stop("Unable to write to shared archive file.");
-    }
+  assert(_file_open, "must be");
+  size_t n = os::write(_fd, buffer, (unsigned int)nbytes);
+  if (n != nbytes) {
+    // If the shared archive is corrupted, close it and remove it.
+    close();
+    remove(_full_path);
+    fail_stop("Unable to write to shared archive file.");
   }
   _file_offset += nbytes;
 }
@@ -988,20 +1262,17 @@
 // Align file position to an allocation unit boundary.
 
 void FileMapInfo::align_file_position() {
+  assert(_file_open, "must be");
   size_t new_file_offset = align_up(_file_offset,
-                                         os::vm_allocation_granularity());
+                                    os::vm_allocation_granularity());
   if (new_file_offset != _file_offset) {
     _file_offset = new_file_offset;
-    if (_file_open) {
-      // Seek one byte back from the target and write a byte to insure
-      // that the written file is the correct length.
-      _file_offset -= 1;
-      if (lseek(_fd, (long)_file_offset, SEEK_SET) < 0) {
-        fail_stop("Unable to seek.");
-      }
-      char zero = 0;
-      write_bytes(&zero, 1);
-    }
+    // Seek one byte back from the target and write a byte to insure
+    // that the written file is the correct length.
+    _file_offset -= 1;
+    seek_to_position(_file_offset);
+    char zero = 0;
+    write_bytes(&zero, 1);
   }
 }
 
@@ -1032,20 +1303,20 @@
 // Remap the shared readonly space to shared readwrite, private.
 bool FileMapInfo::remap_shared_readonly_as_readwrite() {
   int idx = MetaspaceShared::ro;
-  CDSFileMapRegion* si = space_at(idx);
-  if (!si->_read_only) {
+  FileMapRegion* si = space_at(idx);
+  if (!si->read_only()) {
     // the space is already readwrite so we are done
     return true;
   }
-  size_t used = si->_used;
+  size_t used = si->used();
   size_t size = align_up(used, os::vm_allocation_granularity());
   if (!open_for_read()) {
     return false;
   }
   char *addr = region_addr(idx);
-  char *base = os::remap_memory(_fd, _full_path, si->_file_offset,
+  char *base = os::remap_memory(_fd, _full_path, si->file_offset(),
                                 addr, size, false /* !read_only */,
-                                si->_allow_exec);
+                                si->allow_exec());
   close();
   // These have to be errors because the shared region is now unmapped.
   if (base == NULL) {
@@ -1056,7 +1327,7 @@
     log_error(cds)("Unable to remap shared readonly space (errno=%d).", errno);
     vm_exit(1);
   }
-  si->_read_only = false;
+  si->set_read_only(false);
   return true;
 }
 
@@ -1080,7 +1351,7 @@
 }
 
 // Memory map a region in the address space.
-static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly", "MiscCode", "OptionalData",
+static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly", "MiscCode",
                                             "String1", "String2", "OpenArchive1", "OpenArchive2" };
 
 char* FileMapInfo::map_regions(int regions[], char* saved_base[], size_t len) {
@@ -1094,7 +1365,7 @@
       return NULL;
     }
     if (i > 0) {
-      // We require that mc->rw->ro->md->od to be laid out consecutively, with no
+      // We require that mc->rw->ro->md to be laid out consecutively, with no
       // gaps between them. That way, we can ensure that the OS won't be able to
       // allocate any new memory spaces inside _shared_metaspace_{base,top}, which
       // would mess up the simple comparision in MetaspaceShared::is_in_shared_metaspace().
@@ -1109,8 +1380,8 @@
 
 char* FileMapInfo::map_region(int i, char** top_ret) {
   assert(!HeapShared::is_heap_region(i), "sanity");
-  CDSFileMapRegion* si = space_at(i);
-  size_t used = si->_used;
+  FileMapRegion* si = space_at(i);
+  size_t used = si->used();
   size_t alignment = os::vm_allocation_granularity();
   size_t size = align_up(used, alignment);
   char *requested_addr = region_addr(i);
@@ -1118,19 +1389,19 @@
 #ifdef _WINDOWS
   // Windows cannot remap read-only shared memory to read-write when required for
   // RedefineClasses, which is also used by JFR.  Always map windows regions as RW.
-  si->_read_only = false;
+  si->set_read_only(false);
 #else
   // If a tool agent is in use (debugging enabled), or JFR, we must map the address space RW
   if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space() ||
       Arguments::has_jfr_option()) {
-    si->_read_only = false;
+    si->set_read_only(false);
   }
 #endif // _WINDOWS
 
   // map the contents of the CDS archive in this memory
-  char *base = os::map_memory(_fd, _full_path, si->_file_offset,
-                              requested_addr, size, si->_read_only,
-                              si->_allow_exec);
+  char *base = os::map_memory(_fd, _full_path, si->file_offset(),
+                              requested_addr, size, si->read_only(),
+                              si->allow_exec());
   if (base == NULL || base != requested_addr) {
     fail_continue("Unable to map %s shared space at required address.", shared_region_name[i]);
     _memory_mapping_failed = true;
@@ -1162,11 +1433,11 @@
   return count;
 }
 
-address FileMapInfo::decode_start_address(CDSFileMapRegion* spc, bool with_current_oop_encoding_mode) {
+address FileMapInfo::decode_start_address(FileMapRegion* spc, bool with_current_oop_encoding_mode) {
   if (with_current_oop_encoding_mode) {
-    return (address)CompressedOops::decode_not_null(offset_of_space(spc));
+    return (address)CompressedOops::decode_not_null(spc->offset());
   } else {
-    return (address)HeapShared::decode_from_archive(offset_of_space(spc));
+    return (address)HeapShared::decode_from_archive(spc->offset());
   }
 }
 
@@ -1177,7 +1448,7 @@
 
 #if INCLUDE_CDS_JAVA_HEAP
 bool FileMapInfo::has_heap_regions() {
-  return (_header->_space[MetaspaceShared::first_closed_archive_heap_region]._used > 0);
+  return (space_at(MetaspaceShared::first_closed_archive_heap_region)->used() > 0);
 }
 
 // Returns the address range of the archived heap regions computed using the
@@ -1191,8 +1462,8 @@
   for (int i = MetaspaceShared::first_closed_archive_heap_region;
            i <= MetaspaceShared::last_valid_region;
            i++) {
-    CDSFileMapRegion* si = space_at(i);
-    size_t size = si->_used;
+    FileMapRegion* si = space_at(i);
+    size_t size = si->used();
     if (size > 0) {
       address s = start_address_as_decoded_with_current_oop_encoding_mode(si);
       address e = s + size;
@@ -1242,8 +1513,6 @@
     // referenced objects are replaced. See HeapShared::initialize_from_archived_subgraph().
   }
 
-  MemRegion heap_reserved = Universe::heap()->reserved_region();
-
   log_info(cds)("CDS archive was created with max heap size = " SIZE_FORMAT "M, and the following configuration:",
                 max_heap_size()/M);
   log_info(cds)("    narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
@@ -1252,7 +1521,7 @@
                 narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift());
 
   log_info(cds)("The current max heap size = " SIZE_FORMAT "M, HeapRegion::GrainBytes = " SIZE_FORMAT,
-                heap_reserved.byte_size()/M, HeapRegion::GrainBytes);
+                MaxHeapSize/M, HeapRegion::GrainBytes);
   log_info(cds)("    narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
                 p2i(CompressedKlassPointers::base()), CompressedKlassPointers::shift());
   log_info(cds)("    narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
@@ -1271,10 +1540,10 @@
     _heap_pointers_need_patching = true;
   } else {
     MemRegion range = get_heap_regions_range_with_current_oop_encoding_mode();
-    if (!heap_reserved.contains(range)) {
+    if (!CompressedOops::is_in(range)) {
       log_info(cds)("CDS heap data need to be relocated because");
       log_info(cds)("the desired range " PTR_FORMAT " - "  PTR_FORMAT, p2i(range.start()), p2i(range.end()));
-      log_info(cds)("is outside of the heap " PTR_FORMAT " - "  PTR_FORMAT, p2i(heap_reserved.start()), p2i(heap_reserved.end()));
+      log_info(cds)("is outside of the heap " PTR_FORMAT " - "  PTR_FORMAT, p2i(CompressedOops::begin()), p2i(CompressedOops::end()));
       _heap_pointers_need_patching = true;
     }
   }
@@ -1290,15 +1559,15 @@
     // At run time, they may not be inside the heap, so we move them so
     // that they are now near the top of the runtime time. This can be done by
     // the simple math of adding the delta as shown above.
-    address dumptime_heap_end = (address)_header->_heap_reserved.end();
-    address runtime_heap_end = (address)heap_reserved.end();
+    address dumptime_heap_end = header()->heap_end();
+    address runtime_heap_end = (address)CompressedOops::end();
     delta = runtime_heap_end - dumptime_heap_end;
   }
 
   log_info(cds)("CDS heap data relocation delta = " INTX_FORMAT " bytes", delta);
   HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
 
-  CDSFileMapRegion* si = space_at(MetaspaceShared::first_closed_archive_heap_region);
+  FileMapRegion* si = space_at(MetaspaceShared::first_closed_archive_heap_region);
   address relocated_closed_heap_region_bottom = start_address_as_decoded_from_archive(si);
   if (!is_aligned(relocated_closed_heap_region_bottom, HeapRegion::GrainBytes)) {
     // Align the bottom of the closed archive heap regions at G1 region boundary.
@@ -1353,13 +1622,13 @@
 bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first,
                                 int max, int* num, bool is_open_archive) {
   MemRegion * regions = new MemRegion[max];
-  CDSFileMapRegion* si;
+  FileMapRegion* si;
   int region_num = 0;
 
   for (int i = first;
            i < first + max; i++) {
     si = space_at(i);
-    size_t size = si->_used;
+    size_t size = si->used();
     if (size > 0) {
       HeapWord* start = (HeapWord*)start_address_as_decoded_from_archive(si);
       regions[region_num] = MemRegion(start, size / HeapWordSize);
@@ -1392,9 +1661,9 @@
   for (int i = 0; i < region_num; i++) {
     si = space_at(first + i);
     char* addr = (char*)regions[i].start();
-    char* base = os::map_memory(_fd, _full_path, si->_file_offset,
-                                addr, regions[i].byte_size(), si->_read_only,
-                                si->_allow_exec);
+    char* base = os::map_memory(_fd, _full_path, si->file_offset(),
+                                addr, regions[i].byte_size(), si->read_only(),
+                                si->allow_exec());
     if (base == NULL || base != addr) {
       // dealloc the regions from java heap
       dealloc_archive_heap_regions(regions, region_num, is_open_archive);
@@ -1404,7 +1673,7 @@
       return false;
     }
 
-    if (VerifySharedSpaces && !region_crc_check(addr, regions[i].byte_size(), si->_crc)) {
+    if (VerifySharedSpaces && !region_crc_check(addr, regions[i].byte_size(), si->crc())) {
       // dealloc the regions from java heap
       dealloc_archive_heap_regions(regions, region_num, is_open_archive);
       log_info(cds)("UseSharedSpaces: mapped heap regions are corrupt");
@@ -1435,9 +1704,9 @@
 void FileMapInfo::patch_archived_heap_embedded_pointers(MemRegion* ranges, int num_ranges,
                                                         int first_region_idx) {
   for (int i=0; i<num_ranges; i++) {
-    CDSFileMapRegion* si = space_at(i + first_region_idx);
-    HeapShared::patch_archived_heap_embedded_pointers(ranges[i], (address)si->_oopmap,
-                                                      si->_oopmap_size_in_bits);
+    FileMapRegion* si = space_at(i + first_region_idx);
+    HeapShared::patch_archived_heap_embedded_pointers(ranges[i], (address)si->oopmap(),
+                                                      si->oopmap_size_in_bits());
   }
 }
 
@@ -1481,14 +1750,13 @@
 
 bool FileMapInfo::verify_region_checksum(int i) {
   assert(VerifySharedSpaces, "sanity");
-
-  size_t sz = space_at(i)->_used;
+  size_t sz = space_at(i)->used();
 
   if (sz == 0) {
     return true; // no data
+  } else {
+    return region_crc_check(region_addr(i), sz, space_at(i)->crc());
   }
-
-  return region_crc_check(region_addr(i), sz, space_at(i)->_crc);
 }
 
 void FileMapInfo::unmap_regions(int regions[], char* saved_base[], size_t len) {
@@ -1503,8 +1771,8 @@
 
 void FileMapInfo::unmap_region(int i) {
   assert(!HeapShared::is_heap_region(i), "sanity");
-  CDSFileMapRegion* si = space_at(i);
-  size_t used = si->_used;
+  FileMapRegion* si = space_at(i);
+  size_t used = si->used();
   size_t size = align_up(used, os::vm_allocation_granularity());
 
   if (used == 0) {
@@ -1533,6 +1801,7 @@
 SharedPathTable FileMapInfo::_shared_path_table;
 bool FileMapInfo::_validating_shared_path_table = false;
 bool FileMapInfo::_memory_mapping_failed = false;
+GrowableArray<const char*>* FileMapInfo::_non_existent_class_paths = NULL;
 
 // Open the shared archive file, read and validate the header
 // information (version, boot classpath, etc.).  If initialization
@@ -1541,7 +1810,7 @@
 //
 // Validation of the archive is done in two steps:
 //
-// [1] validate_header() - done here. This checks the header, including _paths_misc_info.
+// [1] validate_header() - done here.
 // [2] validate_shared_path_table - this is done later, because the table is in the RW
 //     region of the archive, which is not mapped yet.
 bool FileMapInfo::initialize(bool is_static) {
@@ -1561,20 +1830,22 @@
   }
 
   init_from_file(_fd, is_static);
-  if (!validate_header(is_static)) {
+  // UseSharedSpaces could be disabled if the checking of some of the header fields in
+  // init_from_file has failed.
+  if (!UseSharedSpaces || !validate_header(is_static)) {
     return false;
   }
   return true;
 }
 
 char* FileMapInfo::region_addr(int idx) {
-  CDSFileMapRegion* si = space_at(idx);
+  FileMapRegion* si = space_at(idx);
   if (HeapShared::is_heap_region(idx)) {
     assert(DumpSharedSpaces, "The following doesn't work at runtime");
-    return si->_used > 0 ?
+    return si->used() > 0 ?
           (char*)start_address_as_decoded_with_current_oop_encoding_mode(si) : NULL;
   } else {
-    return si->_addr._base;
+    return si->base();
   }
 }
 
@@ -1589,33 +1860,7 @@
 
 // This function should only be called during run time with UseSharedSpaces enabled.
 bool FileMapHeader::validate() {
-  if (VerifySharedSpaces && compute_crc() != _crc) {
-    FileMapInfo::fail_continue("Header checksum verification failed.");
-    return false;
-  }
 
-  if (!Arguments::has_jimage()) {
-    FileMapInfo::fail_continue("The shared archive file cannot be used with an exploded module build.");
-    return false;
-  }
-
-  if (_version != CURRENT_CDS_ARCHIVE_VERSION) {
-    FileMapInfo::fail_continue("The shared archive file is the wrong version.");
-    return false;
-  }
-  if (_magic != CDS_ARCHIVE_MAGIC && _magic != CDS_DYNAMIC_ARCHIVE_MAGIC) {
-    FileMapInfo::fail_continue("The shared archive file has a bad magic number.");
-    return false;
-  }
-  char header_version[JVM_IDENT_MAX];
-  get_header_version(header_version);
-  if (strncmp(_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) {
-    log_info(class, path)("expected: %s", header_version);
-    log_info(class, path)("actual:   %s", _jvm_ident);
-    FileMapInfo::fail_continue("The shared archive file was created by a different"
-                  " version or build of HotSpot");
-    return false;
-  }
   if (_obj_alignment != ObjectAlignmentInBytes) {
     FileMapInfo::fail_continue("The shared archive file's ObjectAlignmentInBytes of %d"
                   " does not equal the current ObjectAlignmentInBytes of " INTX_FORMAT ".",
@@ -1669,22 +1914,7 @@
 }
 
 bool FileMapInfo::validate_header(bool is_static) {
-  bool status = _header->validate();
-
-  if (status) {
-    if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size, is_static)) {
-      if (!PrintSharedArchiveAndExit) {
-        fail_continue("shared class paths mismatch (hint: enable -Xlog:class+path=info to diagnose the failure)");
-        status = false;
-      }
-    }
-  }
-
-  if (_paths_misc_info != NULL) {
-    FREE_C_HEAP_ARRAY(char, _paths_misc_info);
-    _paths_misc_info = NULL;
-  }
-  return status;
+  return header()->validate();
 }
 
 // Check if a given address is within one of the shared regions
@@ -1694,7 +1924,7 @@
          idx == MetaspaceShared::mc ||
          idx == MetaspaceShared::md, "invalid region index");
   char* base = region_addr(idx);
-  if (p >= base && p < base + space_at(idx)->_used) {
+  if (p >= base && p < base + space_at(idx)->used()) {
     return true;
   }
   return false;
@@ -1712,7 +1942,7 @@
         char *addr = map_info->region_addr(i);
         if (addr != NULL) {
           map_info->unmap_region(i);
-          map_info->space_at(i)->_addr._base = NULL;
+          map_info->space_at(i)->mark_invalid();
         }
       }
     }
@@ -1736,7 +1966,7 @@
   ClassPathEntry* ent = _classpath_entries_for_jvmti[i];
   if (ent == NULL) {
     if (i == 0) {
-      ent = ClassLoader:: get_jrt_entry();
+      ent = ClassLoader::get_jrt_entry();
       assert(ent != NULL, "must be");
     } else {
       SharedClassPathEntry* scpe = shared_path(i);
@@ -1749,7 +1979,7 @@
         jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path);
         THROW_MSG_(vmSymbols::java_io_IOException(), msg, NULL);
       } else {
-        ent = ClassLoader::create_class_path_entry(path, &st, /*throw_exception=*/true, false, CHECK_NULL);
+        ent = ClassLoader::create_class_path_entry(path, &st, /*throw_exception=*/true, false, false, CHECK_NULL);
       }
     }