changeset 7581:c6a0f333733c

Merge
author anoll
date Fri, 12 Dec 2014 08:40:19 -0800
parents eba1bd212c02 fb4ba04c587b
children 2c17ba977ff0
files src/os/aix/vm/os_aix.cpp
diffstat 51 files changed, 2113 insertions(+), 985 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Dec 12 13:13:01 2014 +0100
+++ b/.hgtags	Fri Dec 12 08:40:19 2014 -0800
@@ -443,3 +443,5 @@
 c363a8b87e477ee45d6d3cb2a36cb365141bc596 jdk9-b38
 9cb75e5e394827ccbaf2e15524108a412dc4ddc5 jdk9-b39
 6b09b3193d731e3288e2a240c504a20d0a06c766 jdk9-b40
+1d29b13e8a515a7ea3b882f140576d5d675bc11f jdk9-b41
+38cb4fbd47e3472bd1b5ebac83bda96fe4869c4f jdk9-b42
--- a/make/bsd/makefiles/sa.make	Fri Dec 12 13:13:01 2014 +0100
+++ b/make/bsd/makefiles/sa.make	Fri Dec 12 08:40:19 2014 -0800
@@ -65,6 +65,10 @@
   SA_CLASSPATH=$(shell test -f $(ALT_SA_CLASSPATH) && echo $(ALT_SA_CLASSPATH))
 endif
 
+ifneq ($(SA_CLASSPATH),)
+  SA_CLASSPATH_ARG := -classpath $(SA_CLASSPATH)
+endif
+
 # TODO: if it's a modules image, check if SA module is installed.
 MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules
 
@@ -116,7 +120,7 @@
 # are in AGENT_FILES, so use the shell to expand them.
 # Be extra carefull to not produce too long command lines in the shell!
 	$(foreach file,$(AGENT_FILES),$(shell ls -1 $(file) >> $(AGENT_FILES_LIST)))
-	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES_LIST)
+	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) $(SA_CLASSPATH_ARG) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES_LIST)
 	$(QUIETLY) $(REMOTE) $(COMPILE.RMIC)  -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
 	$(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES)
 	$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
--- a/src/os/aix/vm/os_aix.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/os/aix/vm/os_aix.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -531,15 +531,13 @@
 
 #define DEFAULT_LIBPATH "/usr/lib:/lib"
 #define EXTENSIONS_DIR  "/lib/ext"
-#define ENDORSED_DIR    "/lib/endorsed"
 
   // Buffer that fits several sprintfs.
   // Note that the space for the trailing null is provided
   // by the nulls included by the sizeof operator.
   const size_t bufsize =
-    MAX3((size_t)MAXPATHLEN,  // For dll_dir & friends.
-         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR), // extensions dir
-         (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir
+    MAX2((size_t)MAXPATHLEN,  // For dll_dir & friends.
+         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR)); // extensions dir
   char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
 
   // sysclasspath, java_home, dll_dir
@@ -590,15 +588,10 @@
   sprintf(buf, "%s" EXTENSIONS_DIR, Arguments::get_java_home());
   Arguments::set_ext_dirs(buf);
 
-  // Endorsed standards default directory.
-  sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
-  Arguments::set_endorsed_dirs(buf);
-
   FREE_C_HEAP_ARRAY(char, buf);
 
 #undef DEFAULT_LIBPATH
 #undef EXTENSIONS_DIR
-#undef ENDORSED_DIR
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2803,6 +2796,10 @@
   return ::read(fd, buf, nBytes);
 }
 
+size_t os::read_at(int fd, void *buf, unsigned int nBytes, jlong offset) {
+  return ::pread(fd, buf, nBytes, offset);
+}
+
 void os::naked_short_sleep(jlong ms) {
   struct timespec req;
 
@@ -4151,8 +4148,29 @@
 char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
                         char *addr, size_t bytes, bool read_only,
                         bool allow_exec) {
-  Unimplemented();
-  return NULL;
+  int prot;
+  int flags = MAP_PRIVATE;
+
+  if (read_only) {
+    prot = PROT_READ;
+  } else {
+    prot = PROT_READ | PROT_WRITE;
+  }
+
+  if (allow_exec) {
+    prot |= PROT_EXEC;
+  }
+
+  if (addr != NULL) {
+    flags |= MAP_FIXED;
+  }
+
+  char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags,
+                                     fd, file_offset);
+  if (mapped_address == MAP_FAILED) {
+    return NULL;
+  }
+  return mapped_address;
 }
 
 // Remap a block of memory.
--- a/src/os/bsd/vm/os_bsd.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/os/bsd/vm/os_bsd.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -353,7 +353,6 @@
 // Base path of extensions installed on the system.
 #define SYS_EXT_DIR     "/usr/java/packages"
 #define EXTENSIONS_DIR  "/lib/ext"
-#define ENDORSED_DIR    "/lib/endorsed"
 
 #ifndef __APPLE__
 
@@ -361,9 +360,8 @@
   // Note that the space for the colon and the trailing null are provided
   // by the nulls included by the sizeof operator.
   const size_t bufsize =
-    MAX3((size_t)MAXPATHLEN,  // For dll_dir & friends.
-         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR), // extensions dir
-         (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir
+    MAX2((size_t)MAXPATHLEN,  // For dll_dir & friends.
+         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR)); // extensions dir
   char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
 
   // sysclasspath, java_home, dll_dir
@@ -425,10 +423,6 @@
   sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
   Arguments::set_ext_dirs(buf);
 
-  // Endorsed standards default directory.
-  sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
-  Arguments::set_endorsed_dirs(buf);
-
   FREE_C_HEAP_ARRAY(char, buf);
 
 #else // __APPLE__
@@ -445,9 +439,8 @@
   // Note that the space for the colon and the trailing null are provided
   // by the nulls included by the sizeof operator.
   const size_t bufsize =
-    MAX3((size_t)MAXPATHLEN,  // for dll_dir & friends.
-         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + system_ext_size, // extensions dir
-         (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir
+    MAX2((size_t)MAXPATHLEN,  // for dll_dir & friends.
+         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + system_ext_size); // extensions dir
   char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
 
   // sysclasspath, java_home, dll_dir
@@ -525,10 +518,6 @@
           user_home_dir, Arguments::get_java_home());
   Arguments::set_ext_dirs(buf);
 
-  // Endorsed standards default directory.
-  sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
-  Arguments::set_endorsed_dirs(buf);
-
   FREE_C_HEAP_ARRAY(char, buf);
 
 #undef SYS_EXTENSIONS_DIR
@@ -538,7 +527,6 @@
 
 #undef SYS_EXT_DIR
 #undef EXTENSIONS_DIR
-#undef ENDORSED_DIR
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2576,6 +2564,10 @@
   RESTARTABLE_RETURN_INT(::read(fd, buf, nBytes));
 }
 
+size_t os::read_at(int fd, void *buf, unsigned int nBytes, jlong offset) {
+  RESTARTABLE_RETURN_INT(::pread(fd, buf, nBytes, offset));
+}
+
 void os::naked_short_sleep(jlong ms) {
   struct timespec req;
 
--- a/src/os/linux/vm/os_linux.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/os/linux/vm/os_linux.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -338,15 +338,13 @@
 // Base path of extensions installed on the system.
 #define SYS_EXT_DIR     "/usr/java/packages"
 #define EXTENSIONS_DIR  "/lib/ext"
-#define ENDORSED_DIR    "/lib/endorsed"
 
   // Buffer that fits several sprintfs.
   // Note that the space for the colon and the trailing null are provided
   // by the nulls included by the sizeof operator.
   const size_t bufsize =
-    MAX3((size_t)MAXPATHLEN,  // For dll_dir & friends.
-         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR), // extensions dir
-         (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir
+    MAX2((size_t)MAXPATHLEN,  // For dll_dir & friends.
+         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR)); // extensions dir
   char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
 
   // sysclasspath, java_home, dll_dir
@@ -411,16 +409,11 @@
   sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
   Arguments::set_ext_dirs(buf);
 
-  // Endorsed standards default directory.
-  sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
-  Arguments::set_endorsed_dirs(buf);
-
   FREE_C_HEAP_ARRAY(char, buf);
 
 #undef DEFAULT_LIBPATH
 #undef SYS_EXT_DIR
 #undef EXTENSIONS_DIR
-#undef ENDORSED_DIR
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -3784,6 +3777,10 @@
   return ::read(fd, buf, nBytes);
 }
 
+size_t os::read_at(int fd, void *buf, unsigned int nBytes, jlong offset) {
+  return ::pread(fd, buf, nBytes, offset);
+}
+
 // Short sleep, direct OS call.
 //
 // Note: certain versions of Linux CFS scheduler (since 2.6.23) do not guarantee
--- a/src/os/solaris/vm/os_solaris.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/os/solaris/vm/os_solaris.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -609,17 +609,15 @@
 // Base path of extensions installed on the system.
 #define SYS_EXT_DIR     "/usr/jdk/packages"
 #define EXTENSIONS_DIR  "/lib/ext"
-#define ENDORSED_DIR    "/lib/endorsed"
 
   char cpu_arch[12];
   // Buffer that fits several sprintfs.
   // Note that the space for the colon and the trailing null are provided
   // by the nulls included by the sizeof operator.
   const size_t bufsize =
-    MAX4((size_t)MAXPATHLEN,  // For dll_dir & friends.
+    MAX3((size_t)MAXPATHLEN,  // For dll_dir & friends.
          sizeof(SYS_EXT_DIR) + sizeof("/lib/") + strlen(cpu_arch), // invariant ld_library_path
-         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR), // extensions dir
-         (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir
+         (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR)); // extensions dir
   char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
 
   // sysclasspath, java_home, dll_dir
@@ -765,15 +763,10 @@
   sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
   Arguments::set_ext_dirs(buf);
 
-  // Endorsed standards default directory.
-  sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home());
-  Arguments::set_endorsed_dirs(buf);
-
   FREE_C_HEAP_ARRAY(char, buf);
 
 #undef SYS_EXT_DIR
 #undef EXTENSIONS_DIR
-#undef ENDORSED_DIR
 }
 
 void os::breakpoint() {
@@ -3167,6 +3160,15 @@
   return res;
 }
 
+size_t os::read_at(int fd, void *buf, unsigned int nBytes, jlong offset) {
+  size_t res;
+  JavaThread* thread = (JavaThread*)Thread::current();
+  assert(thread->thread_state() == _thread_in_vm, "Assumed _thread_in_vm");
+  ThreadBlockInVM tbiv(thread);
+  RESTARTABLE(::pread(fd, buf, (size_t) nBytes, offset), res);
+  return res;
+}
+
 size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) {
   size_t res;
   assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
--- a/src/os/windows/vm/os_windows.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/os/windows/vm/os_windows.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -292,19 +292,6 @@
   #undef BIN_DIR
   #undef PACKAGE_DIR
 
-  // Default endorsed standards directory.
-  {
-#define ENDORSED_DIR "\\lib\\endorsed"
-    size_t len = strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR);
-    char * buf = NEW_C_HEAP_ARRAY(char, len, mtInternal);
-    sprintf(buf, "%s%s", Arguments::get_java_home(), ENDORSED_DIR);
-    Arguments::set_endorsed_dirs(buf);
-    // (Arguments::set_endorsed_dirs() calls SystemProperty::set_value(), which
-    //  duplicates the input.)
-    FREE_C_HEAP_ARRAY(char, buf);
-#undef ENDORSED_DIR
-  }
-
 #ifndef _WIN64
   // set our UnhandledExceptionFilter and save any previous one
   prev_uef_handler = SetUnhandledExceptionFilter(Handle_FLT_Exception);
@@ -3087,7 +3074,7 @@
 char* os::pd_reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
   assert((size_t)addr % os::vm_allocation_granularity() == 0,
          "reserve alignment");
-  assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size");
+  assert(bytes % os::vm_page_size() == 0, "reserve page size");
   char* res;
   // note that if UseLargePages is on, all the areas that require interleaving
   // will go thru reserve_memory_special rather than thru here.
@@ -4391,6 +4378,23 @@
   return (jlong) ::_lseeki64(fd, offset, whence);
 }
 
+size_t os::read_at(int fd, void *buf, unsigned int nBytes, jlong offset) {
+  OVERLAPPED ov;
+  DWORD nread;
+  BOOL result;
+
+  ZeroMemory(&ov, sizeof(ov));
+  ov.Offset = (DWORD)offset;
+  ov.OffsetHigh = (DWORD)(offset >> 32);
+
+  HANDLE h = (HANDLE)::_get_osfhandle(fd);
+
+  result = ReadFile(h, (LPVOID)buf, nBytes, &nread, &ov);
+
+  return result ? nread : 0;
+}
+
+
 // This method is a slightly reworked copy of JDK's sysNativePath
 // from src/windows/hpi/src/path_md.c
 
--- a/src/share/vm/classfile/classFileParser.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/classfile/classFileParser.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -3108,21 +3108,39 @@
   }
 }
 
-// Transfer ownership of metadata allocated to the InstanceKlass.
-void ClassFileParser::apply_parsed_class_metadata(
-                                            instanceKlassHandle this_klass,
-                                            int java_fields_count, TRAPS) {
-  // Assign annotations if needed
-  if (_annotations != NULL || _type_annotations != NULL ||
-      _fields_annotations != NULL || _fields_type_annotations != NULL) {
+// Create the Annotations object that will
+// hold the annotations array for the Klass.
+void ClassFileParser::create_combined_annotations(TRAPS) {
+    if (_annotations == NULL &&
+        _type_annotations == NULL &&
+        _fields_annotations == NULL &&
+        _fields_type_annotations == NULL) {
+      // Don't create the Annotations object unnecessarily.
+      return;
+    }
+
     Annotations* annotations = Annotations::allocate(_loader_data, CHECK);
     annotations->set_class_annotations(_annotations);
     annotations->set_class_type_annotations(_type_annotations);
     annotations->set_fields_annotations(_fields_annotations);
     annotations->set_fields_type_annotations(_fields_type_annotations);
-    this_klass->set_annotations(annotations);
-  }
-
+
+    // This is the Annotations object that will be
+    // assigned to InstanceKlass being constructed.
+    _combined_annotations = annotations;
+
+    // The annotations arrays below has been transfered the
+    // _combined_annotations so these fields can now be cleared.
+    _annotations             = NULL;
+    _type_annotations        = NULL;
+    _fields_annotations      = NULL;
+    _fields_type_annotations = NULL;
+}
+
+// Transfer ownership of metadata allocated to the InstanceKlass.
+void ClassFileParser::apply_parsed_class_metadata(
+                                            instanceKlassHandle this_klass,
+                                            int java_fields_count, TRAPS) {
   _cp->set_pool_holder(this_klass());
   this_klass->set_constants(_cp);
   this_klass->set_fields(_fields, java_fields_count);
@@ -3130,6 +3148,7 @@
   this_klass->set_inner_classes(_inner_classes);
   this_klass->set_local_interfaces(_local_interfaces);
   this_klass->set_transitive_interfaces(_transitive_interfaces);
+  this_klass->set_annotations(_combined_annotations);
 
   // Clear out these fields so they don't get deallocated by the destructor
   clear_class_metadata();
@@ -4002,6 +4021,10 @@
     ClassAnnotationCollector parsed_annotations;
     parse_classfile_attributes(&parsed_annotations, CHECK_(nullHandle));
 
+    // Finalize the Annotations metadata object,
+    // now that all annotation arrays have been created.
+    create_combined_annotations(CHECK_(nullHandle));
+
     // Make sure this is the end of class file stream
     guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));
 
@@ -4302,10 +4325,27 @@
   InstanceKlass::deallocate_interfaces(_loader_data, _super_klass(),
                                        _local_interfaces, _transitive_interfaces);
 
-  MetadataFactory::free_array<u1>(_loader_data, _annotations);
-  MetadataFactory::free_array<u1>(_loader_data, _type_annotations);
-  Annotations::free_contents(_loader_data, _fields_annotations);
-  Annotations::free_contents(_loader_data, _fields_type_annotations);
+  if (_combined_annotations != NULL) {
+    // After all annotations arrays have been created, they are installed into the
+    // Annotations object that will be assigned to the InstanceKlass being created.
+
+    // Deallocate the Annotations object and the installed annotations arrays.
+    _combined_annotations->deallocate_contents(_loader_data);
+
+    // If the _combined_annotations pointer is non-NULL,
+    // then the other annotations fields should have been cleared.
+    assert(_annotations             == NULL, "Should have been cleared");
+    assert(_type_annotations        == NULL, "Should have been cleared");
+    assert(_fields_annotations      == NULL, "Should have been cleared");
+    assert(_fields_type_annotations == NULL, "Should have been cleared");
+  } else {
+    // If the annotations arrays were not installed into the Annotations object,
+    // then they have to be deallocated explicitly.
+    MetadataFactory::free_array<u1>(_loader_data, _annotations);
+    MetadataFactory::free_array<u1>(_loader_data, _type_annotations);
+    Annotations::free_contents(_loader_data, _fields_annotations);
+    Annotations::free_contents(_loader_data, _fields_type_annotations);
+  }
 
   clear_class_metadata();
 
--- a/src/share/vm/classfile/classFileParser.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/classfile/classFileParser.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -75,6 +75,7 @@
   Array<u2>*       _inner_classes;
   Array<Klass*>*   _local_interfaces;
   Array<Klass*>*   _transitive_interfaces;
+  Annotations*     _combined_annotations;
   AnnotationArray* _annotations;
   AnnotationArray* _type_annotations;
   Array<AnnotationArray*>* _fields_annotations;
@@ -86,6 +87,8 @@
   void set_class_generic_signature_index(u2 x) { _generic_signature_index = x; }
   void set_class_sde_buffer(char* x, int len)  { _sde_buffer = x; _sde_length = len; }
 
+  void create_combined_annotations(TRAPS);
+
   void init_parsed_class_attributes(ClassLoaderData* loader_data) {
     _loader_data = loader_data;
     _synthetic_flag = false;
@@ -110,6 +113,7 @@
     _inner_classes = NULL;
     _local_interfaces = NULL;
     _transitive_interfaces = NULL;
+    _combined_annotations = NULL;
     _annotations = _type_annotations = NULL;
     _fields_annotations = _fields_type_annotations = NULL;
   }
--- a/src/share/vm/classfile/classLoader.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/classfile/classLoader.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -28,6 +28,7 @@
 #include "classfile/classLoader.hpp"
 #include "classfile/classLoaderExt.hpp"
 #include "classfile/classLoaderData.inline.hpp"
+#include "classfile/imageFile.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -68,7 +69,7 @@
 #endif
 
 
-// Entry points in zip.dll for loading zip/jar file entries
+// Entry points in zip.dll for loading zip/jar file entries and image file entries
 
 typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg);
 typedef void (JNICALL *ZipClose_t)(jzfile *zip);
@@ -76,6 +77,7 @@
 typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
 typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf);
 typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n);
+typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
 typedef jint     (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len);
 
 static ZipOpen_t         ZipOpen            = NULL;
@@ -85,6 +87,7 @@
 static ReadMappedEntry_t ReadMappedEntry    = NULL;
 static GetNextEntry_t    GetNextEntry       = NULL;
 static canonicalize_fn_t CanonicalizeEntry  = NULL;
+static ZipInflateFully_t ZipInflateFully    = NULL;
 static Crc32_t           Crc32              = NULL;
 
 // Globals
@@ -323,6 +326,8 @@
 }
 
 bool LazyClassPathEntry::is_jar_file() {
+  size_t len = strlen(_path);
+  if (len < 4 || strcmp(_path + len - 4, ".jar") != 0) return false;
   return ((_st.st_mode & S_IFREG) == S_IFREG);
 }
 
@@ -386,6 +391,78 @@
   }
 }
 
