From 49f7ef8df4cade226de5754172e208975343967c Mon Sep 17 00:00:00 2001
Date: Sat, 3 Sep 2022 14:25:50 +0000
Subject: 8202951-Support-default-jsa

---
 common/autoconf/configure.ac                  |   3 +
 common/autoconf/generated-configure.sh        |  40 +++++
 common/autoconf/jdk-options.m4                |  32 ++++
 common/autoconf/spec.gmk.in                   |   4 +
 common/bin/compare.sh                         |   1 +
 hotspot/src/share/vm/cds/archiveBuilder.cpp   |  34 +++-
 hotspot/src/share/vm/cds/archiveBuilder.hpp   |   4 +
 hotspot/src/share/vm/cds/dynamicArchive.cpp   |   1 +
 .../src/share/vm/classfile/classLoader.cpp    | 152 +++++++++++++++++-
 .../src/share/vm/classfile/classLoader.hpp    |  15 +-
 .../share/vm/classfile/classLoaderData.hpp    |   1 +                                                                                       
 hotspot/src/share/vm/classfile/dictionary.cpp |   2 +-
 .../vm/classfile/sharedPathsMiscInfo.hpp      |  13 +-
 .../vm/classfile/systemDictionaryShared.cpp   |   2 +-
 hotspot/src/share/vm/memory/filemap.cpp       |  34 +++-
 hotspot/src/share/vm/memory/filemap.hpp       |   7 +
 hotspot/src/share/vm/memory/metachunk.hpp     |   2 +
 hotspot/src/share/vm/memory/metaspace.cpp     |  14 ++
 hotspot/src/share/vm/memory/metaspace.hpp     |   2 +
 .../src/share/vm/memory/metaspaceShared.cpp   |  22 +++
 .../src/share/vm/memory/metaspaceShared.hpp   |   5 +-
 hotspot/src/share/vm/oops/instanceKlass.cpp   |   5 +-
 hotspot/src/share/vm/runtime/arguments.cpp    |  34 ++--
 hotspot/src/share/vm/runtime/arguments.hpp    |   6 +
 hotspot/src/share/vm/utilities/hashtable.cpp  |   1 +
 hotspot/test/runtime/appcds/TestCommon.java   |  74 ++++++++-
 .../appcds/dynamicArchive/DynamicFlag.java    |  39 +++++
 .../dynamicArchive/DynamicHelloTest.java      |  42 +++++
 .../VerifyWithDynamicArchive.java             |  42 +++++
 jdk/make/BuildJdk.gmk                         |   7 +
 30 files changed, 603 insertions(+), 37 deletions(-)
 create mode 100644 hotspot/test/runtime/appcds/dynamicArchive/DynamicFlag.java
 create mode 100644 hotspot/test/runtime/appcds/dynamicArchive/DynamicHelloTest.java
 create mode 100644 hotspot/test/runtime/appcds/dynamicArchive/VerifyWithDynamicArchive.java

diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac
index 151e5a10..dbcdd59e 100644
--- a/common/autoconf/configure.ac
+++ b/common/autoconf/configure.ac
@@ -98,6 +98,9 @@ JDKOPT_SETUP_JVM_INTERPRETER
 JDKOPT_SETUP_JVM_VARIANTS
 JDKOPT_SETUP_DEBUG_LEVEL
 
+# Enable default CDS ARCHIVE
+JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE
+
 # With basic setup done, call the custom early hook.
 CUSTOM_EARLY_HOOK
 
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index c41c4336..f0e49f50 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -883,6 +883,7 @@ OUTPUT_ROOT
 CONF_NAME
 SPEC
 DEVKIT_LIB_DIR
+BUILD_CDS_ARCHIVE
 BUILD_VARIANT_RELEASE
 DEBUG_CLASSFILES
 FASTDEBUG
@@ -1047,6 +1048,7 @@ with_jvm_interpreter
 with_jvm_variants
 enable_debug
 with_debug_level
+enable_cds_archive
 with_devkit
 with_sys_root
 with_sysroot
@@ -1857,6 +1859,8 @@ Optional Features:
                           [disabled]
   --enable-debug          set the debug level to fastdebug (shorthand for
                           --with-debug-level=fastdebug) [disabled]
+  --disable-cds-archive   Set to disable generation of a default CDS archive
+                          in the product image [enabled]
   --disable-headful       disable building headful support (graphical UI
                           support) [enabled]
   --enable-hotspot-test-in-build
@@ -14704,6 +14708,42 @@ fi
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEBUG_LEVEL" >&5
 $as_echo "$DEBUG_LEVEL" >&6; }
 
+
+
+# Enable default CDS ARCHIVE
+
+  # Check whether --enable-cds-archive was given.
+if test "${enable_cds_archive+set}" = set; then :
+  enableval=$enable_cds_archive;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if a default CDS archive should be generated" >&5
+$as_echo_n "checking if a default CDS archive should be generated... " >&6; }
+  if test "x$COMPILE_TYPE" = "xcross"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, not possible with cross compilation" >&5
+$as_echo "no, not possible with cross compilation" >&6; }
+    BUILD_CDS_ARCHIVE="false"
+  elif test "x$enable_cds_archive" = "xyes"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, forced" >&5
+$as_echo "yes, forced" >&6; }
+    BUILD_CDS_ARCHIVE="true"
+  elif test "x$enable_cds_archive" = "x"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    BUILD_CDS_ARCHIVE="true"
+  elif test "x$enable_cds_archive" = "xno"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5
+$as_echo "no, forced" >&6; }
+    BUILD_CDS_ARCHIVE="false"
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    as_fn_error $? "--enable-cds_archive can only be yes/no or empty" "$LINENO" 5
+  fi
+
+
+
   if test "x$DEBUG_LEVEL" != xrelease && \
       test "x$DEBUG_LEVEL" != xfastdebug && \
       test "x$DEBUG_LEVEL" != xslowdebug; then
diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4
index bca78afe..c506086d 100644
--- a/common/autoconf/jdk-options.m4
+++ b/common/autoconf/jdk-options.m4
@@ -789,6 +789,38 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS],
   AC_SUBST(ZIP_DEBUGINFO_FILES)
 ])
 
