src/hotspot/share/memory/filemap.cpp
changeset 54927 1512d88b24c6
parent 54838 d7819bedfaaf
child 55296 357c9dcb6eb9
child 58678 9cf78a70fa4f
--- a/src/hotspot/share/memory/filemap.cpp	Fri May 17 10:48:02 2019 -0400
+++ b/src/hotspot/share/memory/filemap.cpp	Fri May 17 08:29:55 2019 -0700
@@ -34,6 +34,7 @@
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "logging/logMessage.hpp"
+#include "memory/dynamicArchive.hpp"
 #include "memory/filemap.hpp"
 #include "memory/heapShared.inline.hpp"
 #include "memory/iterator.inline.hpp"
@@ -42,6 +43,7 @@
 #include "memory/metaspaceShared.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/universe.hpp"
+#include "oops/compressedOops.hpp"
 #include "oops/compressedOops.inline.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
@@ -101,7 +103,12 @@
 void FileMapInfo::fail_continue(const char *msg, ...) {
   va_list ap;
   va_start(ap, msg);
-  MetaspaceShared::set_archive_loading_failed();
+  if (_dynamic_archive_info == NULL) {
+    MetaspaceShared::set_archive_loading_failed();
+  } else {
+    // _dynamic_archive_info has been setup after mapping the base archive
+    DynamicArchive::disable();
+  }
   if (PrintSharedArchiveAndExit && _validating_shared_path_table) {
     // If we are doing PrintSharedArchiveAndExit and some of the classpath entries
     // do not validate, we can still continue "limping" to validate the remaining
@@ -120,9 +127,15 @@
         ls.vprint_cr(msg, ap);
       }
     }
-    UseSharedSpaces = false;
-    assert(current_info() != NULL, "singleton must be registered");
-    current_info()->close();
+    if (_dynamic_archive_info == NULL) {
+      UseSharedSpaces = false;
+      assert(current_info() != NULL, "singleton must be registered");
+      current_info()->close();
+    } else {
+      // We are failing when loading the top archive, but the base archive should
+      // continue to work.
+      log_warning(cds, dynamic)("Unable to use shared archive. The top archive failed to load: %s", _dynamic_archive_info->_full_path);
+    }
   }
   va_end(ap);
 }
@@ -159,20 +172,36 @@
   }
 }
 
-FileMapInfo::FileMapInfo() {
-  assert(_current_info == NULL, "must be singleton"); // not thread safe
-  _current_info = this;
+FileMapInfo::FileMapInfo(bool is_static) {
   memset((void*)this, 0, sizeof(FileMapInfo));
+  _is_static = is_static;
+  size_t header_size;
+  if (is_static) {
+    assert(_current_info == NULL, "must be singleton"); // not thread safe
+    _current_info = this;
+    header_size = sizeof(FileMapHeader);
+  } else {
+    assert(_dynamic_archive_info == NULL, "must be singleton"); // not thread safe
+    _dynamic_archive_info = this;
+    header_size = sizeof(DynamicArchiveHeader);
+  }
+  _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;
   _file_offset = 0;
   _file_open = false;
-  _header = (FileMapHeader*)os::malloc(sizeof(FileMapHeader), mtInternal);
-  _header->_version = INVALID_CDS_ARCHIVE_VERSION;
-  _header->_has_platform_or_app_classes = true;
 }
 
 FileMapInfo::~FileMapInfo() {
-  assert(_current_info == this, "must be singleton"); // not thread safe
-  _current_info = NULL;
+  if (_is_static) {
+    assert(_current_info == this, "must be singleton"); // not thread safe
+    _current_info = NULL;
+  } else {
+    assert(_dynamic_archive_info == this, "must be singleton"); // not thread safe
+    _dynamic_archive_info = NULL;
+  }
 }
 
 void FileMapInfo::populate_header(size_t alignment) {
@@ -180,7 +209,11 @@
 }
 
 void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
-  _magic = CDS_ARCHIVE_MAGIC;
+  if (DynamicDumpSharedSpaces) {
+    _magic = CDS_DYNAMIC_ARCHIVE_MAGIC;
+  } else {
+    _magic = CDS_ARCHIVE_MAGIC;
+  }
   _version = CURRENT_CDS_ARCHIVE_VERSION;
   _alignment = alignment;
   _obj_alignment = ObjectAlignmentInBytes;
@@ -191,9 +224,7 @@
   _max_heap_size = MaxHeapSize;
   _narrow_klass_base = CompressedKlassPointers::base();
   _narrow_klass_shift = CompressedKlassPointers::shift();
-  _shared_path_table_size = mapinfo->_shared_path_table_size;
   _shared_path_table = mapinfo->_shared_path_table;
-  _shared_path_entry_size = mapinfo->_shared_path_entry_size;
   if (HeapShared::is_heap_object_archiving_allowed()) {
     _heap_reserved = Universe::heap()->reserved_region();
   }
@@ -208,6 +239,7 @@
   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();
   _max_used_path_index = ClassLoaderExt::max_used_path_index();
 
   _verify_local = BytecodeVerificationLocal;
@@ -215,10 +247,13 @@
   _has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes();
   _shared_base_address = SharedBaseAddress;
   _allow_archiving_with_java_agent = AllowArchivingWithJavaAgent;
+  // the following 2 fields will be set in write_header for dynamic archive header
+  _base_archive_name_size = 0;
+  _base_archive_is_default = false;
 }
 
 void SharedClassPathEntry::init(const char* name, bool is_modules_image, TRAPS) {
-  assert(DumpSharedSpaces, "dump time only");
+  assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
   _timestamp = 0;
   _filesize  = 0;
 
@@ -297,6 +332,7 @@
     // If PrintSharedArchiveAndExit is enabled, don't report failure to the
     // caller. Please see above comments for more details.
     ok = true;
+    MetaspaceShared::set_archive_loading_failed();
   }
   return ok;
 }