+ClassPathImageEntry::ClassPathImageEntry(char* name) : ClassPathEntry(), _image(new ImageFile(name)) {
+  bool opened = _image->open();
+  if (!opened) {
+    _image = NULL;
+  }
+}
+
+ClassPathImageEntry::~ClassPathImageEntry() {
+  if (_image) {
+    _image->close();
+    _image = NULL;
+  }
+}
+
+const char* ClassPathImageEntry::name() {
+  return _image ? _image->name() : "";
+}
+
+ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
+  u1* buffer;
+  u8 size;
+  _image->get_resource(name, buffer, size);
+
+  if (buffer) {
+    if (UsePerfData) {
+      ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
+    }
+    return new ClassFileStream(buffer, (int)size, (char*)name);  // Resource allocated
+  }
+
+  return NULL;
+}
+
+#ifndef PRODUCT
+void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
+  tty->print_cr("CompileTheWorld : Compiling all classes in %s", name());
+  tty->cr();
+  const ImageStrings strings = _image->get_strings();
+  // Retrieve each path component string.
+  u4 count = _image->get_location_count();
+  for (u4 i = 0; i < count; i++) {
+    u1* location_data = _image->get_location_data(i);
+
+    if (location_data) {
+       ImageLocation location(location_data);
+       const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
+       const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
+       const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
+       assert((strlen(parent) + strlen(base) + strlen(extension)) < JVM_MAXPATHLEN, "path exceeds buffer");
+       char path[JVM_MAXPATHLEN];
+       strcpy(path, parent);
+       strcat(path, base);
+       strcat(path, extension);
+       ClassLoader::compile_the_world_in(path, loader, CHECK);
+    }
+  }
+  if (HAS_PENDING_EXCEPTION) {
+  if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) {
+    CLEAR_PENDING_EXCEPTION;
+    tty->print_cr("\nCompileTheWorld : Ran out of memory\n");
+    tty->print_cr("Increase class metadata storage if a limit was set");
+  } else {
+    tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n");
+  }
+  }
+}
+
+bool ClassPathImageEntry::is_jrt() {
+  return string_ends_with(name(), "bootmodules.jimage");
+}
+#endif
+
 static void print_meta_index(LazyClassPathEntry* entry,
                              GrowableArray<char*>& meta_packages) {
   tty->print("[Meta index for %s=", entry->name());
@@ -635,7 +712,7 @@
   }
   ClassPathEntry* new_entry = NULL;
   if ((st->st_mode & S_IFREG) == S_IFREG) {
-    // Regular file, should be a zip file
+    // Regular file, should be a zip or image file
     // Canonicalized filename
     char canonical_path[JVM_MAXPATHLEN];
     if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
@@ -646,6 +723,11 @@
         return NULL;
       }
     }
+    // TODO - add proper criteria for selecting image file
+    ClassPathImageEntry* entry = new ClassPathImageEntry(canonical_path);
+    if (entry->is_open()) {
+      new_entry = entry;
+    } else {
     char* error_msg = NULL;
     jzfile* zip;
     {
@@ -656,9 +738,6 @@
     }
     if (zip != NULL && error_msg == NULL) {
       new_entry = new ClassPathZipEntry(zip, path);
-      if (TraceClassLoading || TraceClassPaths) {
-        tty->print_cr("[Opened %s]", path);
-      }
     } else {
       ResourceMark rm(thread);
       char *msg;
@@ -676,10 +755,14 @@
         return NULL;
       }
     }
+    }
+    if (TraceClassLoading || TraceClassPaths) {
+      tty->print_cr("[Opened %s]", path);
+    }
   } else {
     // Directory
     new_entry = new ClassPathDirEntry(path);
-    if (TraceClassLoading || TraceClassPaths) {
+    if (TraceClassLoading) {
       tty->print_cr("[Path %s]", path);
     }
   }
@@ -802,6 +885,7 @@
   ReadEntry    = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry"));
   ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry"));
   GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry"));
+  ZipInflateFully = CAST_TO_FN_PTR(ZipInflateFully_t, os::dll_lookup(handle, "ZIP_InflateFully"));
   Crc32        = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32"));
 
   // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL
@@ -810,12 +894,20 @@
     vm_exit_during_initialization("Corrupted ZIP library", path);
   }
 
+  if (ZipInflateFully == NULL) {
+    vm_exit_during_initialization("Corrupted ZIP library ZIP_InflateFully missing", path);
+  }
+
   // Lookup canonicalize entry in libjava.dll
   void *javalib_handle = os::native_java_library();
   CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, os::dll_lookup(javalib_handle, "Canonicalize"));
   // This lookup only works on 1.3. Do not check for non-null here
 }
 
+jboolean ClassLoader::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) {
+  return (*ZipInflateFully)(in, inSize, out, outSize, pmsg);
+}
+
 int ClassLoader::crc32(int crc, const char* buf, int len) {
   assert(Crc32 != NULL, "ZIP_CRC32 is not found");
   return (*Crc32)(crc, (const jbyte*)buf, len);
@@ -1368,8 +1460,7 @@
   tty->cr();
 }
 
-
-bool ClassPathDirEntry::is_rt_jar() {
+bool ClassPathDirEntry::is_jrt() {
   return false;
 }
 
@@ -1394,13 +1485,13 @@
   }
 }
 
-bool ClassPathZipEntry::is_rt_jar() {
+bool ClassPathZipEntry::is_jrt() {
   real_jzfile* zip = (real_jzfile*) _zip;
   int len = (int)strlen(zip->name);
   // Check whether zip name ends in "rt.jar"
   // This will match other archives named rt.jar as well, but this is
   // only used for debugging.
-  return (len >= 6) && (strcasecmp(zip->name + len - 6, "rt.jar") == 0);
+  return string_ends_with(zip->name, "rt.jar");
 }
 
 void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) {
@@ -1410,7 +1501,7 @@
   }
 }
 
-bool LazyClassPathEntry::is_rt_jar() {
+bool LazyClassPathEntry::is_jrt() {
   Thread* THREAD = Thread::current();
   ClassPathEntry* cpe = resolve_entry(THREAD);
   return (cpe != NULL) ? cpe->is_jar_file() : false;
@@ -1429,7 +1520,7 @@
   jlong start = os::javaTimeMillis();
   while (e != NULL) {
     // We stop at rt.jar, unless it is the first bootstrap path entry
-    if (e->is_rt_jar() && e != _first_entry) break;
+    if (e->is_jrt() && e != _first_entry) break;
     e->compile_the_world(system_class_loader, CATCH);
     e = e->next();
   }
@@ -1477,9 +1568,9 @@
 }
 
 void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) {
-  int len = (int)strlen(name);
-  if (len > 6 && strcmp(".class", name + len - 6) == 0) {
+  if (string_ends_with(name, ".class")) {
     // We have a .class file
+    int len = (int)strlen(name);
     char buffer[2048];
     strncpy(buffer, name, len - 6);
     buffer[len-6] = 0;
--- a/src/share/vm/classfile/classLoader.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/classfile/classLoader.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -67,7 +67,7 @@
   virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
   // Debugging
   NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
-  NOT_PRODUCT(virtual bool is_rt_jar() = 0;)
+  NOT_PRODUCT(virtual bool is_jrt() = 0;)
 };
 
 
@@ -81,7 +81,7 @@
   ClassFileStream* open_stream(const char* name, TRAPS);
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
-  NOT_PRODUCT(bool is_rt_jar();)
+  NOT_PRODUCT(bool is_jrt();)
 };
 
 
@@ -113,7 +113,7 @@
   void contents_do(void f(const char* name, void* context), void* context);
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
-  NOT_PRODUCT(bool is_rt_jar();)
+  NOT_PRODUCT(bool is_jrt();)
 };
 
 
@@ -139,7 +139,25 @@
   virtual bool is_lazy();
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
-  NOT_PRODUCT(bool is_rt_jar();)
+  NOT_PRODUCT(bool is_jrt();)
+};
+
+// For java image files
+class ImageFile;
+class ClassPathImageEntry: public ClassPathEntry {
+private:
+  ImageFile *_image;
+public:
+  bool is_jar_file()  { return false;  }
+  bool is_open()  { return _image != NULL; }
+  const char* name();
+  ClassPathImageEntry(char* name);
+  ~ClassPathImageEntry();
+  ClassFileStream* open_stream(const char* name, TRAPS);
+
+  // Debugging
+  NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
+  NOT_PRODUCT(bool is_jrt();)
 };
 
 class PackageHashtable;
@@ -227,6 +245,7 @@
   // to avoid confusing the zip library
   static bool get_canonical_path(const char* orig, char* out, int len);
  public:
+  static jboolean decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg);
   static int crc32(int crc, const char* buf, int len);
   static bool update_class_path_entry_list(const char *path,
                                            bool check_for_duplicates,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/imageFile.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2014, 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/imageFile.hpp"
+#include "runtime/os.inline.hpp"
+#include "utilities/bytes.hpp"
+
+
+// Compute the Perfect Hashing hash code for the supplied string.
+u4 ImageStrings::hash_code(const char* string, u4 seed) {
+  u1* bytes = (u1*)string;
+
+  // Compute hash code.
+  for (u1 byte = *bytes++; byte; byte = *bytes++) {
+    seed = (seed * HASH_MULTIPLIER) ^ byte;
+  }
+
+  // Ensure the result is unsigned.
+  return seed & 0x7FFFFFFF;
+}
+
+// Test to see if string begins with start.  If so returns remaining portion
+// of string.  Otherwise, NULL.
+const char* ImageStrings::starts_with(const char* string, const char* start) {
+  char ch1, ch2;
+
+  // Match up the strings the best we can.
+  while ((ch1 = *string) && (ch2 = *start)) {
+    if (ch1 != ch2) {
+      // Mismatch, return NULL.
+      return NULL;
+    }
+
+    string++, start++;
+  }
+
+  // Return remainder of string.
+  return string;
+}
+
+ImageLocation::ImageLocation(u1* data) {
+  // Deflate the attribute stream into an array of attributes.
+  memset(_attributes, 0, sizeof(_attributes));
+  u1 byte;
+
+  while ((byte = *data) != ATTRIBUTE_END) {
+    u1 kind = attribute_kind(byte);
+    u1 n = attribute_length(byte);
+    assert(kind < ATTRIBUTE_COUNT, "invalid image location attribute");
+    _attributes[kind] = attribute_value(data + 1, n);
+    data += n + 1;
+  }
+}
+
+ImageFile::ImageFile(const char* name) {
+  // Copy the image file name.
+  _name = NEW_C_HEAP_ARRAY(char, strlen(name)+1, mtClass);
+  strcpy(_name, name);
+
+  // Initialize for a closed file.
+  _fd = -1;
+  _memory_mapped = true;
+  _index_data = NULL;
+}
+
+ImageFile::~ImageFile() {
+  // Ensure file is closed.
+  close();
+
+  // Free up name.
+  FREE_C_HEAP_ARRAY(char, _name);
+}
+
+bool ImageFile::open() {
+  // If file exists open for reading.
+  struct stat st;
+  if (os::stat(_name, &st) != 0 ||
+    (st.st_mode & S_IFREG) != S_IFREG ||
+    (_fd = os::open(_name, 0, O_RDONLY)) == -1) {
+    return false;
+  }
+
+  // Read image file header and verify.
+  u8 header_size = sizeof(ImageHeader);
+  if (os::read(_fd, &_header, header_size) != header_size ||
+    _header._magic != IMAGE_MAGIC ||
+    _header._major_version != MAJOR_VERSION ||
+    _header._minor_version != MINOR_VERSION) {
+    close();
+    return false;
+  }
+
+  // Memory map index.
+  _index_size = index_size();
+  _index_data = (u1*)os::map_memory(_fd, _name, 0, NULL, _index_size, true, false);
+
+  // Failing that, read index into C memory.
+  if (_index_data == NULL) {
+    _memory_mapped = false;
+    _index_data = NEW_RESOURCE_ARRAY(u1, _index_size);
+
+    if (os::seek_to_file_offset(_fd, 0) == -1) {
+      close();
+      return false;
+    }
+
+    if (os::read(_fd, _index_data, _index_size) != _index_size) {
+      close();
+      return false;
+    }
+
+    return true;
+  }
+
+// Used to advance a pointer, unstructured.
+#undef nextPtr
+#define nextPtr(base, fromType, count, toType) (toType*)((fromType*)(base) + (count))
+  // Pull tables out from the index.
+  _redirect_table = nextPtr(_index_data, u1, header_size, s4);
+  _offsets_table = nextPtr(_redirect_table, s4, _header._location_count, u4);
+  _location_bytes = nextPtr(_offsets_table, u4, _header._location_count, u1);
+  _string_bytes = nextPtr(_location_bytes, u1, _header._locations_size, u1);
+#undef nextPtr
+
+  // Successful open.
+  return true;
+}
+
+void ImageFile::close() {
+  // Dealllocate the index.
+  if (_index_data) {
+    if (_memory_mapped) {
+      os::unmap_memory((char*)_index_data, _index_size);
+    } else {
+      FREE_RESOURCE_ARRAY(u1, _index_data, _index_size);
+    }
+
+    _index_data = NULL;
+  }
+
+  // close file.
+  if (_fd != -1) {
+    os::close(_fd);
+    _fd = -1;
+  }
+
+}
+
+// Return the attribute stream for a named resourced.
+u1* ImageFile::find_location_data(const char* path) const {
+  // Compute hash.
+  u4 hash = ImageStrings::hash_code(path) % _header._location_count;
+  s4 redirect = _redirect_table[hash];
+
+  if (!redirect) {
+    return NULL;
+  }
+
+  u4 index;
+
+  if (redirect < 0) {
+    // If no collision.
+    index = -redirect - 1;
+  } else {
+    // If collision, recompute hash code.
+    index = ImageStrings::hash_code(path, redirect) % _header._location_count;
+  }
+
+  assert(index < _header._location_count, "index exceeds location count");
+  u4 offset = _offsets_table[index];
+  assert(offset < _header._locations_size, "offset exceeds location attributes size");
+
+  if (offset == 0) {
+    return NULL;
+  }
+
+  return _location_bytes + offset;
+}
+
+// Verify that a found location matches the supplied path.
+bool ImageFile::verify_location(ImageLocation& location, const char* path) const {
+  // Retrieve each path component string.
+  ImageStrings strings(_string_bytes, _header._strings_size);
+  // Match a path with each subcomponent without concatenation (copy).
+  // Match up path parent.
+  const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
+  const char* next = ImageStrings::starts_with(path, parent);
+  // Continue only if a complete match.
+  if (!next) return false;
+  // Match up path base.
+  const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
+  next = ImageStrings::starts_with(next, base);
+  // Continue only if a complete match.
+  if (!next) return false;
+  // Match up path extension.
+  const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
+  next = ImageStrings::starts_with(next, extension);
+
+  // True only if complete match and no more characters.
+  return next && *next == '\0';
+}
+
+// Return the resource for the supplied location.
+u1* ImageFile::get_resource(ImageLocation& location) const {
+  // Retrieve the byte offset and size of the resource.
+  u8 offset = _index_size + location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET);
+  u8 size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
+  u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED);
+  u8 read_size = compressed_size ? compressed_size : size;
+
+  // Allocate space for the resource.
+  u1* data = NEW_RESOURCE_ARRAY(u1, read_size);
+
+  bool is_read = os::read_at(_fd, data, read_size, offset) == read_size;
+  guarantee(is_read, "error reading from image or short read");
+
+  // If not compressed, just return the data.
+  if (!compressed_size) {
+    return data;
+  }
+
+  u1* uncompressed = NEW_RESOURCE_ARRAY(u1, size);
+  char* msg = NULL;
+  jboolean res = ClassLoader::decompress(data, compressed_size, uncompressed, size, &msg);
+  if (!res) warning("decompression failed due to %s\n", msg);
+  guarantee(res, "decompression failed");
+
+  return uncompressed;
+}
+
+void ImageFile::get_resource(const char* path, u1*& buffer, u8& size) const {
+  buffer = NULL;
+  size = 0;
+  u1* data = find_location_data(path);
+  if (data) {
+    ImageLocation location(data);
+    if (verify_location(location, path)) {
+      size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
+      buffer = get_resource(location);
+    }
+  }
+}
+
+GrowableArray<const char*>* ImageFile::packages(const char* name) {
+  char entry[JVM_MAXPATHLEN];
+  bool overflow = jio_snprintf(entry, sizeof(entry), "%s/packages.offsets", name) == -1;
+  guarantee(!overflow, "package name overflow");
+
+  u1* buffer;
+  u8 size;
+
+  get_resource(entry, buffer, size);
+  guarantee(buffer, "missing module packages reource");
+  ImageStrings strings(_string_bytes, _header._strings_size);
+  GrowableArray<const char*>* pkgs = new GrowableArray<const char*>();
+  int count = size / 4;
+  for (int i = 0; i < count; i++) {
+    u4 offset = Bytes::get_Java_u4(buffer + (i*4));
+    const char* p = strings.get(offset);
+    pkgs->append(p);
+  }
+
+  return pkgs;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/imageFile.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2014, 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_IMAGEFILE_HPP
+#define SHARE_VM_CLASSFILE_IMAGEFILE_HPP
+
+#include "classfile/classLoader.hpp"
+#include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// Image files are an alternate file format for storing classes and resources. The
+// goal is to supply file access which is faster and smaller that the jar format.
+// It should be noted that unlike jars information stored in an image is in native
+// endian format. This allows the image to be memory mapped into memory without
+// endian translation.  This also means that images are platform dependent.
+//
+// Image files are structured as three sections;
+//
+//         +-----------+
+//         |  Header   |
+//         +-----------+
+//         |           |
+//         | Directory |
+//         |           |
+//         +-----------+
+//         |           |
+//         |           |
+//         | Resources |
+//         |           |
+//         |           |
+//         +-----------+
+//
+// The header contains information related to identification and description of
+// contents.
+//
+//         +-------------------------+
+//         |   Magic (0xCAFEDADA)    |
+//         +------------+------------+
+//         | Major Vers | Minor Vers |
+//         +------------+------------+
+//         |      Location Count     |
+//         +-------------------------+
+//         |      Attributes Size    |
+//         +-------------------------+
+//         |       Strings Size      |
+//         +-------------------------+
+//
+// Magic - means of identifying validity of the file.  This avoids requiring a
+//         special file extension.
+// Major vers, minor vers - differences in version numbers indicate structural
+//                          changes in the image.
+// Location count - number of locations/resources in the file.  This count is also
+//                  the length of lookup tables used in the directory.
+// Attributes size - number of bytes in the region used to store location attribute
+//                   streams.
+// Strings size - the size of the region used to store strings used by the
+//                directory and meta data.
+//
+// The directory contains information related to resource lookup. The algorithm
+// used for lookup is "A Practical Minimal Perfect Hashing Method"
+// (http://homepages.dcc.ufmg.br/~nivio/papers/wea05.pdf). Given a path string
+// in the form <package>/<base>.<extension>  return the resource location
+// information;
+//
+//     redirectIndex = hash(path, DEFAULT_SEED) % count;
+//     redirect = redirectTable[redirectIndex];
+//     if (redirect == 0) return not found;
+//     locationIndex = redirect < 0 ? -1 - redirect : hash(path, redirect) % count;
+//     location = locationTable[locationIndex];
+//     if (!verify(location, path)) return not found;
+//     return location;
+//
+// Note: The hash function takes an initial seed value.  A different seed value
+// usually returns a different result for strings that would otherwise collide with
+// other seeds. The verify function guarantees the found resource location is
+// indeed the resource we are looking for.
+//
+// The following is the format of the directory;
+//
+//         +-------------------+
+//         |   Redirect Table  |
+//         +-------------------+
+//         | Attribute Offsets |
+//         +-------------------+
+//         |   Attribute Data  |
+//         +-------------------+
+//         |      Strings      |
+//         +-------------------+
+//
+// Redirect Table - Array of 32-bit signed values representing actions that
+//                  should take place for hashed strings that map to that
+//                  value.  Negative values indicate no hash collision and can be
+//                  quickly converted to indices into attribute offsets.  Positive
+//                  values represent a new seed for hashing an index into attribute
+//                  offsets.  Zero indicates not found.
+// Attribute Offsets - Array of 32-bit unsigned values representing offsets into
+//                     attribute data.  Attribute offsets can be iterated to do a
+//                     full survey of resources in the image.
+// Attribute Data - Bytes representing compact attribute data for locations. (See
+//                  comments in ImageLocation.)
+// Strings - Collection of zero terminated UTF-8 strings used by the directory and
+//           image meta data.  Each string is accessed by offset.  Each string is
+//           unique.  Offset zero is reserved for the empty string.
+//
+// Note that the memory mapped directory assumes 32 bit alignment of the image
+// header, the redirect table and the attribute offsets.
+//
+
+
+// Manage image file string table.
+class ImageStrings {
+private:
+  // Data bytes for strings.
+  u1* _data;
+  // Number of bytes in the string table.
+  u4 _size;
+
+public:
+  // Prime used to generate hash for Perfect Hashing.
+  static const u4 HASH_MULTIPLIER = 0x01000193;
+
+  ImageStrings(u1* data, u4 size) : _data(data), _size(size) {}
+
+  // Return the UTF-8 string beginning at offset.
+  inline const char* get(u4 offset) const {
+    assert(offset < _size, "offset exceeds string table size");
+    return (const char*)(_data + offset);
+  }
+
+  // Compute the Perfect Hashing hash code for the supplied string.
+  inline static u4 hash_code(const char* string) {
+    return hash_code(string, HASH_MULTIPLIER);
+  }
+
+  // Compute the Perfect Hashing hash code for the supplied string, starting at seed.
+  static u4 hash_code(const char* string, u4 seed);
+
+  // Test to see if string begins with start.  If so returns remaining portion
+  // of string.  Otherwise, NULL.  Used to test sections of a path without
+  // copying.
+  static const char* starts_with(const char* string, const char* start);
+
+};
+
+// Manage image file location attribute streams.  Within an image, a location's
+// attributes are compressed into a stream of bytes.  An attribute stream is
+// composed of individual attribute sequences.  Each attribute sequence begins with
+// a header byte containing the attribute 'kind' (upper 5 bits of header) and the
+// 'length' less 1 (lower 3 bits of header) of bytes that follow containing the
+// attribute value.  Attribute values present as most significant byte first.
+//
+// Ex. Container offset (ATTRIBUTE_OFFSET) 0x33562 would be represented as 0x22
+// (kind = 4, length = 3), 0x03, 0x35, 0x62.
+//
+// An attribute stream is terminated with a header kind of ATTRIBUTE_END (header
+// byte of zero.)
+//
+// ImageLocation inflates the stream into individual values stored in the long
+// array _attributes. This allows an attribute value can be quickly accessed by
+// direct indexing. Unspecified values default to zero.
+//
+// Notes:
+//  - Even though ATTRIBUTE_END is used to mark the end of the attribute stream,
+//    streams will contain zero byte values to represent lesser significant bits.
+//    Thus, detecting a zero byte is not sufficient to detect the end of an attribute
+//    stream.
+//  - ATTRIBUTE_OFFSET represents the number of bytes from the beginning of the region
+//    storing the resources.  Thus, in an image this represents the number of bytes
+//    after the directory.
+//  - Currently, compressed resources are represented by having a non-zero
+//    ATTRIBUTE_COMPRESSED value.  This represents the number of bytes stored in the
+//    image, and the value of ATTRIBUTE_UNCOMPRESSED represents number of bytes of the
+//    inflated resource in memory. If the ATTRIBUTE_COMPRESSED is zero then the value
+//    of ATTRIBUTE_UNCOMPRESSED represents both the number of bytes in the image and
+//    in memory.  In the future, additional compression techniques will be used and
+//    represented differently.
+//  - Package strings include trailing slash and extensions include prefix period.
+//
+class ImageLocation {
+public:
+  // Attribute kind enumeration.
+  static const u1 ATTRIBUTE_END = 0; // End of attribute stream marker
+  static const u1 ATTRIBUTE_BASE = 1; // String table offset of resource path base
+  static const u1 ATTRIBUTE_PARENT = 2; // String table offset of resource path parent
+  static const u1 ATTRIBUTE_EXTENSION = 3; // String table offset of resource path extension
+  static const u1 ATTRIBUTE_OFFSET = 4; // Container byte offset of resource
+  static const u1 ATTRIBUTE_COMPRESSED = 5; // In image byte size of the compressed resource
+  static const u1 ATTRIBUTE_UNCOMPRESSED = 6; // In memory byte size of the uncompressed resource
+  static const u1 ATTRIBUTE_COUNT = 7; // Number of attribute kinds
+
+private:
+  // Values of inflated attributes.
+  u8 _attributes[ATTRIBUTE_COUNT];
+
+  // Return the attribute value number of bytes.
+  inline static u1 attribute_length(u1 data) {
+    return (data & 0x7) + 1;
+  }
+
+  // Return the attribute kind.
+  inline static u1 attribute_kind(u1 data) {
+    u1 kind = data >> 3;
+    assert(kind < ATTRIBUTE_COUNT, "invalid attribute kind");
+    return kind;
+  }
+
+  // Return the attribute length.
+  inline static u8 attribute_value(u1* data, u1 n) {
+    assert(0 < n && n <= 8, "invalid attribute value length");
+    u8 value = 0;
+
+    // Most significant bytes first.
+    for (u1 i = 0; i < n; i++) {
+      value <<= 8;
+      value |= data[i];
+    }
+
+    return value;
+  }
+
+public:
+  ImageLocation(u1* data);
+
+  // Retrieve an attribute value from the inflated array.
+  inline u8 get_attribute(u1 kind) const {
+    assert(ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT, "invalid attribute kind");
+    return _attributes[kind];
+  }
+
+  // Retrieve an attribute string value from the inflated array.
+  inline const char* get_attribute(u4 kind, const ImageStrings& strings) const {
+    return strings.get((u4)get_attribute(kind));
+  }
+};
+
+// Manage the image file.
+class ImageFile: public CHeapObj<mtClass> {
+private:
+  // Image file marker.
+  static const u4 IMAGE_MAGIC = 0xCAFEDADA;
+  // Image file major version number.
+  static const u2 MAJOR_VERSION = 0;
+  // Image file minor version number.
+  static const u2 MINOR_VERSION = 1;
+
+  struct ImageHeader {
+    u4 _magic;          // Image file marker
+    u2 _major_version;  // Image file major version number
+    u2 _minor_version;  // Image file minor version number
+    u4 _location_count; // Number of locations managed in index.
+    u4 _locations_size; // Number of bytes in attribute table.
+    u4 _strings_size;   // Number of bytes in string table.
+  };
+
+  char* _name;          // Name of image
+  int _fd;              // File descriptor
+  bool _memory_mapped;  // Is file memory mapped
+  ImageHeader _header;  // Image header
+  u8 _index_size;       // Total size of index
+  u1* _index_data;      // Raw index data
+  s4* _redirect_table;  // Perfect hash redirect table
+  u4* _offsets_table;   // Location offset table
+  u1* _location_bytes;  // Location attributes
+  u1* _string_bytes;    // String table
+
+  // Compute number of bytes in image file index.
+  inline u8 index_size() {
+    return sizeof(ImageHeader) +
+    _header._location_count * sizeof(u4) * 2 +
+    _header._locations_size +
+    _header._strings_size;
+  }
+
+public:
+  ImageFile(const char* name);
+  ~ImageFile();
+
+  // Open image file for access.
+  bool open();
+  // Close image file.
+  void close();
+
+  // Retrieve name of image file.
+  inline const char* name() const {
+    return _name;
+  }
+
+  // Return a string table accessor.
+  inline const ImageStrings get_strings() const {
+    return ImageStrings(_string_bytes, _header._strings_size);
+  }
+
+  // Return number of locations in image file index.
+  inline u4 get_location_count() const {
+    return _header._location_count;
+  }
+
+  // Return location attribute stream for location i.
+  inline u1* get_location_data(u4 i) const {
+    u4 offset = _offsets_table[i];
+
+    return offset != 0 ? _location_bytes + offset : NULL;
+  }
+
+  // Return the attribute stream for a named resourced.
+  u1* find_location_data(const char* path) const;
+
+  // Verify that a found location matches the supplied path.
+  bool verify_location(ImageLocation& location, const char* path) const;
+
+  // Return the resource for the supplied location info.
+  u1* get_resource(ImageLocation& location) const;
+
+  // Return the resource associated with the path else NULL if not found.
+  void get_resource(const char* path, u1*& buffer, u8& size) const;
+
+  // Return an array of packages for a given module
+  GrowableArray<const char*>* packages(const char* name);
+};
+
+#endif // SHARE_VM_CLASSFILE_IMAGEFILE_HPP
--- a/src/share/vm/classfile/sharedPathsMiscInfo.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/classfile/sharedPathsMiscInfo.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -110,7 +110,7 @@
 bool SharedPathsMiscInfo::check(jint type, const char* path) {
   switch (type) {
   case BOOT:
-    if (strcmp(path, Arguments::get_sysclasspath()) != 0) {
+    if (os::file_name_strcmp(path, Arguments::get_sysclasspath()) != 0) {
       return fail("[BOOT classpath mismatch, actual: -Dsun.boot.class.path=", Arguments::get_sysclasspath());
     }
     break;
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -793,11 +793,6 @@
   }
 }
 
-CompactibleSpace*
-ConcurrentMarkSweepGeneration::first_compaction_space() const {
-  return _cmsSpace;
-}
-
 void ConcurrentMarkSweepGeneration::reset_after_compaction() {
   // Clear the promotion information.  These pointers can be adjusted
   // along with all the other pointers into the heap but
@@ -808,10 +803,6 @@
   }
 }
 
-void ConcurrentMarkSweepGeneration::space_iterate(SpaceClosure* blk, bool usedOnly) {
-  blk->do_space(_cmsSpace);
-}
-
 void ConcurrentMarkSweepGeneration::compute_new_size() {
   assert_locked_or_safepoint(Heap_lock);
 
@@ -882,7 +873,7 @@
         expand_bytes);
     }
     // safe if expansion fails
