8140802: Clean up and refactor of class loading code for CDS
authoriklam
Tue, 18 Aug 2015 11:27:23 -0700
changeset 34257 4be3504cc03b
parent 34132 aa73af640c61
child 34258 fb4f53f3e92f
8140802: Clean up and refactor of class loading code for CDS Reviewed-by: jiangli, acorn, coleenp
hotspot/make/excludeSrc.make
hotspot/src/share/vm/classfile/classListParser.cpp
hotspot/src/share/vm/classfile/classListParser.hpp
hotspot/src/share/vm/classfile/classLoaderData.cpp
hotspot/src/share/vm/classfile/classLoaderData.hpp
hotspot/src/share/vm/classfile/classLoaderExt.cpp
hotspot/src/share/vm/classfile/classLoaderExt.hpp
hotspot/src/share/vm/classfile/dictionary.cpp
hotspot/src/share/vm/classfile/dictionary.hpp
hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp
hotspot/src/share/vm/classfile/systemDictionary.cpp
hotspot/src/share/vm/classfile/systemDictionary.hpp
hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
hotspot/src/share/vm/classfile/systemDictionary_ext.hpp
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/classfile/vmSymbols_ext.hpp
hotspot/src/share/vm/memory/metaspaceShared.cpp
hotspot/src/share/vm/memory/metaspaceShared.hpp
hotspot/src/share/vm/prims/whitebox.cpp
hotspot/src/share/vm/utilities/hashtable.cpp
--- a/hotspot/make/excludeSrc.make	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/make/excludeSrc.make	Tue Aug 18 11:27:23 2015 -0700
@@ -73,8 +73,9 @@
       CXXFLAGS += -DINCLUDE_CDS=0
       CFLAGS += -DINCLUDE_CDS=0
 
-      Src_Files_EXCLUDE += filemap.cpp metaspaceShared*.cpp sharedPathsMiscInfo.cpp \
-        systemDictionaryShared.cpp classLoaderExt.cpp sharedClassUtil.cpp
+      Src_Files_EXCLUDE += classListParser.cpp classLoaderExt.cpp \
+        filemap.cpp metaspaceShared*.cpp sharedClassUtil.cpp sharedPathsMiscInfo.cpp \
+        systemDictionaryShared.cpp
 endif
 
 ifeq ($(INCLUDE_ALL_GCS), false)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/classListParser.cpp	Tue Aug 18 11:27:23 2015 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/classListParser.hpp"
+#include "runtime/os.hpp"
+#include "runtime/java.hpp"
+
+ClassListParser::ClassListParser(const char* file) {
+  _classlist_file = file;
+  _file = fopen(file, "r");
+  if (_file == NULL) {
+    char errmsg[JVM_MAXPATHLEN];
+    os::lasterror(errmsg, JVM_MAXPATHLEN);
+    vm_exit_during_initialization("Loading classlist failed", errmsg);
+  }
+}
+
+ClassListParser::~ClassListParser() {
+  if (_file) {
+    fclose(_file);
+  }
+}
+
+bool ClassListParser::parse_one_line() {
+  for (;;) {
+    if (fgets(_line, sizeof(_line), _file) == NULL) {
+      return false;
+    }
+    int line_len = (int)strlen(_line);
+    if (line_len > _max_allowed_line_len) {
+      tty->print_cr("input line too long (must be no longer than %d chars)", _max_allowed_line_len);
+      vm_exit_during_initialization("Loading classlist failed");
+    }
+    if (*_line == '#') { // comment
+      continue;
+    }
+    break;
+  }
+
+  // Remove trailing \r\n
+  _line[strcspn(_line, "\r\n")] = 0;
+  return true;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/classListParser.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_CLASSLISTPARSER_HPP
+#define SHARE_VM_MEMORY_CLASSLISTPARSER_HPP
+
+#include "utilities/exceptions.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class ClassListParser : public StackObj {
+  enum {
+    // Max number of bytes allowed per line in the classlist.
+    // Theoretically Java class names could be 65535 bytes in length. In reality,
+    // 4K bytes is more than enough.
+    _max_allowed_line_len = 4096,
+    _line_buf_extra       = 10, // for detecting input too long
+    _line_buf_size        = _max_allowed_line_len + _line_buf_extra
+  };
+
+  const char* _classlist_file;
+  FILE* _file;
+  char  _line[_line_buf_size];  // The buffer that holds the current line.
+
+public:
+  ClassListParser(const char* file);
+  ~ClassListParser();
+  bool parse_one_line();
+
+  const char* current_class_name() {
+    return _line;
+  }
+};
+
+
+#endif // SHARE_VM_MEMORY_CLASSLISTPARSER_HPP
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp	Tue Aug 18 11:27:23 2015 -0700
@@ -82,7 +82,7 @@
   _keep_alive(is_anonymous || h_class_loader.is_null()),
   _metaspace(NULL), _unloading(false), _klasses(NULL),
   _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