@@ -306,8 +342,27 @@
   it->push(&_manifest);
 }
 
+void SharedPathTable::metaspace_pointers_do(MetaspaceClosure* it) {
+  it->push(&_table);
+  for (int i=0; i<_size; i++) {
+    path_at(i)->metaspace_pointers_do(it);
+  }
+}
+
+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;
+  size_t bytes = entry_size * num_entries;
+
+  _table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD);
+  _size = num_entries;
+}
+
 void FileMapInfo::allocate_shared_path_table() {
-  assert(DumpSharedSpaces, "Sanity");
+  assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "Sanity");
 
   Thread* THREAD = Thread::current();
   ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
@@ -316,16 +371,7 @@
   assert(jrt != NULL,
          "No modular java runtime image present when allocating the CDS classpath entry table");
 
-  size_t entry_size = sizeof(SharedClassPathEntry); // assert ( should be 8 byte aligned??)
-  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;
-  size_t bytes = entry_size * num_entries;
-
-  _shared_path_table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD);
-  _shared_path_table_size = num_entries;
-  _shared_path_entry_size = entry_size;
+  _shared_path_table.dumptime_init(loader_data, THREAD);
 
   // 1. boot class path
   int i = 0;
@@ -343,7 +389,7 @@
     cpe = ClassLoader::get_next_boot_classpath_entry(cpe);
     i++;
   }
-  assert(i == num_boot_classpath_entries,
+  assert(i == ClassLoader::num_boot_classpath_entries(),
          "number of boot class path entry mismatch");
 
   // 2. app class path
@@ -369,15 +415,15 @@
     mpe = mpe->next();
     i++;
   }