-    expand(expand_bytes, 0, CMSExpansionCause::_satisfy_free_ratio);
+    expand_for_gc_cause(expand_bytes, 0, CMSExpansionCause::_satisfy_free_ratio);
     if (PrintGCDetails && Verbose) {
       gclog_or_tty->print_cr("  Expanded free fraction %f",
         ((double) free()) / capacity());
@@ -1048,8 +1039,7 @@
   if (res == NULL) {
     // expand and retry
     size_t s = _cmsSpace->expansionSpaceRequired(obj_size);  // HeapWords
-    expand(s*HeapWordSize, MinHeapDeltaBytes,
-      CMSExpansionCause::_satisfy_promotion);
+    expand_for_gc_cause(s*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_satisfy_promotion);
     // Since there's currently no next generation, we don't try to promote
     // into a more senior generation.
     assert(next_gen() == NULL, "assumption, based upon which no attempt "
@@ -2625,13 +2615,6 @@
 ALL_SINCE_SAVE_MARKS_CLOSURES(CMS_SINCE_SAVE_MARKS_DEFN)
 
 void
-ConcurrentMarkSweepGeneration::younger_refs_iterate(OopsInGenClosure* cl) {
-  cl->set_generation(this);
-  younger_refs_in_space_iterate(_cmsSpace, cl);
-  cl->reset_generation();
-}
-
-void
 ConcurrentMarkSweepGeneration::oop_iterate(ExtendedOopClosure* cl) {
   if (freelistLock()->owned_by_self()) {
     Generation::oop_iterate(cl);
@@ -2803,23 +2786,17 @@
   CMSSynchronousYieldRequest yr;
   assert(!tlab, "Can't deal with TLAB allocation");
   MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
-  expand(word_size*HeapWordSize, MinHeapDeltaBytes,
-    CMSExpansionCause::_satisfy_allocation);
+  expand_for_gc_cause(word_size*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_satisfy_allocation);
   if (GCExpandToAllocateDelayMillis > 0) {
     os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false);
   }
   return have_lock_and_allocate(word_size, tlab);
 }
 
-// YSR: All of this generation expansion/shrinking stuff is an exact copy of
-// TenuredGeneration, which makes me wonder if we should move this
-// to CardGeneration and share it...
-bool ConcurrentMarkSweepGeneration::expand(size_t bytes, size_t expand_bytes) {
-  return CardGeneration::expand(bytes, expand_bytes);
-}
-
-void ConcurrentMarkSweepGeneration::expand(size_t bytes, size_t expand_bytes,
-  CMSExpansionCause::Cause cause)
+void ConcurrentMarkSweepGeneration::expand_for_gc_cause(
+    size_t bytes,
+    size_t expand_bytes,
+    CMSExpansionCause::Cause cause)
 {
 
   bool success = expand(bytes, expand_bytes);
@@ -2848,8 +2825,7 @@
       return NULL;
     }
     // Otherwise, we try expansion.
-    expand(word_sz*HeapWordSize, MinHeapDeltaBytes,
-      CMSExpansionCause::_allocate_par_lab);
+    expand_for_gc_cause(word_sz*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_allocate_par_lab);
     // Now go around the loop and try alloc again;
     // A competing par_promote might beat us to the expansion space,
     // so we may go around the loop again if promotion fails again.
@@ -2876,8 +2852,7 @@
       return false;
     }
     // Otherwise, we try expansion.
-    expand(refill_size_bytes, MinHeapDeltaBytes,
-      CMSExpansionCause::_allocate_par_spooling_space);
+    expand_for_gc_cause(refill_size_bytes, MinHeapDeltaBytes, CMSExpansionCause::_allocate_par_spooling_space);
     // Now go around the loop and try alloc again;
     // A competing allocation might beat us to the expansion space,
     // so we may go around the loop again if allocation fails again.
@@ -2887,77 +2862,16 @@
   }
 }
 
-
-void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) {
-  assert_locked_or_safepoint(ExpandHeap_lock);
-  // Shrink committed space
-  _virtual_space.shrink_by(bytes);
-  // Shrink space; this also shrinks the space's BOT
-  _cmsSpace->set_end((HeapWord*) _virtual_space.high());
-  size_t new_word_size = heap_word_size(_cmsSpace->capacity());
-  // Shrink the shared block offset array
-  _bts->resize(new_word_size);
-  MemRegion mr(_cmsSpace->bottom(), new_word_size);
-  // Shrink the card table
-  Universe::heap()->barrier_set()->resize_covered_region(mr);
-
-  if (Verbose && PrintGC) {
-    size_t new_mem_size = _virtual_space.committed_size();
-    size_t old_mem_size = new_mem_size + bytes;
-    gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K",
-                  name(), old_mem_size/K, new_mem_size/K);
-  }
-}
-
 void ConcurrentMarkSweepGeneration::shrink(size_t bytes) {
-  assert_locked_or_safepoint(Heap_lock);
-  size_t size = ReservedSpace::page_align_size_down(bytes);
   // Only shrink if a compaction was done so that all the free space
   // in the generation is in a contiguous block at the end.
-  if (size > 0 && did_compact()) {
-    shrink_by(size);
-  }
-}
-
-bool ConcurrentMarkSweepGeneration::grow_by(size_t bytes) {
+  if (did_compact()) {
+    CardGeneration::shrink(bytes);
+  }
+}
+
+void ConcurrentMarkSweepGeneration::assert_correct_size_change_locking() {
   assert_locked_or_safepoint(Heap_lock);
-  bool result = _virtual_space.expand_by(bytes);
-  if (result) {
-    size_t new_word_size =
-      heap_word_size(_virtual_space.committed_size());
-    MemRegion mr(_cmsSpace->bottom(), new_word_size);
-    _bts->resize(new_word_size);  // resize the block offset shared array
-    Universe::heap()->barrier_set()->resize_covered_region(mr);
-    // Hmmmm... why doesn't CFLS::set_end verify locking?
-    // This is quite ugly; FIX ME XXX
-    _cmsSpace->assert_locked(freelistLock());
-    _cmsSpace->set_end((HeapWord*)_virtual_space.high());
-
-    // update the space and generation capacity counters
-    if (UsePerfData) {
-      _space_counters->update_capacity();
-      _gen_counters->update_all();
-    }
-
-    if (Verbose && PrintGC) {
-      size_t new_mem_size = _virtual_space.committed_size();
-      size_t old_mem_size = new_mem_size - bytes;
-      gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K",
-                    name(), old_mem_size/K, bytes/K, new_mem_size/K);
-    }
-  }
-  return result;
-}
-
-bool ConcurrentMarkSweepGeneration::grow_to_reserved() {
-  assert_locked_or_safepoint(Heap_lock);
-  bool success = true;
-  const size_t remaining_bytes = _virtual_space.uncommitted_size();
-  if (remaining_bytes > 0) {
-    success = grow_by(remaining_bytes);
-    DEBUG_ONLY(if (!success) warning("grow to reserved failed");)
-  }
-  return success;
 }
 
 void ConcurrentMarkSweepGeneration::shrink_free_list_by(size_t bytes) {
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, 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
@@ -30,9 +30,10 @@
 #include "gc_implementation/shared/gcStats.hpp"
 #include "gc_implementation/shared/gcWhen.hpp"
 #include "gc_implementation/shared/generationCounters.hpp"
+#include "memory/cardGeneration.hpp"
 #include "memory/freeBlockDictionary.hpp"
-#include "memory/generation.hpp"
 #include "memory/iterator.hpp"
+#include "memory/space.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/virtualspace.hpp"
 #include "services/memoryService.hpp"
@@ -171,9 +172,7 @@
 // Represents a marking stack used by the CMS collector.
 // Ideally this should be GrowableArray<> just like MSC's marking stack(s).
 class CMSMarkStack: public CHeapObj<mtGC>  {
-  //
   friend class CMSCollector;   // To get at expansion stats further below.
-  //
 
   VirtualSpace _virtual_space;  // Space for the stack
   oop*   _base;      // Bottom of stack
@@ -1031,6 +1030,9 @@
   void set_expansion_cause(CMSExpansionCause::Cause v) { _expansion_cause = v;}
   CMSExpansionCause::Cause expansion_cause() const { return _expansion_cause; }
 
+  // Accessing spaces
+  CompactibleSpace* space() const { return (CompactibleSpace*)_cmsSpace; }
+
  private:
   // For parallel young-gen GC support.
   CMSParGCThreadState** _par_gc_thread_states;
@@ -1064,6 +1066,10 @@
   double initiating_occupancy() const { return _initiating_occupancy; }
   void   init_initiating_occupancy(intx io, uintx tr);
 
+  void expand_for_gc_cause(size_t bytes, size_t expand_bytes, CMSExpansionCause::Cause cause);
+
+  void assert_correct_size_change_locking();
+
  public:
   ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
                                 int level, CardTableRS* ct,
@@ -1100,23 +1106,14 @@
   // Override
   virtual void ref_processor_init();
 
-  // Grow generation by specified size (returns false if unable to grow)
-  bool grow_by(size_t bytes);
-  // Grow generation to reserved size.
-  bool grow_to_reserved();
-
   void clear_expansion_cause() { _expansion_cause = CMSExpansionCause::_no_expansion; }
 
   // Space enquiries
-  size_t capacity() const;
-  size_t used() const;
-  size_t free() const;
   double occupancy() const { return ((double)used())/((double)capacity()); }
   size_t contiguous_available() const;
   size_t unsafe_max_alloc_nogc() const;
 
   // over-rides
-  MemRegion used_region() const;
   MemRegion used_region_at_save_marks() const;
 
   // Does a "full" (forced) collection invoked on this generation collect
@@ -1127,10 +1124,6 @@
     return !ScavengeBeforeFullGC;
   }
 
-  void space_iterate(SpaceClosure* blk, bool usedOnly = false);
-
-  // Support for compaction
-  CompactibleSpace* first_compaction_space() const;
   // Adjust quantities in the generation affected by
   // the compaction.
   void reset_after_compaction();
@@ -1190,18 +1183,13 @@
   }
 
   // Allocation failure
-  void expand(size_t bytes, size_t expand_bytes,
-    CMSExpansionCause::Cause cause);
-  virtual bool expand(size_t bytes, size_t expand_bytes);
   void shrink(size_t bytes);
-  void shrink_by(size_t bytes);
   HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz);
   bool expand_and_ensure_spooling_space(PromotionInfo* promo);
 
   // Iteration support and related enquiries
   void save_marks();
   bool no_allocs_since_save_marks();
-  void younger_refs_iterate(OopsInGenClosure* cl);
 
   // Iteration support specific to CMS generations
   void save_sweep_limit();
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, 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
@@ -369,22 +369,6 @@
   cmsSpace()->save_sweep_limit();
 }
 
-inline size_t ConcurrentMarkSweepGeneration::capacity() const {
-  return _cmsSpace->capacity();
-}
-
-inline size_t ConcurrentMarkSweepGeneration::used() const {
-  return _cmsSpace->used();
-}
-
-inline size_t ConcurrentMarkSweepGeneration::free() const {
-  return _cmsSpace->free();
-}
-
-inline MemRegion ConcurrentMarkSweepGeneration::used_region() const {
-  return _cmsSpace->used_region();
-}
-
 inline MemRegion ConcurrentMarkSweepGeneration::used_region_at_save_marks() const {
   return _cmsSpace->used_region_at_save_marks();
 }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -352,7 +352,7 @@
 }
 
 void G1RegionMappingChangedListener::reset_from_card_cache(uint start_idx, size_t num_regions) {
-  OtherRegionsTable::invalidate(start_idx, num_regions);
+  HeapRegionRemSet::invalidate_from_card_cache(start_idx, num_regions);
 }
 
 void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_regions, bool zero_filled) {
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -407,20 +407,8 @@
   }
 }
 
-void OtherRegionsTable::initialize(uint max_regions) {
-  FromCardCache::initialize(HeapRegionRemSet::num_par_rem_sets(), max_regions);
-}
-
-void OtherRegionsTable::invalidate(uint start_idx, size_t num_regions) {
-  FromCardCache::invalidate(start_idx, num_regions);
-}
-
-void OtherRegionsTable::print_from_card_cache() {
-  FromCardCache::print();
-}
-
 void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) {
-  uint cur_hrm_ind = hr()->hrm_index();
+  uint cur_hrm_ind = _hr->hrm_index();
 
   if (G1TraceHeapRegionRememberedSet) {
     gclog_or_tty->print_cr("ORT::add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").",
@@ -434,7 +422,7 @@
 
   if (G1TraceHeapRegionRememberedSet) {
     gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = %d)",
-                  hr()->bottom(), from_card,
+                  _hr->bottom(), from_card,
                   FromCardCache::at(tid, cur_hrm_ind));
   }
 