-  _next(NULL), _dependencies(dependencies),
+  _next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
   _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
                             Monitor::_safepoint_check_never)) {
     // empty
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -187,6 +187,9 @@
   // Support for walking class loader data objects
   ClassLoaderData* _next; /// Next loader_datas created
 
+  // CDS
+  int _shared_class_loader_id;
+
   // ReadOnly and ReadWrite metaspaces (static because only on the null
   // class loader for now).
   static Metaspace* _ro_metaspace;
@@ -308,6 +311,15 @@
   Metaspace* ro_metaspace();
   Metaspace* rw_metaspace();
   void initialize_shared_metaspaces();
+
+  int shared_class_loader_id() {
+    return _shared_class_loader_id;
+  }
+  void set_shared_class_loader_id(int id) {
+    assert(id >= 0, "sanity");
+    assert(_shared_class_loader_id <0, "cannot be assigned more than once");
+    _shared_class_loader_id = id;
+  }
 };
 
 // An iterator that distributes Klasses to parallel worker threads.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/classLoaderExt.cpp	Tue Aug 18 11:27:23 2015 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/classListParser.hpp"
+#include "classfile/classLoaderExt.hpp"
+#include "classfile/symbolTable.hpp"
+#include "classfile/systemDictionary.hpp"
+
+
+Klass* ClassLoaderExt::load_one_class(ClassListParser* parser, TRAPS) {
+  TempNewSymbol class_name_symbol = SymbolTable::new_symbol(parser->current_class_name(), THREAD);
+  guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
+  return SystemDictionary::resolve_or_null(class_name_symbol, THREAD);
+}
--- a/hotspot/src/share/vm/classfile/classLoaderExt.hpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/classLoaderExt.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. 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
@@ -29,6 +29,8 @@
 #include "oops/instanceKlass.hpp"
 #include "runtime/handles.hpp"
 
+class ClassListParser;
+
 class ClassLoaderExt: public ClassLoader { // AllStatic
 public:
 
@@ -69,6 +71,7 @@
     ClassLoader::add_to_list(new_entry);
   }
   static void setup_search_paths() {}
+  static Klass* load_one_class(ClassListParser* parser, TRAPS);
 };
 
 #endif // SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
--- a/hotspot/src/share/vm/classfile/dictionary.cpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp	Tue Aug 18 11:27:23 2015 -0700
@@ -23,8 +23,10 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/sharedClassUtil.hpp"
 #include "classfile/dictionary.hpp"
 #include "classfile/systemDictionary.hpp"
+#include "classfile/systemDictionaryShared.hpp"
 #include "memory/iterator.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/jvmtiRedefineClassesTrace.hpp"
@@ -34,9 +36,16 @@
 DictionaryEntry*  Dictionary::_current_class_entry = NULL;
 int               Dictionary::_current_class_index =    0;
 
+size_t Dictionary::entry_size() {
+  if (DumpSharedSpaces) {
+    return SystemDictionaryShared::dictionary_entry_size();
+  } else {
+    return sizeof(DictionaryEntry);
+  }
+}
 
 Dictionary::Dictionary(int table_size)