+################################################################################
+#
+# Disable the default CDS archive generation
+#   cross compilation - disabled
+#
+AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE],
+[
+  AC_ARG_ENABLE([cds-archive], [AS_HELP_STRING([--disable-cds-archive],
+      [Set to disable generation of a default CDS archive in the product image @<:@enabled@:>@])])
+
+  AC_MSG_CHECKING([if a default CDS archive should be generated])
+  if test "x$COMPILE_TYPE" = "xcross"; then
+    AC_MSG_RESULT([no, not possible with cross compilation])
+    BUILD_CDS_ARCHIVE="false"
+  elif test "x$enable_cds_archive" = "xyes"; then
+    AC_MSG_RESULT([yes, forced])
+    BUILD_CDS_ARCHIVE="true"
+  elif test "x$enable_cds_archive" = "x"; then
+    AC_MSG_RESULT([yes])
+    BUILD_CDS_ARCHIVE="true"
+  elif test "x$enable_cds_archive" = "xno"; then
+    AC_MSG_RESULT([no, forced])
+    BUILD_CDS_ARCHIVE="false"
+  else
+    AC_MSG_RESULT([no])
+    AC_MSG_ERROR([--enable-cds_archive can only be yes/no or empty])
+  fi
+
+  AC_SUBST(BUILD_CDS_ARCHIVE)
+])
+
+
 # Support for customization of the build process. Some build files
 # will include counterparts from this location, if they exist. This allows
 # for a degree of customization of the build targets and the rules/recipes
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index 4c3a9f61..79248cbf 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -612,6 +612,10 @@ LIBZIP_CAN_USE_MMAP:=@LIBZIP_CAN_USE_MMAP@
 VCRUNTIME_1_DLL:=@VCRUNTIME_1_DLL@
 MSVCP_DLL:=@MSVCP_DLL@
 UCRT_DLL_DIR:=@UCRT_DLL_DIR@
+# CDS_ARCHIVE
+BUILD_CDS_ARCHIVE:=@BUILD_CDS_ARCHIVE@
+
+
 
 
 # ADD_SRCS takes a single argument with source roots
diff --git a/common/bin/compare.sh b/common/bin/compare.sh
index ff88bb1f..a36464a9 100644
--- a/common/bin/compare.sh
+++ b/common/bin/compare.sh
@@ -290,6 +290,7 @@ compare_general_files() {
         ! -name "ct.sym" ! -name "*.diz" ! -name "*.dll" \
         ! -name "*.pdb" ! -name "*.exp" ! -name "*.ilk" \
         ! -name "*.lib" ! -name "*.war" ! -name "JavaControlPanel" \
+        ! -name "classes.jsa" \
         | $GREP -v "./bin/"  | $SORT | $FILTER)
 
     echo General files...
diff --git a/hotspot/src/share/vm/cds/archiveBuilder.cpp b/hotspot/src/share/vm/cds/archiveBuilder.cpp
index 144dedfa..13a62002 100644
--- a/hotspot/src/share/vm/cds/archiveBuilder.cpp
+++ b/hotspot/src/share/vm/cds/archiveBuilder.cpp
@@ -59,6 +59,18 @@ ArchiveBuilder::SourceObjList::~SourceObjList() {
   delete _objs;
 }
 