@@ -477,13 +465,13 @@
       if (G1HRRSUseSparseTable &&
           _sparse_table.add_card(from_hrm_ind, card_index)) {
         if (G1RecordHRRSOops) {
-          HeapRegionRemSet::record(hr(), from);
+          HeapRegionRemSet::record(_hr, from);
           if (G1TraceHeapRegionRememberedSet) {
             gclog_or_tty->print("   Added card " PTR_FORMAT " to region "
                                 "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n",
                                 align_size_down(uintptr_t(from),
                                                 CardTableModRefBS::card_size),
-                                hr()->bottom(), from);
+                                _hr->bottom(), from);
           }
         }
         if (G1TraceHeapRegionRememberedSet) {
@@ -539,13 +527,13 @@
   prt->add_reference(from);
 
   if (G1RecordHRRSOops) {
-    HeapRegionRemSet::record(hr(), from);
+    HeapRegionRemSet::record(_hr, from);
     if (G1TraceHeapRegionRememberedSet) {
       gclog_or_tty->print("Added card " PTR_FORMAT " to region "
                           "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n",
                           align_size_down(uintptr_t(from),
                                           CardTableModRefBS::card_size),
-                          hr()->bottom(), from);
+                          _hr->bottom(), from);
     }
   }
   assert(contains_reference(from), "We just added it!");
@@ -614,7 +602,7 @@
     if (G1TraceHeapRegionRememberedSet) {
       gclog_or_tty->print("Coarsened entry in region [" PTR_FORMAT "...] "
                  "for region [" PTR_FORMAT "...] (" SIZE_FORMAT " coarse entries).\n",
-                 hr()->bottom(),
+                 _hr->bottom(),
                  max->hr()->bottom(),
                  _n_coarse_entries);
     }
@@ -627,13 +615,11 @@
   return max;
 }
 
-
-// At present, this must be called stop-world single-threaded.
 void OtherRegionsTable::scrub(CardTableModRefBS* ctbs,
                               BitMap* region_bm, BitMap* card_bm) {
   // First eliminated garbage regions from the coarse map.
   if (G1RSScrubVerbose) {
-    gclog_or_tty->print_cr("Scrubbing region %u:", hr()->hrm_index());
+    gclog_or_tty->print_cr("Scrubbing region %u:", _hr->hrm_index());
   }
 
   assert(_coarse_map.size() == region_bm->size(), "Precondition");
@@ -752,7 +738,7 @@
 }
 
 void OtherRegionsTable::clear_fcc() {
-  FromCardCache::clear(hr()->hrm_index());
+  FromCardCache::clear(_hr->hrm_index());
 }
 
 void OtherRegionsTable::clear() {
@@ -774,27 +760,6 @@
   clear_fcc();
 }
 
-bool OtherRegionsTable::del_single_region_table(size_t ind,
-                                                HeapRegion* hr) {
-  assert(0 <= ind && ind < _max_fine_entries, "Preconditions.");
-  PerRegionTable** prev_addr = &_fine_grain_regions[ind];
-  PerRegionTable* prt = *prev_addr;
-  while (prt != NULL && prt->hr() != hr) {
-    prev_addr = prt->collision_list_next_addr();
-    prt = prt->collision_list_next();
-  }
-  if (prt != NULL) {
-    assert(prt->hr() == hr, "Loop postcondition.");
-    *prev_addr = prt->collision_list_next();
-    unlink_from_all(prt);
-    PerRegionTable::free(prt);
-    _n_fine_entries--;
-    return true;
-  } else {
-    return false;
-  }
-}
-
 bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const {
   // Cast away const in this case.
   MutexLockerEx x((Mutex*)_m, Mutex::_no_safepoint_check_flag);
@@ -975,7 +940,7 @@
   _hrrs(hrrs),
   _g1h(G1CollectedHeap::heap()),
   _coarse_map(&hrrs->_other_regions._coarse_map),
-  _bosa(hrrs->bosa()),
+  _bosa(hrrs->_bosa),
   _is(Sparse),
   // Set these values so that we increment to the first region.
   _coarse_cur_region_index(-1),
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -162,32 +162,36 @@
   // to hold _m, and the fine-grain table to be full.
   PerRegionTable* delete_region_table();
 
-  // If a PRT for "hr" is in the bucket list indicated by "ind" (which must
-  // be the correct index for "hr"), delete it and return true; else return
-  // false.
-  bool del_single_region_table(size_t ind, HeapRegion* hr);
-
   // link/add the given fine grain remembered set into the "all" list
   void link_to_all(PerRegionTable * prt);
   // unlink/remove the given fine grain remembered set into the "all" list
   void unlink_from_all(PerRegionTable * prt);
 
+  bool contains_reference_locked(OopOrNarrowOopStar from) const;
+
+  // Clear the from_card_cache entries for this region.
+  void clear_fcc();
 public:
+  // Create a new remembered set for the given heap region. The given mutex should
+  // be used to ensure consistency.
   OtherRegionsTable(HeapRegion* hr, Mutex* m);
 
-  HeapRegion* hr() const { return _hr; }
-
   // For now.  Could "expand" some tables in the future, so that this made
   // sense.
   void add_reference(OopOrNarrowOopStar from, uint tid);
 
+  // Returns whether the remembered set contains the given reference.
+  bool contains_reference(OopOrNarrowOopStar from) const;
+
   // Removes any entries shown by the given bitmaps to contain only dead
-  // objects.
+  // objects. Not thread safe.
+  // Set bits in the bitmaps indicate that the given region or card is live.
   void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
 
-  // Returns whether this remembered set (and all sub-sets) contain no entries.
+  // Returns whether this remembered set (and all sub-sets) does not contain any entry.
   bool is_empty() const;
 
+  // Returns the number of cards contained in this remembered set.
   size_t occupied() const;
   size_t occ_fine() const;
   size_t occ_coarse() const;
@@ -195,31 +199,17 @@
 
   static jint n_coarsenings() { return _n_coarsenings; }
 
-  // Returns size in bytes.
-  // Not const because it takes a lock.
+  // Returns size of the actual remembered set containers in bytes.
   size_t mem_size() const;
+  // Returns the size of static data in bytes.
   static size_t static_mem_size();
+  // Returns the size of the free list content in bytes.
   static size_t fl_mem_size();
 
-  bool contains_reference(OopOrNarrowOopStar from) const;
-  bool contains_reference_locked(OopOrNarrowOopStar from) const;
-
+  // Clear the entire contents of this remembered set.
   void clear();
 
-  // Specifically clear the from_card_cache.
-  void clear_fcc();
-
   void do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task);
-
-  // Declare the heap size (in # of regions) to the OtherRegionsTable.
-  // (Uses it to initialize from_card_cache).
-  static void initialize(uint max_regions);
-
-  // Declares that regions between start_idx <= i < start_idx + num_regions are
-  // not in use. Make sure that any entries for these regions are invalid.
-  static void invalidate(uint start_idx, size_t num_regions);
-
-  static void print_from_card_cache();
 };
 
 class HeapRegionRemSet : public CHeapObj<mtGC> {
@@ -233,7 +223,6 @@
 
 private:
   G1BlockOffsetSharedArray* _bosa;
-  G1BlockOffsetSharedArray* bosa() const { return _bosa; }
 
   // A set of code blobs (nmethods) whose code contains pointers into
   // the region that owns this RSet.
@@ -268,10 +257,6 @@
   static uint num_par_rem_sets();
   static void setup_remset_size();
 
-  HeapRegion* hr() const {
-    return _other_regions.hr();
-  }
-
   bool is_empty() const {
     return (strong_code_roots_list_length() == 0) && _other_regions.is_empty();
   }
@@ -305,8 +290,9 @@
     _other_regions.add_reference(from, tid);
   }
 
-  // Removes any entries shown by the given bitmaps to contain only dead
-  // objects.
+  // Removes any entries in the remembered set shown by the given bitmaps to
+  // contain only dead objects. Not thread safe.
+  // One bits in the bitmaps indicate that the given region or card is live.
   void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
 
   // The region is being reclaimed; clear its remset, and any mention of
@@ -397,16 +383,16 @@
   // Declare the heap size (in # of regions) to the HeapRegionRemSet(s).
   // (Uses it to initialize from_card_cache).
   static void init_heap(uint max_regions) {
-    OtherRegionsTable::initialize(max_regions);
+    FromCardCache::initialize(num_par_rem_sets(), max_regions);
   }
 
-  static void invalidate(uint start_idx, uint num_regions) {
-    OtherRegionsTable::invalidate(start_idx, num_regions);
+  static void invalidate_from_card_cache(uint start_idx, size_t num_regions) {
+    FromCardCache::invalidate(start_idx, num_regions);
   }
 
 #ifndef PRODUCT
   static void print_from_card_cache() {
-    OtherRegionsTable::print_from_card_cache();
+    FromCardCache::print();
   }
 #endif
 
--- a/src/share/vm/gc_implementation/shared/gcTrace.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/gc_implementation/shared/gcTrace.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -172,6 +172,27 @@
   _tenuring_threshold = tenuring_threshold;
 }
 
+bool YoungGCTracer::should_report_promotion_in_new_plab_event() const {
+  return should_send_promotion_in_new_plab_event();
+}
+
+bool YoungGCTracer::should_report_promotion_outside_plab_event() const {
+  return should_send_promotion_outside_plab_event();
+}
+
+void YoungGCTracer::report_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
+                                                       uint age, bool tenured,
+                                                       size_t plab_size) const {
+  assert_set_gc_id();
+  send_promotion_in_new_plab_event(klass, obj_size, age, tenured, plab_size);
+}
+
+void YoungGCTracer::report_promotion_outside_plab_event(Klass* klass, size_t obj_size,
+                                                        uint age, bool tenured) const {
+  assert_set_gc_id();
+  send_promotion_outside_plab_event(klass, obj_size, age, tenured);
+}
+
 void OldGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
   assert_set_gc_id();
 
--- a/src/share/vm/gc_implementation/shared/gcTrace.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/gc_implementation/shared/gcTrace.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -156,9 +156,38 @@
   void report_promotion_failed(const PromotionFailedInfo& pf_info);
   void report_tenuring_threshold(const uint tenuring_threshold);
 
+  /*
+   * Methods for reporting Promotion in new or outside PLAB Events.
+   *
+   * The object age is always required as it is not certain that the mark word
+   * of the oop can be trusted at this stage.
+   *
+   * obj_size is the size of the promoted object in bytes.
+   *
+   * tenured should be true if the object has been promoted to the old
+   * space during this GC, if the object is copied to survivor space
+   * from young space or survivor space (aging) tenured should be false.
+   *
+   * plab_size is the size of the newly allocated PLAB in bytes.
+   */
+  bool should_report_promotion_in_new_plab_event() const;
+  bool should_report_promotion_outside_plab_event() const;
+  void report_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
+                                          uint age, bool tenured,
+                                          size_t plab_size) const;
+  void report_promotion_outside_plab_event(Klass* klass, size_t obj_size,
+                                           uint age, bool tenured) const;
+
  private:
   void send_young_gc_event() const;
   void send_promotion_failed_event(const PromotionFailedInfo& pf_info) const;
+  bool should_send_promotion_in_new_plab_event() const;
+  bool should_send_promotion_outside_plab_event() const;
+  void send_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
+                                        uint age, bool tenured,
+                                        size_t plab_size) const;
+  void send_promotion_outside_plab_event(Klass* klass, size_t obj_size,
+                                         uint age, bool tenured) const;
 };
 
 class OldGCTracer : public GCTracer {
--- a/src/share/vm/gc_implementation/shared/gcTraceSend.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/gc_implementation/shared/gcTraceSend.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -111,6 +111,44 @@
   }
 }
 
+bool YoungGCTracer::should_send_promotion_in_new_plab_event() const {
+  return EventPromoteObjectInNewPLAB::is_enabled();
+}
+
+bool YoungGCTracer::should_send_promotion_outside_plab_event() const {
+  return EventPromoteObjectOutsidePLAB::is_enabled();
+}
+
+void YoungGCTracer::send_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
+                                                     uint age, bool tenured,
+                                                     size_t plab_size) const {
+
+  EventPromoteObjectInNewPLAB event;
+  if (event.should_commit()) {
+    event.set_gcId(_shared_gc_info.gc_id().id());
+    event.set_class(klass);
+    event.set_objectSize(obj_size);
+    event.set_tenured(tenured);
+    event.set_tenuringAge(age);
+    event.set_plabSize(plab_size);
+    event.commit();
+  }
+}
+
+void YoungGCTracer::send_promotion_outside_plab_event(Klass* klass, size_t obj_size,
+                                                      uint age, bool tenured) const {
+
+  EventPromoteObjectOutsidePLAB event;
+  if (event.should_commit()) {
+    event.set_gcId(_shared_gc_info.gc_id().id());
+    event.set_class(klass);
+    event.set_objectSize(obj_size);
+    event.set_tenured(tenured);
+    event.set_tenuringAge(age);
+    event.commit();
+  }
+}
+
 void OldGCTracer::send_old_gc_event() const {
   EventGCOldGarbageCollection e(UNTIMED);
   if (e.should_commit()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/cardGeneration.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2014, 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 "memory/blockOffsetTable.inline.hpp"
+#include "memory/cardGeneration.inline.hpp"
+#include "memory/gcLocker.hpp"
+#include "memory/generationSpec.hpp"
+#include "memory/genOopClosures.inline.hpp"
+#include "memory/genRemSet.hpp"
+#include "memory/iterator.hpp"
+#include "memory/memRegion.hpp"
+#include "memory/space.inline.hpp"
+#include "runtime/java.hpp"
+
+CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size,
+                               int level,
+                               GenRemSet* remset) :
+  Generation(rs, initial_byte_size, level), _rs(remset),
+  _shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(),
+  _used_at_prologue()
+{
+  HeapWord* start = (HeapWord*)rs.base();
+  size_t reserved_byte_size = rs.size();
+  assert((uintptr_t(start) & 3) == 0, "bad alignment");
+  assert((reserved_byte_size & 3) == 0, "bad alignment");
+  MemRegion reserved_mr(start, heap_word_size(reserved_byte_size));
+  _bts = new BlockOffsetSharedArray(reserved_mr,
+                                    heap_word_size(initial_byte_size));
+  MemRegion committed_mr(start, heap_word_size(initial_byte_size));
+  _rs->resize_covered_region(committed_mr);
+  if (_bts == NULL) {
+    vm_exit_during_initialization("Could not allocate a BlockOffsetArray");
+  }
+
+  // Verify that the start and end of this generation is the start of a card.
+  // If this wasn't true, a single card could span more than on generation,
+  // which would cause problems when we commit/uncommit memory, and when we
+  // clear and dirty cards.
+  guarantee(_rs->is_aligned(reserved_mr.start()), "generation must be card aligned");
+  if (reserved_mr.end() != Universe::heap()->reserved_region().end()) {
+    // Don't check at the very end of the heap as we'll assert that we're probing off
+    // the end if we try.
+    guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned");
+  }
+  _min_heap_delta_bytes = MinHeapDeltaBytes;
+  _capacity_at_prologue = initial_byte_size;
+  _used_at_prologue = 0;
+}
+
+bool CardGeneration::grow_by(size_t bytes) {
+  assert_correct_size_change_locking();
+  bool result = _virtual_space.expand_by(bytes);
+  if (result) {
+    size_t new_word_size =
+       heap_word_size(_virtual_space.committed_size());
+    MemRegion mr(space()->bottom(), new_word_size);
+    // Expand card table
+    Universe::heap()->barrier_set()->resize_covered_region(mr);
+    // Expand shared block offset array
+    _bts->resize(new_word_size);
+
+    // Fix for bug #4668531
+    if (ZapUnusedHeapArea) {
+      MemRegion mangle_region(space()->end(),
+      (HeapWord*)_virtual_space.high());
+      SpaceMangler::mangle_region(mangle_region);
+    }
+
+    // Expand space -- also expands space's BOT
+    // (which uses (part of) shared array above)
+    space()->set_end((HeapWord*)_virtual_space.high());
+
+    // update the space and generation capacity counters
+    update_counters();
+
+    if (Verbose && PrintGC) {
+      size_t new_mem_size = _virtual_space.committed_size();
+      size_t old_mem_size = new_mem_size - bytes;
+      gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by "
+                      SIZE_FORMAT "K to " SIZE_FORMAT "K",
+                      name(), old_mem_size/K, bytes/K, new_mem_size/K);
+    }
+  }
+  return result;
+}
+
+bool CardGeneration::expand(size_t bytes, size_t expand_bytes) {
+  assert_locked_or_safepoint(Heap_lock);
+  if (bytes == 0) {
+    return true;  // That's what grow_by(0) would return
+  }
+  size_t aligned_bytes  = ReservedSpace::page_align_size_up(bytes);
+  if (aligned_bytes == 0){
+    // The alignment caused the number of bytes to wrap.  An expand_by(0) will
+    // return true with the implication that an expansion was done when it
+    // was not.  A call to expand implies a best effort to expand by "bytes"
+    // but not a guarantee.  Align down to give a best effort.  This is likely
+    // the most that the generation can expand since it has some capacity to
+    // start with.
+    aligned_bytes = ReservedSpace::page_align_size_down(bytes);
+  }
+  size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
+  bool success = false;
+  if (aligned_expand_bytes > aligned_bytes) {
+    success = grow_by(aligned_expand_bytes);
+  }
+  if (!success) {
+    success = grow_by(aligned_bytes);
+  }
+  if (!success) {
+    success = grow_to_reserved();
+  }
+  if (PrintGC && Verbose) {
+    if (success && GC_locker::is_active_and_needs_gc()) {
+      gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
+    }
+  }
+
+  return success;
+}
+
+bool CardGeneration::grow_to_reserved() {
+  assert_correct_size_change_locking();
+  bool success = true;
+  const size_t remaining_bytes = _virtual_space.uncommitted_size();
+  if (remaining_bytes > 0) {
+    success = grow_by(remaining_bytes);
+    DEBUG_ONLY(if (!success) warning("grow to reserved failed");)
+  }
+  return success;
+}
+
+void CardGeneration::shrink(size_t bytes) {
+  assert_correct_size_change_locking();
+
+  size_t size = ReservedSpace::page_align_size_down(bytes);
+  if (size == 0) {
+    return;
+  }
+
+  // Shrink committed space
+  _virtual_space.shrink_by(size);
+  // Shrink space; this also shrinks the space's BOT
+  space()->set_end((HeapWord*) _virtual_space.high());
+  size_t new_word_size = heap_word_size(space()->capacity());
+  // Shrink the shared block offset array
+  _bts->resize(new_word_size);
+  MemRegion mr(space()->bottom(), new_word_size);
+  // Shrink the card table
+  Universe::heap()->barrier_set()->resize_covered_region(mr);
+
+  if (Verbose && PrintGC) {
+    size_t new_mem_size = _virtual_space.committed_size();
+    size_t old_mem_size = new_mem_size + size;
+    gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K",
+                  name(), old_mem_size/K, new_mem_size/K);
+  }
+}
+
+// No young generation references, clear this generation's cards.
+void CardGeneration::clear_remembered_set() {
+  _rs->clear(reserved());
+}
+
+// Objects in this generation may have moved, invalidate this
+// generation's cards.
+void CardGeneration::invalidate_remembered_set() {
+  _rs->invalidate(used_region());
+}
+
+void CardGeneration::compute_new_size() {
+  assert(_shrink_factor <= 100, "invalid shrink factor");
+  size_t current_shrink_factor = _shrink_factor;
+  _shrink_factor = 0;
+
+  // We don't have floating point command-line arguments
+  // Note:  argument processing ensures that MinHeapFreeRatio < 100.
+  const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
+  const double maximum_used_percentage = 1.0 - minimum_free_percentage;
+
+  // Compute some numbers about the state of the heap.
+  const size_t used_after_gc = used();
+  const size_t capacity_after_gc = capacity();
+
+  const double min_tmp = used_after_gc / maximum_used_percentage;
+  size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));
+  // Don't shrink less than the initial generation size
+  minimum_desired_capacity = MAX2(minimum_desired_capacity,
+                                  spec()->init_size());
+  assert(used_after_gc <= minimum_desired_capacity, "sanity check");
+
+  if (PrintGC && Verbose) {
+    const size_t free_after_gc = free();
+    const double free_percentage = ((double)free_after_gc) / capacity_after_gc;
+    gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: ");
+    gclog_or_tty->print_cr("  "
+                  "  minimum_free_percentage: %6.2f"
+                  "  maximum_used_percentage: %6.2f",
+                  minimum_free_percentage,
+                  maximum_used_percentage);
+    gclog_or_tty->print_cr("  "
+                  "   free_after_gc   : %6.1fK"
+                  "   used_after_gc   : %6.1fK"
+                  "   capacity_after_gc   : %6.1fK",
+                  free_after_gc / (double) K,
+                  used_after_gc / (double) K,
+                  capacity_after_gc / (double) K);
+    gclog_or_tty->print_cr("  "
+                  "   free_percentage: %6.2f",
+                  free_percentage);
+  }
+
+  if (capacity_after_gc < minimum_desired_capacity) {
+    // If we have less free space than we want then expand
+    size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
+    // Don't expand unless it's significant
+    if (expand_bytes >= _min_heap_delta_bytes) {
+      expand(expand_bytes, 0); // safe if expansion fails
+    }
+    if (PrintGC && Verbose) {
+      gclog_or_tty->print_cr("    expanding:"
+                    "  minimum_desired_capacity: %6.1fK"
+                    "  expand_bytes: %6.1fK"
+                    "  _min_heap_delta_bytes: %6.1fK",
+                    minimum_desired_capacity / (double) K,
+                    expand_bytes / (double) K,
+                    _min_heap_delta_bytes / (double) K);
+    }
+    return;
+  }
+
+  // No expansion, now see if we want to shrink
+  size_t shrink_bytes = 0;
+  // We would never want to shrink more than this
+  size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity;
+
+  if (MaxHeapFreeRatio < 100) {
+    const double maximum_free_percentage = MaxHeapFreeRatio / 100.0;
+    const double minimum_used_percentage = 1.0 - maximum_free_percentage;
+    const double max_tmp = used_after_gc / minimum_used_percentage;
+    size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
+    maximum_desired_capacity = MAX2(maximum_desired_capacity,
+                                    spec()->init_size());
+    if (PrintGC && Verbose) {
+      gclog_or_tty->print_cr("  "
+                             "  maximum_free_percentage: %6.2f"
+                             "  minimum_used_percentage: %6.2f",
+                             maximum_free_percentage,
+                             minimum_used_percentage);
+      gclog_or_tty->print_cr("  "
+                             "  _capacity_at_prologue: %6.1fK"
+                             "  minimum_desired_capacity: %6.1fK"
+                             "  maximum_desired_capacity: %6.1fK",
+                             _capacity_at_prologue / (double) K,
+                             minimum_desired_capacity / (double) K,
+                             maximum_desired_capacity / (double) K);
+    }
+    assert(minimum_desired_capacity <= maximum_desired_capacity,
+           "sanity check");
+
+    if (capacity_after_gc > maximum_desired_capacity) {
+      // Capacity too large, compute shrinking size
+      shrink_bytes = capacity_after_gc - maximum_desired_capacity;
+      // We don't want shrink all the way back to initSize if people call
+      // System.gc(), because some programs do that between "phases" and then
+      // we'd just have to grow the heap up again for the next phase.  So we
+      // damp the shrinking: 0% on the first call, 10% on the second call, 40%
+      // on the third call, and 100% by the fourth call.  But if we recompute
+      // size without shrinking, it goes back to 0%.
+      shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
+      assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
+      if (current_shrink_factor == 0) {
+        _shrink_factor = 10;
+      } else {
+        _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
+      }
+      if (PrintGC && Verbose) {
+        gclog_or_tty->print_cr("  "
+                      "  shrinking:"
+                      "  initSize: %.1fK"
+                      "  maximum_desired_capacity: %.1fK",
+                      spec()->init_size() / (double) K,
+                      maximum_desired_capacity / (double) K);
+        gclog_or_tty->print_cr("  "
+                      "  shrink_bytes: %.1fK"
+                      "  current_shrink_factor: " SIZE_FORMAT
+                      "  new shrink factor: " SIZE_FORMAT
+                      "  _min_heap_delta_bytes: %.1fK",
+                      shrink_bytes / (double) K,
+                      current_shrink_factor,
+                      _shrink_factor,
+                      _min_heap_delta_bytes / (double) K);
+      }
+    }
+  }
+
+  if (capacity_after_gc > _capacity_at_prologue) {
+    // We might have expanded for promotions, in which case we might want to
+    // take back that expansion if there's room after GC.  That keeps us from
+    // stretching the heap with promotions when there's plenty of room.
+    size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue;
+    expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes);
+    // We have two shrinking computations, take the largest
+    shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion);
+    assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
+    if (PrintGC && Verbose) {
+      gclog_or_tty->print_cr("  "
+                             "  aggressive shrinking:"
+                             "  _capacity_at_prologue: %.1fK"
+                             "  capacity_after_gc: %.1fK"
+                             "  expansion_for_promotion: %.1fK"
+                             "  shrink_bytes: %.1fK",
+                             capacity_after_gc / (double) K,
+                             _capacity_at_prologue / (double) K,
+                             expansion_for_promotion / (double) K,
+                             shrink_bytes / (double) K);
+    }
+  }
+  // Don't shrink unless it's significant
+  if (shrink_bytes >= _min_heap_delta_bytes) {
+    shrink(shrink_bytes);
+  }
+}
+
+// Currently nothing to do.
+void CardGeneration::prepare_for_verify() {}
+
+void CardGeneration::space_iterate(SpaceClosure* blk,
+                                                 bool usedOnly) {
+  blk->do_space(space());
+}
+
+void CardGeneration::younger_refs_iterate(OopsInGenClosure* blk) {
+  blk->set_generation(this);
+  younger_refs_in_space_iterate(space(), blk);
+  blk->reset_generation();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/cardGeneration.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, 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_CARDGENERATION_HPP
+#define SHARE_VM_MEMORY_CARDGENERATION_HPP
+
+// Class CardGeneration is a generation that is covered by a card table,
+// and uses a card-size block-offset array to implement block_start.
+
+#include "memory/generation.hpp"
+
+class BlockOffsetSharedArray;
+class CompactibleSpace;
+
+class CardGeneration: public Generation {
+  friend class VMStructs;
+ protected:
+  // This is shared with other generations.
+  GenRemSet* _rs;
+  // This is local to this generation.
+  BlockOffsetSharedArray* _bts;
+
+  // Current shrinking effect: this damps shrinking when the heap gets empty.
+  size_t _shrink_factor;
+
+  size_t _min_heap_delta_bytes;   // Minimum amount to expand.
+
+  // Some statistics from before gc started.
+  // These are gathered in the gc_prologue (and should_collect)
+  // to control growing/shrinking policy in spite of promotions.
+  size_t _capacity_at_prologue;
+  size_t _used_at_prologue;
+
+  CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level,
+                 GenRemSet* remset);
+
+  virtual void assert_correct_size_change_locking() = 0;
+
+  virtual CompactibleSpace* space() const = 0;
+
+ public:
+
+  // Attempt to expand the generation by "bytes".  Expand by at a
+  // minimum "expand_bytes".  Return true if some amount (not
+  // necessarily the full "bytes") was done.
+  virtual bool expand(size_t bytes, size_t expand_bytes);
+
+  // Shrink generation with specified size
+  virtual void shrink(size_t bytes);
+
+  virtual void compute_new_size();
+
+  virtual void clear_remembered_set();
+
+  virtual void invalidate_remembered_set();
+
+  virtual void prepare_for_verify();
+
+  // Grow generation with specified size (returns false if unable to grow)
+  bool grow_by(size_t bytes);
+  // Grow generation to reserved size.
+  bool grow_to_reserved();
+
+  size_t capacity() const;
+  size_t used() const;
+  size_t free() const;
+  MemRegion used_region() const;
+
+  void space_iterate(SpaceClosure* blk, bool usedOnly = false);
+
+  void younger_refs_iterate(OopsInGenClosure* blk);
+
+  bool is_in(const void* p) const;
+
+  CompactibleSpace* first_compaction_space() const;
+};
+
+#endif // SHARE_VM_MEMORY_CARDGENERATION_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/cardGeneration.inline.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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_CARDGENERATION_INLINE_HPP
+#define SHARE_VM_MEMORY_CARDGENERATION_INLINE_HPP
+
+#include "memory/cardGeneration.hpp"
+#include "memory/space.hpp"
+
+inline size_t CardGeneration::capacity() const {
+  return space()->capacity();
+}
+
+inline size_t CardGeneration::used() const {
+  return space()->used();
+}
+
+inline size_t CardGeneration::free() const {
+  return space()->free();
+}
+
+inline MemRegion CardGeneration::used_region() const {
+  return space()->used_region();
+}
+
+inline bool CardGeneration::is_in(const void* p) const {
+  return space()->is_in(p);
+}
+
+inline CompactibleSpace* CardGeneration::first_compaction_space() const {
+  return space();
+}
+
+#endif // SHARE_VM_MEMORY_CARDGENERATION_INLINE_HPP
--- a/src/share/vm/memory/cardTableModRefBS.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/cardTableModRefBS.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -275,29 +275,26 @@
     // the new_end_aligned does not intrude onto the committed
     // space of another region.
     int ri = 0;