-  : TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry)) {
+  : TwoOopHashtable<Klass*, mtClass>(table_size, (int)entry_size()) {
   _current_class_index = 0;
   _current_class_entry = NULL;
   _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
@@ -45,7 +54,7 @@
 
 Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
                        int number_of_entries)
-  : TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
+  : TwoOopHashtable<Klass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
   _current_class_index = 0;
   _current_class_entry = NULL;
   _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
@@ -61,6 +70,9 @@
   entry->set_loader_data(loader_data);
   entry->set_pd_set(NULL);
   assert(klass->is_instance_klass(), "Must be");
+  if (DumpSharedSpaces) {
+    SystemDictionaryShared::init_shared_dictionary_entry(klass, entry);
+  }
   return entry;
 }
 
--- a/hotspot/src/share/vm/classfile/dictionary.hpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/dictionary.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -53,6 +53,7 @@
   DictionaryEntry* get_entry(int index, unsigned int hash,
                              Symbol* name, ClassLoaderData* loader_data);
 
+protected:
   DictionaryEntry* bucket(int i) {
     return (DictionaryEntry*)Hashtable<Klass*, mtClass>::bucket(i);
   }
@@ -66,6 +67,7 @@
     Hashtable<Klass*, mtClass>::add_entry(index, (HashtableEntry<Klass*, mtClass>*)new_entry);
   }
 
+  static size_t entry_size();
 public:
   Dictionary(int table_size);
   Dictionary(int table_size, HashtableBucket<mtClass>* t, int number_of_entries);
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. 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
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP
 #define SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP
 
+#include "classfile/classLoader.hpp"
 #include "runtime/os.hpp"
 
 // During dumping time, when processing class paths, we build up the dump-time
@@ -106,19 +107,6 @@
     add_path(path, NON_EXIST);
   }
 
-  // The path must exist and have required size and modification time
-  void add_required_file(const char* path) {
-    add_path(path, REQUIRED);
-
-    struct stat st;
-    if (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);
-  }
-
   // The path must exist, and must contain exactly <num_entries> files/dirs
   void add_boot_classpath(const char* path) {
     add_path(path, BOOT);
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Tue Aug 18 11:27:23 2015 -0700
@@ -322,6 +322,17 @@
                                                  Handle protection_domain,
                                                  bool is_superclass,
                                                  TRAPS) {
+#if INCLUDE_CDS
+  if (DumpSharedSpaces) {
+    // Special processing for CDS dump time.
+    Klass* k = SystemDictionaryShared::dump_time_resolve_super_or_fail(child_name,
+        class_name, class_loader, protection_domain, is_superclass, CHECK_NULL);
+    if (k) {
+      return k;
+    }
+  }
+#endif // INCLUDE_CDS
+
   // Double-check, if child class is already loaded, just return super-class,interface
   // Don't add a placedholder if already loaded, i.e. already in system dictionary
   // Make sure there's a placeholder for the *child* before resolving.
@@ -1079,12 +1090,30 @@
   //
   // Note: "name" is updated.
 
-  instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
-                                                             loader_data,
-                                                             protection_domain,
-                                                             parsed_name,
-                                                             verify,
-                                                             THREAD);
+  instanceKlassHandle k;
+
+#if INCLUDE_CDS
+  k = SystemDictionaryShared::lookup_from_stream(class_name,
+                                                 class_loader,
+                                                 protection_domain,
+                                                 st,
+                                                 verify,
+                                                 CHECK_NULL);
+#endif
+
+  if (k.not_null()) {
+    parsed_name = k->name();
+  } else {
+    if (st->buffer() == NULL) {
+      return NULL;
+    }
+    k = ClassFileParser(st).parseClassFile(class_name,
+                                           loader_data,
+                                           protection_domain,
+                                           parsed_name,
+                                           verify,
+                                           THREAD);
+  }
 
   const char* pkg = "java/";
   if (!HAS_PENDING_EXCEPTION &&
@@ -1201,8 +1230,13 @@
 
     if (ik->super() != NULL) {
       Symbol*  cn = ik->super()->name();
-      resolve_super_or_fail(class_name, cn,
-                            class_loader, protection_domain, true, CHECK_(nh));
+      Klass *s = resolve_super_or_fail(class_name, cn,
+                                       class_loader, protection_domain, true, CHECK_(nh));
+      if (s != ik->super()) {
+        // The dynamically resolved super class is not the same as the one we used during dump time,
+        // so we cannot use ik.
+        return nh;
+      }
     }
 
     Array<Klass*>* interfaces = ik->local_interfaces();
@@ -1215,7 +1249,12 @@
       // reinitialized yet (they will be once the interface classes
       // are loaded)
       Symbol*  name  = k->name();
-      resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_(nh));
+      Klass* i = resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_(nh));
+      if (k != i) {
+        // The dynamically resolved interface class is not the same as the one we used during dump time,
+        // so we cannot use ik.
+        return nh;
+      }
     }
 
     // Adjust methods to recover missing data.  They need addresses for
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -27,6 +27,7 @@
 
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
+#include "classfile/systemDictionary_ext.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/java.hpp"
@@ -194,15 +195,18 @@
   do_klass(Integer_klass,                               java_lang_Integer,                         Pre                 ) \
   do_klass(Long_klass,                                  java_lang_Long,                            Pre                 ) \
                                                                                                                          \