-  assert(i == num_entries, "number of shared path entry mismatch");
+  assert(i == _shared_path_table.size(), "number of shared path entry mismatch");
 }
 
 void FileMapInfo::check_nonempty_dir_in_shared_path_table() {
-  assert(DumpSharedSpaces, "dump time only");
+  assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
 
   bool has_nonempty_dir = false;
 
-  int last = _shared_path_table_size - 1;
+  int last = _shared_path_table.size() - 1;
   if (last > ClassLoaderExt::max_used_path_index()) {
      // no need to check any path beyond max_used_path_index
      last = ClassLoaderExt::max_used_path_index();
@@ -479,9 +525,29 @@
   assert(UseSharedSpaces, "runtime only");
 
   _validating_shared_path_table = true;
+
+  // Load the shared path table info from the archive header
   _shared_path_table = _header->_shared_path_table;
-  _shared_path_entry_size = _header->_shared_path_entry_size;
-  _shared_path_table_size = _header->_shared_path_table_size;
+  if (DynamicDumpSharedSpaces) {
+    // Only support dynamic dumping with the usage of the default CDS archive
+    // or a simple base archive.
+    // If the base layer archive contains additional path component besides
+    // the runtime image and the -cp, dynamic dumping is disabled.
+    //
+    // 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) {
+      DynamicDumpSharedSpaces = false;
+      warning(
+        "Dynamic archiving is disabled because base layer archive has appended boot classpath");
+    }
+    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;
 
@@ -491,14 +557,18 @@
       if (shared_path(i)->validate()) {
         log_info(class, path)("ok");
       } else {
-        assert(!UseSharedSpaces, "UseSharedSpaces should be disabled");
+        if (_dynamic_archive_info != NULL && _dynamic_archive_info->_is_static) {
+          assert(!UseSharedSpaces, "UseSharedSpaces should be disabled");
+        }
         return false;
       }
     } else if (i >= module_paths_start_index) {
       if (shared_path(i)->validate(false /* not a class path entry */)) {
         log_info(class, path)("ok");
       } else {
-        assert(!UseSharedSpaces, "UseSharedSpaces should be disabled");
+        if (_dynamic_archive_info != NULL && _dynamic_archive_info->_is_static) {
+          assert(!UseSharedSpaces, "UseSharedSpaces should be disabled");
+        }
         return false;
       }
     }
@@ -510,18 +580,151 @@
   if (_classpath_entries_for_jvmti != NULL) {
     os::free(_classpath_entries_for_jvmti);
   }
-  size_t sz = sizeof(ClassPathEntry*) *  _shared_path_table_size;
+  size_t sz = sizeof(ClassPathEntry*) * get_number_of_shared_paths();
   _classpath_entries_for_jvmti = (ClassPathEntry**)os::malloc(sz, mtClass);
-  memset(_classpath_entries_for_jvmti, 0, sz);
+  memset((void*)_classpath_entries_for_jvmti, 0, sz);
 #endif
 
   return true;
 }
 
+bool FileMapInfo::same_files(const char* file1, const char* file2) {
+  if (strcmp(file1, file2) == 0) {
+    return true;
+  }
+
+  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
+  }
+  return is_same;
+}
+
+bool FileMapInfo::check_archive(const char* archive_name, bool is_static) {
+  int fd = os::open(archive_name, O_RDONLY | O_BINARY, 0);
+  if (fd < 0) {
+    // do not vm_exit_during_initialization here because Arguments::init_shared_archive_paths()
+    // requires a shared archive name. The open_for_read() function will log a message regarding
+    // failure in opening a shared archive.
+    return false;
+  }
+
+  size_t sz = is_static ? sizeof(FileMapHeader) : sizeof(DynamicArchiveHeader);
+  void* header = os::malloc(sz, mtInternal);
+  memset(header, 0, sz);
+  size_t n = os::read(fd, header, (unsigned int)sz);
+  if (n != sz) {
+    os::free(header);
+    os::close(fd);
+    vm_exit_during_initialization("Unable to read header from shared archive", archive_name);
+    return false;
+  }
+  if (is_static) {
+    FileMapHeader* static_header = (FileMapHeader*)header;
+    if (static_header->_magic != CDS_ARCHIVE_MAGIC) {
+      os::free(header);
+      os::close(fd);
+      vm_exit_during_initialization("Not a base shared archive", archive_name);
+      return false;
+    }
+  } else {
+    DynamicArchiveHeader* dynamic_header = (DynamicArchiveHeader*)header;
+    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);
+      return false;
+    }
+  }
+  os::free(header);
+  os::close(fd);
+  return true;
+}
+
+bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name,
+                                                    int* size, char** base_archive_name) {
+  int fd = os::open(archive_name, O_RDONLY | O_BINARY, 0);
+  if (fd < 0) {
+    *size = 0;
+    return false;
+  }
+
+  // read the header as a dynamic archive header
+  size_t sz = sizeof(DynamicArchiveHeader);
+  DynamicArchiveHeader* dynamic_header = (DynamicArchiveHeader*)os::malloc(sz, mtInternal);
+  size_t n = os::read(fd, dynamic_header, (unsigned int)sz);
+  if (n != sz) {
+    fail_continue("Unable to read the file header.");
+    os::free(dynamic_header);
+    os::close(fd);
+    return false;
+  }
+  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) {
+    *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;
+    if (name_size == 0) {
+      os::free(dynamic_header);
+      os::close(fd);
+      return false;
+    }
+    *base_archive_name = NEW_C_HEAP_ARRAY(char, name_size, mtInternal);
+    n = os::read(fd, *base_archive_name, (unsigned int)name_size);
+    if (n != name_size) {
+      fail_continue("Unable to read the base archive name from the header.");
+      FREE_C_HEAP_ARRAY(char, *base_archive_name);
+      *base_archive_name = NULL;
+      os::free(dynamic_header);
+      os::close(fd);
+      return false;
+    }
+  }
+
+  os::free(dynamic_header);
+  os::close(fd);
+  return true;
+}
+
+void FileMapInfo::restore_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) {
-  size_t sz = sizeof(FileMapHeader);
+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);
   if (n != sz) {
     fail_continue("Unable to read the file header.");
@@ -531,14 +734,10 @@
     fail_continue("The shared archive file has the wrong version.");
     return false;
   }