-    for (ri = 0; ri < _cur_covered_regions; ri++) {
-      if (ri != ind) {
-        if (_committed[ri].contains(new_end_aligned)) {
-          // The prior check included in the assert
-          // (new_end_aligned >= _committed[ri].start())
-          // is redundant with the "contains" test.
-          // Any region containing the new end
-          // should start at or beyond the region found (ind)
-          // for the new end (committed regions are not expected to
-          // be proper subsets of other committed regions).
-          assert(_committed[ri].start() >= _committed[ind].start(),
-                 "New end of committed region is inconsistent");
-          new_end_aligned = _committed[ri].start();
-          // new_end_aligned can be equal to the start of its
-          // committed region (i.e., of "ind") if a second
-          // region following "ind" also start at the same location
-          // as "ind".
-          assert(new_end_aligned >= _committed[ind].start(),
-            "New end of committed region is before start");
-          debug_only(collided = true;)
-          // Should only collide with 1 region
-          break;
-        }
+    for (ri = ind + 1; ri < _cur_covered_regions; ri++) {
+      if (new_end_aligned > _committed[ri].start()) {
+        assert(new_end_aligned <= _committed[ri].end(),
+               "An earlier committed region can't cover a later committed region");
+        // Any region containing the new end
+        // should start at or beyond the region found (ind)
+        // for the new end (committed regions are not expected to
+        // be proper subsets of other committed regions).
+        assert(_committed[ri].start() >= _committed[ind].start(),
+               "New end of committed region is inconsistent");
+        new_end_aligned = _committed[ri].start();
+        // new_end_aligned can be equal to the start of its
+        // committed region (i.e., of "ind") if a second
+        // region following "ind" also start at the same location
+        // as "ind".
+        assert(new_end_aligned >= _committed[ind].start(),
+          "New end of committed region is before start");
+        debug_only(collided = true;)
+        // Should only collide with 1 region
+        break;
       }
     }
 #ifdef ASSERT
--- a/src/share/vm/memory/filemap.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/filemap.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -98,11 +98,11 @@
         tty->print_cr("UseSharedSpaces: %s", msg);
       }
     }
+    UseSharedSpaces = false;
+    assert(current_info() != NULL, "singleton must be registered");
+    current_info()->close();
   }
   va_end(ap);
-  UseSharedSpaces = false;
-  assert(current_info() != NULL, "singleton must be registered");
-  current_info()->close();
 }
 
 // Fill in the fileMapInfo structure with data about this VM instance.
@@ -217,9 +217,14 @@
           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);
         } else {
-          ent->_filesize  = -1;
-          if (!os::dir_is_empty(name)) {
-            ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name);
+          struct stat st;
+          if ((os::stat(name, &st) == 0) && ((st.st_mode & S_IFDIR) == S_IFDIR)) {
+            if (!os::dir_is_empty(name)) {
+              ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name);
+            }
+            ent->_filesize = -1;
+          } else {
+            ent->_filesize = -2;
           }
         }
         ent->_name = strptr;
@@ -271,7 +276,7 @@
         fail_continue("directory is not empty: %s", name);
         ok = false;
       }
-    } else {
+    } else if (ent->is_jar()) {
       if (ent->_timestamp != st.st_mtime ||
           ent->_filesize != st.st_size) {
         ok = false;
--- a/src/share/vm/memory/filemap.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/filemap.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -44,8 +44,11 @@
 class SharedClassPathEntry VALUE_OBJ_CLASS_SPEC {
 public:
   const char *_name;
-  time_t _timestamp;          // jar timestamp,  0 if is directory
-  long   _filesize;           // jar file size, -1 if is directory
+  time_t _timestamp;          // jar timestamp,  0 if is directory or other
+  long   _filesize;           // jar file size, -1 if is directory, -2 if other
+  bool is_jar() {
+    return _timestamp != 0;
+  }
   bool is_dir() {
     return _filesize == -1;
   }
--- a/src/share/vm/memory/generation.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/generation.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -361,244 +361,3 @@
     sp = sp->next_compaction_space();
   }
 }
-
-CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size,
-                               int level,
-                               GenRemSet* remset) :
-  Generation(rs, initial_byte_size, level), _rs(remset),
-  _shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(),
-  _used_at_prologue()
-{
-  HeapWord* start = (HeapWord*)rs.base();
-  size_t reserved_byte_size = rs.size();
-  assert((uintptr_t(start) & 3) == 0, "bad alignment");
-  assert((reserved_byte_size & 3) == 0, "bad alignment");
-  MemRegion reserved_mr(start, heap_word_size(reserved_byte_size));
-  _bts = new BlockOffsetSharedArray(reserved_mr,
-                                    heap_word_size(initial_byte_size));
-  MemRegion committed_mr(start, heap_word_size(initial_byte_size));
-  _rs->resize_covered_region(committed_mr);
-  if (_bts == NULL)
-    vm_exit_during_initialization("Could not allocate a BlockOffsetArray");
-
-  // Verify that the start and end of this generation is the start of a card.
-  // If this wasn't true, a single card could span more than on generation,
-  // which would cause problems when we commit/uncommit memory, and when we
-  // clear and dirty cards.
-  guarantee(_rs->is_aligned(reserved_mr.start()), "generation must be card aligned");
-  if (reserved_mr.end() != Universe::heap()->reserved_region().end()) {
-    // Don't check at the very end of the heap as we'll assert that we're probing off
-    // the end if we try.
-    guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned");
-  }
-  _min_heap_delta_bytes = MinHeapDeltaBytes;
-  _capacity_at_prologue = initial_byte_size;
-  _used_at_prologue = 0;
-}
-
-bool CardGeneration::expand(size_t bytes, size_t expand_bytes) {
-  assert_locked_or_safepoint(Heap_lock);
-  if (bytes == 0) {
-    return true;  // That's what grow_by(0) would return
-  }
-  size_t aligned_bytes  = ReservedSpace::page_align_size_up(bytes);
-  if (aligned_bytes == 0){
-    // The alignment caused the number of bytes to wrap.  An expand_by(0) will
-    // return true with the implication that an expansion was done when it
-    // was not.  A call to expand implies a best effort to expand by "bytes"
-    // but not a guarantee.  Align down to give a best effort.  This is likely
-    // the most that the generation can expand since it has some capacity to
-    // start with.
-    aligned_bytes = ReservedSpace::page_align_size_down(bytes);
-  }
-  size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
-  bool success = false;
-  if (aligned_expand_bytes > aligned_bytes) {
-    success = grow_by(aligned_expand_bytes);
-  }
-  if (!success) {
-    success = grow_by(aligned_bytes);
-  }
-  if (!success) {
-    success = grow_to_reserved();
-  }
-  if (PrintGC && Verbose) {
-    if (success && GC_locker::is_active_and_needs_gc()) {
-      gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
-    }
-  }
-
-  return success;
-}
-
-
-// No young generation references, clear this generation's cards.
-void CardGeneration::clear_remembered_set() {
-  _rs->clear(reserved());
-}
-
-
-// Objects in this generation may have moved, invalidate this
-// generation's cards.
-void CardGeneration::invalidate_remembered_set() {
-  _rs->invalidate(used_region());
-}
-
-
-void CardGeneration::compute_new_size() {
-  assert(_shrink_factor <= 100, "invalid shrink factor");
-  size_t current_shrink_factor = _shrink_factor;
-  _shrink_factor = 0;
-
-  // We don't have floating point command-line arguments
-  // Note:  argument processing ensures that MinHeapFreeRatio < 100.
-  const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
-  const double maximum_used_percentage = 1.0 - minimum_free_percentage;
-
-  // Compute some numbers about the state of the heap.
-  const size_t used_after_gc = used();
-  const size_t capacity_after_gc = capacity();
-
-  const double min_tmp = used_after_gc / maximum_used_percentage;
-  size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));
-  // Don't shrink less than the initial generation size
-  minimum_desired_capacity = MAX2(minimum_desired_capacity,
-                                  spec()->init_size());
-  assert(used_after_gc <= minimum_desired_capacity, "sanity check");
-
-  if (PrintGC && Verbose) {
-    const size_t free_after_gc = free();
-    const double free_percentage = ((double)free_after_gc) / capacity_after_gc;
-    gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: ");
-    gclog_or_tty->print_cr("  "
-                  "  minimum_free_percentage: %6.2f"
-                  "  maximum_used_percentage: %6.2f",
-                  minimum_free_percentage,
-                  maximum_used_percentage);
-    gclog_or_tty->print_cr("  "
-                  "   free_after_gc   : %6.1fK"
-                  "   used_after_gc   : %6.1fK"
-                  "   capacity_after_gc   : %6.1fK",
-                  free_after_gc / (double) K,
-                  used_after_gc / (double) K,
-                  capacity_after_gc / (double) K);
-    gclog_or_tty->print_cr("  "
-                  "   free_percentage: %6.2f",
-                  free_percentage);
-  }
-
-  if (capacity_after_gc < minimum_desired_capacity) {
-    // If we have less free space than we want then expand
-    size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
-    // Don't expand unless it's significant
-    if (expand_bytes >= _min_heap_delta_bytes) {
-      expand(expand_bytes, 0); // safe if expansion fails
-    }
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("    expanding:"
-                    "  minimum_desired_capacity: %6.1fK"
-                    "  expand_bytes: %6.1fK"
-                    "  _min_heap_delta_bytes: %6.1fK",
-                    minimum_desired_capacity / (double) K,
-                    expand_bytes / (double) K,
-                    _min_heap_delta_bytes / (double) K);
-    }
-    return;
-  }
-
-  // No expansion, now see if we want to shrink
-  size_t shrink_bytes = 0;
-  // We would never want to shrink more than this
-  size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity;
-
-  if (MaxHeapFreeRatio < 100) {
-    const double maximum_free_percentage = MaxHeapFreeRatio / 100.0;
-    const double minimum_used_percentage = 1.0 - maximum_free_percentage;
-    const double max_tmp = used_after_gc / minimum_used_percentage;
-    size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
-    maximum_desired_capacity = MAX2(maximum_desired_capacity,
-                                    spec()->init_size());
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("  "
-                             "  maximum_free_percentage: %6.2f"
-                             "  minimum_used_percentage: %6.2f",
-                             maximum_free_percentage,
-                             minimum_used_percentage);
-      gclog_or_tty->print_cr("  "
-                             "  _capacity_at_prologue: %6.1fK"
-                             "  minimum_desired_capacity: %6.1fK"
-                             "  maximum_desired_capacity: %6.1fK",
-                             _capacity_at_prologue / (double) K,
-                             minimum_desired_capacity / (double) K,
-                             maximum_desired_capacity / (double) K);
-    }
-    assert(minimum_desired_capacity <= maximum_desired_capacity,
-           "sanity check");
-
-    if (capacity_after_gc > maximum_desired_capacity) {
-      // Capacity too large, compute shrinking size
-      shrink_bytes = capacity_after_gc - maximum_desired_capacity;
-      // We don't want shrink all the way back to initSize if people call
-      // System.gc(), because some programs do that between "phases" and then
-      // we'd just have to grow the heap up again for the next phase.  So we
-      // damp the shrinking: 0% on the first call, 10% on the second call, 40%
-      // on the third call, and 100% by the fourth call.  But if we recompute
-      // size without shrinking, it goes back to 0%.
-      shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
-      assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
-      if (current_shrink_factor == 0) {
-        _shrink_factor = 10;
-      } else {
-        _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
-      }
-      if (PrintGC && Verbose) {
-        gclog_or_tty->print_cr("  "
-                      "  shrinking:"
-                      "  initSize: %.1fK"
-                      "  maximum_desired_capacity: %.1fK",
-                      spec()->init_size() / (double) K,
-                      maximum_desired_capacity / (double) K);
-        gclog_or_tty->print_cr("  "
-                      "  shrink_bytes: %.1fK"
-                      "  current_shrink_factor: " SIZE_FORMAT
-                      "  new shrink factor: " SIZE_FORMAT
-                      "  _min_heap_delta_bytes: %.1fK",
-                      shrink_bytes / (double) K,
-                      current_shrink_factor,
-                      _shrink_factor,
-                      _min_heap_delta_bytes / (double) K);
-      }
-    }
-  }
-
-  if (capacity_after_gc > _capacity_at_prologue) {
-    // We might have expanded for promotions, in which case we might want to
-    // take back that expansion if there's room after GC.  That keeps us from
-    // stretching the heap with promotions when there's plenty of room.
-    size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue;
-    expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes);
-    // We have two shrinking computations, take the largest
-    shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion);
-    assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("  "
-                             "  aggressive shrinking:"
-                             "  _capacity_at_prologue: %.1fK"
-                             "  capacity_after_gc: %.1fK"
-                             "  expansion_for_promotion: %.1fK"
-                             "  shrink_bytes: %.1fK",
-                             capacity_after_gc / (double) K,
-                             _capacity_at_prologue / (double) K,
-                             expansion_for_promotion / (double) K,
-                             shrink_bytes / (double) K);
-    }
-  }
-  // Don't shrink unless it's significant
-  if (shrink_bytes >= _min_heap_delta_bytes) {
-    shrink(shrink_bytes);
-  }
-}
-
-// Currently nothing to do.
-void CardGeneration::prepare_for_verify() {}
-
--- a/src/share/vm/memory/generation.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/generation.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -584,57 +584,4 @@
   virtual CollectorCounters* counters() { return _gc_counters; }
 };
 