+  /* Extensions */                                                                                                       \
+  WK_KLASSES_DO_EXT(do_klass)                                                                                            \
   /* JVMCI classes. These are loaded on-demand. */                                                                       \
-  JVMCI_WK_KLASSES_DO(do_klass) \
-
+  JVMCI_WK_KLASSES_DO(do_klass)                                                                                          \
+                                                                                                                         \
   /*end*/
 
 
 class SystemDictionary : AllStatic {
   friend class VMStructs;
   friend class SystemDictionaryHandles;
+  friend class SharedClassUtil;
 
  public:
   enum WKID {
@@ -667,11 +671,6 @@
   // Basic find on classes in the midst of being loaded
   static Symbol* find_placeholder(Symbol* name, ClassLoaderData* loader_data);
 
-  // Updating entry in dictionary
-  // Add a completely loaded class
-  static void add_klass(int index, Symbol* class_name,
-                        ClassLoaderData* loader_data, KlassHandle obj);
-
   // Add a placeholder for a class being loaded
   static void add_placeholder(int index,
                               Symbol* class_name,
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. 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
@@ -22,11 +22,13 @@
  *
  */
 
-
 #ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
 #define SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
 
 #include "classfile/systemDictionary.hpp"
+#include "classfile/dictionary.hpp"
+
+class ClassFileStream;
 
 class SystemDictionaryShared: public SystemDictionary {
 public:
@@ -42,6 +44,30 @@
     oop class_loader = loader_data->class_loader();
     return (class_loader == NULL);
   }
+
+  static Klass* dump_time_resolve_super_or_fail(Symbol* child_name,
+                                                Symbol* class_name,
+                                                Handle class_loader,
+                                                Handle protection_domain,
+                                                bool is_superclass,
+                                                TRAPS) {
+    return NULL;
+  }
+
+  static size_t dictionary_entry_size() {
+    return sizeof(DictionaryEntry);
+  }
+
+  static void init_shared_dictionary_entry(Klass* k, DictionaryEntry* entry) {}
+
+  static InstanceKlass* lookup_from_stream(Symbol* class_name,
+                                           Handle class_loader,
+                                           Handle protection_domain,
+                                           ClassFileStream* st,
+                                           bool verify,
+                                           TRAPS) {
+    return NULL;
+  }
 };
 
 #endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/systemDictionary_ext.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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.
+ *
+ */
+
+#ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP
+#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP
+
+#define WK_KLASSES_DO_EXT(do_klass)
+
+#endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
 #define SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
 
+#include "classfile/vmSymbols_ext.hpp"
 #include "oops/symbol.hpp"
 #include "memory/iterator.hpp"
 #include "trace/traceMacros.hpp"
@@ -617,6 +618,9 @@
   /* trace signatures */                                                                                          \
   TRACE_TEMPLATES(template)                                                                                       \
                                                                                                                   \
+  /* extensions */                                                                                                \
+  VM_SYMBOLS_DO_EXT(template, do_alias)                                                                           \
+                                                                                                                  \
   /*end*/
 
 // Here are all the intrinsics known to the runtime and the CI.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols_ext.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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.
+ *
+ */
+
+#ifndef SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP
+#define SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP
+
+#define VM_SYMBOLS_DO_EXT(template, do_alias)
+
+#endif // SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP
+
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Tue Aug 18 11:27:23 2015 -0700
@@ -23,6 +23,8 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/classListParser.hpp"
+#include "classfile/classLoaderExt.hpp"
 #include "classfile/dictionary.hpp"
 #include "classfile/loaderConstraints.hpp"
 #include "classfile/placeholders.hpp"
@@ -42,6 +44,7 @@
 #include "runtime/signature.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
+#include "utilities/defaultStream.hpp"
 #include "utilities/hashtable.inline.hpp"
 
 int MetaspaceShared::_max_alignment = 0;
@@ -97,6 +100,10 @@
   }
 }
 