-  _file_offset = (long)n;
+  _file_offset = n;
 
   size_t info_size = _header->_paths_misc_info_size;
-  _paths_misc_info = NEW_C_HEAP_ARRAY_RETURN_NULL(char, info_size, mtClass);
-  if (_paths_misc_info == NULL) {
-    fail_continue("Unable to read the file header.");
-    return false;
-  }
+  _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.");
@@ -546,29 +745,45 @@
     _paths_misc_info = NULL;
     return false;
   }
+  _file_offset += n + _header->_base_archive_name_size; // accounts for the size of _base_archive_name
 
-  size_t len = lseek(fd, 0, SEEK_END);
-  CDSFileMapRegion* si = space_at(MetaspaceShared::last_valid_region);
-  // The last space might be empty
-  if (si->_file_offset > len || len - si->_file_offset < si->_used) {
-    fail_continue("The shared archive file has been truncated.");
-    return false;
+  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);
+    // The last space might be empty
+    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;
   }
 
-  _file_offset += (long)n;
-  SharedBaseAddress = _header->_shared_base_address;
   return true;
 }
 
 
 // Read the FileMapInfo information from the file.
-bool FileMapInfo::open_for_read() {
-  _full_path = Arguments::GetSharedArchivePath();
+bool FileMapInfo::open_for_read(const char* path) {
+  if (_file_open) {
+    return true;
+  }
+  if (path == NULL) {
+    _full_path = Arguments::GetSharedArchivePath();
+  } else {
+    _full_path = path;
+  }
   int fd = os::open(_full_path, O_RDONLY | O_BINARY, 0);
   if (fd < 0) {
     if (errno == ENOENT) {
       // Not locating the shared archive is ok.
-      fail_continue("Specified shared archive not found.");
+      fail_continue("Specified shared archive not found (%s).", _full_path);
     } else {
       fail_continue("Failed to open shared archive file (%s).",
                     os::strerror(errno));
@@ -581,11 +796,14 @@
   return true;
 }
 
-
 // Write the FileMapInfo information to the file.
 
-void FileMapInfo::open_for_write() {
-  _full_path = Arguments::GetSharedArchivePath();
+void FileMapInfo::open_for_write(const char* path) {
+  if (path == NULL) {
+    _full_path = Arguments::GetSharedArchivePath();
+  } else {
+    _full_path = path;
+  }
   LogMessage(cds) msg;
   if (msg.is_info()) {
     msg.info("Dumping shared data to file: ");
@@ -593,7 +811,7 @@
   }
 
 #ifdef _WINDOWS  // On Windows, need WRITE permission to remove the file.
-  chmod(_full_path, _S_IREAD | _S_IWRITE);
+    chmod(_full_path, _S_IREAD | _S_IWRITE);
 #endif
 
   // Use remove() to delete the existing file because, on Unix, this will
@@ -617,40 +835,59 @@
 
   _header->_paths_misc_info_size = info_size;
 
-  align_file_position();
-  write_bytes(_header, sizeof(FileMapHeader));
+  char* base_archive_name = NULL;
+  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);
+  }
+
+  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);
+  if (base_archive_name != NULL) {
+    write_bytes(base_archive_name, (size_t)_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 FileMapInfo::write_region(int region, char* base, size_t size,
                                bool read_only, bool allow_exec) {
+  assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "Dump time only");
+
   CDSFileMapRegion* si = space_at(region);
+  char* target_base = base;
+  if (DynamicDumpSharedSpaces) {
+    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(base), _file_offset);
+                  region, size, p2i(target_base), _file_offset);
   } else {
     si->_file_offset = _file_offset;
   }
+
   if (HeapShared::is_heap_region(region)) {
-    assert((base - (char*)CompressedOops::base()) % HeapWordSize == 0, "Sanity");
-    if (base != NULL) {
-      si->_addr._offset = (intx)CompressedOops::encode_not_null((oop)base);
+    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 = base;
+    si->_addr._base = target_base;
   }
   si->_used = size;
   si->_read_only = read_only;
   si->_allow_exec = allow_exec;
+
+  // 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);
@@ -734,8 +971,7 @@
   if (_file_open) {
     size_t n = os::write(_fd, buffer, (unsigned int)nbytes);
     if (n != nbytes) {
-      // It is dangerous to leave the corrupted shared archive file around,
-      // close and remove the file. See bug 6372906.
+      // If the shared archive is corrupted, close it and remove it.
       close();
       remove(_full_path);
       fail_stop("Unable to write to shared archive file.");
@@ -744,6 +980,10 @@
   _file_offset += nbytes;
 }
 
+bool FileMapInfo::is_file_position_aligned() const {
+  return _file_offset == align_up(_file_offset,
+                                  os::vm_allocation_granularity());
+}
 
 // Align file position to an allocation unit boundary.
 
@@ -843,6 +1083,30 @@
 static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly", "MiscCode", "OptionalData",
                                             "String1", "String2", "OpenArchive1", "OpenArchive2" };
 
+char* FileMapInfo::map_regions(int regions[], char* saved_base[], size_t len) {
+  char* prev_top = NULL;
+  char* curr_base;
+  char* curr_top;
+  int i = 0;
+  for (i = 0; i < (int)len; i++) {
+    curr_base = map_region(regions[i], &curr_top);
+    if (curr_base == NULL) {
+      return NULL;
+    }
+    if (i > 0) {
+      // We require that mc->rw->ro->md->od 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().
+      assert(curr_base == prev_top, "must be");
+    }
+    log_info(cds)("Mapped region #%d at base %p top %p", regions[i], curr_base, curr_top);
+    saved_base[i] = curr_base;
+    prev_top = curr_top;
+  }
+  return curr_top;
+}
+
 char* FileMapInfo::map_region(int i, char** top_ret) {
   assert(!HeapShared::is_heap_region(i), "sanity");
   CDSFileMapRegion* si = space_at(i);
@@ -869,6 +1133,7 @@
                               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;
     return NULL;
   }
 #ifdef _WINDOWS
@@ -885,6 +1150,18 @@
   return base;
 }
 
+size_t FileMapInfo::read_bytes(void* buffer, size_t count) {
+  assert(_file_open, "Archive file is not open");
+  size_t n = os::read(_fd, buffer, (unsigned int)count);
+  if (n != count) {
+    // Close the file if there's a problem reading it.
+    close();
+    return 0;
+  }
+  _file_offset += count;
+  return count;
+}
+
 address FileMapInfo::decode_start_address(CDSFileMapRegion* spc, bool with_current_oop_encoding_mode) {
   if (with_current_oop_encoding_mode) {
     return (address)CompressedOops::decode_not_null(offset_of_space(spc));
@@ -1126,13 +1403,13 @@
                     p2i(addr), regions[i].byte_size());
       return false;
     }
-  }
 
-  if (!verify_mapped_heap_regions(first, region_num)) {
-    // 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");
-    return false;
+    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");
+      return false;
+    }
   }
 
   // the shared heap data is mapped successfully