-// Class CardGeneration is a generation that is covered by a card table,
-// and uses a card-size block-offset array to implement block_start.
-
-// class BlockOffsetArray;
-// class BlockOffsetArrayContigSpace;
-class BlockOffsetSharedArray;
-
-class CardGeneration: public Generation {
-  friend class VMStructs;
- protected:
-  // This is shared with other generations.
-  GenRemSet* _rs;
-  // This is local to this generation.
-  BlockOffsetSharedArray* _bts;
-
-  // current shrinking effect: this damps shrinking when the heap gets empty.
-  size_t _shrink_factor;
-
-  size_t _min_heap_delta_bytes;   // Minimum amount to expand.
-
-  // Some statistics from before gc started.
-  // These are gathered in the gc_prologue (and should_collect)
-  // to control growing/shrinking policy in spite of promotions.
-  size_t _capacity_at_prologue;
-  size_t _used_at_prologue;
-
-  CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level,
-                 GenRemSet* remset);
-
- public:
-
-  // Attempt to expand the generation by "bytes".  Expand by at a
-  // minimum "expand_bytes".  Return true if some amount (not
-  // necessarily the full "bytes") was done.
-  virtual bool expand(size_t bytes, size_t expand_bytes);
-
-  // Shrink generation with specified size (returns false if unable to shrink)
-  virtual void shrink(size_t bytes) = 0;
-
-  virtual void compute_new_size();
-
-  virtual void clear_remembered_set();
-
-  virtual void invalidate_remembered_set();
-
-  virtual void prepare_for_verify();
-
-  // Grow generation with specified size (returns false if unable to grow)
-  virtual bool grow_by(size_t bytes) = 0;
-  // Grow generation to reserved size.
-  virtual bool grow_to_reserved() = 0;
-};
-
 #endif // SHARE_VM_MEMORY_GENERATION_HPP
--- a/src/share/vm/memory/metaspace.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/metaspace.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -3158,7 +3158,25 @@
     SharedMiscDataSize  = align_size_up(SharedMiscDataSize,  max_alignment);
     SharedMiscCodeSize  = align_size_up(SharedMiscCodeSize,  max_alignment);
 
-    // the min_misc_code_size estimate is based on MetaspaceShared::generate_vtable_methods()
+    // make sure SharedReadOnlySize and SharedReadWriteSize are not less than
+    // the minimum values.
+    if (SharedReadOnlySize < MetaspaceShared::min_ro_size){
+      report_out_of_shared_space(SharedReadOnly);
+    }
+
+    if (SharedReadWriteSize < MetaspaceShared::min_rw_size){
+      report_out_of_shared_space(SharedReadWrite);
+    }
+
+    // the min_misc_data_size and min_misc_code_size estimates are based on
+    // MetaspaceShared::generate_vtable_methods()
+    uint min_misc_data_size = align_size_up(
+      MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size * sizeof(void*), max_alignment);
+
+    if (SharedMiscDataSize < min_misc_data_size) {
+      report_out_of_shared_space(SharedMiscData);
+    }
+
     uintx min_misc_code_size = align_size_up(
       (MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size) *
         (sizeof(void*) + MetaspaceShared::vtbl_method_size) + MetaspaceShared::vtbl_common_code_size,
--- a/src/share/vm/memory/metaspaceShared.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/metaspaceShared.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -969,7 +969,7 @@
 #endif
     // If -Xshare:on is specified, print out the error message and exit VM,
     // otherwise, set UseSharedSpaces to false and continue.
-    if (RequireSharedSpaces) {
+    if (RequireSharedSpaces || PrintSharedArchiveAndExit) {
       vm_exit_during_initialization("Unable to use shared archive.", "Failed map_region for using -Xshare:on.");
     } else {
       FLAG_SET_DEFAULT(UseSharedSpaces, false);
--- a/src/share/vm/memory/metaspaceShared.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/metaspaceShared.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -70,6 +70,11 @@
   };
 
   enum {
+    min_ro_size = NOT_LP64(8*M) LP64_ONLY(9*M), // minimum ro and rw regions sizes based on dumping
+    min_rw_size = NOT_LP64(7*M) LP64_ONLY(12*M) // of a shared archive using the default classlist
+  };
+
+  enum {
     ro = 0,  // read-only shared space in the heap
     rw = 1,  // read-write shared space in the heap
     md = 2,  // miscellaneous data for initializing tables, etc.
--- a/src/share/vm/memory/tenuredGeneration.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/tenuredGeneration.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, 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
@@ -235,34 +235,6 @@
   return CardGeneration::expand(bytes, expand_bytes);
 }
 
-
-void TenuredGeneration::shrink(size_t bytes) {
-  assert_locked_or_safepoint(ExpandHeap_lock);
-  size_t size = ReservedSpace::page_align_size_down(bytes);
-  if (size > 0) {
-    shrink_by(size);
-  }
-}
-
-
-size_t TenuredGeneration::capacity() const {
-  return _the_space->capacity();
-}
-
-
-size_t TenuredGeneration::used() const {
-  return _the_space->used();
-}
-
-
-size_t TenuredGeneration::free() const {
-  return _the_space->free();
-}
-
-MemRegion TenuredGeneration::used_region() const {
-  return the_space()->used_region();
-}
-
 size_t TenuredGeneration::unsafe_max_alloc_nogc() const {
   return _the_space->free();
 }
@@ -271,74 +243,8 @@
   return _the_space->free() + _virtual_space.uncommitted_size();
 }
 
-bool TenuredGeneration::grow_by(size_t bytes) {
+void TenuredGeneration::assert_correct_size_change_locking() {
   assert_locked_or_safepoint(ExpandHeap_lock);
-  bool result = _virtual_space.expand_by(bytes);
-  if (result) {
-    size_t new_word_size =
-       heap_word_size(_virtual_space.committed_size());
-    MemRegion mr(_the_space->bottom(), new_word_size);
-    // Expand card table
-    Universe::heap()->barrier_set()->resize_covered_region(mr);
-    // Expand shared block offset array
-    _bts->resize(new_word_size);
-
-    // Fix for bug #4668531
-    if (ZapUnusedHeapArea) {
-      MemRegion mangle_region(_the_space->end(),
-      (HeapWord*)_virtual_space.high());
-      SpaceMangler::mangle_region(mangle_region);
-    }
-
-    // Expand space -- also expands space's BOT
-    // (which uses (part of) shared array above)
-    _the_space->set_end((HeapWord*)_virtual_space.high());
-
-    // update the space and generation capacity counters
-    update_counters();
-
-    if (Verbose && PrintGC) {
-      size_t new_mem_size = _virtual_space.committed_size();
-      size_t old_mem_size = new_mem_size - bytes;
-      gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by "
-                      SIZE_FORMAT "K to " SIZE_FORMAT "K",
-                      name(), old_mem_size/K, bytes/K, new_mem_size/K);
-    }
-  }
-  return result;
-}
-
-
-bool TenuredGeneration::grow_to_reserved() {
-  assert_locked_or_safepoint(ExpandHeap_lock);
-  bool success = true;
-  const size_t remaining_bytes = _virtual_space.uncommitted_size();
-  if (remaining_bytes > 0) {
-    success = grow_by(remaining_bytes);
-    DEBUG_ONLY(if (!success) warning("grow to reserved failed");)
-  }
-  return success;
-}
-
-void TenuredGeneration::shrink_by(size_t bytes) {
-  assert_locked_or_safepoint(ExpandHeap_lock);
-  // Shrink committed space
-  _virtual_space.shrink_by(bytes);
-  // Shrink space; this also shrinks the space's BOT
-  _the_space->set_end((HeapWord*) _virtual_space.high());
-  size_t new_word_size = heap_word_size(_the_space->capacity());
-  // Shrink the shared block offset array
-  _bts->resize(new_word_size);
-  MemRegion mr(_the_space->bottom(), new_word_size);
-  // Shrink the card table
-  Universe::heap()->barrier_set()->resize_covered_region(mr);
-
-  if (Verbose && PrintGC) {
-    size_t new_mem_size = _virtual_space.committed_size();
-    size_t old_mem_size = new_mem_size + bytes;
-    gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K",
-                  name(), old_mem_size/K, new_mem_size/K);
-  }
 }
 
 // Currently nothing to do.
@@ -348,27 +254,14 @@
   _the_space->object_iterate(blk);
 }
 
-void TenuredGeneration::space_iterate(SpaceClosure* blk,
-                                                 bool usedOnly) {
-  blk->do_space(_the_space);
-}
-
-void TenuredGeneration::younger_refs_iterate(OopsInGenClosure* blk) {
-  blk->set_generation(this);
-  younger_refs_in_space_iterate(_the_space, blk);
-  blk->reset_generation();
-}
-
 void TenuredGeneration::save_marks() {
   _the_space->set_saved_mark();
 }
 
-
 void TenuredGeneration::reset_saved_marks() {
   _the_space->reset_saved_mark();
 }
 
-
 bool TenuredGeneration::no_allocs_since_save_marks() {
   return _the_space->saved_mark_at_top();
 }
@@ -387,28 +280,25 @@
 
 #undef TenuredGen_SINCE_SAVE_MARKS_ITERATE_DEFN
 
-
 void TenuredGeneration::gc_epilogue(bool full) {
-  _last_gc = WaterMark(the_space(), the_space()->top());
-
   // update the generation and space performance counters
   update_counters();
   if (ZapUnusedHeapArea) {
-    the_space()->check_mangled_unused_area_complete();
+    _the_space->check_mangled_unused_area_complete();
   }
 }
 
 void TenuredGeneration::record_spaces_top() {
   assert(ZapUnusedHeapArea, "Not mangling unused space");
-  the_space()->set_top_for_allocations();
+  _the_space->set_top_for_allocations();
 }
 
 void TenuredGeneration::verify() {
-  the_space()->verify();
+  _the_space->verify();
 }
 
 void TenuredGeneration::print_on(outputStream* st)  const {
   Generation::print_on(st);
   st->print("   the");
-  the_space()->print_on(st);
+  _the_space->print_on(st);
 }
--- a/src/share/vm/memory/tenuredGeneration.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/tenuredGeneration.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, 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
@@ -28,7 +28,7 @@
 #include "gc_implementation/shared/cSpaceCounters.hpp"
 #include "gc_implementation/shared/gcStats.hpp"
 #include "gc_implementation/shared/generationCounters.hpp"
-#include "memory/generation.hpp"
+#include "memory/cardGeneration.hpp"
 #include "utilities/macros.hpp"
 
 // TenuredGeneration models the heap containing old (promoted/tenured) objects
@@ -42,27 +42,18 @@
   friend class VM_PopulateDumpSharedSpace;
 
  protected:
-  ContiguousSpace*  _the_space;       // actual space holding objects
-  WaterMark  _last_gc;                // watermark between objects allocated before
-                                      // and after last GC.
+  ContiguousSpace*  _the_space;       // Actual space holding objects
 
   GenerationCounters*   _gen_counters;
   CSpaceCounters*       _space_counters;
 
-  // Grow generation with specified size (returns false if unable to grow)
-  virtual bool grow_by(size_t bytes);
-  // Grow generation to reserved size.
-  virtual bool grow_to_reserved();
-  // Shrink generation with specified size (returns false if unable to shrink)
-  void shrink_by(size_t bytes);
-
   // Allocation failure
   virtual bool expand(size_t bytes, size_t expand_bytes);
-  void shrink(size_t bytes);
 
   // Accessing spaces
-  ContiguousSpace* the_space() const { return _the_space; }
+  ContiguousSpace* space() const { return _the_space; }
 
+  void assert_correct_size_change_locking();
  public:
   TenuredGeneration(ReservedSpace rs, size_t initial_byte_size,
                                int level, GenRemSet* remset);
@@ -81,33 +72,15 @@
     return !ScavengeBeforeFullGC;
   }
 
-  inline bool is_in(const void* p) const;
-
-  // Space enquiries
-  size_t capacity() const;
-  size_t used() const;
-  size_t free() const;
-
-  MemRegion used_region() const;
-
   size_t unsafe_max_alloc_nogc() const;
   size_t contiguous_available() const;
 
   // Iteration
   void object_iterate(ObjectClosure* blk);
-  void space_iterate(SpaceClosure* blk, bool usedOnly = false);
-
-  void younger_refs_iterate(OopsInGenClosure* blk);
-
-  inline CompactibleSpace* first_compaction_space() const;
 
   virtual inline HeapWord* allocate(size_t word_size, bool is_tlab);
   virtual inline HeapWord* par_allocate(size_t word_size, bool is_tlab);
 
-  // Accessing marks
-  inline WaterMark top_mark();
-  inline WaterMark bottom_mark();
-
 #define TenuredGen_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix)     \
   void oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl);
   TenuredGen_SINCE_SAVE_MARKS_DECL(OopsInGenClosure,_v)
--- a/src/share/vm/memory/tenuredGeneration.inline.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/memory/tenuredGeneration.inline.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, 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,53 +22,35 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_GENERATION_INLINE_HPP
-#define SHARE_VM_MEMORY_GENERATION_INLINE_HPP
+#ifndef SHARE_VM_MEMORY_TENUREDGENERATION_INLINE_HPP
+#define SHARE_VM_MEMORY_TENUREDGENERATION_INLINE_HPP
 
-#include "memory/genCollectedHeap.hpp"
 #include "memory/space.hpp"
 #include "memory/tenuredGeneration.hpp"
 