+static void collect_classes2(Klass* k, ClassLoaderData* class_data) {
+  collect_classes(k);
+}
+
 static void remove_unshareable_in_classes() {
   for (int i = 0; i < _global_klass_objects->length(); i++) {
     Klass* k = _global_klass_objects->at(i);
@@ -422,12 +429,15 @@
   VirtualSpace _mc_vs;
   CompactHashtableWriter* _string_cht;
   GrowableArray<MemRegion> *_string_regions;
+  char* _md_alloc_low;
+  char* _md_alloc_top;
+  char* _md_alloc_max;
+  static VM_PopulateDumpSharedSpace* _instance;
 
 public:
   VM_PopulateDumpSharedSpace(ClassLoaderData* loader_data,
                              GrowableArray<Klass*> *class_promote_order) :
     _loader_data(loader_data) {
-
     // Split up and initialize the misc code and data spaces
     ReservedSpace* shared_rs = MetaspaceShared::shared_rs();
     size_t metadata_size = SharedReadOnlySize + SharedReadWriteSize;
@@ -440,11 +450,43 @@
     _md_vs.initialize(md_rs, SharedMiscDataSize);
     _mc_vs.initialize(mc_rs, SharedMiscCodeSize);
     _class_promote_order = class_promote_order;
+
+    _md_alloc_low = _md_vs.low();
+    _md_alloc_top = _md_alloc_low + sizeof(char*);
+    _md_alloc_max = _md_vs.low() + SharedMiscDataSize;
+
+    assert(_instance == NULL, "must be singleton");
+    _instance = this;
+  }
+
+  ~VM_PopulateDumpSharedSpace() {
+    assert(_instance == this, "must be singleton");
+    _instance = NULL;
+  }
+
+  static VM_PopulateDumpSharedSpace* instance() {
+    assert(_instance != NULL, "sanity");
+    return _instance;
   }
 
   VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
   void doit();   // outline because gdb sucks
 
+  char* misc_data_space_alloc(size_t num_bytes) {
+    size_t alignment = sizeof(char*);
+    num_bytes = align_size_up(num_bytes, alignment);
+    _md_alloc_top = (char*)align_ptr_up(_md_alloc_top, alignment);
+    if (_md_alloc_top + num_bytes > _md_alloc_max) {
+      report_out_of_shared_space(SharedMiscData);
+    }
+
+    char* p = _md_alloc_top;
+    _md_alloc_top += num_bytes;
+
+    memset(p, 0, num_bytes);
+    return p;
+  }
+
 private:
   void handle_misc_data_space_failure(bool success) {
     if (!success) {
@@ -453,6 +495,7 @@
   }
 }; // class VM_PopulateDumpSharedSpace
 
+VM_PopulateDumpSharedSpace* VM_PopulateDumpSharedSpace::_instance;
 
 void VM_PopulateDumpSharedSpace::doit() {
   Thread* THREAD = VMThread::vm_thread();
@@ -475,7 +518,11 @@
   // that so we don't have to walk the SystemDictionary again.
   _global_klass_objects = new GrowableArray<Klass*>(1000);
   Universe::basic_type_classes_do(collect_classes);
-  SystemDictionary::classes_do(collect_classes);
+
+  // Need to call SystemDictionary::classes_do(void f(Klass*, ClassLoaderData*))
+  // as we may have some classes with NULL ClassLoaderData* in the dictionary. Other
+  // variants of SystemDictionary::classes_do will skip those classes.
+  SystemDictionary::classes_do(collect_classes2);
 
   tty->print_cr("Number of classes %d", _global_klass_objects->length());
   {
@@ -515,6 +562,10 @@
   char* mc_top = mc_low;
   char* mc_end = _mc_vs.high();
 
+  assert(_md_alloc_top != NULL, "sanity");
+  *(char**)_md_alloc_low = _md_alloc_top;
+  md_top = _md_alloc_top;
+
   // Reserve space for the list of Klass*s whose vtables are used
   // for patching others as needed.
 
@@ -735,6 +786,7 @@
 void MetaspaceShared::preload_and_dump(TRAPS) {
   TraceTime timer("Dump Shared Spaces", TraceStartupTime);
   ResourceMark rm;
+  char class_list_path_str[JVM_MAXPATHLEN];
 
   tty->print_cr("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
                 MetaspaceShared::shared_rs()->size(),
@@ -747,7 +799,6 @@
     // Construct the path to the class list (in jre/lib)
     // Walk up two directories from the location of the VM and
     // optionally tack on "lib" (depending on platform)
-    char class_list_path_str[JVM_MAXPATHLEN];
     os::jvm_path(class_list_path_str, sizeof(class_list_path_str));
     for (int i = 0; i < 3; i++) {
       char *end = strrchr(class_list_path_str, *os::file_separator());
@@ -785,6 +836,11 @@
   static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;";
   SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD);
 
+  // Need to allocate the op here:
+  // op.misc_data_space_alloc() will be called during preload_and_dump().
+  ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
+  VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
+
   tty->print_cr("Loading classes to share ...");
   _has_error_classes = false;
   class_count += preload_and_dump(class_list_path, class_promote_order,
@@ -809,44 +865,27 @@
   link_and_cleanup_shared_classes(CATCH);
   tty->print_cr("Rewriting and linking classes: done");
 
-  // Create and dump the shared spaces.   Everything so far is loaded
-  // with the null class loader.
-  ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
-  VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
   VMThread::execute(&op);
-
   // Since various initialization steps have been undone by this process,
   // it is not reasonable to continue running a java process.
   exit(0);
 }
 
-int MetaspaceShared::preload_and_dump(const char * class_list_path,
+
+int MetaspaceShared::preload_and_dump(const char* class_list_path,
                                       GrowableArray<Klass*>* class_promote_order,
                                       TRAPS) {
-  FILE* file = fopen(class_list_path, "r");
-  char class_name[256];
+  ClassListParser parser(class_list_path);
   int class_count = 0;
 
-  if (file != NULL) {
-    while ((fgets(class_name, sizeof class_name, file)) != NULL) {
-      if (*class_name == '#') { // comment
-        continue;
-      }
-      // Remove trailing newline
-      size_t name_len = strlen(class_name);
-      if (class_name[name_len-1] == '\n') {
-        class_name[name_len-1] = '\0';
-      }
+    while (parser.parse_one_line()) {
+      Klass* klass = ClassLoaderExt::load_one_class(&parser, THREAD);
 
-      // Got a class name - load it.
-      TempNewSymbol class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD);
-      guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
-      Klass* klass = SystemDictionary::resolve_or_null(class_name_symbol,
-                                                         THREAD);
       CLEAR_PENDING_EXCEPTION;
       if (klass != NULL) {
         if (PrintSharedSpaces && Verbose && WizardMode) {
-          tty->print_cr("Shared spaces preloaded: %s", class_name);
+          ResourceMark rm;
+          tty->print_cr("Shared spaces preloaded: %s", klass->external_name());
         }
 
         InstanceKlass* ik = InstanceKlass::cast(klass);
@@ -862,17 +901,8 @@
         guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class");
 
         class_count++;
-      } else {
-        //tty->print_cr("Preload failed: %s", class_name);
       }
     }
-    fclose(file);
-  } else {
-    char errmsg[JVM_MAXPATHLEN];
-    os::lasterror(errmsg, JVM_MAXPATHLEN);
-    tty->print_cr("Loading classlist failed: %s", errmsg);
-    exit(1);
-  }
 
   return class_count;
 }
@@ -908,6 +938,11 @@
   }
 }
 
+// Allocate misc data blocks during dumping.
+char* MetaspaceShared::misc_data_space_alloc(size_t num_bytes) {
+  return VM_PopulateDumpSharedSpace::instance()->misc_data_space_alloc(num_bytes);
+}
+
 // Closure for serializing initialization data in from a data area
 // (ptr_array) read from the shared file.
 
@@ -1033,6 +1068,8 @@
 
   char* buffer = mapinfo->header()->region_addr(md);
 
+  buffer = *((char**)buffer); // skip over the md_alloc'ed blocks
+
   // Skip over (reserve space for) a list of addresses of C++ vtables
   // for Klass objects.  They get filled in later.
 
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp	Tue Aug 18 11:27:23 2015 -0700
@@ -160,5 +160,8 @@
 
   static int count_class(const char* classlist_file);
   static void estimate_regions_size() NOT_CDS_RETURN;
+
+  // Allocate a block of memory from the "md" region.
+  static char* misc_data_space_alloc(size_t num_bytes);
 };
 #endif // SHARE_VM_MEMORY_METASPACESHARED_HPP
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Tue Aug 18 11:27:23 2015 -0700
@@ -1271,6 +1271,10 @@
                    attemptedNoSafepointValue == JNI_TRUE);
 WB_END
 
+WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
+  return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
+WB_END
+
 WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
   oop obj_oop = JNIHandles::resolve(obj);
   return (jboolean) obj_oop->mark()->has_monitor();
@@ -1471,6 +1475,7 @@
   {CC"runMemoryUnitTests", CC"()V",                   (void*)&WB_RunMemoryUnitTests},
   {CC"readFromNoaccessArea",CC"()V",                  (void*)&WB_ReadFromNoaccessArea},
   {CC"stressVirtualSpaceResize",CC"(JJJ)I",           (void*)&WB_StressVirtualSpaceResize},
+  {CC"isSharedClass", CC"(Ljava/lang/Class;)Z",       (void*)&WB_IsSharedClass },
 #if INCLUDE_ALL_GCS
   {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
   {CC"g1IsHumongous0",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
--- a/hotspot/src/share/vm/utilities/hashtable.cpp	Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/utilities/hashtable.cpp	Tue Aug 18 11:27:23 2015 -0700
@@ -365,6 +365,7 @@
 template class RehashableHashtable<oopDesc*, mtSymbol>;
 template class Hashtable<Symbol*, mtSymbol>;
 template class Hashtable<Klass*, mtClass>;
+template class Hashtable<InstanceKlass*, mtClass>;
 template class Hashtable<oop, mtClass>;
 #if defined(SOLARIS) || defined(CHECK_UNHANDLED_OOPS)
 template class Hashtable<oop, mtSymbol>;
@@ -378,6 +379,7 @@
 template class BasicHashtableEntry<mtSymbol>;
 template class BasicHashtableEntry<mtCode>;
 template class BasicHashtable<mtClass>;
+template class BasicHashtable<mtClassShared>;
 template class BasicHashtable<mtSymbol>;
 template class BasicHashtable<mtCode>;
 template class BasicHashtable<mtInternal>;