@@ -1141,18 +1418,6 @@
   return true;
 }
 
-bool FileMapInfo::verify_mapped_heap_regions(int first, int num) {
-  assert(num > 0, "sanity");
-  if (VerifySharedSpaces) {
-    for (int i = first; i < first + num; i++) {
-      if (!verify_region_checksum(i)) {
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
 void FileMapInfo::patch_archived_heap_embedded_pointers() {
   if (!_heap_pointers_need_patching) {
     return;
@@ -1205,6 +1470,15 @@
 }
 #endif // INCLUDE_CDS_JAVA_HEAP
 
+bool FileMapInfo::region_crc_check(char* buf, size_t size, int expected_crc) {
+  int crc = ClassLoader::crc32(0, buf, (jint)size);
+  if (crc != expected_crc) {
+    fail_continue("Checksum verification failed.");
+    return false;
+  }
+  return true;
+}
+
 bool FileMapInfo::verify_region_checksum(int i) {
   assert(VerifySharedSpaces, "sanity");
 
@@ -1213,19 +1487,16 @@
   if (sz == 0) {
     return true; // no data
   }
-  if ((HeapShared::is_closed_archive_heap_region(i) &&
-       !HeapShared::closed_archive_heap_region_mapped()) ||
-      (HeapShared::is_open_archive_heap_region(i) &&
-       !HeapShared::open_archive_heap_region_mapped())) {
-    return true; // archived heap data is not mapped
+
+  return region_crc_check(region_addr(i), sz, space_at(i)->_crc);
+}
+
+void FileMapInfo::unmap_regions(int regions[], char* saved_base[], size_t len) {
+  for (int i = 0; i < (int)len; i++) {
+    if (saved_base[i] != NULL) {
+      unmap_region(regions[i]);
+    }
   }
-  const char* buf = region_addr(i);
-  int crc = ClassLoader::crc32(0, buf, (jint)sz);
-  if (crc != space_at(i)->_crc) {
-    fail_continue("Checksum verification failed.");
-    return false;
-  }
-  return true;
 }
 
 // Unmap a memory region in the address space.
@@ -1253,19 +1524,15 @@
 }
 
 void FileMapInfo::metaspace_pointers_do(MetaspaceClosure* it) {
-  it->push(&_shared_path_table);
-  for (int i=0; i<_shared_path_table_size; i++) {
-    shared_path(i)->metaspace_pointers_do(it);
-  }
+  _shared_path_table.metaspace_pointers_do(it);
 }
 
-
 FileMapInfo* FileMapInfo::_current_info = NULL;
+FileMapInfo* FileMapInfo::_dynamic_archive_info = NULL;
 bool FileMapInfo::_heap_pointers_need_patching = false;
-Array<u8>* FileMapInfo::_shared_path_table = NULL;
-int FileMapInfo::_shared_path_table_size = 0;
-size_t FileMapInfo::_shared_path_entry_size = 0x1234baad;
+SharedPathTable FileMapInfo::_shared_path_table;
 bool FileMapInfo::_validating_shared_path_table = false;
+bool FileMapInfo::_memory_mapping_failed = false;
 
 // Open the shared archive file, read and validate the header
 // information (version, boot classpath, etc.).  If initialization
@@ -1277,7 +1544,7 @@
 // [1] validate_header() - done here. This checks the header, including _paths_misc_info.
 // [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 FileMapInfo::initialize(bool is_static) {
   assert(UseSharedSpaces, "UseSharedSpaces expected.");
 
   if (JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()) {
@@ -1293,8 +1560,8 @@
     return false;
   }
 
-  init_from_file(_fd);
-  if (!validate_header()) {
+  init_from_file(_fd, is_static);
+  if (!validate_header(is_static)) {
     return false;
   }
   return true;
@@ -1315,7 +1582,7 @@
   char* start = (char*)this;
   // start computing from the field after _crc
   char* buf = (char*)&_crc + sizeof(_crc);
-  size_t sz = sizeof(FileMapHeader) - (buf - start);
+  size_t sz = _header_size - (buf - start);
   int crc = ClassLoader::crc32(0, buf, (jint)sz);
   return crc;
 }
@@ -1336,7 +1603,7 @@
     FileMapInfo::fail_continue("The shared archive file is the wrong version.");
     return false;
   }
-  if (_magic != CDS_ARCHIVE_MAGIC) {
+  if (_magic != CDS_ARCHIVE_MAGIC && _magic != CDS_DYNAMIC_ARCHIVE_MAGIC) {
     FileMapInfo::fail_continue("The shared archive file has a bad magic number.");
     return false;
   }
@@ -1401,11 +1668,11 @@
   return true;
 }
 
-bool FileMapInfo::validate_header() {
+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)) {
+    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;
@@ -1435,7 +1702,7 @@
 
 // Unmap mapped regions of shared space.
 void FileMapInfo::stop_sharing_and_unmap(const char* msg) {
-  MetaspaceObj::set_shared_metaspace_range(NULL, NULL);
+  MetaspaceShared::set_shared_metaspace_range(NULL, NULL);
 
   FileMapInfo *map_info = FileMapInfo::current_info();
   if (map_info) {
@@ -1502,7 +1769,7 @@
 ClassFileStream* FileMapInfo::open_stream_for_jvmti(InstanceKlass* ik, Handle class_loader, TRAPS) {
   int path_index = ik->shared_classpath_index();
   assert(path_index >= 0, "should be called for shared built-in classes only");
-  assert(path_index < (int)_shared_path_table_size, "sanity");
+  assert(path_index < (int)get_number_of_shared_paths(), "sanity");
 
   ClassPathEntry* cpe = get_classpath_entry_for_jvmti(path_index, CHECK_NULL);
   assert(cpe != NULL, "must be");