-bool TenuredGeneration::is_in(const void* p) const {
-  return the_space()->is_in(p);
-}
-
-
-WaterMark TenuredGeneration::top_mark() {
-  return the_space()->top_mark();
-}
-
-CompactibleSpace*
-TenuredGeneration::first_compaction_space() const {
-  return the_space();
-}
-
 HeapWord* TenuredGeneration::allocate(size_t word_size,
                                                  bool is_tlab) {
   assert(!is_tlab, "TenuredGeneration does not support TLAB allocation");
-  return the_space()->allocate(word_size);
+  return _the_space->allocate(word_size);
 }
 
 HeapWord* TenuredGeneration::par_allocate(size_t word_size,
                                                      bool is_tlab) {
   assert(!is_tlab, "TenuredGeneration does not support TLAB allocation");
-  return the_space()->par_allocate(word_size);
-}
-
-WaterMark TenuredGeneration::bottom_mark() {
-  return the_space()->bottom_mark();
+  return _the_space->par_allocate(word_size);
 }
 
 size_t TenuredGeneration::block_size(const HeapWord* addr) const {
-  if (addr < the_space()->top()) return oop(addr)->size();
-  else {
-    assert(addr == the_space()->top(), "non-block head arg to block_size");
-    return the_space()->end() - the_space()->top();
+  if (addr < _the_space->top()) {
+    return oop(addr)->size();
+  } else {
+    assert(addr == _the_space->top(), "non-block head arg to block_size");
+    return _the_space->end() - _the_space->top();
   }
 }
 
 bool TenuredGeneration::block_is_obj(const HeapWord* addr) const {
-  return addr < the_space()->top();
+  return addr < _the_space  ->top();
 }
 
-#endif // SHARE_VM_MEMORY_GENERATION_INLINE_HPP
+#endif // SHARE_VM_MEMORY_TENUREDGENERATION_INLINE_HPP
--- a/src/share/vm/oops/cpCache.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/oops/cpCache.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -287,9 +287,13 @@
   // the lock, so that when the losing writer returns, he can use the linked
   // cache entry.
 
-  // Use the lock from the metaspace for this, which cannot stop for safepoint.
-  Mutex* metaspace_lock = cpool->pool_holder()->class_loader_data()->metaspace_lock();
-  MutexLockerEx ml(metaspace_lock,  Mutex::_no_safepoint_check_flag);
+  objArrayHandle resolved_references = cpool->resolved_references();
+  // Use the resolved_references() lock for this cpCache entry.
+  // resolved_references are created for all classes with Invokedynamic, MethodHandle
+  // or MethodType constant pool cache entries.
+  assert(resolved_references() != NULL,
+         "a resolved_references array should have been created for this class");
+  ObjectLocker ol(resolved_references, Thread::current());
   if (!is_f1_null()) {
     return;
   }
@@ -336,7 +340,6 @@
   // This allows us to create fewer Methods, while keeping type safety.
   //
 
-  objArrayHandle resolved_references = cpool->resolved_references();
   // Store appendix, if any.
   if (has_appendix) {
     const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset;
--- a/src/share/vm/runtime/arguments.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -115,8 +115,6 @@
 vfprintf_hook_t  Arguments::_vfprintf_hook      = NULL;
 
 
-SystemProperty *Arguments::_java_ext_dirs = NULL;
-SystemProperty *Arguments::_java_endorsed_dirs = NULL;
 SystemProperty *Arguments::_sun_boot_library_path = NULL;
 SystemProperty *Arguments::_java_library_path = NULL;
 SystemProperty *Arguments::_java_home = NULL;
@@ -125,9 +123,10 @@
 
 char* Arguments::_meta_index_path = NULL;
 char* Arguments::_meta_index_dir = NULL;
-
-// Check if head of 'option' matches 'name', and sets 'tail' remaining part of option string
-
+char* Arguments::_ext_dirs = NULL;
+
+// Check if head of 'option' matches 'name', and sets 'tail' to the remaining
+// part of the option string.
 static bool match_option(const JavaVMOption *option, const char* name,
                          const char** tail) {
   int len = (int)strlen(name);
@@ -139,6 +138,32 @@
   }
 }
 
+// Check if 'option' matches 'name'. No "tail" is allowed.
+static bool match_option(const JavaVMOption *option, const char* name) {
+  const char* tail = NULL;
+  bool result = match_option(option, name, &tail);
+  if (tail != NULL && *tail == '\0') {
+    return result;
+  } else {
+    return false;
+  }
+}
+
+// Return true if any of the strings in null-terminated array 'names' matches.
+// If tail_allowed is true, then the tail must begin with a colon; otherwise,
+// the option must match exactly.
+static bool match_option(const JavaVMOption* option, const char** names, const char** tail,
+  bool tail_allowed) {
+  for (/* empty */; *names != NULL; ++names) {
+    if (match_option(option, *names, tail)) {
+      if (**tail == '\0' || tail_allowed && **tail == ':') {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 static void logOption(const char* opt) {
   if (PrintVMOptions) {
     jio_fprintf(defaultStream::output_stream(), "VM option '%s'\n", opt);
@@ -184,8 +209,6 @@
   // Following are JVMTI agent writable properties.
   // Properties values are set to NULL and they are
   // os specific they are initialized in os::init_system_properties_values().
-  _java_ext_dirs = new SystemProperty("java.ext.dirs", NULL,  true);
-  _java_endorsed_dirs = new SystemProperty("java.endorsed.dirs", NULL,  true);
   _sun_boot_library_path = new SystemProperty("sun.boot.library.path", NULL,  true);
   _java_library_path = new SystemProperty("java.library.path", NULL,  true);
   _java_home =  new SystemProperty("java.home", NULL,  true);
@@ -194,8 +217,6 @@
   _java_class_path = new SystemProperty("java.class.path", "",  true);
 
   // Add to System Property list.
-  PropertyList_add(&_system_properties, _java_ext_dirs);
-  PropertyList_add(&_system_properties, _java_endorsed_dirs);
   PropertyList_add(&_system_properties, _sun_boot_library_path);
   PropertyList_add(&_system_properties, _java_library_path);
   PropertyList_add(&_system_properties, _java_home);
@@ -348,13 +369,9 @@
 // components, in order:
 //
 //     prefix           // from -Xbootclasspath/p:...
-//     endorsed         // the expansion of -Djava.endorsed.dirs=...
 //     base             // from os::get_system_properties() or -Xbootclasspath=
 //     suffix           // from -Xbootclasspath/a:...
 //
-// java.endorsed.dirs is a list of directories; any jar or zip files in the
-// directories are added to the sysclasspath just before the base.
-//
 // This could be AllStatic, but it isn't needed after argument processing is
 // complete.
 class SysClassPath: public StackObj {
@@ -368,16 +385,9 @@
   inline void add_suffix(const char* suffix);
   inline void reset_path(const char* base);
 
-  // Expand the jar/zip files in each directory listed by the java.endorsed.dirs
-  // property.  Must be called after all command-line arguments have been
-  // processed (in particular, -Djava.endorsed.dirs=...) and before calling
-  // combined_path().
-  void expand_endorsed();
-
   inline const char* get_base()     const { return _items[_scp_base]; }
   inline const char* get_prefix()   const { return _items[_scp_prefix]; }
   inline const char* get_suffix()   const { return _items[_scp_suffix]; }
-  inline const char* get_endorsed() const { return _items[_scp_endorsed]; }
 
   // Combine all the components into a single c-heap-allocated string; caller
   // must free the string if/when no longer needed.
@@ -394,20 +404,17 @@
   // base are allocated in the C heap and freed by this class.
   enum {
     _scp_prefix,        // from -Xbootclasspath/p:...
-    _scp_endorsed,      // the expansion of -Djava.endorsed.dirs=...
     _scp_base,          // the default sysclasspath
     _scp_suffix,        // from -Xbootclasspath/a:...
     _scp_nitems         // the number of items, must be last.
   };
 
   const char* _items[_scp_nitems];
-  DEBUG_ONLY(bool _expansion_done;)
 };
 
 SysClassPath::SysClassPath(const char* base) {
   memset(_items, 0, sizeof(_items));
   _items[_scp_base] = base;
-  DEBUG_ONLY(_expansion_done = false;)
 }
 
 SysClassPath::~SysClassPath() {
@@ -415,7 +422,6 @@
   for (int i = 0; i < _scp_nitems; ++i) {
     if (i != _scp_base) reset_item_at(i);
   }
-  DEBUG_ONLY(_expansion_done = false;)
 }
 
 inline void SysClassPath::set_base(const char* base) {
@@ -451,41 +457,11 @@
 
 //------------------------------------------------------------------------------
 
-void SysClassPath::expand_endorsed() {
-  assert(_items[_scp_endorsed] == NULL, "can only be called once.");
-
-  const char* path = Arguments::get_property("java.endorsed.dirs");
-  if (path == NULL) {
-    path = Arguments::get_endorsed_dir();
-    assert(path != NULL, "no default for java.endorsed.dirs");
-  }
-
-  char* expanded_path = NULL;
-  const char separator = *os::path_separator();
-  const char* const end = path + strlen(path);
-  while (path < end) {
-    const char* tmp_end = strchr(path, separator);
-    if (tmp_end == NULL) {
-      expanded_path = add_jars_to_path(expanded_path, path);
-      path = end;
-    } else {
-      char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtInternal);
-      memcpy(dirpath, path, tmp_end - path);
-      dirpath[tmp_end - path] = '\0';
-      expanded_path = add_jars_to_path(expanded_path, dirpath);
-      FREE_C_HEAP_ARRAY(char, dirpath);
-      path = tmp_end + 1;
-    }
-  }
-  _items[_scp_endorsed] = expanded_path;
-  DEBUG_ONLY(_expansion_done = true;)
-}
 
 // Combine the bootclasspath elements, some of which may be null, into a single
 // c-heap-allocated string.
 char* SysClassPath::combined_path() {
   assert(_items[_scp_base] != NULL, "empty default sysclasspath");
-  assert(_expansion_done, "must call expand_endorsed() first.");
 
   size_t lengths[_scp_nitems];
   size_t total_len = 0;
@@ -2576,21 +2552,6 @@
   "-dsa", "-esa", "-disablesystemassertions", "-enablesystemassertions", 0
 };
 
-// Return true if any of the strings in null-terminated array 'names' matches.
-// If tail_allowed is true, then the tail must begin with a colon; otherwise,
-// the option must match exactly.
-static bool match_option(const JavaVMOption* option, const char** names, const char** tail,
-  bool tail_allowed) {
-  for (/* empty */; *names != NULL; ++names) {
-    if (match_option(option, *names, tail)) {
-      if (**tail == '\0' || tail_allowed && **tail == ':') {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
 bool Arguments::parse_uintx(const char* value,
                             uintx* uintx_arg,
                             uintx min_size) {
@@ -2832,16 +2793,16 @@
       }
 #endif // !INCLUDE_JVMTI
     // -Xnoclassgc
-    } else if (match_option(option, "-Xnoclassgc", &tail)) {
+    } else if (match_option(option, "-Xnoclassgc")) {
       FLAG_SET_CMDLINE(bool, ClassUnloading, false);
     // -Xconcgc
-    } else if (match_option(option, "-Xconcgc", &tail)) {
+    } else if (match_option(option, "-Xconcgc")) {
       FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, true);
     // -Xnoconcgc
-    } else if (match_option(option, "-Xnoconcgc", &tail)) {
+    } else if (match_option(option, "-Xnoconcgc")) {
       FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, false);
     // -Xbatch
-    } else if (match_option(option, "-Xbatch", &tail)) {
+    } else if (match_option(option, "-Xbatch")) {
       FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
     // -Xmn for compatibility with other JVM vendors
     } else if (match_option(option, "-Xmn", &tail)) {
@@ -2986,28 +2947,28 @@
         }
         FLAG_SET_CMDLINE(uintx, IncreaseFirstTierCompileThresholdAt, (uintx)uint_IncreaseFirstTierCompileThresholdAt);
     // -green
-    } else if (match_option(option, "-green", &tail)) {
+    } else if (match_option(option, "-green")) {
       jio_fprintf(defaultStream::error_stream(),
                   "Green threads support not available\n");
           return JNI_EINVAL;
     // -native
-    } else if (match_option(option, "-native", &tail)) {
+    } else if (match_option(option, "-native")) {
           // HotSpot always uses native threads, ignore silently for compatibility
     // -Xsqnopause
-    } else if (match_option(option, "-Xsqnopause", &tail)) {
+    } else if (match_option(option, "-Xsqnopause")) {
           // EVM option, ignore silently for compatibility
     // -Xrs
-    } else if (match_option(option, "-Xrs", &tail)) {
+    } else if (match_option(option, "-Xrs")) {
           // Classic/EVM option, new functionality
       FLAG_SET_CMDLINE(bool, ReduceSignalUsage, true);
-    } else if (match_option(option, "-Xusealtsigs", &tail)) {
+    } else if (match_option(option, "-Xusealtsigs")) {
           // change default internal VM signals used - lower case for back compat
       FLAG_SET_CMDLINE(bool, UseAltSigs, true);
     // -Xoptimize
-    } else if (match_option(option, "-Xoptimize", &tail)) {
+    } else if (match_option(option, "-Xoptimize")) {
           // EVM option, ignore silently for compatibility
     // -Xprof
-    } else if (match_option(option, "-Xprof", &tail)) {
+    } else if (match_option(option, "-Xprof")) {
 #if INCLUDE_FPROF
       _has_profile = true;
 #else // INCLUDE_FPROF
@@ -3016,7 +2977,7 @@
       return JNI_ERR;
 #endif // INCLUDE_FPROF
     // -Xconcurrentio
-    } else if (match_option(option, "-Xconcurrentio", &tail)) {
+    } else if (match_option(option, "-Xconcurrentio")) {
       FLAG_SET_CMDLINE(bool, UseLWPSynchronization, true);
       FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
       FLAG_SET_CMDLINE(intx, DeferThrSuspendLoopCount, 1);
@@ -3024,18 +2985,32 @@
       FLAG_SET_CMDLINE(uintx, NewSizeThreadIncrease, 16 * K);  // 20Kb per thread added to new generation
 
       // -Xinternalversion
-    } else if (match_option(option, "-Xinternalversion", &tail)) {
+    } else if (match_option(option, "-Xinternalversion")) {
       jio_fprintf(defaultStream::output_stream(), "%s\n",
                   VM_Version::internal_vm_info_string());
       vm_exit(0);
 #ifndef PRODUCT
     // -Xprintflags
-    } else if (match_option(option, "-Xprintflags", &tail)) {
+    } else if (match_option(option, "-Xprintflags")) {
       CommandLineFlags::printFlags(tty, false);
       vm_exit(0);
 #endif
     // -D
     } else if (match_option(option, "-D", &tail)) {
+      if (match_option(option, "-Djava.endorsed.dirs=", &tail)) {
+        // abort if -Djava.endorsed.dirs is set
+        jio_fprintf(defaultStream::output_stream(),
+          "-Djava.endorsed.dirs is not supported. Endorsed standards and standalone APIs\n"
+          "in modular form will be supported via the concept of upgradeable modules.\n");
+        return JNI_EINVAL;
+      }
+      if (match_option(option, "-Djava.ext.dirs=", &tail)) {
+        // abort if -Djava.ext.dirs is set
+        jio_fprintf(defaultStream::output_stream(),
+          "-Djava.ext.dirs is not supported.  Use -classpath instead.\n");
+        return JNI_EINVAL;
+      }
+
       if (!add_property(tail)) {
         return JNI_ENOMEM;
       }
@@ -3050,29 +3025,29 @@
 #endif
       }
     // -Xint
-    } else if (match_option(option, "-Xint", &tail)) {
+    } else if (match_option(option, "-Xint")) {
           set_mode_flags(_int);
     // -Xmixed
-    } else if (match_option(option, "-Xmixed", &tail)) {
+    } else if (match_option(option, "-Xmixed")) {
           set_mode_flags(_mixed);
     // -Xcomp
-    } else if (match_option(option, "-Xcomp", &tail)) {
+    } else if (match_option(option, "-Xcomp")) {
       // for testing the compiler; turn off all flags that inhibit compilation
           set_mode_flags(_comp);
     // -Xshare:dump
-    } else if (match_option(option, "-Xshare:dump", &tail)) {
+    } else if (match_option(option, "-Xshare:dump")) {
       FLAG_SET_CMDLINE(bool, DumpSharedSpaces, true);
       set_mode_flags(_int);     // Prevent compilation, which creates objects
     // -Xshare:on
-    } else if (match_option(option, "-Xshare:on", &tail)) {
+    } else if (match_option(option, "-Xshare:on")) {
       FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
       FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true);
     // -Xshare:auto
-    } else if (match_option(option, "-Xshare:auto", &tail)) {
+    } else if (match_option(option, "-Xshare:auto")) {
       FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
       FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false);
     // -Xshare:off
-    } else if (match_option(option, "-Xshare:off", &tail)) {
+    } else if (match_option(option, "-Xshare:off")) {
       FLAG_SET_CMDLINE(bool, UseSharedSpaces, false);
       FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false);
     // -Xverify
@@ -3090,13 +3065,13 @@
         return JNI_EINVAL;
       }
     // -Xdebug
-    } else if (match_option(option, "-Xdebug", &tail)) {
+    } else if (match_option(option, "-Xdebug")) {
       // note this flag has been used, then ignore
       set_xdebug_mode(true);
     // -Xnoagent
-    } else if (match_option(option, "-Xnoagent", &tail)) {
+    } else if (match_option(option, "-Xnoagent")) {
       // For compatibility with classic. HotSpot refuses to load the old style agent.dll.
-    } else if (match_option(option, "-Xboundthreads", &tail)) {
+    } else if (match_option(option, "-Xboundthreads")) {
       // Bind user level threads to kernel threads (Solaris only)
       FLAG_SET_CMDLINE(bool, UseBoundThreads, true);
     } else if (match_option(option, "-Xloggc:", &tail)) {
@@ -3126,14 +3101,14 @@
                                      "check")) {
         return JNI_EINVAL;
       }
-    } else if (match_option(option, "vfprintf", &tail)) {
+    } else if (match_option(option, "vfprintf")) {
       _vfprintf_hook = CAST_TO_FN_PTR(vfprintf_hook_t, option->extraInfo);
-    } else if (match_option(option, "exit", &tail)) {
+    } else if (match_option(option, "exit")) {
       _exit_hook = CAST_TO_FN_PTR(exit_hook_t, option->extraInfo);
-    } else if (match_option(option, "abort", &tail)) {
+    } else if (match_option(option, "abort")) {
       _abort_hook = CAST_TO_FN_PTR(abort_hook_t, option->extraInfo);
     // -XX:+AggressiveHeap
-    } else if (match_option(option, "-XX:+AggressiveHeap", &tail)) {
+    } else if (match_option(option, "-XX:+AggressiveHeap")) {
 
       // This option inspects the machine and attempts to set various
       // parameters to be optimal for long-running, memory allocation
@@ -3224,11 +3199,11 @@
 
     // Need to keep consistency of MaxTenuringThreshold and AlwaysTenure/NeverTenure;
     // and the last option wins.
-    } else if (match_option(option, "-XX:+NeverTenure", &tail)) {
+    } else if (match_option(option, "-XX:+NeverTenure")) {
       FLAG_SET_CMDLINE(bool, NeverTenure, true);
       FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
       FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, markOopDesc::max_age + 1);
-    } else if (match_option(option, "-XX:+AlwaysTenure", &tail)) {
+    } else if (match_option(option, "-XX:+AlwaysTenure")) {
       FLAG_SET_CMDLINE(bool, NeverTenure, false);
       FLAG_SET_CMDLINE(bool, AlwaysTenure, true);
       FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0);
@@ -3247,17 +3222,17 @@
         FLAG_SET_CMDLINE(bool, NeverTenure, false);
         FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
       }
-    } else if (match_option(option, "-XX:+CMSPermGenSweepingEnabled", &tail) ||
-               match_option(option, "-XX:-CMSPermGenSweepingEnabled", &tail)) {
+    } else if (match_option(option, "-XX:+CMSPermGenSweepingEnabled") ||
+               match_option(option, "-XX:-CMSPermGenSweepingEnabled")) {
       jio_fprintf(defaultStream::error_stream(),
         "Please use CMSClassUnloadingEnabled in place of "
         "CMSPermGenSweepingEnabled in the future\n");
-    } else if (match_option(option, "-XX:+UseGCTimeLimit", &tail)) {
+    } else if (match_option(option, "-XX:+UseGCTimeLimit")) {
       FLAG_SET_CMDLINE(bool, UseGCOverheadLimit, true);
       jio_fprintf(defaultStream::error_stream(),
         "Please use -XX:+UseGCOverheadLimit in place of "
         "-XX:+UseGCTimeLimit in the future\n");
-    } else if (match_option(option, "-XX:-UseGCTimeLimit", &tail)) {
+    } else if (match_option(option, "-XX:-UseGCTimeLimit")) {
       FLAG_SET_CMDLINE(bool, UseGCOverheadLimit, false);
       jio_fprintf(defaultStream::error_stream(),
         "Please use -XX:-UseGCOverheadLimit in place of "
@@ -3267,13 +3242,13 @@
     // are not to be documented.
     } else if (match_option(option, "-XX:MaxTLERatio=", &tail)) {
       // No longer used.
-    } else if (match_option(option, "-XX:+ResizeTLE", &tail)) {
+    } else if (match_option(option, "-XX:+ResizeTLE")) {
       FLAG_SET_CMDLINE(bool, ResizeTLAB, true);
-    } else if (match_option(option, "-XX:-ResizeTLE", &tail)) {
+    } else if (match_option(option, "-XX:-ResizeTLE")) {
       FLAG_SET_CMDLINE(bool, ResizeTLAB, false);
-    } else if (match_option(option, "-XX:+PrintTLE", &tail)) {
+    } else if (match_option(option, "-XX:+PrintTLE")) {
       FLAG_SET_CMDLINE(bool, PrintTLAB, true);
-    } else if (match_option(option, "-XX:-PrintTLE", &tail)) {
+    } else if (match_option(option, "-XX:-PrintTLE")) {
       FLAG_SET_CMDLINE(bool, PrintTLAB, false);
     } else if (match_option(option, "-XX:TLEFragmentationRatio=", &tail)) {
       // No longer used.
@@ -3289,17 +3264,17 @@
       FLAG_SET_CMDLINE(uintx, TLABSize, long_tlab_size);
     } else if (match_option(option, "-XX:TLEThreadRatio=", &tail)) {
       // No longer used.
-    } else if (match_option(option, "-XX:+UseTLE", &tail)) {
+    } else if (match_option(option, "-XX:+UseTLE")) {
       FLAG_SET_CMDLINE(bool, UseTLAB, true);
-    } else if (match_option(option, "-XX:-UseTLE", &tail)) {
+    } else if (match_option(option, "-XX:-UseTLE")) {
       FLAG_SET_CMDLINE(bool, UseTLAB, false);
-    } else if (match_option(option, "-XX:+DisplayVMOutputToStderr", &tail)) {
+    } else if (match_option(option, "-XX:+DisplayVMOutputToStderr")) {
       FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, false);
       FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, true);
-    } else if (match_option(option, "-XX:+DisplayVMOutputToStdout", &tail)) {
+    } else if (match_option(option, "-XX:+DisplayVMOutputToStdout")) {
       FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, false);
       FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, true);
-    } else if (match_option(option, "-XX:+ExtendedDTraceProbes", &tail)) {
+    } else if (match_option(option, "-XX:+ExtendedDTraceProbes")) {
 #if defined(DTRACE_ENABLED)
       FLAG_SET_CMDLINE(bool, ExtendedDTraceProbes, true);
       FLAG_SET_CMDLINE(bool, DTraceMethodProbes, true);
@@ -3311,7 +3286,7 @@
       return JNI_EINVAL;
 #endif // defined(DTRACE_ENABLED)
 #ifdef ASSERT
-    } else if (match_option(option, "-XX:+FullGCALot", &tail)) {
+    } else if (match_option(option, "-XX:+FullGCALot")) {
       FLAG_SET_CMDLINE(bool, FullGCALot, true);
       // disable scavenge before parallel mark-compact
       FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
@@ -3397,7 +3372,7 @@
       }
       FLAG_SET_CMDLINE(uintx, MaxDirectMemorySize, max_direct_memory_size);
 #if !INCLUDE_MANAGEMENT
-    } else if (match_option(option, "-XX:+ManagementServer", &tail)) {
+    } else if (match_option(option, "-XX:+ManagementServer")) {
         jio_fprintf(defaultStream::error_stream(),
           "ManagementServer is not supported in this VM.\n");
         return JNI_ERR;
@@ -3481,11 +3456,89 @@
   }
 }
 