+static void caculate_fingerprint(Klass * klass) {
+  if (klass->oop_is_instance()) {
+    InstanceKlass* ik = InstanceKlass::cast(klass);
+    for (int i = 0; i < ik->methods()->length(); i++) {
+      Method* m = ik->methods()->at(i);
+      Fingerprinter fp(m);
+      // The side effect of this call sets method's fingerprint field.
+      fp.fingerprint();
+    }
+  }
+}
+
 void ArchiveBuilder::SourceObjList::append(MetaspaceClosure::Ref* enclosing_ref, SourceObjInfo* src_info) {
   // Save this source object for copying
   _objs->append(src_info);
@@ -166,6 +178,7 @@ ArchiveBuilder::ArchiveBuilder() :
   _buffer_to_requested_delta(0),
   _rw_region("rw", MAX_SHARED_DELTA),
   _ro_region("ro", MAX_SHARED_DELTA),
+  _md_region("md", MAX_SHARED_DELTA),
   _rw_src_objs(),
   _ro_src_objs(),
   _src_obj_table(INITIAL_TABLE_SIZE),
@@ -384,6 +397,7 @@ bool ArchiveBuilder::gather_klass_and_symbol(MetaspaceClosure::Ref* ref, bool re
     Klass* klass = (Klass*)ref->obj();
     assert(klass->is_klass(), "must be");
     if (!is_excluded(klass)) {
+      caculate_fingerprint(klass);
       _klasses->append(klass);
       if (klass->oop_is_instance()) {
         _num_instance_klasses ++;
@@ -434,7 +448,8 @@ size_t ArchiveBuilder::estimate_archive_size() {
 
 address ArchiveBuilder::reserve_buffer() {
   size_t buffer_size = estimate_archive_size();
-  ReservedSpace rs(buffer_size, os::vm_allocation_granularity(), false);
+  size_t package_hash_table_est = align_up(ClassLoader::estimate_size_for_archive(), (size_t)os::vm_allocation_granularity());
+  ReservedSpace rs(buffer_size + package_hash_table_est, os::vm_allocation_granularity(), false);
   if (!rs.is_reserved()) {
     tty->print_cr("Failed to reserve " SIZE_FORMAT " bytes of output buffer.", buffer_size);
     vm_direct_exit(0);
@@ -443,7 +458,8 @@ address ArchiveBuilder::reserve_buffer() {
   // buffer_bottom is the lowest address of the 2 core regions (rw, ro) when
   // we are copying the class metadata into the buffer.
   address buffer_bottom = (address)rs.base();
-  _shared_rs = rs;
+  _shared_rs = rs.first_part(buffer_size);
+  _md_rs = rs.last_part(buffer_size);
 
   _buffer_bottom = buffer_bottom;
   _last_verified_top = buffer_bottom;
@@ -508,6 +524,19 @@ void ArchiveBuilder::dump_ro_metadata() {
   make_shallow_copies(&_ro_region, &_ro_src_objs);
 }
 
+void ArchiveBuilder::dump_md_metadata() {
+  ResourceMark rm;
+  if (InfoDynamicCDS) {
+    dynamic_cds_log->print_cr("Allocating MD objects ... ");
+  }
+  _current_dump_space = &_md_region;
+  _md_region.init(&_md_rs, &_md_vs);
+  char* md_top = _md_vs.low();
+  char* md_end = _md_vs.high_boundary();
+  _md_region.allocate(md_end - md_top);
+  ClassLoader::serialize_package_hash_table(&md_top, md_end);
+}
+
 void ArchiveBuilder::start_dump_space(DumpRegion* next) {
   address bottom = _last_verified_top;
   address top = (address)(_current_dump_space->top());
@@ -749,6 +778,7 @@ void ArchiveBuilder::write_archive(FileMapInfo* mapinfo) {
 
   write_region(mapinfo, MetaspaceShared::d_rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
   write_region(mapinfo, MetaspaceShared::d_ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
+  write_region(mapinfo, MetaspaceShared::d_md, &_md_region, /*read_only=*/true, /*allow_exec=*/false);
 
   char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap());
 
diff --git a/hotspot/src/share/vm/cds/archiveBuilder.hpp b/hotspot/src/share/vm/cds/archiveBuilder.hpp
index 18cd3c62..f7a5c107 100644
--- a/hotspot/src/share/vm/cds/archiveBuilder.hpp
+++ b/hotspot/src/share/vm/cds/archiveBuilder.hpp
@@ -163,10 +163,13 @@ private:
   static const int MAX_TABLE_SIZE     = 1000000;
 
   ReservedSpace _shared_rs;
+  ReservedSpace _md_rs;
   VirtualSpace _shared_vs;
+  VirtualSpace _md_vs;
 
   DumpRegion _rw_region;
   DumpRegion _ro_region;
+  DumpRegion _md_region;
   BitMap _ptrmap;
 
   SourceObjList _rw_src_objs;                 // objs to put in rw region
@@ -327,6 +330,7 @@ public:
 
   void dump_rw_metadata();
   void dump_ro_metadata();
+  void dump_md_metadata();
   void relocate_metaspaceobj_embedded_pointers();
   void relocate_roots();
   void make_klasses_shareable();
diff --git a/hotspot/src/share/vm/cds/dynamicArchive.cpp b/hotspot/src/share/vm/cds/dynamicArchive.cpp
index efed275c..a623c5b0 100644
--- a/hotspot/src/share/vm/cds/dynamicArchive.cpp
+++ b/hotspot/src/share/vm/cds/dynamicArchive.cpp
@@ -149,6 +149,7 @@ public:
 
     relocate_to_requested();
 
+    dump_md_metadata();
     write_archive(serialized_data);
     release_header();
 
diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp
index e3470ca8..04fa84d4 100644
--- a/hotspot/src/share/vm/classfile/classLoader.cpp
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp
@@ -219,6 +219,30 @@ const char* ClassLoader::package_from_name(const char* const class_name, bool* b
   return (const char *)pkg_name;
 }
 
+const char* ClassLoader::get_file_name_from_path(const char* path) {
+  const char* pos = strrchr(path, '/');
+  if (pos == NULL) {
+    return path;
+  } else {
+    return pos + 1;
+  }
+}
+
+const char* ClassLoader::get_boot_class_path(const char* shared_path) {
+  const char* shared_name = get_file_name_from_path(shared_path);
+  ClassPathEntry* e = _first_entry;
+  while (e != NULL) {
+    if (e->sys_class()) {
+      const char* name = get_file_name_from_path(e->name());
+      if (strcmp(name, shared_name) == 0) {
+        return e->name();
+      }
+    }
+    e = e->next();
+  }
+  return NULL;
+}
+
 MetaIndex::MetaIndex(char** meta_package_names, int num_meta_package_names) {
   if (num_meta_package_names == 0) {
     _meta_package_names = NULL;
@@ -512,6 +536,8 @@ void ClassLoader::setup_meta_index(const char* meta_index_path, const char* meta
   int line_no = 0;
 #if INCLUDE_CDS
   if (DumpSharedSpaces) {
+    meta_index_path = Arguments::get_is_default_jsa() ?
+                        get_file_name_from_path(meta_index_path) : meta_index_path;
     if (file != NULL) {
       _shared_paths_misc_info->add_required_file(meta_index_path);
     } else {
@@ -644,7 +670,9 @@ void ClassLoader::setup_bootstrap_search_path() {
   }
 #if INCLUDE_CDS
   if (DumpSharedSpaces) {
-    _shared_paths_misc_info->add_boot_classpath(sys_class_path);
+    const char* new_sys_class_path = Arguments::get_is_default_jsa() ?
+                                       get_file_name_from_path(sys_class_path) : sys_class_path;
+    _shared_paths_misc_info->add_boot_classpath(new_sys_class_path);
   }
 #endif
   setup_search_path(sys_class_path);
@@ -688,7 +716,7 @@ void ClassLoader::setup_search_path(const char *class_path, bool canonicalize) {
         path = canonical_path;
       }
     }
-    update_class_path_entry_list(path, /*check_for_duplicates=*/canonicalize);
+    update_class_path_entry_list(path, /*check_for_duplicates=*/canonicalize, true, true);
 #if INCLUDE_CDS
     if (DumpSharedSpaces) {
       check_shared_classpath(path);
@@ -816,7 +844,9 @@ void ClassLoader::add_to_list(ClassPathEntry *new_entry) {
 // Returns true IFF the file/dir exists and the entry was successfully created.
 bool ClassLoader::update_class_path_entry_list(const char *path,
                                                bool check_for_duplicates,
-                                               bool throw_exception) {
+                                               bool throw_exception,
+                                               bool sys_class_type) {
+  // sys_class_type indicates whether *path is a system path. The default value is false.
   struct stat st;
   if (os::stat(path, &st) == 0) {
     // File or directory found
@@ -826,6 +856,11 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
     if (new_entry == NULL) {
       return false;
     }
+    // If the path is a system path, set sys_class of the newly created
+    // linked list node to true. The default value is false.
+    if (sys_class_type) {
+      new_entry->set_sys_class(true);
+    }
     // The kernel VM adds dynamically to the end of the classloader path and
     // doesn't reorder the bootclasspath which would break java.lang.Package
     // (see PackageInfo).
@@ -837,6 +872,8 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
   } else {
 #if INCLUDE_CDS
     if (DumpSharedSpaces) {
+      path = Arguments::get_is_default_jsa() ?
+               get_file_name_from_path(path) : path;
       _shared_paths_misc_info->add_nonexist_path(path);
     }
 #endif
@@ -918,6 +955,7 @@ int ClassLoader::crc32(int crc, const char* buf, int len) {
 class PackageInfo: public BasicHashtableEntry<mtClass> {
 public:
   const char* _pkgname;       // Package name
+  const char* _filename;      // File name
   int _classpath_index;       // Index of directory or JAR file loaded from
 
   PackageInfo* next() {
@@ -926,9 +964,10 @@ public:
 
   const char* pkgname()           { return _pkgname; }
   void set_pkgname(char* pkgname) { _pkgname = pkgname; }
+  void set_filename(char* filename) { _filename = filename; }
 
   const char* filename() {
-    return ClassLoader::classpath_entry(_classpath_index)->name();
+    return _filename == NULL ? ClassLoader::classpath_entry(_classpath_index)->name() : _filename;
   }
 
   void set_index(int index) {
@@ -975,11 +1014,12 @@ public:
     return get_entry(hash_to_index(hash), hash, pkgname, n);
   }
 
-  PackageInfo* new_entry(char* pkgname, int n) {
+  PackageInfo* new_entry(char* pkgname, int n, char* filename = NULL) {
     unsigned int hash = compute_hash(pkgname, n);
     PackageInfo* pp;
     pp = (PackageInfo*)BasicHashtable<mtClass>::new_entry(hash);
     pp->set_pkgname(pkgname);
+    pp->set_filename(filename);
     return pp;
   }
 
@@ -999,6 +1039,9 @@ public:
   }
 
   CDS_ONLY(void copy_table(char** top, char* end, PackageHashtable* table);)
+  CDS_ONLY(void serialize(char** top, char* end);)
+  CDS_ONLY(void deserialize(char* start);)
+  CDS_ONLY(size_t estimate_size();)
 };
 
 #if INCLUDE_CDS
@@ -1035,6 +1078,93 @@ void PackageHashtable::copy_table(char** top, char* end,
   *tableSize = len;
 }
 
+size_t PackageHashtable::estimate_size() {
+  int size = sizeof(int);
+  ClassPathEntry* e = ClassLoader::_first_entry;
+  while (e != NULL) {
+    int length = (int)(strlen(e->name()) + 1);
+    size += length;
+    e = e->next();
+  }
+  size = align_size_up(size, sizeof(int));
+
+  size += sizeof(int);
+  for (int i = 0; i < table_size(); ++i) {
+    for (PackageInfo* pp = bucket(i);
+                      pp != NULL;
+                      pp = pp->next()) {
+      size += sizeof(int);
+      int n1 = (int)(strlen(pp->pkgname()) + 1);
+      n1 = align_size_up(n1, sizeof(int));
+      size += n1;
+    }
+  }
+  return align_size_up(size, sizeof(int));
+}
+
+void PackageHashtable::serialize(char** top, char* end) {
+  *(int*)(*top) = ClassLoader::_num_entries;
+  *top += sizeof(int);
+
+  ClassPathEntry* e = ClassLoader::_first_entry;
+  while (e != NULL) {
+    int length = (int)(strlen(e->name()) + 1);
+    memcpy(*top, e->name(), length);
+    *top += length;
+    e = e->next();
+  }
+  *top = (char*)align_size_up((intptr_t)*top, sizeof(int));
+  *(int*)(*top) = number_of_entries();
+  *top += sizeof(int);
+
+  for (int i = 0; i < table_size(); ++i) {
+    for (PackageInfo* pp = bucket(i);
+                      pp != NULL;
+                      pp = pp->next()) {
+      *(int*)(*top) = pp->_classpath_index;
+      *top += sizeof(int);
+      int n1 = (int)(strlen(pp->pkgname()) + 1);
+      memcpy(*top, pp->pkgname(), n1);
+      n1 = align_size_up(n1, sizeof(int));
+      *top += n1;
+    }
+  }
+}
+
+void PackageHashtable::deserialize(char* start) {
+  int num_entries = *(int*)start;
+  char** class_loader_entries = NEW_C_HEAP_ARRAY(char*, num_entries, mtClass);
+  start += sizeof(int);
+  int entries_len = 0;
+  for (int i = 0, index = 0; i < num_entries; i++) {
+    class_loader_entries[index++] = start + entries_len;
+    entries_len += (int)(strlen(start + entries_len) + 1);
+  }
+  start += align_size_up(entries_len, sizeof(int));
+  int number_of_entries = *(int*)start;
+  start += sizeof(int);
+  for (int i = 0; i < number_of_entries; i++) {
+    int classpath_index = *(int*)start;
+    start += sizeof(int);
+    char* pkgname = start;
+    const char *cp = strrchr(pkgname, '/');
+    if (cp != NULL) {
+      int n = cp - pkgname + 1;
+      if (get_entry(pkgname, n) == NULL) {
+        PackageInfo* info = new_entry(pkgname, n, class_loader_entries[classpath_index]);
+        add_entry(info);
+      }
+    }
+    int n1 = (int)(strlen(start) + 1);
+    start += align_size_up(n1, sizeof(int));
+  }
+  FREE_C_HEAP_ARRAY(char*, class_loader_entries, mtClass);
+}
+
+void ClassLoader::deserialize_package_hash_table(char* start) {
+  assert(_package_hash_table != NULL, "should have one yet");
+  _package_hash_table->deserialize(start);
+}
 
 void ClassLoader::copy_package_info_buckets(char** top, char* end) {
   _package_hash_table->copy_buckets(top, end);
@@ -1043,6 +1173,14 @@ void ClassLoader::copy_package_info_buckets(char** top, char* end) {
 void ClassLoader::copy_package_info_table(char** top, char* end) {
   _package_hash_table->copy_table(top, end, _package_hash_table);
 }
+
+size_t ClassLoader::estimate_size_for_archive() {
+  return _package_hash_table->estimate_size();
+}
+
+void ClassLoader::serialize_package_hash_table(char** top, char* end) {
+  return _package_hash_table->serialize(top, end);
+}
 #endif
 
 PackageInfo* ClassLoader::lookup_package(const char *pkgname) {
@@ -1226,8 +1364,8 @@ void ClassLoader::create_package_info_table(HashtableBucket<mtClass> *t, int len
 
 
 void ClassLoader::create_package_info_table() {
-    assert(_package_hash_table == NULL, "shouldn't have one yet");
-    _package_hash_table = new PackageHashtable(package_hash_table_size);
+  assert(_package_hash_table == NULL, "shouldn't have one yet");
+  _package_hash_table = new PackageHashtable(package_hash_table_size);
 }
 
 
diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp
index 9514d3bb..cf39ce99 100644
--- a/hotspot/src/share/vm/classfile/classLoader.hpp
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp
@@ -49,13 +49,18 @@ class MetaIndex: public CHeapObj<mtClass> {
 class ClassPathEntry: public CHeapObj<mtClass> {
  private:
   ClassPathEntry* _next;
+  bool _sys_class;
  public:
   // Next entry in class path
   ClassPathEntry* next()              { return _next; }
+  bool sys_class() const { return _sys_class; }
   void set_next(ClassPathEntry* next) {
     // may have unlocked readers, so write atomically.
     OrderAccess::release_store_ptr(&_next, next);
   }
+  void set_sys_class(bool isSysClass) {
+    _sys_class = isSysClass;
+  }
   virtual bool is_jar_file() = 0;
   virtual const char* name() = 0;
   virtual bool is_lazy();
@@ -158,6 +163,7 @@ class ClassLoader: AllStatic {
   };
  protected:
   friend class LazyClassPathEntry;
+  friend class PackageHashtable;
 
   // Performance counters
   static PerfCounter* _perf_accumulated_time;
@@ -234,7 +240,8 @@ class ClassLoader: AllStatic {
   static int crc32(int crc, const char* buf, int len);
   static bool update_class_path_entry_list(const char *path,
                                            bool check_for_duplicates,
-                                           bool throw_exception=true);
+                                           bool throw_exception=true,
+                                           bool sys_class=false);
   static void print_bootclasspath();
 
   // Timing
@@ -318,6 +325,9 @@ class ClassLoader: AllStatic {
   // Initialization
   static void initialize();
   CDS_ONLY(static void initialize_shared_path();)
+  static const char* get_file_name_from_path(const char* path);
+  static const char* get_boot_class_path(const char* shared_path);
+
   static void create_package_info_table();
   static void create_package_info_table(HashtableBucket<mtClass> *t, int length,
                                         int number_of_entries);
@@ -340,6 +350,9 @@ class ClassLoader: AllStatic {
   // Sharing dump and restore
   static void copy_package_info_buckets(char** top, char* end);
   static void copy_package_info_table(char** top, char* end);
+  static size_t estimate_size_for_archive();
+  static void serialize_package_hash_table(char** top, char* end);
+  static void deserialize_package_hash_table(char* start);
 
   static void  check_shared_classpath(const char *path);
   static void  finalize_shared_paths_misc_info();
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp
index 9b901303..7155257e 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp
@@ -168,6 +168,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
   friend class ClassLoaderDataGraphMetaspaceIterator;
   friend class MetaDataFactory;
   friend class Method;
+  friend class VM_PopulateDumpSharedSpace;
 
   static ClassLoaderData * _the_null_class_loader_data;
 
diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp
index b9d473b0..d41372ec 100644
--- a/hotspot/src/share/vm/classfile/dictionary.cpp
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp
@@ -197,7 +197,7 @@ void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
 }
 
 void Dictionary::remove_classes_in_error_state() {
-  assert(DumpSharedSpaces, "supported only when dumping");
+  assert(DynamicDumpSharedSpaces || DumpSharedSpaces, "supported only when dumping");
   DictionaryEntry* probe = NULL;
   for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp
index 882fed01..b1609e46 100644
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp
@@ -26,6 +26,7 @@
 #define SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP
 
 #include "runtime/os.hpp"
+#include "runtime/arguments.hpp"
 
 // During dumping time, when processing class paths, we build up the dump-time
 // classpath. The JAR files that exist are stored in the list ClassLoader::_first_entry.
@@ -111,12 +112,18 @@ public:
     add_path(path, REQUIRED);
 
     struct stat st;
-    if (os::stat(path, &st) != 0) {
+    if (!Arguments::get_is_default_jsa() && os::stat(path, &st) != 0) {
       assert(0, "sanity");
       ClassLoader::exit_with_path_failure("failed to os::stat(%s)", path); // should not happen
     }
-    write_time(st.st_mtime);
-    write_long(st.st_size);
+
+    if (Arguments::get_is_default_jsa()) {
+      write_time(0);
+      write_long(0);
+    } else {
+      write_time(st.st_mtime);
+      write_long(st.st_size);
+    }
   }
 
   // The path must exist, and must contain exactly <num_entries> files/dirs
diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp
index 99354cd4..3a601ee3 100644
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp
@@ -659,7 +659,7 @@ bool SystemDictionaryShared::warn_excluded(InstanceKlass* k, const char* reason)
 
 bool SystemDictionaryShared::is_jfr_event_class(InstanceKlass *k) {
   while (k) {
-    if (k->name()->equals("jdk/jfr/Event")) {
+    if (k->name()->equals("jdk/jfr/Event") || k->name()->starts_with("jdk/jfr/event")) {
       return true;
     }
     k = k->java_super();
diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp
index 3f410647..5fd62a74 100644
--- a/hotspot/src/share/vm/memory/filemap.cpp
+++ b/hotspot/src/share/vm/memory/filemap.cpp
@@ -263,7 +263,12 @@ void FileMapInfo::allocate_classpath_entry_table() {
 
     for (int cur_entry = 0 ; cpe != NULL; cpe = cpe->next(), cur_entry++) {
       const char *name = cpe->name();
-      int name_bytes = (int)(strlen(name) + 1);
+      int name_bytes;
+      if (cpe->sys_class()) {
+        name_bytes = (int)(strlen(ClassLoader::get_file_name_from_path(name)) + 1);
+      } else {
+        name_bytes = (int)(strlen(name) + 1);
+      }
 
       if (pass == 0) {
         count ++;
@@ -286,7 +291,13 @@ void FileMapInfo::allocate_classpath_entry_table() {
           }
 
           EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
-          SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);
+          if (cpe->sys_class()) {
+            // Jdk boot jar not need validate timestamp for we may copy whole jdk.
+            SharedClassUtil::update_shared_classpath(cpe, ent, 0, st.st_size, THREAD);
+            ent->set_sys_class(true);
+          } else {
+            SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);
+          }
         } else {
           ent->_filesize  = -1;
           if (!os::dir_is_empty(name)) {
@@ -295,7 +306,11 @@ void FileMapInfo::allocate_classpath_entry_table() {
         }
         ent->_name = strptr;
         if (strptr + name_bytes <= strptr_max) {
-          strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0.
+          if (cpe->sys_class()) {
+            strncpy(strptr, ClassLoader::get_file_name_from_path(name), (size_t)name_bytes);
+          } else {
+            strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0.
+          }
           strptr += name_bytes;
         } else {
           assert(0, "miscalculated buffer size");
@@ -334,6 +349,14 @@ bool FileMapInfo::validate_classpath_entry_table() {
     if (TraceClassPaths || (TraceClassLoading && Verbose)) {
       tty->print_cr("[Checking shared classpath entry: %s]", name);
     }
+    if (ent->_sys_class) {
+      name = ClassLoader::get_boot_class_path(name);
+      if (name == NULL) {
+        fail_continue("Required classpath entry of system class does not exist");
+        continue;
+      }
+    }
+
     if (os::stat(name, &st) != 0) {
       fail_continue("Required classpath entry does not exist: %s", name);
       ok = false;
@@ -343,7 +366,7 @@ bool FileMapInfo::validate_classpath_entry_table() {
         ok = false;
       }
     } else {
-      if (ent->_timestamp != st.st_mtime ||
+      if ((ent->_timestamp != 0 && ent->_timestamp != st.st_mtime) ||
           ent->_filesize != st.st_size) {
         ok = false;
         if (PrintSharedArchiveAndExit) {
@@ -640,6 +663,7 @@ void FileMapInfo::write_space(int i, Metaspace* space, bool read_only) {
   size_t used = space->used_bytes_slow(Metaspace::NonClassType);
   size_t capacity = space->capacity_bytes_slow(Metaspace::NonClassType);
   struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
+  space->reset_metachunks();
   write_region(i, (char*)space->bottom(), used, capacity, read_only, false);
 }
 
@@ -967,7 +991,7 @@ bool FileMapInfo::validate_header() {
     return DynamicArchive::validate(this);
   }
 
-  if (status) {
+  if (status && !_header->_is_default_jsa) {
     if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size)) {
       if (!PrintSharedArchiveAndExit) {
         fail_continue("shared class paths mismatch (hint: enable -XX:+TraceClassPaths to diagnose the failure)");
diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp
index eab9ebcf..36b27f13 100644
--- a/hotspot/src/share/vm/memory/filemap.hpp
+++ b/hotspot/src/share/vm/memory/filemap.hpp
@@ -52,9 +52,13 @@ public:
   const char *_name;
   time_t _timestamp;          // jar timestamp,  0 if is directory
   long   _filesize;           // jar file size, -1 if is directory
+  bool _sys_class;
   bool is_dir() {
     return _filesize == -1;
   }
+  void set_sys_class(bool isSysClass) {
+    _sys_class = isSysClass;
+  }
 };
 
 class FileMapInfo : public CHeapObj<mtInternal> {
@@ -100,6 +104,7 @@ public:
     int          _version;                  // (from enum, above.)
     size_t       _alignment;                // how shared archive should be aligned
     int          _obj_alignment;            // value of ObjectAlignmentInBytes
+    bool         _is_default_jsa;           // indicates whether is the default jsa file
 
     struct space_info {
       int    _crc;           // crc checksum of the current space
@@ -264,6 +269,8 @@ public:
   bool  is_open()                                   { return _file_open; }
   bool  is_static()                           const { return _is_static; }
   bool  is_mapped()                           const { return _is_mapped; }
+  bool  is_default_jsa()                      const { return _header->_is_default_jsa; }
+  void  set_is_default_jsa(bool v)                  { _header->_is_default_jsa = v; }
   void  set_is_mapped(bool v)                       { _is_mapped = v; }
   ReservedSpace reserve_shared_memory();
   void set_requested_base(char* b)                  { dynamic_header()->set_requested_base(b); }
diff --git a/hotspot/src/share/vm/memory/metachunk.hpp b/hotspot/src/share/vm/memory/metachunk.hpp
index e873dc6a..7889b622 100644
--- a/hotspot/src/share/vm/memory/metachunk.hpp
+++ b/hotspot/src/share/vm/memory/metachunk.hpp
@@ -126,6 +126,8 @@ class Metachunk : public Metabase<Metachunk> {
 
   VirtualSpaceNode* container() const { return _container; }
 
+  void reset_container() { _container = NULL; }
+
   MetaWord* bottom() const { return (MetaWord*) this; }
 
   // Reset top to bottom so chunk can be reused.
diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp
index 7e95b5c0..6c4654b2 100644
--- a/hotspot/src/share/vm/memory/metaspace.cpp
+++ b/hotspot/src/share/vm/memory/metaspace.cpp
@@ -775,6 +775,7 @@ class SpaceManager : public CHeapObj<mtClass> {
   // Notify memory usage to MemoryService.
   void track_metaspace_memory_usage();
 
+  void reset_metachunks();
   // debugging support.
 
   void dump(outputStream* const out) const;
@@ -1923,6 +1924,15 @@ void ChunkManager::print_on(outputStream* out) const {
 
 // SpaceManager methods
 
+void SpaceManager::reset_metachunks() {
+  for (ChunkIndex i = ZeroIndex; i <= HumongousIndex; i = next_chunk_index(i)) {
+    Metachunk* chunks = chunks_in_use(i);
+    if (chunks != NULL) {
+      chunks->reset_container();
+    }
+  }
+}
+
 size_t SpaceManager::adjust_initial_chunk_size(size_t requested, bool is_class_space) {
   size_t chunk_sizes[] = {
       specialized_chunk_size(is_class_space),
@@ -3002,6 +3012,10 @@ Metaspace::~Metaspace() {
   }
 }
 
+void Metaspace::reset_metachunks() {
+  vsm()->reset_metachunks();
+}
+
 VirtualSpaceList* Metaspace::_space_list = NULL;
 VirtualSpaceList* Metaspace::_class_space_list = NULL;
 
diff --git a/hotspot/src/share/vm/memory/metaspace.hpp b/hotspot/src/share/vm/memory/metaspace.hpp
index 2b06cb62..122dd4bf 100644
--- a/hotspot/src/share/vm/memory/metaspace.hpp
+++ b/hotspot/src/share/vm/memory/metaspace.hpp
@@ -243,6 +243,8 @@ class Metaspace : public CHeapObj<mtClass> {
   MetaWord* expand_and_allocate(size_t size,
                                 MetadataType mdtype);
 
+  void reset_metachunks();
+
   static bool contains(const void* ptr);
 
   void dump(outputStream* const out) const;
diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp
index 00fb9fe9..b31d0a3f 100644
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp
@@ -205,6 +205,21 @@ static void patch_klass_vtables(void** vtbl_list, void* new_vtable_start) {
   }
 }
 
+static void patch_deallocate_meta_vtables(void** vtbl_list, void* new_vtable_start, GrowableArray<Metadata*>* deallocate_list) {
+  if (deallocate_list == NULL) {
+    return;
+  }
+  for (int i = deallocate_list->length() - 1; i >= 0; i--) {
+    Metadata* m = deallocate_list->at(i);
+    if (!m->on_stack()) {
+      if (m->is_constantPool()) {
+        ((ConstantPool*)m)->remove_unshareable_info();
+        *(void**)m = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, m);
+      }
+    }
+  }
+}
+
 // Closure for serializing initialization data out to a data area to be
 // written to the shared file.
 
@@ -591,6 +606,7 @@ void VM_PopulateDumpSharedSpace::doit() {
   // Update the vtable pointers in all of the Klass objects in the
   // heap. They should point to newly generated vtable.
   patch_klass_vtables(vtbl_list, vtable);
+  patch_deallocate_meta_vtables(vtbl_list, vtable, _loader_data->_deallocate_list);
 
   // dunno what this is for.
   char* saved_vtbl = (char*)os::malloc(vtbl_list_size * sizeof(void*), mtClass);
@@ -602,6 +618,9 @@ void VM_PopulateDumpSharedSpace::doit() {
   FileMapInfo* mapinfo = new FileMapInfo();
   mapinfo->populate_header(MetaspaceShared::max_alignment());
 
+  if (Arguments::get_is_default_jsa()) {
+    mapinfo->set_is_default_jsa(true);
+  }
   // Pass 1 - update file offsets in header.
   mapinfo->write_header();
   mapinfo->write_space(MetaspaceShared::ro, _loader_data->ro_metaspace(), true);
@@ -997,6 +1016,8 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
          mapinfo->verify_region_checksum(d_rw) &&
         (_ro_base = mapinfo->map_region(d_ro)) != NULL &&
          mapinfo->verify_region_checksum(d_ro) &&
+        (_ro_base = mapinfo->map_region(d_md)) != NULL &&
+         mapinfo->verify_region_checksum(d_md) &&
         (image_alignment == (size_t)max_alignment())) {
       mapinfo->set_is_mapped(true);
       return true;
@@ -1153,6 +1174,7 @@ void MetaspaceShared::initialize_shared_spaces() {
     ReadClosure rc(&buffer);
     SymbolTable::serialize_shared_table_header(&rc);
     SystemDictionaryShared::serialize_dictionary_headers(&rc);
+    ClassLoader::deserialize_package_hash_table(dynamic_mapinfo->region_base(d_md));
     dynamic_mapinfo->close();
   }
 
diff --git a/hotspot/src/share/vm/memory/metaspaceShared.hpp b/hotspot/src/share/vm/memory/metaspaceShared.hpp
index a9dadfbb..3eb8b12c 100644
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp
@@ -90,8 +90,9 @@ class MetaspaceShared : AllStatic {
     // core dynamic archive spaces
     d_rw = 0,          // read-write shared space in the heap
     d_ro = 1,          // read-only shared space in the heap
-    d_bm = 2,          // relocation bitmaps (freed after file mapping is finished)
-    d_n_regions = 2    // d_rw and d_ro
+    d_md = 2,          // miscellaneous data
+    d_bm = 3,          // relocation bitmaps (freed after file mapping is finished)
+    d_n_regions = 3    // d_rw, d_ro, d_md
   };
 
   // Accessor functions to save shared space created for metadata, which has
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
index 0d1b1a8d..9276b895 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
@@ -2633,7 +2633,7 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl
 
 // returns true IFF is_in_error_state() has been changed as a result of this call.
 bool InstanceKlass::check_sharing_error_state() {
-  assert(DumpSharedSpaces, "should only be called during dumping");
+  assert(DynamicDumpSharedSpaces || DumpSharedSpaces, "should only be called during dumping");
   bool old_state = is_in_error_state();
 
   if (!is_in_error_state()) {
@@ -3573,6 +3573,9 @@ void InstanceKlass::verify_on(outputStream* st) {
   // Avoid redundant verifies, this really should be in product.
   if (_verify_count == Universe::verify_count()) return;
   _verify_count = Universe::verify_count();
+  if (is_in_error_state()) {
+    return;
+  }
 #endif
 
   // Verify Klass
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 1f603021..5a79ab7e 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -100,6 +100,7 @@ do {                                                                  \
   }                                                                   \
 } while(0)
 
+bool    Arguments::_is_default_jsa              = false;
 char**  Arguments::_jvm_flags_array             = NULL;
 int     Arguments::_num_jvm_flags               = 0;
 char**  Arguments::_jvm_args_array              = NULL;
@@ -4041,23 +4042,32 @@ static void force_serial_gc() {
 }
 #endif // INCLUDE_ALL_GCS
 
+char* Arguments::get_default_shared_archive_path() {
+  char *default_archive_path;
+  char jvm_path[JVM_MAXPATHLEN];
+  os::jvm_path(jvm_path, sizeof(jvm_path));
+  char *end = strrchr(jvm_path, *os::file_separator());
+  if (end != NULL) {
+     *end = '\0';
+  }
+  size_t jvm_path_len = strlen(jvm_path);
+  size_t file_sep_len = strlen(os::file_separator());
+  const size_t len = jvm_path_len + file_sep_len + 20;
+  default_archive_path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
+  if (default_archive_path != NULL) {
+    jio_snprintf(default_archive_path, len, "%s%sclasses.jsa",
+      jvm_path, os::file_separator());
+  }
+  Arguments::set_is_default_jsa(true);
+  return default_archive_path;
+}
+
 // Sharing support
 // Construct the path to the archive
 static char* get_shared_archive_path() {
   char *shared_archive_path;
   if (SharedArchiveFile == NULL) {
-    char jvm_path[JVM_MAXPATHLEN];
-    os::jvm_path(jvm_path, sizeof(jvm_path));
-    char *end = strrchr(jvm_path, *os::file_separator());
-    if (end != NULL) *end = '\0';
-    size_t jvm_path_len = strlen(jvm_path);
-    size_t file_sep_len = strlen(os::file_separator());
-    const size_t len = jvm_path_len + file_sep_len + 20;
-    shared_archive_path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
-    if (shared_archive_path != NULL) {
-      jio_snprintf(shared_archive_path, len, "%s%sclasses.jsa",
-        jvm_path, os::file_separator());
-    }
+    shared_archive_path = Arguments::get_default_shared_archive_path();
   } else {
     shared_archive_path = os::strdup(SharedArchiveFile, mtInternal);
   }
diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp
index 19f5cb60..65907eb4 100644
--- a/hotspot/src/share/vm/runtime/arguments.hpp
+++ b/hotspot/src/share/vm/runtime/arguments.hpp
@@ -240,6 +240,8 @@ class Arguments : AllStatic {
 
  private:
 
+  // Indicates whether the JSA file is the default jsa file.
+  static bool _is_default_jsa;
   // an array containing all flags specified in the .hotspotrc file
   static char** _jvm_flags_array;
   static int    _num_jvm_flags;
@@ -487,6 +489,9 @@ class Arguments : AllStatic {
   // Return the maximum size a heap with compressed oops can take
   static size_t max_heap_for_compressed_oops();
 
+  static void set_is_default_jsa(bool is_default) { _is_default_jsa = is_default; }
+  static bool get_is_default_jsa()         { return _is_default_jsa; }
+
   // return a char* array containing all options
   static char** jvm_flags_array()          { return _jvm_flags_array; }
   static char** jvm_args_array()           { return _jvm_args_array; }
@@ -622,6 +627,7 @@ class Arguments : AllStatic {
   static char* get_ext_dirs() { return _java_ext_dirs->value(); }
   static char* get_appclasspath() { return _java_class_path->value(); }
   static void  fix_appclasspath();
+  static char* get_default_shared_archive_path();
 
   // Operation modi
   static Mode mode()                { return _mode; }
diff --git a/hotspot/src/share/vm/utilities/hashtable.cpp b/hotspot/src/share/vm/utilities/hashtable.cpp
index 66df8f1f..df290d99 100644
--- a/hotspot/src/share/vm/utilities/hashtable.cpp
+++ b/hotspot/src/share/vm/utilities/hashtable.cpp
@@ -58,6 +58,7 @@ template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry(unsig
       len = 1 << log2_int(len); // round down to power of 2
       assert(len >= _entry_size, "");
       _first_free_entry = NEW_C_HEAP_ARRAY2(char, len, F, CURRENT_PC);
+      memset(_first_free_entry, 0, len);
       _end_block = _first_free_entry + len;
     }
     entry = (BasicHashtableEntry<F>*)_first_free_entry;
diff --git a/hotspot/test/runtime/appcds/TestCommon.java b/hotspot/test/runtime/appcds/TestCommon.java
index 22eef4ed..6a61dc31 100644
--- a/hotspot/test/runtime/appcds/TestCommon.java
+++ b/hotspot/test/runtime/appcds/TestCommon.java
@@ -54,6 +54,7 @@ public class TestCommon extends CDSTestUtils {
         System.getProperty("test.timeout.factor", "1.0");
 
     private static String currentArchiveName;
+    private static String topArchiveName;
 
     // Call this method to start new archive with new unique name
     public static void startNewArchiveName() {
@@ -62,6 +63,13 @@ public class TestCommon extends CDSTestUtils {
             timeStampFormat.format(new Date()) + ".jsa";
     }
 
+    public static String getTopArchiveName() {
+        topArchiveName =  System.getProperty("user.dir") +
+            File.separator + "d-appcds-" + timeStampFormat.format(new Date()) + ".jsa";
+        currentArchiveName = topArchiveName;
+        return topArchiveName;
+    }
+
     // Call this method to get current archive name
     public static String getCurrentArchiveName() {
         return currentArchiveName;
@@ -90,6 +98,16 @@ public class TestCommon extends CDSTestUtils {
         }
     }
 
+    public static void deletePriorTopArchives() {
+        File dir = new File(System.getProperty("user.dir"));
+        String files[] = dir.list();
+        for (String name : files) {
+            if (name.startsWith("d-appcds-") && name.endsWith(".jsa")) {
+                if (!(new File(dir, name)).delete())
+                    System.out.println("deletePriorArchives(): delete failed for file " + name);
+            }
+        }
+    }
 
     // Create AppCDS archive using most common args - convenience method
     // Legacy name preserved for compatibility
@@ -132,7 +150,6 @@ public class TestCommon extends CDSTestUtils {
 
         cmd.add("-Xshare:dump");
         cmd.add("-XX:+UseAppCDS");
-//        cmd.add("-Xlog:cds,cds+hashtables"); comment out because it will be run by jdk1.8
         cmd.add("-XX:ExtraSharedClassListFile=" + classList.getPath());
 
         if (opts.archiveName == null)
@@ -147,6 +164,36 @@ public class TestCommon extends CDSTestUtils {
         return executeAndLog(pb, "dump");
     }
 
+    public static OutputAnalyzer createBaseArchive(String appJar, String appClasses[], String... suffix)
+        throws Exception {
+        return createArchive(appJar, appClasses, suffix);
+    }
+
+    public static OutputAnalyzer createTopArchive(String appJar, String...suffix)
+        throws Exception {
+        AppCDSOptions opts = new AppCDSOptions();
+        opts.setAppJar(appJar);
+        opts.addSuffix(suffix);
+
+        ArrayList<String> cmd = new ArrayList<String>();
+        cmd.add("-cp");
+        cmd.add(opts.appJar);
+
+        String baseArchiveName = getCurrentArchiveName();
+        deletePriorTopArchives();
+        String topArchiveNmae = getTopArchiveName();
+        cmd.add("-XX:+UnlockExperimentalVMOptions");
+        cmd.add("-Xshare:on");
+        cmd.add("-XX:SharedArchiveFile=" + baseArchiveName);
+        cmd.add("-XX:ArchiveClassesAtExit=" + topArchiveNmae);
+        cmd.add("-XX:+InfoDynamicCDS");
+
+        for (String s : opts.suffix) cmd.add(s);
+
+        String[] cmdLine = cmd.toArray(new String[cmd.size()]);
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, makeCommandLineForAppCDS(cmdLine));
+        return executeAndLog(pb, "dump");
+    }
 
     // Execute JVM using AppCDS archive with specified AppCDSOptions
     public static OutputAnalyzer runWithArchive(AppCDSOptions opts)
@@ -156,6 +203,9 @@ public class TestCommon extends CDSTestUtils {
 
         for (String p : opts.prefix) cmd.add(p);
 
+        if (topArchiveName != null) {
+            cmd.add("-XX:+InfoDynamicCDS");
+        }
         cmd.add("-Xshare:" + opts.xShareMode);
         cmd.add("-XX:+UseAppCDS");
         cmd.add("-showversion");
@@ -174,7 +224,6 @@ public class TestCommon extends CDSTestUtils {
         return executeAndLog(pb, "exec");
     }
 
-
     public static OutputAnalyzer execCommon(String... suffix) throws Exception {
         AppCDSOptions opts = (new AppCDSOptions());
         opts.addSuffix(suffix);
@@ -261,6 +310,27 @@ public class TestCommon extends CDSTestUtils {
     }
 
 
+    public static OutputAnalyzer testDynamicCDS(String appJar, String appClasses[], String... args)
+        throws Exception {
+        // Create base archive
+        OutputAnalyzer output = createBaseArchive(appJar, appClasses, args);
+        output.shouldContain("Loading classes to share");
+        output.shouldHaveExitValue(0);
+
+        // Create top archive
+        output = createTopArchive(appJar, args);
+        output.shouldContain("Written dynamic archive");
+        output.shouldHaveExitValue(0);
+
+        // Exec with top archive
+        output = exec(appJar, args);
+
+        // Check exec result
+        checkMatches(output, "SharedArchivePath", "SharedDynamicArchivePath");
+        output.shouldHaveExitValue(0);
+        return output;
+    }
+
     public static OutputAnalyzer checkExecReturn(OutputAnalyzer output, int ret,
                            boolean checkContain, String... matches) throws Exception {
         try {
diff --git a/hotspot/test/runtime/appcds/dynamicArchive/DynamicFlag.java b/hotspot/test/runtime/appcds/dynamicArchive/DynamicFlag.java
new file mode 100644
index 00000000..79f30759
--- /dev/null
+++ b/hotspot/test/runtime/appcds/dynamicArchive/DynamicFlag.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary The DynamicDumpShareSpaces flag is internal, setting it at the command line should have no effect.
+ * @library /testlibrary /runtime/appcds /runtime/appcds/test-classes
+ * @compile ../test-classes/Hello.java
+ * @run driver DynamicFlag
+ */
+
+public class DynamicFlag {
+  public static void main(String[] args) throws Exception {
+      TestCommon.testDynamicCDS(JarBuilder.getOrCreateHelloJar(),
+          TestCommon.list("Hello"), "-XX:+DynamicDumpSharedSpaces", "Hello");
+  }
+}
diff --git a/hotspot/test/runtime/appcds/dynamicArchive/DynamicHelloTest.java b/hotspot/test/runtime/appcds/dynamicArchive/DynamicHelloTest.java
new file mode 100644
index 00000000..48e97cb2
--- /dev/null
+++ b/hotspot/test/runtime/appcds/dynamicArchive/DynamicHelloTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Hello World test for dynamic cds
+ * @library /testlibrary /runtime/appcds /runtime/appcds/test-classes
+ * @compile ../test-classes/Hello.java
+ * @run main DynamicHelloTest
+ */
+
+public class DynamicHelloTest {
+    public static void main(String[] args) throws Exception {
+        TestCommon.testDynamicCDS(JarBuilder.getOrCreateHelloJar(),
+            null, "Hello");
+
+        TestCommon.testDynamicCDS(JarBuilder.getOrCreateHelloJar(),
+            TestCommon.list("Hello"), "Hello");
+    }
+}
diff --git a/hotspot/test/runtime/appcds/dynamicArchive/VerifyWithDynamicArchive.java b/hotspot/test/runtime/appcds/dynamicArchive/VerifyWithDynamicArchive.java
new file mode 100644
index 00000000..eacc1aff
--- /dev/null
+++ b/hotspot/test/runtime/appcds/dynamicArchive/VerifyWithDynamicArchive.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Hello World test for dynamic cds
+ * @library /testlibrary /runtime/appcds /runtime/appcds/test-classes
+ * @compile ../test-classes/Hello.java
+ * @run main VerifyWithDynamicArchive
+ */
+
+public class VerifyWithDynamicArchive {
+    public static void main(String[] args) throws Exception {
+        TestCommon.testDynamicCDS(JarBuilder.getOrCreateHelloJar(),
+            null, "-XX:+VerifySharedSpaces", "Hello");
+    
+        TestCommon.testDynamicCDS(JarBuilder.getOrCreateHelloJar(),
+            TestCommon.list("Hello"), "-XX:+VerifySharedSpaces", "Hello");
+    }
+}
diff --git a/jdk/make/BuildJdk.gmk b/jdk/make/BuildJdk.gmk
index 467792fa..bb8ea8a9 100644
--- a/jdk/make/BuildJdk.gmk
+++ b/jdk/make/BuildJdk.gmk
@@ -103,6 +103,13 @@ images:
         ifeq ($(OPENJDK_TARGET_OS), macosx)
 	  +$(MAKE) -f Bundles.gmk
         endif
+        ifeq ($(BUILD_CDS_ARCHIVE), true)
+	  echo Creating CDS archive for jdk image
+	  $(JDK_IMAGE_DIR)/bin/java -Xshare:dump -Xmx128M -Xms128M -XX:ParallelGCThreads=1 -Xint $(LOG_INFO)
+	  echo Creating CDS archive for jre image
+	  $(JRE_IMAGE_DIR)/bin/java -Xshare:dump -Xmx128M -Xms128M -XX:ParallelGCThreads=1 -Xint $(LOG_INFO)
+        endif
+
 
 overlay-images:
 	+$(MAKE) -f CompileLaunchers.gmk OVERLAY_IMAGES=true