+static bool has_jar_files(const char* directory) {
+  DIR* dir = os::opendir(directory);
+  if (dir == NULL) return false;
+
+  struct dirent *entry;
+  char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal);
+  bool hasJarFile = false;
+  while (!hasJarFile && (entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
+    const char* name = entry->d_name;
+    const char* ext = name + strlen(name) - 4;
+    hasJarFile = ext > name && (os::file_name_strcmp(ext, ".jar") == 0);
+  }
+  FREE_C_HEAP_ARRAY(char, dbuf);
+  os::closedir(dir);
+  return hasJarFile ;
+}
+
+static int check_non_empty_dirs(const char* path) {
+  const char separator = *os::path_separator();
+  const char* const end = path + strlen(path);
+  int nonEmptyDirs = 0;
+  while (path < end) {
+    const char* tmp_end = strchr(path, separator);
+    if (tmp_end == NULL) {
+      if (has_jar_files(path)) {
+        nonEmptyDirs++;
+        jio_fprintf(defaultStream::output_stream(),
+          "Non-empty directory: %s\n", path);
+      }
+      path = end;
+    } else {
+      char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtInternal);
+      memcpy(dirpath, path, tmp_end - path);
+      dirpath[tmp_end - path] = '\0';
+      if (has_jar_files(dirpath)) {
+        nonEmptyDirs++;
+        jio_fprintf(defaultStream::output_stream(),
+          "Non-empty directory: %s\n", dirpath);
+      }
+      FREE_C_HEAP_ARRAY(char, dirpath);
+      path = tmp_end + 1;
+    }
+  }
+  return nonEmptyDirs;
+}
+
 jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required) {
-  // This must be done after all -D arguments have been processed.
-  scp_p->expand_endorsed();
-
-  if (scp_assembly_required || scp_p->get_endorsed() != NULL) {
+  // check if the default lib/endorsed directory exists; if so, error
+  char path[JVM_MAXPATHLEN];
+  const char* fileSep = os::file_separator();
+  sprintf(path, "%s%slib%sendorsed", Arguments::get_java_home(), fileSep, fileSep);
+
+  if (CheckEndorsedAndExtDirs) {
+    int nonEmptyDirs = 0;
+    // check endorsed directory
+    nonEmptyDirs += check_non_empty_dirs(path);
+    // check the extension directories
+    nonEmptyDirs += check_non_empty_dirs(Arguments::get_ext_dirs());
+    if (nonEmptyDirs > 0) {
+      return JNI_ERR;
+    }
+  }
+
+  DIR* dir = os::opendir(path);
+  if (dir != NULL) {
+    jio_fprintf(defaultStream::output_stream(),
+      "<JAVA_HOME>/lib/endorsed is not supported. Endorsed standards and standalone APIs\n"
+      "in modular form will be supported via the concept of upgradeable modules.\n");
+    os::closedir(dir);
+    return JNI_ERR;
+  }
+
+  sprintf(path, "%s%slib%sext", Arguments::get_java_home(), fileSep, fileSep);
+  dir = os::opendir(path);
+  if (dir != NULL) {
+    jio_fprintf(defaultStream::output_stream(),
+      "<JAVA_HOME>/lib/ext exists, extensions mechanism no longer supported; "
+      "Use -classpath instead.\n.");
+    os::closedir(dir);
+    return JNI_ERR;
+  }
+
+  if (scp_assembly_required) {
     // Assemble the bootclasspath elements into the final path.
     Arguments::set_sysclasspath(scp_p->combined_path());
   }
@@ -3754,23 +3807,23 @@
       settings_file_specified = true;
       continue;
     }
-    if (match_option(option, "-XX:+PrintVMOptions", &tail)) {
+    if (match_option(option, "-XX:+PrintVMOptions")) {
       PrintVMOptions = true;
       continue;
     }
-    if (match_option(option, "-XX:-PrintVMOptions", &tail)) {
+    if (match_option(option, "-XX:-PrintVMOptions")) {
       PrintVMOptions = false;
       continue;
     }
-    if (match_option(option, "-XX:+IgnoreUnrecognizedVMOptions", &tail)) {
+    if (match_option(option, "-XX:+IgnoreUnrecognizedVMOptions")) {
       IgnoreUnrecognizedVMOptions = true;
       continue;
     }
-    if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions", &tail)) {
+    if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions")) {
       IgnoreUnrecognizedVMOptions = false;
       continue;
     }
-    if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) {
+    if (match_option(option, "-XX:+PrintFlagsInitial")) {
       CommandLineFlags::printFlags(tty, false);
       vm_exit(0);
     }
@@ -3796,7 +3849,7 @@
 
 
 #ifndef PRODUCT
-    if (match_option(option, "-XX:+PrintFlagsWithComments", &tail)) {
+    if (match_option(option, "-XX:+PrintFlagsWithComments")) {
       CommandLineFlags::printFlags(tty, true);
       vm_exit(0);
     }
--- a/src/share/vm/runtime/arguments.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/runtime/arguments.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -254,8 +254,6 @@
   static SystemProperty* _system_properties;
 
   // Quick accessor to System properties in the list:
-  static SystemProperty *_java_ext_dirs;
-  static SystemProperty *_java_endorsed_dirs;
   static SystemProperty *_sun_boot_library_path;
   static SystemProperty *_java_library_path;
   static SystemProperty *_java_home;
@@ -266,6 +264,10 @@
   static char* _meta_index_path;
   static char* _meta_index_dir;
 
+  // temporary: to emit warning if the default ext dirs are not empty.
+  // remove this variable when the warning is no longer needed.
+  static char* _ext_dirs;
+
   // java.vendor.url.bug, bug reporting URL for fatal errors.
   static const char* _java_vendor_url_bug;
 
@@ -585,8 +587,7 @@
   static void set_dll_dir(char *value) { _sun_boot_library_path->set_value(value); }
   static void set_java_home(char *value) { _java_home->set_value(value); }
   static void set_library_path(char *value) { _java_library_path->set_value(value); }
-  static void set_ext_dirs(char *value) { _java_ext_dirs->set_value(value); }
-  static void set_endorsed_dirs(char *value) { _java_endorsed_dirs->set_value(value); }
+  static void set_ext_dirs(char *value)     { _ext_dirs = os::strdup_check_oom(value); }
   static void set_sysclasspath(char *value) { _sun_boot_class_path->set_value(value); }
   static void append_sysclasspath(const char *value) { _sun_boot_class_path->append_value(value); }
   static void set_meta_index_path(char* meta_index_path, char* meta_index_dir) {
@@ -596,14 +597,14 @@
 
   static char* get_java_home() { return _java_home->value(); }
   static char* get_dll_dir() { return _sun_boot_library_path->value(); }
-  static char* get_endorsed_dir() { return _java_endorsed_dirs->value(); }
   static char* get_sysclasspath() { return _sun_boot_class_path->value(); }
   static char* get_meta_index_path() { return _meta_index_path; }
   static char* get_meta_index_dir()  { return _meta_index_dir;  }
-  static char* get_ext_dirs() { return _java_ext_dirs->value(); }
+  static char* get_ext_dirs()        { return _ext_dirs;  }
   static char* get_appclasspath() { return _java_class_path->value(); }
   static void  fix_appclasspath();
 
+
   // Operation modi
   static Mode mode()                { return _mode; }
   static bool is_interpreter_only() { return mode() == _int; }
--- a/src/share/vm/runtime/globals.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/runtime/globals.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -1230,6 +1230,9 @@
   product(bool, CheckJNICalls, false,                                       \
           "Verify all arguments to JNI calls")                              \
                                                                             \
+  product(bool, CheckEndorsedAndExtDirs, false,                             \
+          "Verify the endorsed and extension directories are not used")     \
+                                                                            \
   product(bool, UseFastJNIAccessors, true,                                  \
           "Use optimized versions of Get<Primitive>Field")                  \
                                                                             \
--- a/src/share/vm/runtime/os.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/runtime/os.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -1230,11 +1230,21 @@
   Arguments::set_meta_index_path(meta_index, meta_index_dir);
 
   char* sysclasspath = NULL;
+  struct stat st;
+
+  // modular image if bootmodules.jimage exists
+  char* jimage = format_boot_path("%/lib/modules/bootmodules.jimage", home, home_len, fileSep, pathSep);
+  if (jimage == NULL) return false;
+  bool has_jimage = (os::stat(jimage, &st) == 0);
+  if (has_jimage) {
+    Arguments::set_sysclasspath(jimage);
+    return true;
+  }
+  FREE_C_HEAP_ARRAY(char, jimage);
 
   // images build if rt.jar exists
   char* rt_jar = format_boot_path("%/lib/rt.jar", home, home_len, fileSep, pathSep);
   if (rt_jar == NULL) return false;
-  struct stat st;
   bool has_rt_jar = (os::stat(rt_jar, &st) == 0);
   FREE_C_HEAP_ARRAY(char, rt_jar);
 
--- a/src/share/vm/runtime/os.hpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/runtime/os.hpp	Fri Dec 12 08:40:19 2014 -0800
@@ -500,6 +500,7 @@
   //File i/o operations
 
   static size_t read(int fd, void *buf, unsigned int nBytes);
+  static size_t read_at(int fd, void *buf, unsigned int nBytes, jlong offset);
   static size_t restartable_read(int fd, void *buf, unsigned int nBytes);
   static size_t write(int fd, const void *buf, unsigned int nBytes);
 
--- a/src/share/vm/runtime/statSampler.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/runtime/statSampler.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -225,8 +225,6 @@
   "java.vm.info",
   "java.library.path",
   "java.class.path",
-  "java.endorsed.dirs",
-  "java.ext.dirs",
   "java.version",
   "java.home",
   NULL
--- a/src/share/vm/runtime/vmStructs.cpp	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Fri Dec 12 08:40:19 2014 -0800
@@ -556,9 +556,6 @@
                                                                                                                                      \
   nonstatic_field(TenuredGeneration,           _min_heap_delta_bytes,                         size_t)                                \
   nonstatic_field(TenuredGeneration,           _the_space,                                    ContiguousSpace*)                      \
-  nonstatic_field(TenuredGeneration,           _last_gc,                                      WaterMark)                             \
-                                                                                                                                     \
-                                                                                                                                     \
                                                                                                                                      \
   nonstatic_field(Space,                       _bottom,                                       HeapWord*)                             \
   nonstatic_field(Space,                       _end,                                          HeapWord*)                             \
--- a/src/share/vm/trace/trace.xml	Fri Dec 12 13:13:01 2014 +0100
+++ b/src/share/vm/trace/trace.xml	Fri Dec 12 08:40:19 2014 -0800
@@ -314,6 +314,28 @@
       <value type="BYTES64" field="totalSize" label="Total Size" />
     </event>
 
+    <!-- Promotion events, Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. -->
+    <event id="PromoteObjectInNewPLAB" path="vm/gc/detailed/object_promotion_in_new_PLAB" label="Promotion in new PLAB"
+        description="Object survived scavenge and was copied to a new Promotion Local Allocation Buffer (PLAB). Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects." 
+           has_thread="true" has_stacktrace="false" is_instant="true">
+      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID" description="ID of GC during which the object was promoted"/>
+      <value type="CLASS" field="class" label="Class" description="Class of promoted object"/>
+      <value type="BYTES64" field="objectSize" label="Object Size" description="Size of promoted object"/>
+      <value type="UINT" field="tenuringAge" label="Object Tenuring Age" description="Tenuring age of a surviving object before being copied. The tenuring age of an object is a value between 0-15 and is incremented each scavange the object survives. Newly allocated objects have tenuring age 0."/>
+      <value type="BOOLEAN" field="tenured" label="Tenured" description="True if object was promoted to Old space, otherwise the object was aged and copied to a Survivor space"/>
+      <value type="BYTES64" field="plabSize" label="PLAB Size" description="Size of the allocated PLAB to which the object was copied"/>
+    </event>
+    
+    <event id="PromoteObjectOutsidePLAB" path="vm/gc/detailed/object_promotion_outside_PLAB" label="Promotion outside PLAB"
+        description="Object survived scavenge and was copied directly to the heap. Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects." 
+           has_thread="true" has_stacktrace="false" is_instant="true">
+      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID" description="ID of GC during which the object was promoted"/>
+      <value type="CLASS" field="class" label="Class" description="Class of promoted object"/>
+      <value type="BYTES64" field="objectSize" label="Object Size" description="Size of promoted object"/>
+      <value type="UINT" field="tenuringAge" label="Object Tenuring Age" description="Tenuring age of a surviving object before being copied. The tenuring age of an object is a value between 0-15 and is incremented each scavange the object survives. Newly allocated objects have tenuring age 0."/>
+      <value type="BOOLEAN" field="tenured" label="Tenured" description="True if object was promoted to Old space, otherwise the object was aged and copied to a Survivor space"/>
+    </event>
+
     <event id="PromotionFailed" path="vm/gc/detailed/promotion_failed" label="Promotion Failed" is_instant="true"
            description="Promotion of an object failed">
       <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
--- a/test/Makefile	Fri Dec 12 13:13:01 2014 +0100
+++ b/test/Makefile	Fri Dec 12 08:40:19 2014 -0800
@@ -275,6 +275,9 @@
 # Ignore tests are not run and completely silent about it
 JTREG_IGNORE_OPTION = -ignore:quiet
 JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION)
+# Multiply by 4 the timeout factor
+JTREG_TIMEOUT_OPTION =  -timeoutFactor:4
+JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
 # Add any extra options
 JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS)
 # Set other vm and test options
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/TestCardTablePageCommits.java	Fri Dec 12 08:40:19 2014 -0800
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2014, 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.
+*/
+
+import com.oracle.java.testlibrary.JDKToolFinder;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.Platform;
+
+/*
+ * @test TestCardTablePageCommits
+ * @key gc
+ * @bug 8059066
+ * @summary Tests that the card table does not commit the same page twice
+ * @library /testlibrary
+ * @run driver TestCardTablePageCommits
+ */
+public class TestCardTablePageCommits {
+    public static void main(String args[]) throws Exception {
+        // The test is run with a small heap to make sure all pages in the card
+        // table gets committed. Need 8 MB heap to trigger the bug on SPARC
+        // because of 8kB pages, assume 4 KB pages for all other CPUs.
+        String Xmx = Platform.isSparc() ? "-Xmx8m" : "-Xmx4m";
+
+        String[] opts = {Xmx, "-XX:NativeMemoryTracking=detail", "-XX:+UseParallelGC", "-version"};
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(opts);
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldHaveExitValue(0);
+    }
+}
--- a/test/runtime/SharedArchiveFile/LimitSharedSizes.java	Fri Dec 12 13:13:01 2014 +0100
+++ b/test/runtime/SharedArchiveFile/LimitSharedSizes.java	Fri Dec 12 08:40:19 2014 -0800
@@ -30,40 +30,96 @@
 import com.oracle.java.testlibrary.*;
 
 public class LimitSharedSizes {
+    static enum Region {
+        RO, RW, MD, MC
+    }
+
     private static class SharedSizeTestData {
         public String optionName;
         public String optionValue;
         public String expectedErrorMsg;
 
-        public SharedSizeTestData(String name, String value, String msg) {
-            optionName = name;
+        public SharedSizeTestData(Region region, String value, String msg) {
+            optionName = getName(region);
             optionValue = value;
             expectedErrorMsg = msg;
         }
+
+        public SharedSizeTestData(Region region, String msg) {
+            optionName = getName(region);
+            optionValue = getValue(region);
+            expectedErrorMsg = msg;
+        }
+
+        private String getName(Region region) {
+            String name;
+            switch (region) {
+                case RO:
+                    name = "-XX:SharedReadOnlySize";
+                    break;
+                case RW:
+                    name = "-XX:SharedReadWriteSize";
+                    break;
+                case MD:
+                    name = "-XX:SharedMiscDataSize";
+                    break;
+                case MC:
+                    name = "-XX:SharedMiscCodeSize";
+                    break;
+                default:
+                    name = "Unknown";
+                    break;
+            }
+            return name;
+        }
+
+        private String getValue(Region region) {
+            String value;
+            switch (region) {
+                case RO:
+                    value = Platform.is64bit() ? "9M" : "8M";
+                    break;
+                case RW:
+                    value = Platform.is64bit() ? "12M" : "7M";
+                    break;
+                case MD:
+                    value = Platform.is64bit() ? "4M" : "2M";
+                    break;
+                case MC:
+                    value = "120k";
+                    break;
+                default:
+                    value = "0M";
+                    break;
+            }
+            return value;
+        }
     }
 
     private static final SharedSizeTestData[] testTable = {
-        // values in this part of the test table should cause failure
-        // (shared space sizes are deliberately too small)
-        new SharedSizeTestData("-XX:SharedReadOnlySize", "4M",      "read only"),
-        new SharedSizeTestData("-XX:SharedReadWriteSize","4M",      "read write"),
-
-        // Known issue, JDK-8038422 (assert() on Windows)
-        // new SharedSizeTestData("-XX:SharedMiscDataSize", "500k",    "miscellaneous data"),
-
-        // Too small of a misc code size should not cause a vm crash.
-        // It should result in the following error message:
+        // Too small of a region size should not cause a vm crash.
+        // It should result in an error message like the following:
         // The shared miscellaneous code space is not large enough
         // to preload requested classes. Use -XX:SharedMiscCodeSize=
         // to increase the initial size of shared miscellaneous code space.
-        new SharedSizeTestData("-XX:SharedMiscCodeSize", "20k",     "miscellaneous code"),
+        new SharedSizeTestData(Region.RO, "4M",   "read only"),
+        new SharedSizeTestData(Region.RW, "4M",   "read write"),
+        new SharedSizeTestData(Region.MD, "50k",  "miscellaneous data"),
+        new SharedSizeTestData(Region.MC, "20k",  "miscellaneous code"),
 
         // these values are larger than default ones, but should
         // be acceptable and not cause failure
-        new SharedSizeTestData("-XX:SharedReadOnlySize",    "20M", null),
-        new SharedSizeTestData("-XX:SharedReadWriteSize",   "20M", null),
-        new SharedSizeTestData("-XX:SharedMiscDataSize",    "20M", null),
-        new SharedSizeTestData("-XX:SharedMiscCodeSize",    "20M", null)
+        new SharedSizeTestData(Region.RO, "20M", null),
+        new SharedSizeTestData(Region.RW, "20M", null),
+        new SharedSizeTestData(Region.MD, "20M", null),
+        new SharedSizeTestData(Region.MC, "20M", null),
+
+        // test with sizes which just meet the minimum required sizes
+        // the following tests also attempt to use the shared archive
+        new SharedSizeTestData(Region.RO, "UseArchive"),
+        new SharedSizeTestData(Region.RW, "UseArchive"),
+        new SharedSizeTestData(Region.MD, "UseArchive"),
+        new SharedSizeTestData(Region.MC, "UseArchive")
     };
 
     public static void main(String[] args) throws Exception {
@@ -82,10 +138,39 @@
             OutputAnalyzer output = new OutputAnalyzer(pb.start());
 
             if (td.expectedErrorMsg != null) {
-                output.shouldContain("The shared " + td.expectedErrorMsg
-                    + " space is not large enough");
+                if (!td.expectedErrorMsg.equals("UseArchive")) {
+                    output.shouldContain("The shared " + td.expectedErrorMsg
+                        + " space is not large enough");
 
-                output.shouldHaveExitValue(2);
+                    output.shouldHaveExitValue(2);
+                } else {
+                    output.shouldNotContain("space is not large enough");
+                    output.shouldHaveExitValue(0);
+
+                    // try to use the archive
+                    pb = ProcessTools.createJavaProcessBuilder(
+                       "-XX:+UnlockDiagnosticVMOptions",
+                       "-XX:SharedArchiveFile=./" + fileName,
+                       "-XX:+PrintSharedArchiveAndExit",
+                       "-version");
+
+                    try {
+                        output = new OutputAnalyzer(pb.start());
+                        output.shouldContain("archive is valid");
+                    } catch (RuntimeException e) {
+                        // if sharing failed due to ASLR or similar reasons,
+                        // check whether sharing was attempted at all (UseSharedSpaces)
+                        if ((output.getOutput().contains("Unable to use shared archive") ||
+                             output.getOutput().contains("Unable to map ReadOnly shared space at required address.") ||
+                             output.getOutput().contains("Unable to map ReadWrite shared space at required address.") ||
+                             output.getOutput().contains("Unable to reserve shared space at required address")) &&
+                             output.getExitValue() == 1) {
+                             System.out.println("Unable to use shared archive: test not executed; assumed passed");
+                             return;
+                        }
+                    }
+                    output.shouldHaveExitValue(0);
+                }
             } else {
                 output.shouldNotContain("space is not large enough");
                 output.shouldHaveExitValue(0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java	Fri Dec 12 08:40:19 2014 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/*
+ * @test
+ * @bug 8066670
+ * @summary Testing -XX:+PrintSharedArchiveAndExit option
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class PrintSharedArchiveAndExit {
+  public static void main(String[] args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    try {
+      output.shouldContain("Loading classes to share");
+      output.shouldHaveExitValue(0);
+
+      // (1) With a valid archive
+      pb = ProcessTools.createJavaProcessBuilder(
+          "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa",
+          "-XX:+PrintSharedArchiveAndExit", "-version");
+      output = new OutputAnalyzer(pb.start());
+      output.shouldContain("archive is valid");
+      output.shouldNotContain("java version");     // Should not print JVM version
+      output.shouldHaveExitValue(0);               // Should report success in error code.
+
+      pb = ProcessTools.createJavaProcessBuilder(
+          "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa",
+          "-XX:+PrintSharedArchiveAndExit");
+      output = new OutputAnalyzer(pb.start());
+      output.shouldContain("archive is valid");
+      output.shouldNotContain("Usage:");           // Should not print JVM help message
+      output.shouldHaveExitValue(0);               // Should report success in error code.
+
+      // (2) With an invalid archive (boot class path has been prepended)
+      pb = ProcessTools.createJavaProcessBuilder(
+          "-Xbootclasspath/p:foo.jar",
+          "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa",
+          "-XX:+PrintSharedArchiveAndExit", "-version");
+      output = new OutputAnalyzer(pb.start());
+      output.shouldContain("archive is invalid");
+      output.shouldNotContain("java version");     // Should not print JVM version
+      output.shouldHaveExitValue(1);               // Should report failure in error code.
+
+      pb = ProcessTools.createJavaProcessBuilder(
+          "-Xbootclasspath/p:foo.jar",
+          "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa",
+          "-XX:+PrintSharedArchiveAndExit");
+      output = new OutputAnalyzer(pb.start());
+      output.shouldContain("archive is invalid");
+      output.shouldNotContain("Usage:");           // Should not print JVM help message
+      output.shouldHaveExitValue(1);               // Should report failure in error code.
+    } catch (RuntimeException e) {
+      e.printStackTrace();
+      output.shouldContain("Unable to use shared archive");
+      output.shouldHaveExitValue(1);
+    }
+  }
+}
--- a/test/serviceability/sa/jmap-hashcode/Test8028623.java	Fri Dec 12 13:13:01 2014 +0100
+++ b/test/serviceability/sa/jmap-hashcode/Test8028623.java	Fri Dec 12 08:40:19 2014 -0800
@@ -41,12 +41,12 @@
 
 public class Test8028623 {
 
-  public static int à = 1;
+  public static int \u00CB = 1;
   public static String dumpFile = "heap.out";
 
   public static void main (String[] args) {
 
-    System.out.println(Ã);
+    System.out.println(\u00CB);
 
     try {
         if (!Platform.shouldSAAttach()) {