Merge
authoracorn
Wed, 27 Jul 2016 13:33:55 +0000
changeset 40194 7b26e83709cd
parent 40193 1de2394fd836 (current diff)
parent 40192 64c0b3d47afb (diff)
child 40195 a13e4945de1d
child 40196 0b3f554d2480
Merge
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/ClassTracker.java
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/FailOverExecutionControl.java
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIConnection.java
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIEventHandler.java
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIExecutionControl.java
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDINotConnectedException.java
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteClassLoader.java
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java
langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Internal.java
langtools/test/jdk/jshell/LocalExecutionControl.java
nashorn/test/script/currently-failing/logcoverage.js
--- a/.hgtags	Wed Jul 27 08:33:15 2016 -0400
+++ b/.hgtags	Wed Jul 27 13:33:55 2016 +0000
@@ -370,3 +370,4 @@
 3aa52182b3ad7c5b3a61cf05a59dd07e4c5884e5 jdk-9+125
 03e7b2c5ae345be3caf981d76ceb3efe5ff447f8 jdk-9+126
 8e45018bde9de4ad15b972ae62874bba52dba2d5 jdk-9+127
+5bf88dce615f6804f9e101a96ffa7c9dfb4fbbbe jdk-9+128
--- a/.hgtags-top-repo	Wed Jul 27 08:33:15 2016 -0400
+++ b/.hgtags-top-repo	Wed Jul 27 13:33:55 2016 +0000
@@ -370,3 +370,4 @@
 9aa7d40f3a453f51e47f4c1b19eff5740a74a9f8 jdk-9+125
 3a58466296d36944454756ef01e7513ac5e14a16 jdk-9+126
 8fa686245bd2a072ece3392743460030f0854520 jdk-9+127
+b30ae794d974d7dd3eb4e84203f70021823fa6c6 jdk-9+128
--- a/common/autoconf/boot-jdk.m4	Wed Jul 27 08:33:15 2016 -0400
+++ b/common/autoconf/boot-jdk.m4	Wed Jul 27 13:33:55 2016 +0000
@@ -345,6 +345,9 @@
   # Disable special log output when a debug build is used as Boot JDK...
   ADD_JVM_ARG_IF_OK([-XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput],boot_jdk_jvmargs,[$JAVA])
 
+  # Force en-US environment
+  ADD_JVM_ARG_IF_OK([-Duser.language=en -Duser.country=US],boot_jdk_jvmargs,[$JAVA])
+
   # Apply user provided options.
   ADD_JVM_ARG_IF_OK([$with_boot_jdk_jvmargs],boot_jdk_jvmargs,[$JAVA])
 
--- a/common/autoconf/generated-configure.sh	Wed Jul 27 08:33:15 2016 -0400
+++ b/common/autoconf/generated-configure.sh	Wed Jul 27 13:33:55 2016 +0000
@@ -5094,7 +5094,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1467960715
+DATE_WHEN_GENERATED=1469202305
 
 ###############################################################################
 #
@@ -65048,6 +65048,23 @@
   fi
 
 
+  # Force en-US environment
+
+  $ECHO "Check if jvm arg is ok: -Duser.language=en -Duser.country=US" >&5
+  $ECHO "Command: $JAVA -Duser.language=en -Duser.country=US -version" >&5
+  OUTPUT=`$JAVA -Duser.language=en -Duser.country=US -version 2>&1`
+  FOUND_WARN=`$ECHO "$OUTPUT" | $GREP -i warn`
+  FOUND_VERSION=`$ECHO $OUTPUT | $GREP " version \""`
+  if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then
+    boot_jdk_jvmargs="$boot_jdk_jvmargs -Duser.language=en -Duser.country=US"
+    JVM_ARG_OK=true
+  else
+    $ECHO "Arg failed:" >&5
+    $ECHO "$OUTPUT" >&5
+    JVM_ARG_OK=false
+  fi
+
+
   # Apply user provided options.
 
   $ECHO "Check if jvm arg is ok: $with_boot_jdk_jvmargs" >&5
--- a/corba/.hgtags	Wed Jul 27 08:33:15 2016 -0400
+++ b/corba/.hgtags	Wed Jul 27 13:33:55 2016 +0000
@@ -370,3 +370,4 @@
 1d48e67d1b91eb9f72e49e69a4021edb85e357fc jdk-9+125
 c7f5ba08fcd4b8416e62c21229f9a07c95498919 jdk-9+126
 8fab452b6f4710762ba1d8e55fd62db00b1355fe jdk-9+127
+1f093d3f8cd99cd37c3b0af4cf5c3bffaa9c8b98 jdk-9+128
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/activation/ORBD.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/activation/ORBD.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,4 @@
 /*
- *
  * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -22,7 +21,6 @@
  * 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.
- *
  */
 
 package com.sun.corba.se.impl.activation;
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/ORBUtility.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/ORBUtility.java	Wed Jul 27 13:33:55 2016 +0000
@@ -34,21 +34,13 @@
 import java.security.Policy;
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Set;
-import java.util.Map.Entry;
-import java.util.Collection;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Enumeration;
-import java.util.Properties;
-import java.util.IdentityHashMap;
 import java.util.StringTokenizer;
 import java.util.NoSuchElementException;
 
@@ -165,8 +157,18 @@
      * Return default ValueHandler
      */
     public static ValueHandler createValueHandler() {
+        ValueHandler vh;
+        try {
+            vh = AccessController.doPrivileged(new PrivilegedExceptionAction<ValueHandler>() {
+                public ValueHandler run() throws Exception {
         return Util.createValueHandler();
     }
+            });
+        } catch (PrivilegedActionException e) {
+            throw new InternalError(e.getCause());
+        }
+        return vh;
+    }
 
     /**
      * Returns true if it was accurately determined that the remote ORB is
@@ -664,7 +666,16 @@
      * ValueHandler.
      */
     public static byte getMaxStreamFormatVersion() {
-        ValueHandler vh = Util.createValueHandler();
+        ValueHandler vh;
+        try {
+            vh = AccessController.doPrivileged(new PrivilegedExceptionAction<ValueHandler>() {
+                public ValueHandler run() throws Exception {
+                    return Util.createValueHandler();
+                }
+            });
+        } catch (PrivilegedActionException e) {
+            throw new InternalError(e.getCause());
+        }
 
         if (!(vh instanceof javax.rmi.CORBA.ValueHandlerMultiFormat))
             return ORBConstants.STREAM_FORMAT_VERSION_1;
--- a/corba/src/java.corba/share/classes/javax/rmi/CORBA/Util.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/corba/src/java.corba/share/classes/javax/rmi/CORBA/Util.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -45,6 +45,7 @@
 import java.rmi.Remote;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.SerializablePermission;
 import java.net.MalformedURLException ;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -195,6 +196,8 @@
      */
     public static ValueHandler createValueHandler() {
 
+        isCustomSerializationPermitted();
+
         if (utilDelegate != null) {
             return utilDelegate.createValueHandler();
         }
@@ -337,6 +340,7 @@
     // security reasons. If you know a better solution how to share this code
     // then remove it from PortableRemoteObject. Also in Stub.java
     private static Object createDelegate(String classKey) {
+
         String className = (String)
             AccessController.doPrivileged(new GetPropertyAction(classKey));
         if (className == null) {
@@ -345,7 +349,6 @@
                 className = props.getProperty(classKey);
             }
         }
-
         if (className == null) {
             return new com.sun.corba.se.impl.javax.rmi.CORBA.Util();
         }
@@ -389,4 +392,14 @@
             new GetORBPropertiesFileAction());
     }
 
+    private static void isCustomSerializationPermitted() {
+        SecurityManager sm = System.getSecurityManager();
+        if ( sm != null) {
+            // check that a serialization permission has been
+            // set to allow the loading of the Util delegate
+            // which provides access to custom ValueHandler
+            sm.checkPermission(new SerializablePermission(
+                    "enableCustomValueHandler"));
 }
+    }
+}
--- a/hotspot/.hgtags	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/.hgtags	Wed Jul 27 13:33:55 2016 +0000
@@ -530,3 +530,4 @@
 bb640b49741af3f57f9994129934c46fc173219f jdk-9+125
 adc8c84b7cf8c540d920182f78a2bc982366432a jdk-9+126
 352357128f602dcf0426b1cbe011a4685a4d9f97 jdk-9+127
+22bf6db9767b1b3a1994cbf32eb3331f31ae2093 jdk-9+128
--- a/hotspot/make/test/JtregNative.gmk	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/make/test/JtregNative.gmk	Wed Jul 27 13:33:55 2016 +0000
@@ -51,6 +51,7 @@
     $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
     $(HOTSPOT_TOPDIR)/test/compiler/calls \
     $(HOTSPOT_TOPDIR)/test/compiler/native \
+    $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetNamedModule \
     $(HOTSPOT_TOPDIR)/test/testlibrary/jvmti \
     #
 
@@ -64,6 +65,7 @@
 ifeq ($(TOOLCHAIN_TYPE), solstudio)
     BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_liboverflow := -lc
     BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libSimpleClassFileLoadHook := -lc
+    BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libGetNamedModuleTest := -lc
 endif
 
 BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/hotspot/jtreg/native
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1742,11 +1742,11 @@
   }
 
   typedef struct {
-    Elf32_Half  code;         // Actual value as defined in elf.h
-    Elf32_Half  compat_class; // Compatibility of archs at VM's sense
-    char        elf_class;    // 32 or 64 bit
-    char        endianess;    // MSB or LSB
-    char*       name;         // String representation
+    Elf32_Half    code;         // Actual value as defined in elf.h
+    Elf32_Half    compat_class; // Compatibility of archs at VM's sense
+    unsigned char elf_class;    // 32 or 64 bit
+    unsigned char endianess;    // MSB or LSB
+    char*         name;         // String representation
   } arch_t;
 
 #ifndef EM_486
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1320,36 +1320,8 @@
 }
 
 bool os::supports_vtime() { return true; }
-
-bool os::enable_vtime() {
-  int fd = ::open("/proc/self/ctl", O_WRONLY);
-  if (fd == -1) {
-    return false;
-  }
-
-  long cmd[] = { PCSET, PR_MSACCT };
-  int res = ::write(fd, cmd, sizeof(long) * 2);
-  ::close(fd);
-  if (res != sizeof(long) * 2) {
-    return false;
-  }
-  return true;
-}
-
-bool os::vtime_enabled() {
-  int fd = ::open("/proc/self/status", O_RDONLY);
-  if (fd == -1) {
-    return false;
-  }
-
-  pstatus_t status;
-  int res = os::read(fd, (void*) &status, sizeof(pstatus_t));
-  ::close(fd);
-  if (res != sizeof(pstatus_t)) {
-    return false;
-  }
-  return status.pr_flags & PR_MSACCT;
-}
+bool os::enable_vtime() { return false; }
+bool os::vtime_enabled() { return false; }
 
 double os::elapsedVTime() {
   return (double)gethrvtime() / (double)hrtime_hz;
--- a/hotspot/src/share/vm/classfile/altHashing.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/altHashing.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -224,7 +224,7 @@
 static const jbyte THREE_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82};
 static const jbyte FOUR_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83};
 static const jchar TWO_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382};
-static const jint ONE_INT[] = { 0x83828180};
+static const jint ONE_INT[] = { (jint)0x83828180};
 static const jbyte SIX_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85};
 static const jchar THREE_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382, (jchar) 0x8584};
 static const jbyte EIGHT_BYTE[] = {
@@ -235,7 +235,7 @@
   (jchar) 0x8180, (jchar) 0x8382,
   (jchar) 0x8584, (jchar) 0x8786};
 
-static const jint TWO_INT[] = { 0x83828180, 0x87868584};
+static const jint TWO_INT[] = { (jint)0x83828180, (jint)0x87868584};
 
 static const juint MURMUR3_32_X86_CHECK_VALUE = 0xB0F57EE3;
 
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -142,7 +142,9 @@
 
   f->do_oop(&_class_loader);
   _dependencies.oops_do(f);
-  _handles->oops_do(f);
+  if (_handles != NULL) {
+    _handles->oops_do(f);
+  }
   if (klass_closure != NULL) {
     classes_do(klass_closure);
   }
--- a/hotspot/src/share/vm/classfile/compactHashtable.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/compactHashtable.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -270,6 +270,10 @@
 
   // For reading from/writing to the CDS archive
   void serialize(SerializeClosure* soc);
+
+  uintx base_address() {
+    return (uintx) _base_address;
+  }
 };
 
 ////////////////////////////////////////////////////////////////////////
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -871,12 +871,17 @@
 
 int  java_lang_Class::oop_size(oop java_class) {
   assert(_oop_size_offset != 0, "must be set");
-  return java_class->int_field(_oop_size_offset);
-}
+  int size = java_class->int_field(_oop_size_offset);
+  assert(size > 0, "Oop size must be greater than zero, not %d", size);
+  return size;
+}
+
 void java_lang_Class::set_oop_size(oop java_class, int size) {
   assert(_oop_size_offset != 0, "must be set");
+  assert(size > 0, "Oop size must be greater than zero, not %d", size);
   java_class->int_field_put(_oop_size_offset, size);
 }
+
 int  java_lang_Class::static_oop_field_count(oop java_class) {
   assert(_static_oop_field_count_offset != 0, "must be set");
   return java_class->int_field(_static_oop_field_count_offset);
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -275,7 +275,6 @@
   static int static_oop_field_count(oop java_class);
   static void set_static_oop_field_count(oop java_class, int size);
 
-
   static GrowableArray<Klass*>* fixup_mirror_list() {
     return _fixup_mirror_list;
   }
--- a/hotspot/src/share/vm/classfile/modules.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/modules.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -820,6 +820,28 @@
 }
 
 
+jobject Modules::get_named_module(Handle h_loader, const char* package_str, TRAPS) {
+  assert(ModuleEntryTable::javabase_defined(),
+         "Attempt to call get_named_module before java.base is defined");
+  assert(h_loader.is_null() || java_lang_ClassLoader::is_subclass(h_loader->klass()),
+         "Class loader is not a subclass of java.lang.ClassLoader");
+  assert(package_str != NULL, "the package_str should not be NULL");
+
+  if (strlen(package_str) == 0) {
+    return NULL;
+  }
+  TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
+  const PackageEntry* const pkg_entry =
+    get_package_entry_by_name(package_sym, h_loader, THREAD);
+  const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
+
+  if (module_entry != NULL && module_entry->module() != NULL && module_entry->is_named()) {
+    return JNIHandles::make_local(THREAD, JNIHandles::resolve(module_entry->module()));
+  }
+  return NULL;
+}
+
+
 // This method is called by JFR and by the above method.
 jobject Modules::get_module(Symbol* package_name, Handle h_loader, TRAPS) {
   const PackageEntry* const pkg_entry =
--- a/hotspot/src/share/vm/classfile/modules.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/modules.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -121,6 +121,7 @@
   // IllegalArgumentException is thrown if loader is neither null nor a subtype of
   // java/lang/ClassLoader.
   static jobject get_module_by_package_name(jobject loader, jstring package, TRAPS);
+  static jobject get_named_module(Handle h_loader, const char* package, TRAPS);
 
   // If package is defined by loader, return the
   // java.lang.reflect.Module object for the module in which the package is defined.
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -238,6 +238,29 @@
   }
 }
 
+u4 SymbolTable::encode_shared(Symbol* sym) {
+  assert(DumpSharedSpaces, "called only during dump time");
+  uintx base_address = uintx(MetaspaceShared::shared_rs()->base());
+  uintx offset = uintx(sym) - base_address;
+  assert(offset < 0x7fffffff, "sanity");
+  return u4(offset);
+}
+
+Symbol* SymbolTable::decode_shared(u4 offset) {
+  assert(!DumpSharedSpaces, "called only during runtime");
+  uintx base_address = _shared_table.base_address();
+  Symbol* sym = (Symbol*)(base_address + offset);
+
+#ifndef PRODUCT
+  const char* s = (const char*)sym->bytes();
+  int len = sym->utf8_length();
+  unsigned int hash = hash_symbol(s, len);
+  assert(sym == lookup_shared(s, len, hash), "must be shared symbol");
+#endif
+
+  return sym;
+}
+
 // Pick hashing algorithm.
 unsigned int SymbolTable::hash_symbol(const char* s, int len) {
   return use_alternate_hashcode() ?
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -253,6 +253,8 @@
 
   // Sharing
   static void serialize(SerializeClosure* soc);
+  static u4 encode_shared(Symbol* sym);
+  static Symbol* decode_shared(u4 offset);
 
   // Rehash the symbol table if it gets out of balance
   static void rehash_table();
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -78,7 +78,19 @@
                                            TRAPS) {
     return NULL;
   }
+
   static void serialize(SerializeClosure* soc) {}
+
+  // The (non-application) CDS implementation supports only classes in the boot
+  // class loader, which ensures that the verification constraints are the same
+  // during archive creation time and runtime. Thus we can do the constraint checks
+  // entirely during archive creation time.
+  static bool add_verification_constraint(Klass* k, Symbol* name,
+                  Symbol* from_name, bool from_field_is_protected,
+                  bool from_is_array, bool from_is_object) {return false;}
+  static void finalize_verification_constraints() {}
+  static void check_verification_constraints(instanceKlassHandle klass,
+                                              TRAPS) {}
 };
 
 #endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
--- a/hotspot/src/share/vm/classfile/verificationType.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/verificationType.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/symbolTable.hpp"
+#include "classfile/systemDictionaryShared.hpp"
 #include "classfile/verificationType.hpp"
 #include "classfile/verifier.hpp"
 
@@ -41,6 +42,39 @@
   }
 }
 
+bool VerificationType::resolve_and_check_assignability(instanceKlassHandle klass, Symbol* name,
+         Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object, TRAPS) {
+  Klass* obj = SystemDictionary::resolve_or_fail(
+      name, Handle(THREAD, klass->class_loader()),
+      Handle(THREAD, klass->protection_domain()), true, CHECK_false);
+  if (log_is_enabled(Debug, class, resolve)) {
+    Verifier::trace_class_resolution(obj, klass());
+  }
+
+  KlassHandle this_class(THREAD, obj);
+
+  if (this_class->is_interface() && (!from_field_is_protected ||
+      from_name != vmSymbols::java_lang_Object())) {
+    // If we are not trying to access a protected field or method in
+    // java.lang.Object then, for arrays, we only allow assignability
+    // to interfaces java.lang.Cloneable and java.io.Serializable.
+    // Otherwise, we treat interfaces as java.lang.Object.
+    return !from_is_array ||
+      this_class == SystemDictionary::Cloneable_klass() ||
+      this_class == SystemDictionary::Serializable_klass();
+  } else if (from_is_object) {
+    Klass* from_class = SystemDictionary::resolve_or_fail(
+        from_name, Handle(THREAD, klass->class_loader()),
+        Handle(THREAD, klass->protection_domain()), true, CHECK_false);
+    if (log_is_enabled(Debug, class, resolve)) {
+      Verifier::trace_class_resolution(from_class, klass());
+    }
+    return InstanceKlass::cast(from_class)->is_subclass_of(this_class());
+  }
+
+  return false;
+}
+
 bool VerificationType::is_reference_assignable_from(
     const VerificationType& from, ClassVerifier* context,
     bool from_field_is_protected, TRAPS) const {
@@ -58,33 +92,17 @@
       // any object or array is assignable to java.lang.Object
       return true;
     }
-    Klass* obj = SystemDictionary::resolve_or_fail(
-        name(), Handle(THREAD, klass->class_loader()),
-        Handle(THREAD, klass->protection_domain()), true, CHECK_false);
-    if (log_is_enabled(Debug, class, resolve)) {
-      Verifier::trace_class_resolution(obj, klass());
+
+    if (DumpSharedSpaces && SystemDictionaryShared::add_verification_constraint(klass(),
+              name(), from.name(), from_field_is_protected, from.is_array(),
+              from.is_object())) {
+      // If add_verification_constraint() returns true, the resolution/check should be
+      // delayed until runtime.
+      return true;
     }
 
-    KlassHandle this_class(THREAD, obj);
-
-    if (this_class->is_interface() && (!from_field_is_protected ||
-        from.name() != vmSymbols::java_lang_Object())) {
-      // If we are not trying to access a protected field or method in
-      // java.lang.Object then, for arrays, we only allow assignability
-      // to interfaces java.lang.Cloneable and java.io.Serializable.
-      // Otherwise, we treat interfaces as java.lang.Object.
-      return !from.is_array() ||
-        this_class == SystemDictionary::Cloneable_klass() ||
-        this_class == SystemDictionary::Serializable_klass();
-    } else if (from.is_object()) {
-      Klass* from_class = SystemDictionary::resolve_or_fail(
-          from.name(), Handle(THREAD, klass->class_loader()),
-          Handle(THREAD, klass->protection_domain()), true, CHECK_false);
-      if (log_is_enabled(Debug, class, resolve)) {
-        Verifier::trace_class_resolution(from_class, klass());
-      }
-      return InstanceKlass::cast(from_class)->is_subclass_of(this_class());
-    }
+    return resolve_and_check_assignability(klass(), name(), from.name(),
+          from_field_is_protected, from.is_array(), from.is_object(), THREAD);
   } else if (is_array() && from.is_array()) {
     VerificationType comp_this = get_component(context, CHECK_false);
     VerificationType comp_from = from.get_component(context, CHECK_false);
--- a/hotspot/src/share/vm/classfile/verificationType.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/verificationType.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -333,6 +333,12 @@
   bool is_reference_assignable_from(
     const VerificationType&, ClassVerifier*, bool from_field_is_protected,
     TRAPS) const;
+
+ public:
+  static bool resolve_and_check_assignability(instanceKlassHandle klass, Symbol* name,
+                                              Symbol* from_name, bool from_field_is_protected,
+                                              bool from_is_array, bool from_is_object,
+                                              TRAPS);
 };
 
 #endif // SHARE_VM_CLASSFILE_VERIFICATIONTYPE_HPP
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -2377,9 +2377,17 @@
       case Bytecodes::_ifnonnull:
         target = bcs.dest();
         if (visited_branches->contains(bci)) {
-          if (bci_stack->is_empty()) return true;
-          // Pop a bytecode starting offset and scan from there.
-          bcs.set_start(bci_stack->pop());
+          if (bci_stack->is_empty()) {
+            if (handler_stack->is_empty()) {
+              return true;
+            } else {
+              // Parse the catch handlers for try blocks containing athrow.
+              bcs.set_start(handler_stack->pop());
+            }
+          } else {
+            // Pop a bytecode starting offset and scan from there.
+            bcs.set_start(bci_stack->pop());
+          }
         } else {
           if (target > bci) { // forward branch
             if (target >= code_length) return false;
@@ -2402,9 +2410,17 @@
       case Bytecodes::_goto_w:
         target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w());
         if (visited_branches->contains(bci)) {
-          if (bci_stack->is_empty()) return true;
-          // Been here before, pop new starting offset from stack.
-          bcs.set_start(bci_stack->pop());
+          if (bci_stack->is_empty()) {
+            if (handler_stack->is_empty()) {
+              return true;
+            } else {
+              // Parse the catch handlers for try blocks containing athrow.
+              bcs.set_start(handler_stack->pop());
+            }
+          } else {
+            // Been here before, pop new starting offset from stack.
+            bcs.set_start(bci_stack->pop());
+          }
         } else {
           if (target >= code_length) return false;
           // Continue scanning from the target onward.
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1256,9 +1256,7 @@
       // set between the last GC or pause and now. We need to clear the
       // incremental collection set and then start rebuilding it afresh
       // after this full GC.
-      abandon_collection_set(collection_set()->inc_head());
-      collection_set()->clear_incremental();
-      collection_set()->stop_incremental_building();
+      abandon_collection_set(collection_set());
 
       tear_down_region_sets(false /* free_list_only */);
       collector_state()->set_gcs_are_young(true);
@@ -1379,7 +1377,6 @@
       _verifier->check_bitmaps("Full GC End");
 
       // Start a new incremental collection set for the next pause
-      assert(collection_set()->head() == NULL, "must be");
       collection_set()->start_incremental_building();
 
       clear_cset_fast_test();
@@ -1724,8 +1721,6 @@
   _old_marking_cycles_started(0),
   _old_marking_cycles_completed(0),
   _in_cset_fast_test(),
-  _worker_cset_start_region(NULL),
-  _worker_cset_start_region_time_stamp(NULL),
   _gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()),
   _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()) {
 
@@ -1748,8 +1743,6 @@
   uint n_queues = ParallelGCThreads;
   _task_queues = new RefToScanQueueSet(n_queues);
 
-  _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues, mtGC);
-  _worker_cset_start_region_time_stamp = NEW_C_HEAP_ARRAY(uint, n_queues, mtGC);
   _evacuation_failed_info_array = NEW_C_HEAP_ARRAY(EvacuationFailedInfo, n_queues, mtGC);
 
   for (uint i = 0; i < n_queues; i++) {
@@ -1758,7 +1751,6 @@
     _task_queues->register_queue(i, q);
     ::new (&_evacuation_failed_info_array[i]) EvacuationFailedInfo();
   }
-  clear_cset_start_regions();
 
   // Initialize the G1EvacuationFailureALot counters and flags.
   NOT_PRODUCT(reset_evacuation_should_fail();)
@@ -1987,6 +1979,8 @@
 
   _preserved_marks_set.init(ParallelGCThreads);
 
+  _collection_set.initialize(max_regions());
+
   return JNI_OK;
 }
 
@@ -2420,117 +2414,12 @@
   _hrm.par_iterate(cl, worker_id, hrclaimer, concurrent);
 }
 
-// Clear the cached CSet starting regions and (more importantly)
-// the time stamps. Called when we reset the GC time stamp.
-void G1CollectedHeap::clear_cset_start_regions() {
-  assert(_worker_cset_start_region != NULL, "sanity");
-  assert(_worker_cset_start_region_time_stamp != NULL, "sanity");
-
-  for (uint i = 0; i < ParallelGCThreads; i++) {
-    _worker_cset_start_region[i] = NULL;
-    _worker_cset_start_region_time_stamp[i] = 0;
-  }
+void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) {
+  _collection_set.iterate(cl);
 }
 
-// Given the id of a worker, obtain or calculate a suitable
-// starting region for iterating over the current collection set.
-HeapRegion* G1CollectedHeap::start_cset_region_for_worker(uint worker_i) {
-  assert(get_gc_time_stamp() > 0, "should have been updated by now");
-
-  HeapRegion* result = NULL;
-  unsigned gc_time_stamp = get_gc_time_stamp();
-
-  if (_worker_cset_start_region_time_stamp[worker_i] == gc_time_stamp) {
-    // Cached starting region for current worker was set
-    // during the current pause - so it's valid.
-    // Note: the cached starting heap region may be NULL
-    // (when the collection set is empty).
-    result = _worker_cset_start_region[worker_i];
-    assert(result == NULL || result->in_collection_set(), "sanity");
-    return result;
-  }
-
-  // The cached entry was not valid so let's calculate
-  // a suitable starting heap region for this worker.
-
-  // We want the parallel threads to start their collection
-  // set iteration at different collection set regions to
-  // avoid contention.
-  // If we have:
-  //          n collection set regions
-  //          p threads
-  // Then thread t will start at region floor ((t * n) / p)
-
-  result = collection_set()->head();
-  uint cs_size = collection_set()->region_length();
-  uint active_workers = workers()->active_workers();
-
-  uint end_ind   = (cs_size * worker_i) / active_workers;
-  uint start_ind = 0;
-
-  if (worker_i > 0 &&
-      _worker_cset_start_region_time_stamp[worker_i - 1] == gc_time_stamp) {
-    // Previous workers starting region is valid
-    // so let's iterate from there
-    start_ind = (cs_size * (worker_i - 1)) / active_workers;
-    OrderAccess::loadload();
-    result = _worker_cset_start_region[worker_i - 1];
-  }
-
-  for (uint i = start_ind; i < end_ind; i++) {
-    result = result->next_in_collection_set();
-  }
-
-  // Note: the calculated starting heap region may be NULL
-  // (when the collection set is empty).
-  assert(result == NULL || result->in_collection_set(), "sanity");
-  assert(_worker_cset_start_region_time_stamp[worker_i] != gc_time_stamp,
-         "should be updated only once per pause");
-  _worker_cset_start_region[worker_i] = result;
-  OrderAccess::storestore();
-  _worker_cset_start_region_time_stamp[worker_i] = gc_time_stamp;
-  return result;
-}
-
-void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) {
-  HeapRegion* r = collection_set()->head();
-  while (r != NULL) {
-    HeapRegion* next = r->next_in_collection_set();
-    if (cl->doHeapRegion(r)) {
-      cl->incomplete();
-      return;
-    }
-    r = next;
-  }
-}
-
-void G1CollectedHeap::collection_set_iterate_from(HeapRegion* r,
-                                                  HeapRegionClosure *cl) {
-  if (r == NULL) {
-    // The CSet is empty so there's nothing to do.
-    return;
-  }
-
-  assert(r->in_collection_set(),
-         "Start region must be a member of the collection set.");
-  HeapRegion* cur = r;
-  while (cur != NULL) {
-    HeapRegion* next = cur->next_in_collection_set();
-    if (cl->doHeapRegion(cur) && false) {
-      cl->incomplete();
-      return;
-    }
-    cur = next;
-  }
-  cur = collection_set()->head();
-  while (cur != r) {
-    HeapRegion* next = cur->next_in_collection_set();
-    if (cl->doHeapRegion(cur) && false) {
-      cl->incomplete();
-      return;
-    }
-    cur = next;
-  }
+void G1CollectedHeap::collection_set_iterate_from(HeapRegionClosure *cl, uint worker_id) {
+  _collection_set.iterate_from(cl, worker_id, workers()->active_workers());
 }
 
 HeapRegion* G1CollectedHeap::next_compaction_region(const HeapRegion* from) const {
@@ -3090,6 +2979,18 @@
   g1_policy()->phase_times()->record_root_region_scan_wait_time(wait_time_ms);
 }
 
+class G1PrintCollectionSetClosure : public HeapRegionClosure {
+private:
+  G1HRPrinter* _hr_printer;
+public:
+  G1PrintCollectionSetClosure(G1HRPrinter* hr_printer) : HeapRegionClosure(), _hr_printer(hr_printer) { }
+
+  virtual bool doHeapRegion(HeapRegion* r) {
+    _hr_printer->cset(r);
+    return false;
+  }
+};
+
 bool
 G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
   assert_at_safepoint(true /* should_be_vm_thread */);
@@ -3268,11 +3169,8 @@
         _cm->verify_no_cset_oops();
 
         if (_hr_printer.is_active()) {
-          HeapRegion* hr = collection_set()->head();
-          while (hr != NULL) {
-            _hr_printer.cset(hr);
-            hr = hr->next_in_collection_set();
-          }
+          G1PrintCollectionSetClosure cl(&_hr_printer);
+          _collection_set.iterate(&cl);
         }
 
         // Initialize the GC alloc regions.
@@ -3287,12 +3185,10 @@
         post_evacuate_collection_set(evacuation_info, &per_thread_states);
 
         const size_t* surviving_young_words = per_thread_states.surviving_young_words();
-        free_collection_set(collection_set()->head(), evacuation_info, surviving_young_words);
+        free_collection_set(&_collection_set, evacuation_info, surviving_young_words);
 
         eagerly_reclaim_humongous_regions();
 
-        collection_set()->clear_head();
-
         record_obj_copy_mem_stats();
         _survivor_evac_stats.adjust_desired_plab_sz();
         _old_evac_stats.adjust_desired_plab_sz();
@@ -4704,120 +4600,139 @@
   workers()->run_task(&g1_par_scrub_rs_task);
 }
 
-void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info, const size_t* surviving_young_words) {
-  size_t pre_used = 0;
-  FreeRegionList local_free_list("Local List for CSet Freeing");
-
-  double young_time_ms     = 0.0;
-  double non_young_time_ms = 0.0;
-
-  _eden.clear();
-
-  G1Policy* policy = g1_policy();
-
-  double start_sec = os::elapsedTime();
-  bool non_young = true;
-
-  HeapRegion* cur = cs_head;
-  int age_bound = -1;
-  size_t rs_lengths = 0;
-
-  while (cur != NULL) {
-    assert(!is_on_master_free_list(cur), "sanity");
-    if (non_young) {
-      if (cur->is_young()) {
-        double end_sec = os::elapsedTime();
-        double elapsed_ms = (end_sec - start_sec) * 1000.0;
-        non_young_time_ms += elapsed_ms;
-
-        start_sec = os::elapsedTime();
-        non_young = false;
-      }
+class G1FreeCollectionSetClosure : public HeapRegionClosure {
+private:
+  const size_t* _surviving_young_words;
+
+  FreeRegionList _local_free_list;
+  size_t _rs_lengths;
+  // Bytes used in successfully evacuated regions before the evacuation.
+  size_t _before_used_bytes;
+  // Bytes used in unsucessfully evacuated regions before the evacuation
+  size_t _after_used_bytes;
+
+  size_t _bytes_allocated_in_old_since_last_gc;
+
+  size_t _failure_used_words;
+  size_t _failure_waste_words;
+
+  double _young_time;
+  double _non_young_time;
+public:
+  G1FreeCollectionSetClosure(const size_t* surviving_young_words) :
+    HeapRegionClosure(),
+    _surviving_young_words(surviving_young_words),
+    _local_free_list("Local Region List for CSet Freeing"),
+    _rs_lengths(0),
+    _before_used_bytes(0),
+    _after_used_bytes(0),
+    _bytes_allocated_in_old_since_last_gc(0),
+    _failure_used_words(0),
+    _failure_waste_words(0),
+    _young_time(0.0),
+    _non_young_time(0.0) {
+  }
+
+  virtual bool doHeapRegion(HeapRegion* r) {
+    double start_time = os::elapsedTime();
+
+    bool is_young = r->is_young();
+
+    G1CollectedHeap* g1h = G1CollectedHeap::heap();
+    assert(!g1h->is_on_master_free_list(r), "sanity");
+
+    _rs_lengths += r->rem_set()->occupied_locked();
+
+    assert(r->in_collection_set(), "Region %u should be in collection set.", r->hrm_index());
+    g1h->clear_in_cset(r);
+
+    if (is_young) {
+      int index = r->young_index_in_cset();
+      assert(index != -1, "Young index in collection set must not be -1 for region %u", r->hrm_index());
+      assert((uint) index < g1h->collection_set()->young_region_length(), "invariant");
+      size_t words_survived = _surviving_young_words[index];
+      r->record_surv_words_in_group(words_survived);
     } else {
-      if (!cur->is_young()) {
-        double end_sec = os::elapsedTime();
-        double elapsed_ms = (end_sec - start_sec) * 1000.0;
-        young_time_ms += elapsed_ms;
-
-        start_sec = os::elapsedTime();
-        non_young = true;
-      }
+      assert(r->young_index_in_cset() == -1, "Young index for old region %u in collection set must be -1", r->hrm_index());
     }
 
-    rs_lengths += cur->rem_set()->occupied_locked();
-
-    HeapRegion* next = cur->next_in_collection_set();
-    assert(cur->in_collection_set(), "bad CS");
-    cur->set_next_in_collection_set(NULL);
-    clear_in_cset(cur);
-
-    if (cur->is_young()) {
-      int index = cur->young_index_in_cset();
-      assert(index != -1, "invariant");
-      assert((uint) index < collection_set()->young_region_length(), "invariant");
-      size_t words_survived = surviving_young_words[index];
-      cur->record_surv_words_in_group(words_survived);
-
+    if (!r->evacuation_failed()) {
+      assert(r->not_empty(), "Region %u is an empty region in the collection set.", r->hrm_index());
+      _before_used_bytes += r->used();
+      g1h->free_region(r, &_local_free_list, false /* par */, true /* locked */);
     } else {
-      int index = cur->young_index_in_cset();
-      assert(index == -1, "invariant");
-    }
-
-    assert( (cur->is_young() && cur->young_index_in_cset() > -1) ||
-            (!cur->is_young() && cur->young_index_in_cset() == -1),
-            "invariant" );
-
-    if (!cur->evacuation_failed()) {
-      MemRegion used_mr = cur->used_region();
-
-      // And the region is empty.
-      assert(!used_mr.is_empty(), "Should not have empty regions in a CS.");
-      pre_used += cur->used();
-      free_region(cur, &local_free_list, false /* par */, true /* locked */);
-    } else {
-      cur->uninstall_surv_rate_group();
-      if (cur->is_young()) {
-        cur->set_young_index_in_cset(-1);
-      }
-      cur->set_evacuation_failed(false);
+      r->uninstall_surv_rate_group();
+      r->set_young_index_in_cset(-1);
+      r->set_evacuation_failed(false);
       // When moving a young gen region to old gen, we "allocate" that whole region
       // there. This is in addition to any already evacuated objects. Notify the
       // policy about that.
       // Old gen regions do not cause an additional allocation: both the objects
       // still in the region and the ones already moved are accounted for elsewhere.
-      if (cur->is_young()) {
-        policy->add_bytes_allocated_in_old_since_last_gc(HeapRegion::GrainBytes);
+      if (is_young) {
+        _bytes_allocated_in_old_since_last_gc += HeapRegion::GrainBytes;
       }
       // The region is now considered to be old.
-      cur->set_old();
+      r->set_old();
       // Do some allocation statistics accounting. Regions that failed evacuation
       // are always made old, so there is no need to update anything in the young
       // gen statistics, but we need to update old gen statistics.
-      size_t used_words = cur->marked_bytes() / HeapWordSize;
-      _old_evac_stats.add_failure_used_and_waste(used_words, HeapRegion::GrainWords - used_words);
-      _old_set.add(cur);
-      evacuation_info.increment_collectionset_used_after(cur->used());
+      size_t used_words = r->marked_bytes() / HeapWordSize;
+
+      _failure_used_words += used_words;
+      _failure_waste_words += HeapRegion::GrainWords - used_words;
+
+      g1h->old_set_add(r);
+      _after_used_bytes += r->used();
+    }
+
+    if (is_young) {
+      _young_time += os::elapsedTime() - start_time;
+    } else {
+      _non_young_time += os::elapsedTime() - start_time;
     }
-    cur = next;
+    return false;
   }
 
-  evacuation_info.set_regions_freed(local_free_list.length());
-  policy->record_max_rs_lengths(rs_lengths);
+  FreeRegionList* local_free_list() { return &_local_free_list; }
+  size_t rs_lengths() const { return _rs_lengths; }
+  size_t before_used_bytes() const { return _before_used_bytes; }
+  size_t after_used_bytes() const { return _after_used_bytes; }
+
+  size_t bytes_allocated_in_old_since_last_gc() const { return _bytes_allocated_in_old_since_last_gc; }
+
+  size_t failure_used_words() const { return _failure_used_words; }
+  size_t failure_waste_words() const { return _failure_waste_words; }
+
+  double young_time() const { return _young_time; }
+  double non_young_time() const { return _non_young_time; }
+};
+
+void G1CollectedHeap::free_collection_set(G1CollectionSet* collection_set, EvacuationInfo& evacuation_info, const size_t* surviving_young_words) {
+  _eden.clear();
+
+  G1FreeCollectionSetClosure cl(surviving_young_words);
+  collection_set_iterate(&cl);
+
+  evacuation_info.set_regions_freed(cl.local_free_list()->length());
+  evacuation_info.increment_collectionset_used_after(cl.after_used_bytes());
+
+  G1Policy* policy = g1_policy();
+
+  policy->record_max_rs_lengths(cl.rs_lengths());
   policy->cset_regions_freed();
 
-  double end_sec = os::elapsedTime();
-  double elapsed_ms = (end_sec - start_sec) * 1000.0;
-
-  if (non_young) {
-    non_young_time_ms += elapsed_ms;
-  } else {
-    young_time_ms += elapsed_ms;
-  }
-
-  prepend_to_freelist(&local_free_list);
-  decrement_summary_bytes(pre_used);
-  policy->phase_times()->record_young_free_cset_time_ms(young_time_ms);
-  policy->phase_times()->record_non_young_free_cset_time_ms(non_young_time_ms);
+  prepend_to_freelist(cl.local_free_list());
+  decrement_summary_bytes(cl.before_used_bytes());
+
+  policy->add_bytes_allocated_in_old_since_last_gc(cl.bytes_allocated_in_old_since_last_gc());
+
+  _old_evac_stats.add_failure_used_and_waste(cl.failure_used_words(), cl.failure_waste_words());
+
+  policy->phase_times()->record_young_free_cset_time_ms(cl.young_time() * 1000.0);
+  policy->phase_times()->record_non_young_free_cset_time_ms(cl.non_young_time() * 1000.0);
+
+  collection_set->clear();
 }
 
 class G1FreeHumongousRegionClosure : public HeapRegionClosure {
@@ -4960,25 +4875,22 @@
                                                                     cl.humongous_free_count());
 }
 
-// This routine is similar to the above but does not record
-// any policy statistics or update free lists; we are abandoning
-// the current incremental collection set in preparation of a
-// full collection. After the full GC we will start to build up
-// the incremental collection set again.
-// This is only called when we're doing a full collection
-// and is immediately followed by the tearing down of the young list.
-
-void G1CollectedHeap::abandon_collection_set(HeapRegion* cs_head) {
-  HeapRegion* cur = cs_head;
-
-  while (cur != NULL) {
-    HeapRegion* next = cur->next_in_collection_set();
-    assert(cur->in_collection_set(), "bad CS");
-    cur->set_next_in_collection_set(NULL);
-    clear_in_cset(cur);
-    cur->set_young_index_in_cset(-1);
-    cur = next;
+class G1AbandonCollectionSetClosure : public HeapRegionClosure {
+public:
+  virtual bool doHeapRegion(HeapRegion* r) {
+    assert(r->in_collection_set(), "Region %u must have been in collection set", r->hrm_index());
+    G1CollectedHeap::heap()->clear_in_cset(r);
+    r->set_young_index_in_cset(-1);
+    return false;
   }
+};
+
+void G1CollectedHeap::abandon_collection_set(G1CollectionSet* collection_set) {
+  G1AbandonCollectionSetClosure cl;
+  collection_set->iterate(&cl);
+
+  collection_set->clear();
+  collection_set->stop_incremental_building();
 }
 
 void G1CollectedHeap::set_free_regions_coming() {
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -778,13 +778,13 @@
   // The closure used to refine a single card.
   RefineCardTableEntryClosure* _refine_cte_cl;
 
-  // After a collection pause, make the regions in the CS into free
+  // After a collection pause, convert the regions in the collection set into free
   // regions.
-  void free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info, const size_t* surviving_young_words);
+  void free_collection_set(G1CollectionSet* collection_set, EvacuationInfo& evacuation_info, const size_t* surviving_young_words);
 
   // Abandon the current collection set without recording policy
   // statistics or updating free lists.
-  void abandon_collection_set(HeapRegion* cs_head);
+  void abandon_collection_set(G1CollectionSet* collection_set);
 
   // The concurrent marker (and the thread it runs in.)
   G1ConcurrentMark* _cm;
@@ -930,16 +930,6 @@
   // discovery.
   G1CMIsAliveClosure _is_alive_closure_cm;
 
-  // Cache used by G1CollectedHeap::start_cset_region_for_worker().
-  HeapRegion** _worker_cset_start_region;
-
-  // Time stamp to validate the regions recorded in the cache
-  // used by G1CollectedHeap::start_cset_region_for_worker().
-  // The heap region entry for a given worker is valid iff
-  // the associated time stamp value matches the current value
-  // of G1CollectedHeap::_gc_time_stamp.
-  uint* _worker_cset_start_region_time_stamp;
-
   volatile bool _free_regions_coming;
 
 public:
@@ -1211,19 +1201,14 @@
                                HeapRegionClaimer* hrclaimer,
                                bool concurrent = false) const;
 
-  // Clear the cached cset start regions and (more importantly)
-  // the time stamps. Called when we reset the GC time stamp.
-  void clear_cset_start_regions();
-
-  // Given the id of a worker, obtain or calculate a suitable
-  // starting region for iterating over the current collection set.
-  HeapRegion* start_cset_region_for_worker(uint worker_i);
-
   // Iterate over the regions (if any) in the current collection set.
   void collection_set_iterate(HeapRegionClosure* blk);
 
-  // As above but starting from region r
-  void collection_set_iterate_from(HeapRegion* r, HeapRegionClosure *blk);
+  // Iterate over the regions (if any) in the current collection set. Starts the
+  // iteration over the entire collection set so that the start regions of a given
+  // worker id over the set active_workers are evenly spread across the set of
+  // collection set regions.
+  void collection_set_iterate_from(HeapRegionClosure *blk, uint worker_id);
 
   HeapRegion* next_compaction_region(const HeapRegion* from) const;
 
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -89,16 +89,13 @@
 }
 
 inline void G1CollectedHeap::reset_gc_time_stamp() {
+  assert_at_safepoint(true);
   _gc_time_stamp = 0;
-  OrderAccess::fence();
-  // Clear the cached CSet starting regions and time stamps.
-  // Their validity is dependent on the GC timestamp.
-  clear_cset_start_regions();
 }
 
 inline void G1CollectedHeap::increment_gc_time_stamp() {
+  assert_at_safepoint(true);
   ++_gc_time_stamp;
-  OrderAccess::fence();
 }
 
 inline void G1CollectedHeap::old_set_add(HeapRegion* hr) {
--- a/hotspot/src/share/vm/gc/g1/g1CollectionSet.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1CollectionSet.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -30,6 +30,7 @@
 #include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/g1/heapRegionSet.hpp"
+#include "logging/logStream.hpp"
 #include "utilities/debug.hpp"
 
 G1CollectorState* G1CollectionSet::collector_state() {
@@ -55,48 +56,63 @@
   _eden_region_length(0),
   _survivor_region_length(0),
   _old_region_length(0),
-
-  _head(NULL),
   _bytes_used_before(0),
   _recorded_rs_lengths(0),
+  _collection_set_regions(NULL),
+  _collection_set_cur_length(0),
+  _collection_set_max_length(0),
   // Incremental CSet attributes
   _inc_build_state(Inactive),
-  _inc_head(NULL),
-  _inc_tail(NULL),
   _inc_bytes_used_before(0),
   _inc_recorded_rs_lengths(0),
   _inc_recorded_rs_lengths_diffs(0),
   _inc_predicted_elapsed_time_ms(0.0),
-  _inc_predicted_elapsed_time_ms_diffs(0.0),
-  _inc_region_length(0) {}
+  _inc_predicted_elapsed_time_ms_diffs(0.0) {
+}
 
 G1CollectionSet::~G1CollectionSet() {
+  if (_collection_set_regions != NULL) {
+    FREE_C_HEAP_ARRAY(uint, _collection_set_regions);
+  }
   delete _cset_chooser;
 }
 
 void G1CollectionSet::init_region_lengths(uint eden_cset_region_length,
                                           uint survivor_cset_region_length) {
+  assert_at_safepoint(true);
+
   _eden_region_length     = eden_cset_region_length;
   _survivor_region_length = survivor_cset_region_length;
 
-  assert(young_region_length() == _inc_region_length, "should match %u == %u", young_region_length(), _inc_region_length);
+  assert((size_t) young_region_length() == _collection_set_cur_length,
+         "Young region length %u should match collection set length " SIZE_FORMAT, young_region_length(), _collection_set_cur_length);
 
   _old_region_length      = 0;
 }
 
+void G1CollectionSet::initialize(uint max_region_length) {
+  guarantee(_collection_set_regions == NULL, "Must only initialize once.");
+  _collection_set_max_length = max_region_length;
+  _collection_set_regions = NEW_C_HEAP_ARRAY(uint, max_region_length, mtGC);
+}
+
 void G1CollectionSet::set_recorded_rs_lengths(size_t rs_lengths) {
   _recorded_rs_lengths = rs_lengths;
 }
 
 // Add the heap region at the head of the non-incremental collection set
 void G1CollectionSet::add_old_region(HeapRegion* hr) {
+  assert_at_safepoint(true);
+
   assert(_inc_build_state == Active, "Precondition");
   assert(hr->is_old(), "the region should be old");
 
   assert(!hr->in_collection_set(), "should not already be in the CSet");
   _g1->register_old_region_with_cset(hr);
-  hr->set_next_in_collection_set(_head);
-  _head = hr;
+
+  _collection_set_regions[_collection_set_cur_length++] = hr->hrm_index();
+  assert(_collection_set_cur_length <= _collection_set_max_length, "Collection set now larger than maximum size.");
+
   _bytes_used_before += hr->used();
   size_t rs_length = hr->rem_set()->occupied();
   _recorded_rs_lengths += rs_length;
@@ -105,12 +121,10 @@
 
 // Initialize the per-collection-set information
 void G1CollectionSet::start_incremental_building() {
+  assert(_collection_set_cur_length == 0, "Collection set must be empty before starting a new collection set.");
   assert(_inc_build_state == Inactive, "Precondition");
 
-  _inc_head = NULL;
-  _inc_tail = NULL;
   _inc_bytes_used_before = 0;
-  _inc_region_length = 0;
 
   _inc_recorded_rs_lengths = 0;
   _inc_recorded_rs_lengths_diffs = 0;
@@ -151,6 +165,38 @@
   _inc_predicted_elapsed_time_ms_diffs = 0.0;
 }
 
+void G1CollectionSet::clear() {
+  assert_at_safepoint(true);
+  _collection_set_cur_length = 0;
+}
+
+void G1CollectionSet::iterate(HeapRegionClosure* cl) const {
+  iterate_from(cl, 0, 1);
+}
+
+void G1CollectionSet::iterate_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const {
+  size_t len = _collection_set_cur_length;
+  OrderAccess::loadload();
+  if (len == 0) {
+    return;
+  }
+  size_t start_pos = (worker_id * len) / total_workers;
+  size_t cur_pos = start_pos;
+
+  do {
+    HeapRegion* r = G1CollectedHeap::heap()->region_at(_collection_set_regions[cur_pos]);
+    bool result = cl->doHeapRegion(r);
+    if (result) {
+      cl->incomplete();
+      return;
+    }
+    cur_pos++;
+    if (cur_pos == len) {
+      cur_pos = 0;
+    }
+  } while (cur_pos != start_pos);
+}
+
 void G1CollectionSet::update_young_region_prediction(HeapRegion* hr,
                                                      size_t new_rs_length) {
   // Update the CSet information that is dependent on the new RS length
@@ -183,8 +229,16 @@
   assert(hr->is_young(), "invariant");
   assert(_inc_build_state == Active, "Precondition");
 
-  hr->set_young_index_in_cset(_inc_region_length);
-  _inc_region_length++;
+  size_t collection_set_length = _collection_set_cur_length;
+  assert(collection_set_length <= INT_MAX, "Collection set is too large with %d entries", (int)collection_set_length);
+  hr->set_young_index_in_cset((int)collection_set_length);
+
+  _collection_set_regions[collection_set_length] = hr->hrm_index();
+  // Concurrent readers must observe the store of the value in the array before an
+  // update to the length field.
+  OrderAccess::storestore();
+  _collection_set_cur_length++;
+  assert(_collection_set_cur_length <= _collection_set_max_length, "Collection set larger than maximum allowed.");
 
   // This routine is used when:
   // * adding survivor regions to the incremental cset at the end of an
@@ -218,59 +272,81 @@
 
   assert(!hr->in_collection_set(), "invariant");
   _g1->register_young_region_with_cset(hr);
-  assert(hr->next_in_collection_set() == NULL, "invariant");
 }
 
-// Add the region at the RHS of the incremental cset
 void G1CollectionSet::add_survivor_regions(HeapRegion* hr) {
-  // We should only ever be appending survivors at the end of a pause
-  assert(hr->is_survivor(), "Logic");
-
-  // Do the 'common' stuff
+  assert(hr->is_survivor(), "Must only add survivor regions, but is %s", hr->get_type_str());
   add_young_region_common(hr);
-
-  // Now add the region at the right hand side
-  if (_inc_tail == NULL) {
-    assert(_inc_head == NULL, "invariant");
-    _inc_head = hr;
-  } else {
-    _inc_tail->set_next_in_collection_set(hr);
-  }
-  _inc_tail = hr;
 }
 
-// Add the region to the LHS of the incremental cset
 void G1CollectionSet::add_eden_region(HeapRegion* hr) {
-  // Survivors should be added to the RHS at the end of a pause
-  assert(hr->is_eden(), "Logic");
-
-  // Do the 'common' stuff
+  assert(hr->is_eden(), "Must only add eden regions, but is %s", hr->get_type_str());
   add_young_region_common(hr);
-
-  // Add the region at the left hand side
-  hr->set_next_in_collection_set(_inc_head);
-  if (_inc_head == NULL) {
-    assert(_inc_tail == NULL, "Invariant");
-    _inc_tail = hr;
-  }
-  _inc_head = hr;
 }
 
 #ifndef PRODUCT
-void G1CollectionSet::print(HeapRegion* list_head, outputStream* st) {
-  assert(list_head == inc_head() || list_head == head(), "must be");
+class G1VerifyYoungAgesClosure : public HeapRegionClosure {
+public:
+  bool _valid;
+public:
+  G1VerifyYoungAgesClosure() : HeapRegionClosure(), _valid(true) { }
+
+  virtual bool doHeapRegion(HeapRegion* r) {
+    guarantee(r->is_young(), "Region must be young but is %s", r->get_type_str());
+
+    SurvRateGroup* group = r->surv_rate_group();
+
+    if (group == NULL) {
+      log_error(gc, verify)("## encountered NULL surv_rate_group in young region");
+      _valid = false;
+    }
+
+    if (r->age_in_surv_rate_group() < 0) {
+      log_error(gc, verify)("## encountered negative age in young region");
+      _valid = false;
+    }
+
+    return false;
+  }
+
+  bool valid() const { return _valid; }
+};
 
+bool G1CollectionSet::verify_young_ages() {
+  assert_at_safepoint(true);
+
+  G1VerifyYoungAgesClosure cl;
+  iterate(&cl);
+
+  if (!cl.valid()) {
+    LogStreamHandle(Error, gc, verify) log;
+    print(&log);
+  }
+
+  return cl.valid();
+}
+
+class G1PrintCollectionSetClosure : public HeapRegionClosure {
+  outputStream* _st;
+public:
+  G1PrintCollectionSetClosure(outputStream* st) : HeapRegionClosure(), _st(st) { }
+
+  virtual bool doHeapRegion(HeapRegion* r) {
+    assert(r->in_collection_set(), "Region %u should be in collection set", r->hrm_index());
+    _st->print_cr("  " HR_FORMAT ", P: " PTR_FORMAT "N: " PTR_FORMAT ", age: %4d",
+                  HR_FORMAT_PARAMS(r),
+                  p2i(r->prev_top_at_mark_start()),
+                  p2i(r->next_top_at_mark_start()),
+                  r->age_in_surv_rate_group_cond());
+    return false;
+  }
+};
+
+void G1CollectionSet::print(outputStream* st) {
   st->print_cr("\nCollection_set:");
-  HeapRegion* csr = list_head;
-  while (csr != NULL) {
-    HeapRegion* next = csr->next_in_collection_set();
-    assert(csr->in_collection_set(), "bad CS");
-    st->print_cr("  " HR_FORMAT ", P: " PTR_FORMAT "N: " PTR_FORMAT ", age: %4d",
-                 HR_FORMAT_PARAMS(csr),
-                 p2i(csr->prev_top_at_mark_start()), p2i(csr->next_top_at_mark_start()),
-                 csr->age_in_surv_rate_group_cond());
-    csr = next;
-  }
+
+  G1PrintCollectionSetClosure cl(st);
+  iterate(&cl);
 }
 #endif // !PRODUCT
 
@@ -281,7 +357,6 @@
 
   guarantee(target_pause_time_ms > 0.0,
             "target_pause_time_ms = %1.6lf should be positive", target_pause_time_ms);
-  guarantee(_head == NULL, "Precondition");
 
   size_t pending_cards = _policy->pending_cards();
   double base_time_ms = _policy->predict_base_elapsed_time_ms(pending_cards);
@@ -305,7 +380,6 @@
   // Clear the fields that point to the survivor list - they are all young now.
   survivors->convert_to_eden();
 
-  _head = _inc_head;
   _bytes_used_before = _inc_bytes_used_before;
   time_remaining_ms = MAX2(time_remaining_ms - _inc_predicted_elapsed_time_ms, 0.0);
 
@@ -422,23 +496,41 @@
 }
 
 #ifdef ASSERT
-void G1CollectionSet::verify_young_cset_indices() const {
-  ResourceMark rm;
-  uint* heap_region_indices = NEW_RESOURCE_ARRAY(uint, young_region_length());
-  for (uint i = 0; i < young_region_length(); ++i) {
-    heap_region_indices[i] = (uint)-1;
+class G1VerifyYoungCSetIndicesClosure : public HeapRegionClosure {
+private:
+  size_t _young_length;
+  int* _heap_region_indices;
+public:
+  G1VerifyYoungCSetIndicesClosure(size_t young_length) : HeapRegionClosure(), _young_length(young_length) {
+    _heap_region_indices = NEW_C_HEAP_ARRAY(int, young_length, mtGC);
+    for (size_t i = 0; i < young_length; i++) {
+      _heap_region_indices[i] = -1;
+    }
+  }
+  ~G1VerifyYoungCSetIndicesClosure() {
+    FREE_C_HEAP_ARRAY(int, _heap_region_indices);
   }
 
-  for (HeapRegion* hr = _inc_head; hr != NULL; hr = hr->next_in_collection_set()) {
-    const int idx = hr->young_index_in_cset();
-    assert(idx > -1, "must be set for all inc cset regions");
-    assert((uint)idx < young_region_length(), "young cset index too large");
+  virtual bool doHeapRegion(HeapRegion* r) {
+    const int idx = r->young_index_in_cset();
+
+    assert(idx > -1, "Young index must be set for all regions in the incremental collection set but is not for region %u.", r->hrm_index());
+    assert((size_t)idx < _young_length, "Young cset index too large for region %u", r->hrm_index());
+
+    assert(_heap_region_indices[idx] == -1,
+           "Index %d used by multiple regions, first use by region %u, second by region %u",
+           idx, _heap_region_indices[idx], r->hrm_index());
 
-    assert(heap_region_indices[idx] == (uint)-1,
-           "index %d used by multiple regions, first use by %u, second by %u",
-           idx, heap_region_indices[idx], hr->hrm_index());
+    _heap_region_indices[idx] = r->hrm_index();
+
+    return false;
+  }
+};
 
-    heap_region_indices[idx] = hr->hrm_index();
-  }
+void G1CollectionSet::verify_young_cset_indices() const {
+  assert_at_safepoint(true);
+
+  G1VerifyYoungCSetIndicesClosure cl(_collection_set_cur_length);
+  iterate(&cl);
 }
 #endif
--- a/hotspot/src/share/vm/gc/g1/g1CollectionSet.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1CollectionSet.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -47,10 +47,15 @@
   uint _survivor_region_length;
   uint _old_region_length;
 
-  // The head of the list (via "next_in_collection_set()") representing the
-  // current collection set. Set from the incrementally built collection
-  // set at the start of the pause.
-  HeapRegion* _head;
+  // The actual collection set as a set of region indices.
+  // All entries in _collection_set_regions below _collection_set_cur_length are
+  // assumed to be valid entries.
+  // We assume that at any time there is at most only one writer and (one or more)
+  // concurrent readers. This means we are good with using storestore and loadload
+  // barriers on the writer and reader respectively only.
+  uint* _collection_set_regions;
+  volatile size_t _collection_set_cur_length;
+  size_t _collection_set_max_length;
 
   // The number of bytes in the collection set before the pause. Set from
   // the incrementally built collection set at the start of an evacuation
@@ -71,12 +76,6 @@
 
   CSetBuildType _inc_build_state;
 
-  // The head of the incrementally built collection set.
-  HeapRegion* _inc_head;
-
-  // The tail of the incrementally built collection set.
-  HeapRegion* _inc_tail;
-
   // The number of bytes in the incrementally built collection set.
   // Used to set _collection_set_bytes_used_before at the start of
   // an evacuation pause.
@@ -105,8 +104,6 @@
   // See the comment for _inc_recorded_rs_lengths_diffs.
   double _inc_predicted_elapsed_time_ms_diffs;
 
-  uint _inc_region_length;
-
   G1CollectorState* collector_state();
   G1GCPhaseTimes* phase_times();
 
@@ -117,6 +114,9 @@
   G1CollectionSet(G1CollectedHeap* g1h, G1Policy* policy);
   ~G1CollectionSet();
 
+  // Initializes the collection set giving the maximum possible length of the collection set.
+  void initialize(uint max_region_length);
+
   CollectionSetChooser* cset_chooser();
 
   void init_region_lengths(uint eden_cset_region_length,
@@ -133,35 +133,30 @@
   uint survivor_region_length() const { return _survivor_region_length; }
   uint old_region_length() const      { return _old_region_length;      }
 
-  // Incremental CSet Support
-
-  // The head of the incrementally built collection set.
-  HeapRegion* inc_head() { return _inc_head; }
-
-  // The tail of the incrementally built collection set.
-  HeapRegion* inc_tail() { return _inc_tail; }
+  // Incremental collection set support
 
   // Initialize incremental collection set info.
   void start_incremental_building();
 
-  // Perform any final calculations on the incremental CSet fields
+  // Perform any final calculations on the incremental collection set fields
   // before we can use them.
   void finalize_incremental_building();
 
-  void clear_incremental() {
-    _inc_head = NULL;
-    _inc_tail = NULL;
-    _inc_region_length = 0;
-  }
+  // Reset the contents of the collection set.
+  void clear();
+
+  // Iterate over the collection set, applying the given HeapRegionClosure on all of them.
+  // If may_be_aborted is true, iteration may be aborted using the return value of the
+  // called closure method.
+  void iterate(HeapRegionClosure* cl) const;
 
-  // Stop adding regions to the incremental collection set
-  void stop_incremental_building() { _inc_build_state = Inactive; }
+  // Iterate over the collection set, applying the given HeapRegionClosure on all of them,
+  // trying to optimally spread out starting position of total_workers workers given the
+  // caller's worker_id.
+  void iterate_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const;
 
-  // The head of the list (via "next_in_collection_set()") representing the
-  // current collection set.
-  HeapRegion* head() { return _head; }
-
-  void clear_head() { _head = NULL; }
+  // Stop adding regions to the incremental collection set.
+  void stop_incremental_building() { _inc_build_state = Inactive; }
 
   size_t recorded_rs_lengths() { return _recorded_rs_lengths; }
 
@@ -174,33 +169,32 @@
   }
 
   // Choose a new collection set.  Marks the chosen regions as being
-  // "in_collection_set", and links them together.  The head and number of
-  // the collection set are available via access methods.
+  // "in_collection_set".
   double finalize_young_part(double target_pause_time_ms, G1SurvivorRegions* survivors);
   void finalize_old_part(double time_remaining_ms);
 
-  // Add old region "hr" to the CSet.
+  // Add old region "hr" to the collection set.
   void add_old_region(HeapRegion* hr);
 
   // Update information about hr in the aggregated information for
   // the incrementally built collection set.
   void update_young_region_prediction(HeapRegion* hr, size_t new_rs_length);
 
-  // Add hr to the LHS of the incremental collection set.
+  // Add eden region to the collection set.
   void add_eden_region(HeapRegion* hr);
 
-  // Add hr to the RHS of the incremental collection set.
+  // Add survivor region to the collection set.
   void add_survivor_regions(HeapRegion* hr);
 
 #ifndef PRODUCT
-  void print(HeapRegion* list_head, outputStream* st);
+  bool verify_young_ages();
+
+  void print(outputStream* st);
 #endif // !PRODUCT
 
 private:
-  // Update the incremental cset information when adding a region
-  // (should not be called directly).
+  // Update the incremental collection set information when adding a region.
   void add_young_region_common(HeapRegion* hr);
-
 };
 
 #endif // SHARE_VM_GC_G1_G1COLLECTIONSET_HPP
--- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -394,37 +394,6 @@
   }
 }
 
-#ifndef PRODUCT
-bool G1DefaultPolicy::verify_young_ages() {
-  bool ret = true;
-
-  for (HeapRegion* curr = _collection_set->inc_head();
-       curr != NULL;
-       curr = curr->next_in_collection_set()) {
-    guarantee(curr->is_young(), "Region must be young");
-
-    SurvRateGroup* group = curr->surv_rate_group();
-
-    if (group == NULL) {
-      log_error(gc, verify)("## encountered NULL surv_rate_group in young region");
-      ret = false;
-    }
-
-    if (curr->age_in_surv_rate_group() < 0) {
-      log_error(gc, verify)("## encountered negative age in young region");
-      ret = false;
-    }
-  }
-
-  if (!ret) {
-    LogStreamHandle(Error, gc, verify) log;
-    _collection_set->print(_collection_set->inc_head(), &log);
-  }
-
-  return ret;
-}
-#endif // PRODUCT
-
 void G1DefaultPolicy::record_full_collection_start() {
   _full_collection_start_sec = os::elapsedTime();
   // Release the future to-space so that it is available for compaction into.
@@ -488,7 +457,7 @@
   _short_lived_surv_rate_group->stop_adding_regions();
   _survivors_age_table.clear();
 
-  assert( verify_young_ages(), "region age verification" );
+  assert(_g1->collection_set()->verify_young_ages(), "region age verification failed");
 }
 
 void G1DefaultPolicy::record_concurrent_mark_init_end(double mark_init_elapsed_time_ms) {
--- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -89,10 +89,6 @@
 
   size_t _rs_lengths_prediction;
 
-#ifndef PRODUCT
-  bool verify_young_ages(HeapRegion* head, SurvRateGroup *surv_rate_group);
-#endif // PRODUCT
-
   size_t _pending_cards;
 
   // The amount of allocated bytes in old gen during the last mutator and the following
@@ -116,10 +112,6 @@
     hr->install_surv_rate_group(_survivor_surv_rate_group);
   }
 
-#ifndef PRODUCT
-  bool verify_young_ages();
-#endif // PRODUCT
-
   void record_max_rs_lengths(size_t rs_lengths) {
     _max_rs_lengths = rs_lengths;
   }
--- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -251,6 +251,5 @@
 void G1ParRemoveSelfForwardPtrsTask::work(uint worker_id) {
   RemoveSelfForwardPtrHRClosure rsfp_cl(worker_id, &_hrclaimer);
 
-  HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id);
-  _g1h->collection_set_iterate_from(hr, &rsfp_cl);
+  _g1h->collection_set_iterate_from(&rsfp_cl, worker_id);
 }
--- a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -580,15 +580,20 @@
   }
 }
 
-void G1HeapVerifier::verify_dirty_young_list(HeapRegion* head) {
-  G1SATBCardTableModRefBS* ct_bs = _g1h->g1_barrier_set();
-  for (HeapRegion* hr = head; hr != NULL; hr = hr->next_in_collection_set()) {
-    verify_dirty_region(hr);
+class G1VerifyDirtyYoungListClosure : public HeapRegionClosure {
+private:
+  G1HeapVerifier* _verifier;
+public:
+  G1VerifyDirtyYoungListClosure(G1HeapVerifier* verifier) : HeapRegionClosure(), _verifier(verifier) { }
+  virtual bool doHeapRegion(HeapRegion* r) {
+    _verifier->verify_dirty_region(r);
+    return false;
   }
-}
+};
 
 void G1HeapVerifier::verify_dirty_young_regions() {
-  verify_dirty_young_list(_g1h->collection_set()->inc_head());
+  G1VerifyDirtyYoungListClosure cl(this);
+  _g1h->collection_set()->iterate(&cl);
 }
 
 bool G1HeapVerifier::verify_no_bits_over_tams(const char* bitmap_name, G1CMBitMapRO* bitmap,
--- a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -108,7 +108,6 @@
 
   void verify_not_dirty_region(HeapRegion* hr) PRODUCT_RETURN;
   void verify_dirty_region(HeapRegion* hr) PRODUCT_RETURN;
-  void verify_dirty_young_list(HeapRegion* head) PRODUCT_RETURN;
   void verify_dirty_young_regions() PRODUCT_RETURN;
 };
 
--- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -382,10 +382,8 @@
                               uint worker_i) {
   double rs_time_start = os::elapsedTime();
 
-  HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
-
   G1ScanRSClosure cl(_scan_state, oops_in_heap_closure, heap_region_codeblobs, worker_i);
-  _g1->collection_set_iterate_from(startRegion, &cl);
+  _g1->collection_set_iterate_from(&cl, worker_i);
 
    double scan_rs_time_sec = (os::elapsedTime() - rs_time_start) -
                               cl.strong_code_root_scan_time_sec();
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupQueue.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupQueue.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -154,8 +154,8 @@
 }
 
 void G1StringDedupQueue::print_statistics() {
-  log_debug(gc, stringdedup)("   [Queue]");
-  log_debug(gc, stringdedup)("      [Dropped: " UINTX_FORMAT "]", _queue->_dropped);
+  log_debug(gc, stringdedup)("  Queue");
+  log_debug(gc, stringdedup)("    Dropped: " UINTX_FORMAT, _queue->_dropped);
 }
 
 void G1StringDedupQueue::verify() {
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupStat.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupStat.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -42,7 +42,9 @@
   _idle(0),
   _exec(0),
   _block(0),
-  _start(0.0),
+  _start_concurrent(0.0),
+  _end_concurrent(0.0),
+  _start_phase(0.0),
   _idle_elapsed(0.0),
   _exec_elapsed(0.0),
   _block_elapsed(0.0) {
@@ -69,7 +71,13 @@
   _block_elapsed       += stat._block_elapsed;
 }
 
-void G1StringDedupStat::print_summary(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
+void G1StringDedupStat::print_start(const G1StringDedupStat& last_stat) {
+  log_info(gc, stringdedup)(
+     "Concurrent String Deduplication (" G1_STRDEDUP_TIME_FORMAT ")",
+     G1_STRDEDUP_TIME_PARAM(last_stat._start_concurrent));
+}
+
+void G1StringDedupStat::print_end(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
   double total_deduped_bytes_percent = 0.0;
 
   if (total_stat._new_bytes > 0) {
@@ -79,13 +87,16 @@
 
   log_info(gc, stringdedup)(
     "Concurrent String Deduplication "
-    G1_STRDEDUP_BYTES_FORMAT_NS "->" G1_STRDEDUP_BYTES_FORMAT_NS "(" G1_STRDEDUP_BYTES_FORMAT_NS "), avg "
-    G1_STRDEDUP_PERCENT_FORMAT_NS ", " G1_STRDEDUP_TIME_FORMAT,
+    G1_STRDEDUP_BYTES_FORMAT_NS "->" G1_STRDEDUP_BYTES_FORMAT_NS "(" G1_STRDEDUP_BYTES_FORMAT_NS ") "
+    "avg " G1_STRDEDUP_PERCENT_FORMAT_NS " "
+    "(" G1_STRDEDUP_TIME_FORMAT ", " G1_STRDEDUP_TIME_FORMAT ") " G1_STRDEDUP_TIME_FORMAT_MS,
     G1_STRDEDUP_BYTES_PARAM(last_stat._new_bytes),
     G1_STRDEDUP_BYTES_PARAM(last_stat._new_bytes - last_stat._deduped_bytes),
     G1_STRDEDUP_BYTES_PARAM(last_stat._deduped_bytes),
     total_deduped_bytes_percent,
-    last_stat._exec_elapsed);
+    G1_STRDEDUP_TIME_PARAM(last_stat._start_concurrent),
+    G1_STRDEDUP_TIME_PARAM(last_stat._end_concurrent),
+    G1_STRDEDUP_TIME_PARAM_MS(last_stat._exec_elapsed));
 }
 
 void G1StringDedupStat::print_statistics(const G1StringDedupStat& stat, bool total) {
@@ -134,23 +145,31 @@
 
   if (total) {
     log_debug(gc, stringdedup)(
-      "   [Total Exec: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT ", Idle: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT ", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT "]",
-      stat._exec, stat._exec_elapsed, stat._idle, stat._idle_elapsed, stat._block, stat._block_elapsed);
+      "  Total Exec: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT_MS
+      ", Idle: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT_MS
+      ", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT_MS,
+      stat._exec, G1_STRDEDUP_TIME_PARAM_MS(stat._exec_elapsed),
+      stat._idle, G1_STRDEDUP_TIME_PARAM_MS(stat._idle_elapsed),
+      stat._block, G1_STRDEDUP_TIME_PARAM_MS(stat._block_elapsed));
   } else {
     log_debug(gc, stringdedup)(
-      "   [Last Exec: " G1_STRDEDUP_TIME_FORMAT ", Idle: " G1_STRDEDUP_TIME_FORMAT ", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT "]",
-      stat._exec_elapsed, stat._idle_elapsed, stat._block, stat._block_elapsed);
+      "  Last Exec: " G1_STRDEDUP_TIME_FORMAT_MS
+      ", Idle: " G1_STRDEDUP_TIME_FORMAT_MS
+      ", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT_MS,
+      G1_STRDEDUP_TIME_PARAM_MS(stat._exec_elapsed),
+      G1_STRDEDUP_TIME_PARAM_MS(stat._idle_elapsed),
+      stat._block, G1_STRDEDUP_TIME_PARAM_MS(stat._block_elapsed));
   }
-  log_debug(gc, stringdedup)("      [Inspected:    " G1_STRDEDUP_OBJECTS_FORMAT "]", stat._inspected);
-  log_debug(gc, stringdedup)("         [Skipped:   " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]", stat._skipped, skipped_percent);
-  log_debug(gc, stringdedup)("         [Hashed:    " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]", stat._hashed, hashed_percent);
-  log_debug(gc, stringdedup)("         [Known:     " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]", stat._known, known_percent);
-  log_debug(gc, stringdedup)("         [New:       " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "]",
+  log_debug(gc, stringdedup)("    Inspected:    " G1_STRDEDUP_OBJECTS_FORMAT, stat._inspected);
+  log_debug(gc, stringdedup)("      Skipped:    " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")", stat._skipped, skipped_percent);
+  log_debug(gc, stringdedup)("      Hashed:     " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")", stat._hashed, hashed_percent);
+  log_debug(gc, stringdedup)("      Known:      " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")", stat._known, known_percent);
+  log_debug(gc, stringdedup)("      New:        " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT,
                              stat._new, new_percent, G1_STRDEDUP_BYTES_PARAM(stat._new_bytes));
-  log_debug(gc, stringdedup)("      [Deduplicated: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]",
+  log_debug(gc, stringdedup)("    Deduplicated: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")",
                              stat._deduped, deduped_percent, G1_STRDEDUP_BYTES_PARAM(stat._deduped_bytes), deduped_bytes_percent);
-  log_debug(gc, stringdedup)("         [Young:     " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]",
+  log_debug(gc, stringdedup)("      Young:      " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")",
                              stat._deduped_young, deduped_young_percent, G1_STRDEDUP_BYTES_PARAM(stat._deduped_young_bytes), deduped_young_bytes_percent);
-  log_debug(gc, stringdedup)("         [Old:       " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]",
+  log_debug(gc, stringdedup)("      Old:        " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")",
                              stat._deduped_old, deduped_old_percent, G1_STRDEDUP_BYTES_PARAM(stat._deduped_old_bytes), deduped_old_bytes_percent);
 }
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupStat.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupStat.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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,11 +30,14 @@
 
 // Macros for GC log output formating
 #define G1_STRDEDUP_OBJECTS_FORMAT         UINTX_FORMAT_W(12)
-#define G1_STRDEDUP_TIME_FORMAT            "%1.7lf secs"
-#define G1_STRDEDUP_PERCENT_FORMAT         "%5.1lf%%"
-#define G1_STRDEDUP_PERCENT_FORMAT_NS      "%.1lf%%"
-#define G1_STRDEDUP_BYTES_FORMAT           "%8.1lf%s"
-#define G1_STRDEDUP_BYTES_FORMAT_NS        "%.1lf%s"
+#define G1_STRDEDUP_TIME_FORMAT            "%.3fs"
+#define G1_STRDEDUP_TIME_PARAM(time)       (time)
+#define G1_STRDEDUP_TIME_FORMAT_MS         "%.3fms"
+#define G1_STRDEDUP_TIME_PARAM_MS(time)    ((time) * MILLIUNITS)
+#define G1_STRDEDUP_PERCENT_FORMAT         "%5.1f%%"
+#define G1_STRDEDUP_PERCENT_FORMAT_NS      "%.1f%%"
+#define G1_STRDEDUP_BYTES_FORMAT           "%8.1f%s"
+#define G1_STRDEDUP_BYTES_FORMAT_NS        "%.1f%s"
 #define G1_STRDEDUP_BYTES_PARAM(bytes)     byte_size_in_proper_unit((double)(bytes)), proper_unit_for_byte_size((bytes))
 
 //
@@ -60,7 +63,9 @@
   uintx  _block;
 
   // Time spent by the deduplication thread in different phases
-  double _start;
+  double _start_concurrent;
+  double _end_concurrent;
+  double _start_phase;
   double _idle_elapsed;
   double _exec_elapsed;
   double _block_elapsed;
@@ -104,38 +109,41 @@
   }
 
   void mark_idle() {
-    _start = os::elapsedTime();
+    _start_phase = os::elapsedTime();
     _idle++;
   }
 
   void mark_exec() {
     double now = os::elapsedTime();
-    _idle_elapsed = now - _start;
-    _start = now;
+    _idle_elapsed = now - _start_phase;
+    _start_phase = now;
+    _start_concurrent = now;
     _exec++;
   }
 
   void mark_block() {
     double now = os::elapsedTime();
-    _exec_elapsed += now - _start;
-    _start = now;
+    _exec_elapsed += now - _start_phase;
+    _start_phase = now;
     _block++;
   }
 
   void mark_unblock() {
     double now = os::elapsedTime();
-    _block_elapsed += now - _start;
-    _start = now;
+    _block_elapsed += now - _start_phase;
+    _start_phase = now;
   }
 
   void mark_done() {
     double now = os::elapsedTime();
-    _exec_elapsed += now - _start;
+    _exec_elapsed += now - _start_phase;
+    _end_concurrent = now;
   }
 
   void add(const G1StringDedupStat& stat);
 
-  static void print_summary(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
+  static void print_start(const G1StringDedupStat& last_stat);
+  static void print_end(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
   static void print_statistics(const G1StringDedupStat& stat, bool total);
 };
 
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -196,7 +196,8 @@
   }
 
   double end = os::elapsedTime();
-  log_trace(gc, stringdedup)("Deleted " UINTX_FORMAT " entries, " G1_STRDEDUP_TIME_FORMAT, count, end - start);
+  log_trace(gc, stringdedup)("Deleted " UINTX_FORMAT " entries, " G1_STRDEDUP_TIME_FORMAT_MS,
+                             count, G1_STRDEDUP_TIME_PARAM_MS(end - start));
 }
 
 G1StringDedupTable*      G1StringDedupTable::_table = NULL;
@@ -610,14 +611,14 @@
 
 void G1StringDedupTable::print_statistics() {
   Log(gc, stringdedup) log;
-  log.debug("   [Table]");
-  log.debug("      [Memory Usage: " G1_STRDEDUP_BYTES_FORMAT_NS "]",
+  log.debug("  Table");
+  log.debug("    Memory Usage: " G1_STRDEDUP_BYTES_FORMAT_NS,
             G1_STRDEDUP_BYTES_PARAM(_table->_size * sizeof(G1StringDedupEntry*) + (_table->_entries + _entry_cache->size()) * sizeof(G1StringDedupEntry)));
-  log.debug("      [Size: " SIZE_FORMAT ", Min: " SIZE_FORMAT ", Max: " SIZE_FORMAT "]", _table->_size, _min_size, _max_size);
-  log.debug("      [Entries: " UINTX_FORMAT ", Load: " G1_STRDEDUP_PERCENT_FORMAT_NS ", Cached: " UINTX_FORMAT ", Added: " UINTX_FORMAT ", Removed: " UINTX_FORMAT "]",
+  log.debug("    Size: " SIZE_FORMAT ", Min: " SIZE_FORMAT ", Max: " SIZE_FORMAT, _table->_size, _min_size, _max_size);
+  log.debug("    Entries: " UINTX_FORMAT ", Load: " G1_STRDEDUP_PERCENT_FORMAT_NS ", Cached: " UINTX_FORMAT ", Added: " UINTX_FORMAT ", Removed: " UINTX_FORMAT,
             _table->_entries, (double)_table->_entries / (double)_table->_size * 100.0, _entry_cache->size(), _entries_added, _entries_removed);
-  log.debug("      [Resize Count: " UINTX_FORMAT ", Shrink Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS "), Grow Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS ")]",
+  log.debug("    Resize Count: " UINTX_FORMAT ", Shrink Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS "), Grow Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS ")",
             _resize_count, _table->_shrink_threshold, _shrink_load_factor * 100.0, _table->_grow_threshold, _grow_load_factor * 100.0);
-  log.debug("      [Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: 0x%x]", _rehash_count, _rehash_threshold, _table->_hash_seed);
-  log.debug("      [Age Threshold: " UINTX_FORMAT "]", StringDeduplicationAgeThreshold);
+  log.debug("    Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: 0x%x", _rehash_count, _rehash_threshold, _table->_hash_seed);
+  log.debug("    Age Threshold: " UINTX_FORMAT, StringDeduplicationAgeThreshold);
 }
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupThread.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupThread.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -103,6 +103,7 @@
       SuspendibleThreadSetJoiner sts_join;
 
       stat.mark_exec();
+      print_start(stat);
 
       // Process the queue
       for (;;) {
@@ -123,9 +124,8 @@
 
       stat.mark_done();
 
-      // Print statistics
       total_stat.add(stat);
-      print(stat, total_stat);
+      print_end(stat, total_stat);
     }
 
     G1StringDedupTable::clean_entry_cache();
@@ -136,14 +136,16 @@
   G1StringDedupQueue::cancel_wait();
 }
 
-void G1StringDedupThread::print(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
-  if (log_is_enabled(Info, gc, stringdedup)) {
-    G1StringDedupStat::print_summary(last_stat, total_stat);
-    if (log_is_enabled(Debug, gc, stringdedup)) {
-      G1StringDedupStat::print_statistics(last_stat, false);
-      G1StringDedupStat::print_statistics(total_stat, true);
-      G1StringDedupTable::print_statistics();
-      G1StringDedupQueue::print_statistics();
-    }
+void G1StringDedupThread::print_start(const G1StringDedupStat& last_stat) {
+  G1StringDedupStat::print_start(last_stat);
+}
+
+void G1StringDedupThread::print_end(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
+  G1StringDedupStat::print_end(last_stat, total_stat);
+  if (log_is_enabled(Debug, gc, stringdedup)) {
+    G1StringDedupStat::print_statistics(last_stat, false);
+    G1StringDedupStat::print_statistics(total_stat, true);
+    G1StringDedupTable::print_statistics();
+    G1StringDedupQueue::print_statistics();
   }
 }
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupThread.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupThread.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -43,7 +43,8 @@
   G1StringDedupThread();
   ~G1StringDedupThread();
 
-  void print(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
+  void print_start(const G1StringDedupStat& last_stat);
+  void print_end(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
 
   void run_service();
   void stop_service();
--- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -71,38 +71,51 @@
   _monitor.notify();
 }
 
+class G1YoungRemSetSamplingClosure : public HeapRegionClosure {
+  SuspendibleThreadSetJoiner* _sts;
+  size_t _regions_visited;
+  size_t _sampled_rs_lengths;
+public:
+  G1YoungRemSetSamplingClosure(SuspendibleThreadSetJoiner* sts) :
+    HeapRegionClosure(), _sts(sts), _regions_visited(0), _sampled_rs_lengths(0) { }
+
+  virtual bool doHeapRegion(HeapRegion* r) {
+    size_t rs_length = r->rem_set()->occupied();
+    _sampled_rs_lengths += rs_length;
+
+    // Update the collection set policy information for this region
+    G1CollectedHeap::heap()->collection_set()->update_young_region_prediction(r, rs_length);
+
+    _regions_visited++;
+
+    if (_regions_visited == 10) {
+      if (_sts->should_yield()) {
+        _sts->yield();
+        // A gc may have occurred and our sampling data is stale and further
+        // traversal of the collection set is unsafe
+        return true;
+      }
+      _regions_visited = 0;
+    }
+    return false;
+  }
+
+  size_t sampled_rs_lengths() const { return _sampled_rs_lengths; }
+};
+
 void G1YoungRemSetSamplingThread::sample_young_list_rs_lengths() {
   SuspendibleThreadSetJoiner sts;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   G1Policy* g1p = g1h->g1_policy();
-  G1CollectionSet* g1cs = g1h->collection_set();
+
   if (g1p->adaptive_young_list_length()) {
-    int regions_visited = 0;
-    HeapRegion* hr = g1cs->inc_head();
-    size_t sampled_rs_lengths = 0;
-
-    while (hr != NULL) {
-      size_t rs_length = hr->rem_set()->occupied();
-      sampled_rs_lengths += rs_length;
-
-      // Update the collection set policy information for this region
-      g1cs->update_young_region_prediction(hr, rs_length);
-
-      ++regions_visited;
+    G1YoungRemSetSamplingClosure cl(&sts);
 
-      // we try to yield every time we visit 10 regions
-      if (regions_visited == 10) {
-        if (sts.should_yield()) {
-          sts.yield();
-          // A gc may have occurred and our sampling data is stale and further
-          // traversal of the collection set is unsafe
-          return;
-        }
-        regions_visited = 0;
-      }
-      assert(hr == g1cs->inc_tail() || hr->next_in_collection_set() != NULL, "next should only be null at tail of icset");
-      hr = hr->next_in_collection_set();
+    G1CollectionSet* g1cs = g1h->collection_set();
+    g1cs->iterate(&cl);
+
+    if (cl.complete()) {
+      g1p->revise_young_list_target_length_if_necessary(cl.sampled_rs_lengths());
     }
-    g1p->revise_young_list_target_length_if_necessary(sampled_rs_lengths);
   }
 }
--- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -284,7 +284,6 @@
     _hrm_index(hrm_index),
     _allocation_context(AllocationContext::system()),
     _humongous_start_region(NULL),
-    _next_in_special_set(NULL),
     _evacuation_failed(false),
     _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0),
     _next(NULL), _prev(NULL),
--- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -261,12 +261,6 @@
   // True iff an attempt to evacuate an object in the region failed.
   bool _evacuation_failed;
 
-  // A heap region may be a member one of a number of special subsets, each
-  // represented as linked lists through the field below.  Currently, there
-  // is only one set:
-  //   The collection set.
-  HeapRegion* _next_in_special_set;
-
   // Fields used by the HeapRegionSetBase class and subclasses.
   HeapRegion* _next;
   HeapRegion* _prev;
@@ -476,9 +470,6 @@
 
   inline bool in_collection_set() const;
 
-  inline HeapRegion* next_in_collection_set() const;
-  inline void set_next_in_collection_set(HeapRegion* r);
-
   void set_allocation_context(AllocationContext_t context) {
     _allocation_context = context;
   }
@@ -744,7 +735,7 @@
 // Terminates the iteration when the "doHeapRegion" method returns "true".
 class HeapRegionClosure : public StackObj {
   friend class HeapRegionManager;
-  friend class G1CollectedHeap;
+  friend class G1CollectionSet;
 
   bool _complete;
   void incomplete() { _complete = false; }
--- a/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -230,18 +230,4 @@
   return G1CollectedHeap::heap()->is_in_cset(this);
 }
 
-inline HeapRegion* HeapRegion::next_in_collection_set() const {
-  assert(in_collection_set(), "should only invoke on member of CS.");
-  assert(_next_in_special_set == NULL ||
-         _next_in_special_set->in_collection_set(),
-         "Malformed CS.");
-  return _next_in_special_set;
-}
-
-void HeapRegion::set_next_in_collection_set(HeapRegion* r) {
-  assert(in_collection_set(), "should only invoke on member of CS.");
-  assert(r == NULL || r->in_collection_set(), "Malformed CS.");
-  _next_in_special_set = r;
-}
-
 #endif // SHARE_VM_GC_G1_HEAPREGION_INLINE_HPP
--- a/hotspot/src/share/vm/gc/parallel/gcTaskManager.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskManager.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -386,13 +386,21 @@
 
 void GCTaskManager::add_workers(bool initializing) {
   os::ThreadType worker_type = os::pgc_thread;
+  uint previous_created_workers = _created_workers;
+
   _created_workers = WorkerManager::add_workers(this,
                                                 _active_workers,
-                                                (uint) _workers,
+                                                _workers,
                                                 _created_workers,
                                                 worker_type,
                                                 initializing);
   _active_workers = MIN2(_created_workers, _active_workers);
+
+  WorkerManager::log_worker_creation(this, previous_created_workers, _active_workers, _created_workers, initializing);
+}
+
+const char* GCTaskManager::group_name() {
+  return "ParGC Thread";
 }
 
 void GCTaskManager::initialize() {
--- a/hotspot/src/share/vm/gc/parallel/gcTaskManager.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskManager.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -556,6 +556,8 @@
   GCTaskThread* install_worker(uint worker_id);
   // Add GC workers as needed.
   void add_workers(bool initializing);
+  // Base name (without worker id #) of threads.
+  const char* group_name();
 };
 
 //
--- a/hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -45,7 +45,7 @@
   _time_stamp_index(0)
 {
   set_id(which);
-  set_name("ParGC Thread#%d", which);
+  set_name("%s#%d", manager->group_name(), which);
 }
 
 GCTaskThread::~GCTaskThread() {
--- a/hotspot/src/share/vm/gc/parallel/gcTaskThread.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskThread.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -55,6 +55,7 @@
     return new GCTaskThread(manager, which, processor_id);
   }
  public:
+
   static void destroy(GCTaskThread* manager) {
     if (manager != NULL) {
       delete manager;
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -159,6 +159,8 @@
   inline static void post_allocation_setup_array(KlassHandle klass,
                                                  HeapWord* obj, int length);
 
+  inline static void post_allocation_setup_class(KlassHandle klass, HeapWord* obj, int size);
+
   // Clears an allocated object.
   inline static void init_obj(HeapWord* obj, size_t size);
 
@@ -300,6 +302,7 @@
   inline static oop obj_allocate(KlassHandle klass, int size, TRAPS);
   inline static oop array_allocate(KlassHandle klass, int size, int length, TRAPS);
   inline static oop array_allocate_nozero(KlassHandle klass, int size, int length, TRAPS);
+  inline static oop class_allocate(KlassHandle klass, int size, TRAPS);
 
   inline static void post_allocation_install_obj_klass(KlassHandle klass,
                                                        oop obj);
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_GC_SHARED_COLLECTEDHEAP_INLINE_HPP
 #define SHARE_VM_GC_SHARED_COLLECTEDHEAP_INLINE_HPP
 
+#include "classfile/javaClasses.hpp"
 #include "gc/shared/allocTracer.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/threadLocalAllocBuffer.inline.hpp"
@@ -96,6 +97,22 @@
   post_allocation_notify(klass, (oop)obj, size);
 }
 
+void CollectedHeap::post_allocation_setup_class(KlassHandle klass,
+                                                HeapWord* obj,
+                                                int size) {
+  // Set oop_size field before setting the _klass field
+  // in post_allocation_setup_common() because the klass field
+  // indicates that the object is parsable by concurrent GC.
+  oop new_cls = (oop)obj;
+  assert(size > 0, "oop_size must be positive.");
+  java_lang_Class::set_oop_size(new_cls, size);
+  post_allocation_setup_common(klass, obj);
+  assert(Universe::is_bootstrapping() ||
+         !new_cls->is_array(), "must not be an array");
+  // notify jvmti and dtrace
+  post_allocation_notify(klass, new_cls, size);
+}
+
 void CollectedHeap::post_allocation_setup_array(KlassHandle klass,
                                                 HeapWord* obj,
                                                 int length) {
@@ -207,6 +224,16 @@
   return (oop)obj;
 }
 
+oop CollectedHeap::class_allocate(KlassHandle klass, int size, TRAPS) {
+  debug_only(check_for_valid_allocation_state());
+  assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
+  assert(size >= 0, "int won't convert to size_t");
+  HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL);
+  post_allocation_setup_class(klass, obj, size); // set oop_size
+  NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
+  return (oop)obj;
+}
+
 oop CollectedHeap::array_allocate(KlassHandle klass,
                                   int size,
                                   int length,
--- a/hotspot/src/share/vm/gc/shared/workerManager.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/shared/workerManager.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -47,18 +47,18 @@
   // threads and a failure would not be optimal but should not be fatal.
   template <class WorkerType>
   static uint add_workers (WorkerType* holder,
-                   uint active_workers,
-                   uint total_workers,
-                   uint created_workers,
-                   os::ThreadType worker_type,
-                   bool initializing) {
+                           uint active_workers,
+                           uint total_workers,
+                           uint created_workers,
+                           os::ThreadType worker_type,
+                           bool initializing) {
     uint start = created_workers;
     uint end = MIN2(active_workers, total_workers);
     for (uint worker_id = start; worker_id < end; worker_id += 1) {
       WorkerThread* new_worker = holder->install_worker(worker_id);
       assert(new_worker != NULL, "Failed to allocate GangWorker");
       if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) {
-        if(initializing) {
+        if (initializing) {
           vm_exit_out_of_memory(0, OOM_MALLOC_ERROR,
                   "Cannot create worker GC thread. Out of system resources.");
         }
@@ -67,11 +67,21 @@
       os::start_thread(new_worker);
     }
 
-    log_trace(gc, task)("AdaptiveSizePolicy::add_workers() : "
-       "active_workers: %u created_workers: %u",
-       active_workers, created_workers);
+    return created_workers;
+  }
 
-    return created_workers;
+  // Log (at trace level) a change in the number of created workers.
+  template <class WorkerType>
+  static void log_worker_creation(WorkerType* holder,
+                                  uint previous_created_workers,
+                                  uint active_workers,
+                                  uint created_workers,
+                                  bool initializing) {
+    if (previous_created_workers < created_workers) {
+      const char* initializing_msg =  initializing ? "Adding initial" : "Creating additional";
+      log_trace(gc, task)("%s %s(s) previously created workers %u active workers %u total created workers %u",
+                          initializing_msg, holder->group_name(), previous_created_workers, active_workers, created_workers);
+    }
   }
 };
 #endif // SHARE_VM_GC_SHARED_WORKERMANAGER_HPP
--- a/hotspot/src/share/vm/gc/shared/workgroup.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/shared/workgroup.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -66,6 +66,7 @@
   } else {
     worker_type = os::pgc_thread;
   }
+  uint previous_created_workers = _created_workers;
 
   _created_workers = WorkerManager::add_workers(this,
                                                 active_workers,
@@ -74,6 +75,8 @@
                                                 worker_type,
                                                 initializing);
   _active_workers = MIN2(_created_workers, _active_workers);
+
+  WorkerManager::log_worker_creation(this, previous_created_workers, _active_workers, _created_workers, initializing);
 }
 
 AbstractGangWorker* AbstractWorkGang::worker(uint i) const {
--- a/hotspot/src/share/vm/gc/shared/workgroup.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -176,6 +176,9 @@
   // Return the Ith worker.
   AbstractGangWorker* worker(uint i) const;
 
+  // Base name (without worker id #) of threads.
+  const char* group_name() { return name(); }
+
   void threads_do(ThreadClosure* tc) const;
 
   // Create a GC worker and install it into the work gang.
--- a/hotspot/src/share/vm/interpreter/bytecodeStream.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/interpreter/bytecodeStream.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -31,12 +31,12 @@
   // set next bytecode position
   address bcp = RawBytecodeStream::bcp();
   address end = method()->code_base() + end_bci();
-  int l = Bytecodes::raw_special_length_at(bcp, end);
-  if (l <= 0 || (_bci + l) > _end_bci) {
+  int len = Bytecodes::raw_special_length_at(bcp, end);
+  // Very large tableswitch or lookupswitch size can cause _next_bci to overflow.
+  if (len <= 0 || (_bci > _end_bci - len) || (_bci - len >= _next_bci)) {
     code = Bytecodes::_illegal;
   } else {
-    _next_bci += l;
-    assert(_bci < _next_bci, "length must be > 0");
+    _next_bci += len;
     // set attributes
     _is_wide = false;
     // check for special (uncommon) cases
--- a/hotspot/src/share/vm/interpreter/bytecodeStream.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/interpreter/bytecodeStream.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -135,12 +135,15 @@
     code        = Bytecodes::code_or_bp_at(bcp);
 
     // set next bytecode position
-    int l = Bytecodes::length_for(code);
-    if (l > 0 && (_bci + l) <= _end_bci) {
+    int len = Bytecodes::length_for(code);
+    if (len > 0 && (_bci <= _end_bci - len)) {
       assert(code != Bytecodes::_wide && code != Bytecodes::_tableswitch
              && code != Bytecodes::_lookupswitch, "can't be special bytecode");
       _is_wide = false;
-      _next_bci += l;
+      _next_bci += len;
+      if (_next_bci <= _bci) { // Check for integer overflow
+        code = Bytecodes::_illegal;
+      }
       _raw_code = code;
       return code;
     } else {
@@ -189,19 +192,23 @@
       // note that we cannot advance before having the
       // tty bytecode otherwise the stepping is wrong!
       // (carefull: length_for(...) must be used first!)
-      int l = Bytecodes::length_for(code);
-      if (l == 0) l = Bytecodes::length_at(_method(), bcp);
-      _next_bci  += l;
-      assert(_bci < _next_bci, "length must be > 0");
-      // set attributes
-      _is_wide      = false;
-      // check for special (uncommon) cases
-      if (code == Bytecodes::_wide) {
-        raw_code = (Bytecodes::Code)bcp[1];
-        code = raw_code;  // wide BCs are always Java-normal
-        _is_wide = true;
+      int len = Bytecodes::length_for(code);
+      if (len == 0) len = Bytecodes::length_at(_method(), bcp);
+      if (len <= 0 || (_bci > _end_bci - len) || (_bci - len >= _next_bci)) {
+        raw_code = code = Bytecodes::_illegal;
+      } else {
+        _next_bci  += len;
+        assert(_bci < _next_bci, "length must be > 0");
+        // set attributes
+        _is_wide      = false;
+        // check for special (uncommon) cases
+        if (code == Bytecodes::_wide) {
+          raw_code = (Bytecodes::Code)bcp[1];
+          code = raw_code;  // wide BCs are always Java-normal
+          _is_wide = true;
+        }
+        assert(Bytecodes::is_java_code(code), "sanity check");
       }
-      assert(Bytecodes::is_java_code(code), "sanity check");
     }
     _raw_code = raw_code;
     _code = code;
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -576,27 +576,27 @@
   // compute auxiliary field attributes
   TosState state  = as_TosState(info.field_type());
 
-  // We need to delay resolving put instructions on final fields
-  // until we actually invoke one. This is required so we throw
-  // exceptions at the correct place. If we do not resolve completely
-  // in the current pass, leaving the put_code set to zero will
-  // cause the next put instruction to reresolve.
-  Bytecodes::Code put_code = (Bytecodes::Code)0;
-
-  // We also need to delay resolving getstatic instructions until the
-  // class is intitialized.  This is required so that access to the static
+  // Put instructions on final fields are not resolved. This is required so we throw
+  // exceptions at the correct place (when the instruction is actually invoked).
+  // If we do not resolve an instruction in the current pass, leaving the put_code
+  // set to zero will cause the next put instruction to the same field to reresolve.
+  //
+  // Also, we need to delay resolving getstatic and putstatic instructions until the
+  // class is initialized.  This is required so that access to the static
   // field will call the initialization function every time until the class
   // is completely initialized ala. in 2.17.5 in JVM Specification.
   InstanceKlass* klass = InstanceKlass::cast(info.field_holder());
   bool uninitialized_static = ((bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic) &&
                                !klass->is_initialized());
+
+  Bytecodes::Code put_code = (Bytecodes::Code)0;
+  if (is_put && !info.access_flags().is_final() && !uninitialized_static) {
+    put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield);
+  }
+
   Bytecodes::Code get_code = (Bytecodes::Code)0;
-
   if (!uninitialized_static) {
     get_code = ((is_static) ? Bytecodes::_getstatic : Bytecodes::_getfield);
-    if (is_put || !info.access_flags().is_final()) {
-      put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield);
-    }
   }
 
   cp_cache_entry->set_field(
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -970,7 +970,7 @@
       if (is_initialized_static_final_update || is_initialized_instance_final_update) {
         ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ",
                  is_static ? "static" : "non-static", resolved_klass()->external_name(), fd.name()->as_C_string(),
-                 current_klass()->external_name(),
+                 m()->name()->as_C_string(),
                  is_static ? "<clinit>" : "<init>");
         THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
       }
--- a/hotspot/src/share/vm/logging/logConfiguration.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/logging/logConfiguration.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -415,17 +415,8 @@
 void LogConfiguration::describe_current_configuration(outputStream* out){
   out->print_cr("Log output configuration:");
   for (size_t i = 0; i < _n_outputs; i++) {
-    out->print("#" SIZE_FORMAT ": %s ", i, _outputs[i]->name());
-    out->print_raw(_outputs[i]->config_string());
-    out->print(" ");
-    char delimiter[2] = {0};
-    for (size_t d = 0; d < LogDecorators::Count; d++) {
-      LogDecorators::Decorator decorator = static_cast<LogDecorators::Decorator>(d);
-      if (_outputs[i]->decorators().is_decorator(decorator)) {
-        out->print("%s%s", delimiter, LogDecorators::name(decorator));
-        *delimiter = ',';
-      }
-    }
+    out->print("#" SIZE_FORMAT ": ", i);
+    _outputs[i]->describe(out);
     out->cr();
   }
 }
--- a/hotspot/src/share/vm/logging/logFileOutput.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/logging/logFileOutput.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -428,3 +428,13 @@
   result[result_len] = '\0';
   return result;
 }
+
+void LogFileOutput::describe(outputStream *out) {
+  LogOutput::describe(out);
+  out->print(" ");
+
+  out->print("filecount=%u,filesize=" SIZE_FORMAT "%s", _file_count,
+             byte_size_in_proper_unit(_rotate_size),
+             proper_unit_for_byte_size(_rotate_size));
+}
+
--- a/hotspot/src/share/vm/logging/logFileOutput.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/logging/logFileOutput.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -85,6 +85,7 @@
   virtual int write(const LogDecorations& decorations, const char* msg);
   virtual int write(LogMessageBuffer::Iterator msg_iterator);
   virtual void force_rotate();
+  virtual void describe(outputStream *out);
 
   virtual const char* name() const {
     return _name;
--- a/hotspot/src/share/vm/logging/logOutput.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/logging/logOutput.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -83,3 +83,18 @@
     break;
   }
 }
+
+void LogOutput::describe(outputStream *out) {
+  out->print("%s ", name());
+  out->print_raw(config_string());
+  out->print(" ");
+  char delimiter[2] = {0};
+  for (size_t d = 0; d < LogDecorators::Count; d++) {
+    LogDecorators::Decorator decorator = static_cast<LogDecorators::Decorator>(d);
+    if (decorators().is_decorator(decorator)) {
+      out->print("%s%s", delimiter, LogDecorators::name(decorator));
+      *delimiter = ',';
+    }
+  }
+}
+
--- a/hotspot/src/share/vm/logging/logOutput.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/logging/logOutput.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -83,6 +83,8 @@
     // Do nothing by default.
   }
 
+  virtual void describe(outputStream *out);
+
   virtual const char* name() const = 0;
   virtual bool initialize(const char* options, outputStream* errstream) = 0;
   virtual int write(const LogDecorations& decorations, const char* msg) = 0;
--- a/hotspot/src/share/vm/logging/logPrefix.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/logging/logPrefix.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -74,6 +74,7 @@
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ref)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ref, start)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, start)) \
+  LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, stringtable)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, sweep)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task)) \
   LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task, start)) \
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -3106,10 +3106,6 @@
 
   assert(MetaspaceSize <= MaxMetaspaceSize, "MetaspaceSize should be limited by MaxMetaspaceSize");
 
-  if (MetaspaceSize < 256*K) {
-    vm_exit_during_initialization("Too small initial Metaspace size");
-  }
-
   MinMetaspaceExpansion = align_size_down_bounded(MinMetaspaceExpansion, _commit_alignment);
   MaxMetaspaceExpansion = align_size_down_bounded(MaxMetaspaceExpansion, _commit_alignment);
 
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -60,6 +60,7 @@
 bool MetaspaceShared::_check_classes_made_progress;
 bool MetaspaceShared::_has_error_classes;
 bool MetaspaceShared::_archive_loading_failed = false;
+bool MetaspaceShared::_remapped_readwrite = false;
 address MetaspaceShared::_cds_i2i_entry_code_buffers = NULL;
 size_t MetaspaceShared::_cds_i2i_entry_code_buffers_size = 0;
 SharedMiscRegion MetaspaceShared::_mc;
@@ -806,6 +807,10 @@
       exit(1);
     }
   }
+
+  // Copy the verification constraints from C_HEAP-alloced GrowableArrays to RO-alloced
+  // Arrays
+  SystemDictionaryShared::finalize_verification_constraints();
 }
 
 void MetaspaceShared::prepare_for_dumping() {
@@ -1181,6 +1186,7 @@
     if (!mapinfo->remap_shared_readonly_as_readwrite()) {
       return false;
     }
+    _remapped_readwrite = true;
   }
   return true;
 }
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -125,6 +125,7 @@
   static bool _check_classes_made_progress;
   static bool _has_error_classes;
   static bool _archive_loading_failed;
+  static bool _remapped_readwrite;
   static address _cds_i2i_entry_code_buffers;
   static size_t  _cds_i2i_entry_code_buffers_size;
 
@@ -205,6 +206,10 @@
   // sharing is enabled. Simply returns true if sharing is not enabled
   // or if the remapping has already been done by a prior call.
   static bool remap_shared_readonly_as_readwrite() NOT_CDS_RETURN_(true);
+  static bool remapped_readwrite() {
+    CDS_ONLY(return _remapped_readwrite);
+    NOT_CDS(return false);
+  }
 
   static void print_shared_spaces();
 
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -27,6 +27,7 @@
 #include "classfile/classFileStream.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/systemDictionary.hpp"
+#include "classfile/systemDictionaryShared.hpp"
 #include "classfile/verifier.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "code/dependencyContext.hpp"
@@ -597,6 +598,8 @@
 
         // also sets rewritten
         this_k->rewrite_class(CHECK_false);
+      } else if (this_k->is_shared()) {
+        SystemDictionaryShared::check_verification_constraints(this_k, CHECK_false);
       }
 
       // relocate jsrs and link methods after they are all rewritten
@@ -606,7 +609,12 @@
       // methods have been rewritten since rewrite may
       // fabricate new Method*s.
       // also does loader constraint checking
-      if (!this_k()->is_shared()) {
+      //
+      // initialize_vtable and initialize_itable need to be rerun for
+      // a shared class if the class is not loaded by the NULL classloader.
+      ClassLoaderData * loader_data = this_k->class_loader_data();
+      if (!(this_k->is_shared() &&
+            loader_data->is_the_null_class_loader_data())) {
         ResourceMark rm(THREAD);
         this_k->vtable()->initialize_vtable(true, CHECK_false);
         this_k->itable()->initialize_itable(true, CHECK_false);
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -50,13 +50,12 @@
   // Query before forming handle.
   int size = instance_size(k);
   KlassHandle h_k(THREAD, this);
-  instanceOop i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);
+
+  assert(size > 0, "total object size must be positive: %d", size);
 
   // Since mirrors can be variable sized because of the static fields, store
   // the size in the mirror itself.
-  java_lang_Class::set_oop_size(i, size);
-
-  return i;
+  return (instanceOop)CollectedHeap::class_allocate(h_k, size, CHECK_NULL);
 }
 
 int InstanceMirrorKlass::oop_size(oop obj) const {
--- a/hotspot/src/share/vm/oops/klassVtable.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -27,6 +27,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "logging/log.hpp"
+#include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/instanceKlass.hpp"
@@ -42,6 +43,10 @@
   return InstanceKlass::cast(_klass());
 }
 
+bool klassVtable::is_preinitialized_vtable() {
+  return _klass->is_shared() && !MetaspaceShared::remapped_readwrite();
+}
+
 
 // this function computes the vtable size (including the size needed for miranda
 // methods) and the number of miranda methods in this class.
@@ -126,6 +131,12 @@
 int klassVtable::initialize_from_super(KlassHandle super) {
   if (super.is_null()) {
     return 0;
+  } else if (is_preinitialized_vtable()) {
+    // A shared class' vtable is preinitialized at dump time. No need to copy
+    // methods from super class for shared class, as that was already done
+    // during archiving time. However, if Jvmti has redefined a class,
+    // copy super class's vtable in case the super class has changed.
+    return super->vtable()->length();
   } else {
     // copy methods from superKlass
     klassVtable* superVtable = super->vtable();
@@ -152,6 +163,8 @@
   KlassHandle super (THREAD, klass()->java_super());
   int nofNewEntries = 0;
 
+  bool is_shared = _klass->is_shared();
+
   if (!klass()->is_array_klass()) {
     ResourceMark rm(THREAD);
     log_develop_debug(vtables)("Initializing: %s", _klass->name()->as_C_string());
@@ -164,6 +177,7 @@
 #endif
 
   if (Universe::is_bootstrapping()) {
+    assert(!is_shared, "sanity");
     // just clear everything
     for (int i = 0; i < _length; i++) table()[i].clear();
     return;
@@ -203,6 +217,7 @@
       if (len > 0) {
         Array<int>* def_vtable_indices = NULL;
         if ((def_vtable_indices = ik()->default_vtable_indices()) == NULL) {
+          assert(!is_shared, "shared class def_vtable_indices does not exist");
           def_vtable_indices = ik()->create_new_default_vtable_indices(len, CHECK);
         } else {
           assert(def_vtable_indices->length() == len, "reinit vtable len?");
@@ -217,7 +232,15 @@
           // needs new entry
           if (needs_new_entry) {
             put_method_at(mh(), initialized);
-            def_vtable_indices->at_put(i, initialized); //set vtable index
+            if (is_preinitialized_vtable()) {
+              // At runtime initialize_vtable is rerun for a shared class
+              // (loaded by the non-boot loader) as part of link_class_impl().
+              // The dumptime vtable index should be the same as the runtime index.
+              assert(def_vtable_indices->at(i) == initialized,
+                     "dump time vtable index is different from runtime index");
+            } else {
+              def_vtable_indices->at_put(i, initialized); //set vtable index
+            }
             initialized++;
           }
         }
@@ -378,7 +401,8 @@
   }
 
   // we need a new entry if there is no superclass
-  if (klass->super() == NULL) {
+  Klass* super = klass->super();
+  if (super == NULL) {
     return allocate_new;
   }
 
@@ -407,7 +431,15 @@
 
   Symbol* target_classname = target_klass->name();
   for(int i = 0; i < super_vtable_len; i++) {
-    Method* super_method = method_at(i);
+    Method* super_method;
+    if (is_preinitialized_vtable()) {
+      // If this is a shared class, the vtable is already in the final state (fully
+      // initialized). Need to look at the super's vtable.
+      klassVtable* superVtable = super->vtable();
+      super_method = superVtable->method_at(i);
+    } else {
+      super_method = method_at(i);
+    }
     // Check if method name matches
     if (super_method->name() == name && super_method->signature() == signature) {
 
@@ -475,7 +507,15 @@
           target_method()->set_vtable_index(i);
         } else {
           if (def_vtable_indices != NULL) {
-            def_vtable_indices->at_put(default_index, i);
+            if (is_preinitialized_vtable()) {
+              // At runtime initialize_vtable is rerun as part of link_class_impl()
+              // for a shared class loaded by the non-boot loader.
+              // The dumptime vtable index should be the same as the runtime index.
+              assert(def_vtable_indices->at(default_index) == i,
+                     "dump time vtable index is different from runtime index");
+            } else {
+              def_vtable_indices->at_put(default_index, i);
+            }
           }
           assert(super_method->is_default_method() || super_method->is_overpass()
                  || super_method->is_abstract(), "default override error");
@@ -490,17 +530,26 @@
 }
 
 void klassVtable::put_method_at(Method* m, int index) {
-  if (log_develop_is_enabled(Trace, vtables)) {
-    ResourceMark rm;
-    outputStream* logst = Log(vtables)::trace_stream();
-    const char* sig = (m != NULL) ? m->name_and_sig_as_C_string() : "<NULL>";
-    logst->print("adding %s at index %d, flags: ", sig, index);
-    if (m != NULL) {
-      m->print_linkage_flags(logst);
+  if (is_preinitialized_vtable()) {
+    // At runtime initialize_vtable is rerun as part of link_class_impl()
+    // for shared class loaded by the non-boot loader to obtain the loader
+    // constraints based on the runtime classloaders' context. The dumptime
+    // method at the vtable index should be the same as the runtime method.
+    assert(table()[index].method() == m,
+           "archived method is different from the runtime method");
+  } else {
+    if (log_develop_is_enabled(Trace, vtables)) {
+      ResourceMark rm;
+      outputStream* logst = Log(vtables)::trace_stream();
+      const char* sig = (m != NULL) ? m->name_and_sig_as_C_string() : "<NULL>";
+      logst->print("adding %s at index %d, flags: ", sig, index);
+      if (m != NULL) {
+        m->print_linkage_flags(logst);
+      }
+      logst->cr();
     }
-    logst->cr();
+    table()[index].set(m);
   }
-  table()[index].set(m);
 }
 
 // Find out if a method "m" with superclass "super", loader "classloader" and
@@ -950,7 +999,15 @@
 void itableMethodEntry::initialize(Method* m) {
   if (m == NULL) return;
 
-  _method = m;
+  if (MetaspaceShared::is_in_shared_space((void*)&_method) &&
+     !MetaspaceShared::remapped_readwrite()) {
+    // At runtime initialize_itable is rerun as part of link_class_impl()
+    // for a shared class loaded by the non-boot loader.
+    // The dumptime itable method entry should be the same as the runtime entry.
+    assert(_method == m, "sanity");
+  } else {
+    _method = m;
+  }
 }
 
 klassItable::klassItable(instanceKlassHandle klass) {
@@ -1054,7 +1111,11 @@
         logst->cr();
       }
       if (!m->has_vtable_index()) {
-        assert(m->vtable_index() == Method::pending_itable_index, "set by initialize_vtable");
+        // A shared method could have an initialized itable_index that
+        // is < 0.
+        assert(m->vtable_index() == Method::pending_itable_index ||
+               m->is_shared(),
+               "set by initialize_vtable");
         m->set_itable_index(ime_num);
         // Progress to next itable entry
         ime_num++;
@@ -1248,7 +1309,6 @@
 }
 #endif // INCLUDE_JVMTI
 
-
 // Setup
 class InterfaceVisiterClosure : public StackObj {
  public:
--- a/hotspot/src/share/vm/oops/klassVtable.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/oops/klassVtable.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -153,6 +153,19 @@
       Array<Klass*>* local_interfaces);
   void verify_against(outputStream* st, klassVtable* vt, int index);
   inline InstanceKlass* ik() const;
+  // When loading a class from CDS archive at run time, and no class redefintion
+  // has happened, it is expected that the class's itable/vtables are
+  // laid out exactly the same way as they had been during dump time.
+  // Therefore, in klassVtable::initialize_[iv]table, we do not layout the
+  // tables again. Instead, we only rerun the process to create/check
+  // the class loader constraints. In non-product builds, we add asserts to
+  // guarantee that the table's layout would be the same as at dump time.
+  //
+  // If JVMTI redefines any class, the read-only shared memory are remapped
+  // as read-write. A shared class' vtable/itable are re-initialized and
+  // might have different layout due to class redefinition of the shared class
+  // or its super types.
+  bool is_preinitialized_vtable();
 };
 
 
--- a/hotspot/src/share/vm/oops/method.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/oops/method.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -313,6 +313,33 @@
   unlink_method();
 }
 
+void Method::set_vtable_index(int index) {
+  if (is_shared() && !MetaspaceShared::remapped_readwrite()) {
+    // At runtime initialize_vtable is rerun as part of link_class_impl()
+    // for a shared class loaded by the non-boot loader to obtain the loader
+    // constraints based on the runtime classloaders' context.
+    return; // don't write into the shared class
+  } else {
+    _vtable_index = index;
+  }
+}
+
+void Method::set_itable_index(int index) {
+  if (is_shared() && !MetaspaceShared::remapped_readwrite()) {
+    // At runtime initialize_itable is rerun as part of link_class_impl()
+    // for a shared class loaded by the non-boot loader to obtain the loader
+    // constraints based on the runtime classloaders' context. The dumptime
+    // itable index should be the same as the runtime index.
+    assert(_vtable_index == itable_index_max - index,
+           "archived itable index is different from runtime index");
+    return; // don’t write into the shared class
+  } else {
+    _vtable_index = itable_index_max - index;
+  }
+  assert(valid_itable_index(), "");
+}
+
+
 
 bool Method::was_executed_more_than(int n) {
   // Invocation counter is reset when the Method* is compiled.
--- a/hotspot/src/share/vm/oops/method.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/oops/method.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -470,12 +470,12 @@
   DEBUG_ONLY(bool valid_vtable_index() const     { return _vtable_index >= nonvirtual_vtable_index; })
   bool has_vtable_index() const                  { return _vtable_index >= 0; }
   int  vtable_index() const                      { return _vtable_index; }
-  void set_vtable_index(int index)               { _vtable_index = index; }
+  void set_vtable_index(int index);
   DEBUG_ONLY(bool valid_itable_index() const     { return _vtable_index <= pending_itable_index; })
   bool has_itable_index() const                  { return _vtable_index <= itable_index_max; }
   int  itable_index() const                      { assert(valid_itable_index(), "");
                                                    return itable_index_max - _vtable_index; }
-  void set_itable_index(int index)               { _vtable_index = itable_index_max - index; assert(valid_itable_index(), ""); }
+  void set_itable_index(int index);
 
   // interpreter entry
   address interpreter_entry() const              { return _i2i_entry; }
--- a/hotspot/src/share/vm/oops/oop.inline.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -258,8 +258,8 @@
     }
   }
 
-  assert(s % MinObjAlignment == 0, "alignment check");
-  assert(s > 0, "Bad size calculated");
+  assert(s % MinObjAlignment == 0, "Oop size is not properly aligned: %d", s);
+  assert(s > 0, "Oop size must be greater than zero, not %d", s);
   return s;
 }
 
--- a/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -2405,8 +2405,13 @@
   Compile::AliasType* alias_type = C->alias_type(adr_type);
   assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here");
 
-  assert(alias_type->adr_type() == TypeRawPtr::BOTTOM || alias_type->adr_type() == TypeOopPtr::BOTTOM ||
-         alias_type->basic_type() != T_ILLEGAL, "field, array element or unknown");
+  // Only field, array element or unknown locations are supported.
+  if (alias_type->adr_type() != TypeRawPtr::BOTTOM &&
+      alias_type->adr_type() != TypeOopPtr::BOTTOM &&
+      alias_type->basic_type() == T_ILLEGAL) {
+    return false;
+  }
+
   bool mismatched = false;
   BasicType bt = alias_type->basic_type();
   if (bt != T_ILLEGAL) {
@@ -2782,12 +2787,6 @@
       ShouldNotReachHere();
   }
 
-  // Null check receiver.
-  receiver = null_check(receiver);
-  if (stopped()) {
-    return true;
-  }
-
   // Build field offset expression.
   // We currently rely on the cookies produced by Unsafe.xxxFieldOffset
   // to be plain byte offsets, which are also the same as those accepted
@@ -2799,8 +2798,6 @@
   const TypePtr *adr_type = _gvn.type(adr)->isa_ptr();
 
   Compile::AliasType* alias_type = C->alias_type(adr_type);
-  assert(alias_type->adr_type() == TypeRawPtr::BOTTOM || alias_type->adr_type() == TypeOopPtr::BOTTOM ||
-         alias_type->basic_type() != T_ILLEGAL, "field, array element or unknown");
   BasicType bt = alias_type->basic_type();
   if (bt != T_ILLEGAL &&
       ((bt == T_OBJECT || bt == T_ARRAY) != (type == T_OBJECT))) {
@@ -2832,6 +2829,12 @@
       ShouldNotReachHere();
   }
 
+  // Null check receiver.
+  receiver = null_check(receiver);
+  if (stopped()) {
+    return true;
+  }
+
   int alias_idx = C->get_alias_index(adr_type);
 
   // Memory-model-wise, a LoadStore acts like a little synchronized
--- a/hotspot/src/share/vm/prims/jvmti.xml	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/prims/jvmti.xml	Wed Jul 27 13:33:55 2016 +0000
@@ -6509,6 +6509,59 @@
       <errors>
       </errors>
     </function>
+
+    <function id="GetNamedModule" num="40" since="9">
+      <synopsis>Get Named Module</synopsis>
+      <description>
+        Return the <code>java.lang.reflect.Module</code> object for a named
+        module defined to a class loader that contains a given package.
+        The module is returned via <code>module_ptr</code>.
+        <p/>
+        If a named module is defined to the class loader and it
+        contains the package then that named module is returned,
+        otherwise <code>NULL</code> is returned.
+        <p/>
+      </description>
+      <origin>new</origin>
+      <capabilities>
+      </capabilities>
+      <parameters>
+        <param id="class_loader">
+          <ptrtype>
+            <jobject/>
+            <nullok>the bootstrap loader is assumed</nullok>
+          </ptrtype>
+          <description>
+            A class loader.
+            If the <code>class_loader</code> is not <code>NULL</code>
+            or a subclass of <code>java.lang.ClassLoader</code>
+            this function returns
+            <errorlink id="JVMTI_ERROR_ILLEGAL_ARGUMENT"></errorlink>.
+          </description>
+        </param>
+        <param id="package_name">
+          <inbuf><char/></inbuf>
+          <description>
+            The name of the package, encoded as a
+            <internallink id="mUTF">modified UTF-8</internallink> string.
+            The package name is in internal form (JVMS 4.2.1);
+            identifiers are separated by forward slashes rather than periods.
+          </description>
+        </param>
+        <param id="module_ptr">
+          <outptr><jobject/></outptr>
+          <description>
+            On return, points to a <code>java.lang.reflect.Module</code> object
+            or points to <code>NULL</code>.
+          </description>
+        </param>
+      </parameters>
+      <errors>
+        <error id="JVMTI_ERROR_ILLEGAL_ARGUMENT">
+          If class loader is not <code>NULL</code> and is not a class loader object.
+        </error>
+      </errors>
+    </function>
   </category>
 
   <category id="class" label="Class">
@@ -12462,6 +12515,14 @@
     <code>new_class_data</code> has been set, it becomes the 
     <code>class_data</code> for the next agent.
     <p/>
+    When handling a class load in the live phase, then the
+    <functionlink id="GetNamedModule"></functionlink>
+    function can be used to map class loader and a package name to a module.
+    When a class is being redefined or retransformed then
+    <code>class_being_redefined</code> is non <code>NULL</code> and so
+    the JNI <code>GetModule</code> function can also be used
+    to obtain the Module.
+    <p/>
     The order that this event is sent to each environment differs
     from other events.
     This event is sent to environments in the following order:
@@ -14427,20 +14488,15 @@
   <change date="19 June 2013" version="1.2.3">
       Added support for statically linked agents.
   </change>
-  <change date="20 January 2016" version="9.0.0">
+  <change date="5 July 2016" version="9.0.0">
       Support for modules:
        - The majorversion is 9 now
        - The ClassFileLoadHook events are not sent during the primordial phase anymore.
        - Add new function GetAllModules
-  </change>
-  <change date="17 February 2016" version="9.0.0">
-      Support for modules:
        - Add new capability can_generate_early_vmstart
        - Allow CompiledMethodLoad events at start phase
-  </change>
-  <change date="14 April 2016" version="9.0.0">
-      Support for modules:
        - Add new capability can_generate_early_class_hook_events
+       - Add new function GetNamedModule
   </change>
 </changehistory>
 
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/classLoaderExt.hpp"
+#include "classfile/modules.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "interpreter/bytecodeStream.hpp"
@@ -201,6 +202,28 @@
 } /* end GetAllModules */
 
 
+// class_loader - NULL is a valid value, must be pre-checked
+// package_name - pre-checked for NULL
+// module_ptr - pre-checked for NULL
+jvmtiError
+JvmtiEnv::GetNamedModule(jobject class_loader, const char* package_name, jobject* module_ptr) {
+  JavaThread* THREAD = JavaThread::current(); // pass to macros
+  ResourceMark rm(THREAD);
+
+  Handle h_loader (THREAD, JNIHandles::resolve(class_loader));
+  // Check that loader is a subclass of java.lang.ClassLoader.
+  if (h_loader.not_null() && !java_lang_ClassLoader::is_subclass(h_loader->klass())) {
+    return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+  }
+  jobject module = Modules::get_named_module(h_loader, package_name, THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    CLEAR_PENDING_EXCEPTION;
+    return JVMTI_ERROR_INTERNAL; // unexpected exception
+  }
+  *module_ptr = module;
+  return JVMTI_ERROR_NONE;
+} /* end GetNamedModule */
+
   //
   // Class functions
   //
--- a/hotspot/src/share/vm/runtime/objectMonitor.cpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp	Wed Jul 27 13:33:55 2016 +0000
@@ -131,8 +131,6 @@
 static int Knob_QMode               = 0;       // EntryList-cxq policy - queue discipline
 static volatile int InitDone        = 0;
 
-#define TrySpin TrySpin_VaryDuration
-
 // -----------------------------------------------------------------------------
 // Theory of operations -- Monitors lists, thread residency, etc:
 //
@@ -1848,13 +1846,8 @@
 // hysteresis control to damp the transition rate between spinning and
 // not spinning.
 
-intptr_t ObjectMonitor::SpinCallbackArgument = 0;
-int (*ObjectMonitor::SpinCallbackFunction)(intptr_t, int) = NULL;
-
 // Spinning: Fixed frequency (100%), vary duration
-
-
-int ObjectMonitor::TrySpin_VaryDuration(Thread * Self) {
+int ObjectMonitor::TrySpin(Thread * Self) {
   // Dumb, brutal spin.  Good for comparative measurements against adaptive spinning.
   int ctr = Knob_FixedSpin;
   if (ctr != 0) {
@@ -1948,11 +1941,6 @@
         goto Abort;           // abrupt spin egress
       }
       if (Knob_UsePause & 1) SpinPause();
-
-      int (*scb)(intptr_t,int) = SpinCallbackFunction;
-      if (hits > 50 && scb != NULL) {
-        int abend = (*scb)(SpinCallbackArgument, 0);
-      }
     }
 
     if (Knob_UsePause & 2) SpinPause();
--- a/hotspot/src/share/vm/runtime/objectMonitor.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/runtime/objectMonitor.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -161,9 +161,6 @@
   Thread * volatile _Responsible;
 
   volatile int _Spinner;            // for exit->spinner handoff optimization
-  volatile int _SpinFreq;           // Spin 1-out-of-N attempts: success rate
-  volatile int _SpinClock;
-  volatile intptr_t _SpinState;     // MCS/CLH list of spinners
   volatile int _SpinDuration;
 
   volatile jint  _count;            // reference count to prevent reclamation/deflation
@@ -238,10 +235,6 @@
   static int cxq_offset_in_bytes()         { return offset_of(ObjectMonitor, _cxq); }
   static int succ_offset_in_bytes()        { return offset_of(ObjectMonitor, _succ); }
   static int EntryList_offset_in_bytes()   { return offset_of(ObjectMonitor, _EntryList); }
-  static int FreeNext_offset_in_bytes()    { return offset_of(ObjectMonitor, FreeNext); }
-  static int WaitSet_offset_in_bytes()     { return offset_of(ObjectMonitor, _WaitSet); }
-  static int Responsible_offset_in_bytes() { return offset_of(ObjectMonitor, _Responsible); }
-  static int Spinner_offset_in_bytes()     { return offset_of(ObjectMonitor, _Spinner); }
 
   // ObjectMonitor references can be ORed with markOopDesc::monitor_value
   // as part of the ObjectMonitor tagging mechanism. When we combine an
@@ -257,11 +250,6 @@
   #define OM_OFFSET_NO_MONITOR_VALUE_TAG(f) \
     ((ObjectMonitor::f ## _offset_in_bytes()) - markOopDesc::monitor_value)
 
-  // Eventually we'll make provisions for multiple callbacks, but
-  // now one will suffice.
-  static int (*SpinCallbackFunction)(intptr_t, int);
-  static intptr_t SpinCallbackArgument;
-
   markOop   header() const;
   void      set_header(markOop hdr);
 
@@ -312,8 +300,6 @@
     _cxq           = NULL;
     _WaitSet       = NULL;
     _recursions    = 0;
-    _SpinFreq      = 0;
-    _SpinClock     = 0;
   }
 
  public:
@@ -353,9 +339,7 @@
   void      UnlinkAfterAcquire(Thread * Self, ObjectWaiter * SelfNode);
   int       TryLock(Thread * Self);
   int       NotRunnable(Thread * Self, Thread * Owner);
-  int       TrySpin_Fixed(Thread * Self);
-  int       TrySpin_VaryFrequency(Thread * Self);
-  int       TrySpin_VaryDuration(Thread * Self);
+  int       TrySpin(Thread * Self);
   void      ExitEpilog(Thread * Self, ObjectWaiter * Wakee);
   bool      ExitSuspendEquivalent(JavaThread * Self);
   void      post_monitor_wait_event(EventJavaMonitorWait * event,
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -144,8 +144,6 @@
   static void verify() PRODUCT_RETURN;
   static int  verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0;
 
-  static void RegisterSpinCallback(int(*)(intptr_t, int), intptr_t);
-
  private:
   enum { _BLOCKSIZE = 128 };
   // global list of blocks of monitors
--- a/hotspot/test/compiler/ciReplay/TestVM_no_comp_level.sh	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/compiler/ciReplay/TestVM_no_comp_level.sh	Wed Jul 27 13:33:55 2016 +0000
@@ -29,6 +29,7 @@
 ## @summary testing of ciReplay with using generated by VM replay.txt w/o comp_level
 ## @author igor.ignatyev@oracle.com
 ## @requires vm.flightRecorder != true
+## @ignore 8157984
 ## @run shell TestVM_no_comp_level.sh
 ##
 
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java	Wed Jul 27 13:33:55 2016 +0000
@@ -25,6 +25,7 @@
  * @test
  * @requires (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "aarch64")
  * @library ../../../../../
+ * @ignore 8161550
  * @modules java.base/jdk.internal.reflect
  *          jdk.vm.ci/jdk.vm.ci.meta
  *          jdk.vm.ci/jdk.vm.ci.runtime
--- a/hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java	Wed Jul 27 13:33:55 2016 +0000
@@ -28,6 +28,7 @@
  * @library /testlibrary /test/lib /
  * @modules java.base/jdk.internal.misc
  *          java.management
+ * @ignore 8157984
  * @build TestRangeCheckSmearing
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *                                jdk.test.lib.Platform
--- a/hotspot/test/compiler/tiered/NonTieredLevelsTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/compiler/tiered/NonTieredLevelsTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -26,6 +26,7 @@
  * @library /testlibrary /test/lib /
  * @modules java.base/jdk.internal.misc
  * @modules java.management
+ * @ignore 8157984
  * @build NonTieredLevelsTest
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/unsafe/OpaqueAccesses.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 8155781
+ * @modules java.base/jdk.internal.misc
+ *
+ * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
+ *                                 -XX:-TieredCompilation -Xbatch
+ *                                 -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*
+ *                                 compiler.unsafe.OpaqueAccesses
+ */
+package compiler.unsafe;
+
+import jdk.internal.misc.Unsafe;
+
+import java.lang.reflect.Field;
+
+public class OpaqueAccesses {
+    private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
+    private static final Object INSTANCE = new OpaqueAccesses();
+
+    private static final Object[] ARRAY = new Object[10];
+
+    private static final long F_OFFSET;
+    private static final long E_OFFSET;
+
+    static {
+        try {
+            Field field = OpaqueAccesses.class.getDeclaredField("f");
+            F_OFFSET = UNSAFE.objectFieldOffset(field);
+
+            E_OFFSET = UNSAFE.arrayBaseOffset(ARRAY.getClass());
+        } catch (NoSuchFieldException e) {
+            throw new Error(e);
+        }
+    }
+
+    private Object f = new Object();
+
+    static Object testFixedOffsetField(Object o) {
+        return UNSAFE.getObject(o, F_OFFSET);
+    }
+
+    static int testFixedOffsetHeader0(Object o) {
+        return UNSAFE.getInt(o, 0);
+    }
+
+    static int testFixedOffsetHeader4(Object o) {
+        return UNSAFE.getInt(o, 4);
+    }
+
+    static Object testFixedBase(long off) {
+        return UNSAFE.getObject(INSTANCE, off);
+    }
+
+    static Object testOpaque(Object o, long off) {
+        return UNSAFE.getObject(o, off);
+    }
+
+    static int testFixedOffsetHeaderArray0(Object[] arr) {
+        return UNSAFE.getInt(arr, 0);
+    }
+
+    static int testFixedOffsetHeaderArray4(Object[] arr) {
+        return UNSAFE.getInt(arr, 4);
+    }
+
+    static Object testFixedOffsetArray(Object[] arr) {
+        return UNSAFE.getObject(arr, E_OFFSET);
+    }
+
+    static Object testFixedBaseArray(long off) {
+        return UNSAFE.getObject(ARRAY, off);
+    }
+
+    static Object testOpaqueArray(Object[] o, long off) {
+        return UNSAFE.getObject(o, off);
+    }
+
+    static final long ADDR = UNSAFE.allocateMemory(10);
+    static boolean flag;
+
+    static int testMixedAccess() {
+        flag = !flag;
+        Object o = (flag ? INSTANCE : null);
+        long off = (flag ? F_OFFSET : ADDR);
+        return UNSAFE.getInt(o, off);
+    }
+
+    public static void main(String[] args) {
+        for (int i = 0; i < 20_000; i++) {
+            // Instance
+            testFixedOffsetField(INSTANCE);
+            testFixedOffsetHeader0(INSTANCE);
+            testFixedOffsetHeader4(INSTANCE);
+            testFixedBase(F_OFFSET);
+            testOpaque(INSTANCE, F_OFFSET);
+            testMixedAccess();
+
+            // Array
+            testFixedOffsetHeaderArray0(ARRAY);
+            testFixedOffsetHeaderArray4(ARRAY);
+            testFixedOffsetArray(ARRAY);
+            testFixedBaseArray(E_OFFSET);
+            testOpaqueArray(ARRAY, E_OFFSET);
+        }
+        System.out.println("TEST PASSED");
+    }
+}
--- a/hotspot/test/gc/TestSmallHeap.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/gc/TestSmallHeap.java	Wed Jul 27 13:33:55 2016 +0000
@@ -27,6 +27,7 @@
  * @requires vm.gc=="null"
  * @summary Verify that starting the VM with a small heap works
  * @library /testlibrary /test/lib /test/lib/share/classes
+ * @ignore 8161552
  * @modules java.base/jdk.internal.misc
  * @modules java.management/sun.management
  * @build TestSmallHeap
--- a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java	Wed Jul 27 13:33:55 2016 +0000
@@ -29,6 +29,7 @@
  * parallel collectors.
  * @requires vm.gc=="null"
  * @library /testlibrary /test/lib
+ * @ignore 8161552
  * @modules java.base/jdk.internal.misc
  *          java.management
  * @build TestParallelHeapSizeFlags TestMaxHeapSizeTools
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/ergonomics/TestInitialGCThreadLogging.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 2016, 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 TestInitialGCThreadLogging
+ * @bug 8157240
+ * @summary Check trace logging of initial GC threads.
+ * @requires vm.gc=="null"
+ * @key gc
+ * @modules java.base/jdk.internal.misc
+ * @library /testlibrary
+ */
+
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.OutputAnalyzer;
+
+public class TestInitialGCThreadLogging {
+  public static void main(String[] args) throws Exception {
+
+    testInitialGCThreadLogging("UseConcMarkSweepGC", "GC Thread");
+
+    testInitialGCThreadLogging("UseG1GC", "GC Thread");
+
+    testInitialGCThreadLogging("UseParallelGC", "ParGC Thread");
+  }
+
+  private static void verifyDynamicNumberOfGCThreads(OutputAnalyzer output, String threadName) {
+    output.shouldHaveExitValue(0); // test should run succesfully
+    output.shouldContain(threadName);
+  }
+
+  private static void testInitialGCThreadLogging(String gcFlag, String threadName) throws Exception {
+    // UseDynamicNumberOfGCThreads and TraceDynamicGCThreads enabled
+    String[] baseArgs = {"-XX:+" + gcFlag, "-Xmx10M", "-XX:+UseDynamicNumberOfGCThreads", "-Xlog:gc+task=trace", "-version"};
+
+    // Base test with gc and +UseDynamicNumberOfGCThreads:
+    ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder(baseArgs);
+    verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()), threadName);
+  }
+}
--- a/hotspot/test/gc/g1/TestStringSymbolTableStats.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/gc/g1/TestStringSymbolTableStats.java	Wed Jul 27 13:33:55 2016 +0000
@@ -46,7 +46,7 @@
 
     System.out.println("Output:\n" + output.getOutput());
 
-    output.shouldContain("Cleaned string and symbol table");
+    output.shouldMatch("GC\\(\\d+\\) Cleaned string and symbol table");
     output.shouldHaveExitValue(0);
   }
 
--- a/hotspot/test/gc/metaspace/TestMetaspaceInitialization.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/gc/metaspace/TestMetaspaceInitialization.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -24,11 +24,11 @@
 import java.util.ArrayList;
 
 /* @test TestMetaspaceInitialization
- * @bug 8042933
+ * @bug 8024945
  * @summary Tests to initialize metaspace with a very low MetaspaceSize
  * @modules java.base/jdk.internal.misc
  * @library /testlibrary
- * @run main/othervm -XX:MetaspaceSize=2m TestMetaspaceInitialization
+ * @run main/othervm -XX:MetaspaceSize=0 TestMetaspaceInitialization
  */
 public class TestMetaspaceInitialization {
     private class Internal {
--- a/hotspot/test/gc/metaspace/TestMetaspaceSizeFlags.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/gc/metaspace/TestMetaspaceSizeFlags.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -47,9 +47,6 @@
     // 8024650: MaxMetaspaceSize was adjusted instead of MetaspaceSize.
     testMaxMetaspaceSizeLTMetaspaceSize(MAX_ALIGNMENT, MAX_ALIGNMENT * 2);
     testMaxMetaspaceSizeGTMetaspaceSize(MAX_ALIGNMENT * 2, MAX_ALIGNMENT);
-    testTooSmallInitialMetaspace(0, 0);
-    testTooSmallInitialMetaspace(0, MAX_ALIGNMENT);
-    testTooSmallInitialMetaspace(MAX_ALIGNMENT, 0);
   }
 
   private static void testMaxMetaspaceSizeEQMetaspaceSize(long maxMetaspaceSize, long metaspaceSize) throws Exception {
@@ -73,11 +70,6 @@
     Asserts.assertEQ(mf.metaspaceSize, metaspaceSize);
   }
 
-  private static void testTooSmallInitialMetaspace(long maxMetaspaceSize, long metaspaceSize) throws Exception {
-    OutputAnalyzer output = run(maxMetaspaceSize, metaspaceSize);
-    output.shouldContain("Too small initial Metaspace size");
-  }
-
   private static MetaspaceFlags runAndGetValue(long maxMetaspaceSize, long metaspaceSize) throws Exception {
     OutputAnalyzer output = run(maxMetaspaceSize, metaspaceSize);
     output.shouldNotMatch("Error occurred during initialization of VM\n.*");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Final/TestPutField.jasm	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ */
+
+public class TestPutField
+version 53:0
+{
+
+final Field test_field:"I";
+
+
+public Method <init>:"()V"
+       stack 2 locals 1
+{
+	aload_0;
+	dup;
+	invokespecial Method java/lang/Object.<init>:"()V";
+	bipush 13;
+        putfield Field test_field:"I";
+        return;
+}
+
+public Method aMethod:"()I"
+       stack 2 locals 2
+{
+	aload_0;
+	getfield Field test_field:"I";
+	istore_1;
+	aload_0;
+	bipush 14;
+        putfield Field test_field:"I";
+	iload_1;
+        ireturn;
+}
+
+
+public static Method test:"()V"
+       stack 2 locals 2
+{
+	new class TestPutField;
+	astore_0;
+	aload_0;
+	invokespecial Method <init>:"()V";
+	getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
+	astore_1;
+	aload_1;
+	aload_0;
+	invokevirtual Method aMethod:"()I";
+	invokevirtual Method java/io/PrintStream.println:"(I)V";
+	aload_1;
+	aload_0;
+	getfield Field test_field:"I";	
+	invokevirtual Method java/io/PrintStream.println:"(I)V";
+        return;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Final/TestPutMain.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, 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 8160527
+ * @summary The VM does not always perform checks added by 8157181 when updating final instance fields
+ * @library /testlibrary
+ * @compile TestPutField.jasm
+ * @compile TestPutStatic.jasm
+ * @compile TestPutMain.java
+ * @run main/othervm TestPutMain
+ */
+
+import jdk.test.lib.Asserts;
+
+public class TestPutMain {
+    public static void main(String[] args) {
+        boolean exception = false;
+        try {
+            TestPutField.test();
+        } catch (java.lang.IllegalAccessError e) {
+            exception = true;
+        }
+
+        Asserts.assertTrue(exception, "FAILED: Expected IllegalAccessError for illegal update to final instance field was not thrown.");
+
+        exception = false;
+        try {
+            TestPutStatic.test();
+        } catch (java.lang.IllegalAccessError e) {
+            exception = true;
+        }
+
+        Asserts.assertTrue(exception, "FAILED: Expected IllegalAccessError for illegal update to final static field was not thrown.");
+
+        System.out.println("PASSED: Expected IllegalAccessError was thrown.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Final/TestPutStatic.jasm	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ */
+
+public class TestPutStatic
+version 53:0
+{
+
+final static Field test_field:"I";
+
+
+public static Method <clinit>:"()V"
+       stack 2 locals 1
+{
+	bipush 13;
+        putstatic Field test_field:"I";
+        return;
+}
+
+public static Method aMethod:"()I"
+       stack 1 locals 1
+{
+	getstatic Field test_field:"I";
+	istore_0;
+	bipush 14;
+        putstatic Field test_field:"I";
+	iload_0;
+        ireturn;
+}
+
+
+public static Method test:"()V"
+       stack 2 locals 1
+{
+	getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
+	astore_0;
+	aload_0;
+	invokestatic Method aMethod:"()I";
+	invokevirtual Method java/io/PrintStream.println:"(I)V";
+	aload_0;
+	getstatic Field test_field:"I";	
+	invokevirtual Method java/io/PrintStream.println:"(I)V";
+        return;
+}
+
+}
--- a/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -24,6 +24,9 @@
 /*
  * @test SASymbolTableTest
  * @summary Walk symbol table using SA, with and without CDS.
+ * Started failing on 2016.06.24 due to 8160376 on MacOS X so quarantine
+ * it on that platform:
+ * @requires os.family != "mac"
  * @library /testlibrary
  * @modules java.base/jdk.internal.misc
  *          jdk.hotspot.agent/sun.jvm.hotspot.oops
--- a/hotspot/test/runtime/Unsafe/GetUnsafe.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/runtime/Unsafe/GetUnsafe.java	Wed Jul 27 13:33:55 2016 +0000
@@ -26,6 +26,7 @@
  * @summary Verifies that getUnsafe() actually throws SecurityException when unsafeAccess is prohibited.
  * @library /testlibrary
  * @modules java.base/jdk.internal.misc
+ * @ignore 8161947
  * @run main GetUnsafe
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/GetNamedModule/MyPackage/GetNamedModuleTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+package MyPackage;
+
+/**
+ * @test
+ * @summary Verifies the JVMTI GetNamedModule API
+ * @compile GetNamedModuleTest.java
+ * @run main/othervm/native -agentlib:GetNamedModuleTest MyPackage.GetNamedModuleTest
+ */
+
+import java.io.PrintStream;
+
+public class GetNamedModuleTest {
+
+    static {
+        try {
+            System.loadLibrary("GetNamedModuleTest");
+        } catch (UnsatisfiedLinkError ule) {
+            System.err.println("Could not load GetNamedModuleTest library");
+            System.err.println("java.library.path: "
+                + System.getProperty("java.library.path"));
+            throw ule;
+        }
+    }
+
+    native static int check();
+
+    public static void main(String args[]) {
+        int status = check();
+        if (status != 0) {
+            throw new RuntimeException("Non-zero status returned from the agent: " + status);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/GetNamedModule/libGetNamedModuleTest.c	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2016, 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 <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+#define PASSED 0
+#define FAILED 2
+
+static const char *EXC_CNAME = "java/lang/Exception";
+static const char* MOD_CNAME = "Ljava/lang/reflect/Module;";
+
+static jvmtiEnv *jvmti = NULL;
+static jint result = PASSED;
+static jboolean printdump = JNI_FALSE;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+    return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+    return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+    return JNI_VERSION_1_8;
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+    jint res;
+
+    if (options != NULL && strcmp(options, "printdump") == 0) {
+        printdump = JNI_TRUE;
+    }
+
+    res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+        JVMTI_VERSION_9);
+    if (res != JNI_OK || jvmti == NULL) {
+        printf("    Error: wrong result of a valid call to GetEnv!\n");
+        return JNI_ERR;
+    }
+
+    return JNI_OK;
+}
+
+static
+jint throw_exc(JNIEnv *env, char *msg) {
+    jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
+
+    if (exc_class == NULL) {
+        printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
+        return -1;
+    }
+    return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+}
+
+static
+jobject get_class_loader(jclass cls) {
+    jvmtiError err = JVMTI_ERROR_NONE;
+    jobject loader = NULL;
+
+    if (printdump == JNI_TRUE) {
+        printf(">>> getting class loader ...\n");
+    }
+    err = (*jvmti)->GetClassLoader(jvmti, cls, &loader);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("    Error in GetClassLoader: %s (%d)\n", TranslateError(err), err);
+    }
+    return loader;
+}
+
+static
+jclass jlrM(JNIEnv *env) {
+    jclass cls = NULL;
+
+    cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, MOD_CNAME));
+    if (cls == NULL) {
+        printf("    Error in JNI FindClass: %s\n", MOD_CNAME);
+    }
+    return cls;
+}
+
+jmethodID
+get_method(JNIEnv *env, jclass clazz, const char * name, const char *sig) {
+    jmethodID method = NULL;
+
+    method = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, clazz), name, sig);
+    if (method == NULL) {
+        printf("    Error in JNI GetMethodID %s with signature %s", name, sig);
+    }
+    return method;
+}
+
+static
+jobject get_module_loader(JNIEnv *env, jobject module) {
+    static jmethodID cl_method = NULL;
+    jobject loader = NULL;
+
+    if (cl_method == NULL) {
+        cl_method = get_method(env, jlrM(env), "getClassLoader", "()Ljava/lang/ClassLoader;");
+    }
+    loader = (jobject)JNI_ENV_PTR(env)->CallObjectMethod(JNI_ENV_ARG(env, module), cl_method);
+    return loader;
+}
+
+static
+const char* get_module_name(JNIEnv *env, jobject module) {
+    static jmethodID method = NULL;
+    jobject loader = NULL;
+    jstring jstr = NULL;
+    const char *name = NULL;
+    const char *nstr = NULL;
+
+    if (method == NULL) {
+        method = get_method(env, jlrM(env), "getName", "()Ljava/lang/String;");
+    }
+    jstr = (jstring)JNI_ENV_PTR(env)->CallObjectMethod(JNI_ENV_ARG(env, module), method);
+    if (jstr != NULL) {
+        name = JNI_ENV_PTR(env)->GetStringUTFChars(JNI_ENV_ARG(env, jstr), NULL);
+    }
+    loader = get_module_loader(env, module);
+    nstr = (name == NULL) ? "<UNNAMED>" : name;
+    printf("    loader: %p, module: %p, name: %s\n", loader, module, nstr);
+    return name;
+}
+
+static
+jvmtiError get_module(JNIEnv *env,
+                      jobject loader,
+                      const char* pkg_name,
+                      jobject* module_ptr,
+                      const char** mod_name_ptr) {
+    jvmtiError err = JVMTI_ERROR_NONE;
+    const char* name = (pkg_name == NULL) ? "<NULL>" : pkg_name;
+
+    printf(">>> getting module by loader %p and package \"%s\"\n", loader, name);
+    *mod_name_ptr = NULL;
+    err = (*jvmti)->GetNamedModule(jvmti, loader, pkg_name, module_ptr);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("    Error in GetNamedModule for package \"%s\": %s (%d)\n",
+               pkg_name, TranslateError(err), err);
+        return err;
+    }
+    printf("    returned module: %p\n", *module_ptr);
+    if (*module_ptr == NULL) { // named module was not found
+        return err;
+    }
+    *mod_name_ptr = get_module_name(env, *module_ptr);
+    return err;
+}
+
+static
+jint get_all_modules(JNIEnv *env) {
+    jvmtiError err;
+    jint cnt = -1;
+    jint idx = 0;
+    jobject* modules;
+
+    printf(">>> Inspecting modules with GetAllModules\n");
+    err = (*jvmti)->GetAllModules(jvmti, &cnt, &modules);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("Error in GetAllModules: %d\n", err);
+        return -1;
+    }
+    for (idx = 0; idx < cnt; ++idx) {
+        get_module_name(env, modules[idx]);
+    }
+    return cnt;
+}
+
+static
+jint check_bad_loader(JNIEnv *env, jobject loader) {
+    jvmtiError err = JVMTI_ERROR_NONE;
+    jobject module = NULL;
+    const char* mod_name = NULL;
+
+    err = get_module(env, loader, "", &module, &mod_name);
+    if (err != JVMTI_ERROR_ILLEGAL_ARGUMENT) {
+        return FAILED;
+    }
+    printf("    got expected JVMTI_ERROR_ILLEGAL_ARGUMENT for bad loader\n");
+    return PASSED;
+}
+
+static
+jint check_system_loader(JNIEnv *env, jobject loader) {
+    jvmtiError err = JVMTI_ERROR_NONE;
+    jobject module = NULL;
+    const char* exp_name = NULL;
+    const char* mod_name = NULL;
+
+    // NULL pointer for package name
+    err = get_module(env, loader, NULL, &module, &mod_name);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        throw_exc(env, "check #SN1: failed to return JVMTI_ERROR_NULL_POINTER for NULL package");
+        return FAILED;
+    }
+
+    // NULL pointer for module_ptr
+    err = (*jvmti)->GetNamedModule(jvmti, loader, "", NULL);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        throw_exc(env, "check #SN2: failed to return JVMTI_ERROR_NULL_POINTER for NULL module_ptr");
+        return FAILED;
+    }
+
+    // Unnamed/default package ""
+    err = get_module(env, loader, "", &module, &mod_name);
+    if (err != JVMTI_ERROR_NONE) {
+        throw_exc(env, "check #S1: failed to return JVMTI_ERROR_NONE for default package");
+        return FAILED;
+    }
+    if (module != NULL || mod_name != NULL) {
+        throw_exc(env, "check #S2: failed to return NULL-module for default package");
+        return FAILED;
+    }
+
+    // Test package: MyPackage
+    err = get_module(env, loader, "MyPackage", &module, &mod_name);
+    if (err != JVMTI_ERROR_NONE) {
+        throw_exc(env, "check #S3: failed to return JVMTI_ERROR_NONE for MyPackage");
+        return FAILED;
+    }
+    if (module != NULL || mod_name != NULL) {
+        throw_exc(env, "check #S4: failed to return NULL-module for MyPackage");
+        return FAILED;
+    }
+
+    // Package: com/sun/jdi
+    exp_name = "jdk.jdi";
+    err = get_module(env, loader, "com/sun/jdi", &module, &mod_name);
+    if (err != JVMTI_ERROR_NONE) {
+        throw_exc(env, "check #S5: failed to return JVMTI_ERROR_NONE for test package");
+        return FAILED;
+    }
+    if (module == NULL || mod_name == NULL) {
+        throw_exc(env, "check #S6: failed to return named module for com/sun/jdi package");
+        return FAILED;
+    }
+    if (strcmp(mod_name, exp_name) != 0) {
+        printf("check #S7: failed to return right module, expected: %s, returned: %s\n",
+               exp_name, mod_name);
+        throw_exc(env, "check #S7: failed to return jdk.jdi module for com/sun/jdi package");
+        return FAILED;
+    }
+
+    // Non-existing package: "bad/package/name"
+    err = get_module(env, loader, "bad/package/name", &module, &mod_name);
+    if (err != JVMTI_ERROR_NONE) {
+        throw_exc(env, "check #S8: failed to return JVMTI_ERROR_NONE for bad package");
+        return FAILED;
+    }
+    if (module != NULL || mod_name != NULL) {
+        throw_exc(env, "check #S9: failed to return NULL-module for bad package");
+        return FAILED;
+    }
+    return PASSED;
+}
+
+static
+jint check_bootstrap_loader(JNIEnv *env, jobject loader) {
+    jvmtiError err = JVMTI_ERROR_NONE;
+    jobject module = NULL;
+    const char* exp_name = NULL;
+    const char* mod_name = NULL;
+
+    // NULL pointer for package name
+    err = get_module(env, loader, NULL, &module, &mod_name);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        throw_exc(env, "check #BN1: failed to return JVMTI_ERROR_NULL_POINTER for NULL package");
+        return FAILED;
+    }
+
+    // NULL pointer for module_ptr
+    err = (*jvmti)->GetNamedModule(jvmti, loader, "", NULL);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        throw_exc(env, "check #BN2: failed to return JVMTI_ERROR_NULL_POINTER for NULL module_ptr");
+        return FAILED;
+    }
+
+    // Unnamed/default package ""
+    err = get_module(env, loader, "", &module, &mod_name);
+    if (err != JVMTI_ERROR_NONE) {
+        throw_exc(env, "check #B1: failed to return JVMTI_ERROR_NONE for default package");
+        return FAILED;
+    }
+    if (module != NULL || mod_name != NULL) {
+        throw_exc(env, "check #B2: failed to return NULL-module for default package");
+        return FAILED;
+    }
+
+    // Normal package from java.base module: "java/lang"
+    exp_name = "java.base";
+    err = get_module(env, loader, "java/lang", &module, &mod_name);
+    if (err != JVMTI_ERROR_NONE) {
+        throw_exc(env, "check #B3: failed to return JVMTI_ERROR_NONE for java/lang package");
+        return FAILED;
+    }
+    if (module == NULL || mod_name == NULL) {
+        throw_exc(env, "check #B4: failed to return named module for java/lang package");
+        return FAILED;
+    }
+    if (strcmp(exp_name, mod_name) != 0) {
+        printf("check #B5: failed to return right module, expected: %s, returned: %s\n",
+               exp_name, mod_name);
+        throw_exc(env, "check #B5: failed to return expected module for java/lang package");
+        return FAILED;
+    }
+
+    // Non-existing package: "bad/package/name"
+    err = get_module(env, loader, "bad/package/name", &module, &mod_name);
+    if (err != JVMTI_ERROR_NONE) {
+        throw_exc(env, "check #B6: failed to return JVMTI_ERROR_NONE for bad package");
+        return FAILED;
+    }
+    if (module != NULL || mod_name != NULL) {
+        throw_exc(env, "check #B7: failed to return NULL-module for bad package");
+        return FAILED;
+    }
+    return PASSED;
+}
+
+JNIEXPORT jint JNICALL
+Java_MyPackage_GetNamedModuleTest_check(JNIEnv *env, jclass cls) {
+    jobject loader = NULL;
+
+    if (jvmti == NULL) {
+        throw_exc(env, "JVMTI client was not properly loaded!\n");
+        return FAILED;
+    }
+
+    get_all_modules(env);
+
+    printf("\n*** Check for bad ClassLoader ***\n\n");
+    result = check_bad_loader(env, (jobject)cls);
+    if (result != PASSED) {
+        throw_exc(env, "check #L1: failed to return JVMTI_ERROR_ILLEGAL_ARGUMENT for bad loader");
+        return result;
+    }
+
+    loader = get_class_loader(cls);
+    if (loader == NULL) {
+        throw_exc(env, "check #L2: failed to return non-NULL loader for valid test class");
+        return FAILED;
+    }
+
+    printf("\n*** Checks for System ClassLoader ***\n\n");
+    result = check_system_loader(env, loader);
+    if (result != PASSED) {
+        return result;
+    }
+
+    printf("\n*** Checks for Bootstrap ClassLoader ***\n\n");
+    result = check_bootstrap_loader(env, NULL);
+
+    return result;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- a/hotspot/test/serviceability/sa/TestClassLoaderStats.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/serviceability/sa/TestClassLoaderStats.java	Wed Jul 27 13:33:55 2016 +0000
@@ -32,6 +32,9 @@
 
 /*
  * @test
+ * @summary Started failing on 2016.06.24 due to 8160376 on MacOS X so
+ * quarantine it on that platform:
+ * @requires os.family != "mac"
  * @modules java.base/jdk.internal.misc
  * @library /test/lib/share/classes
  * @library /testlibrary
--- a/hotspot/test/serviceability/sa/TestStackTrace.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/serviceability/sa/TestStackTrace.java	Wed Jul 27 13:33:55 2016 +0000
@@ -32,6 +32,9 @@
 
 /*
  * @test
+ * @summary Started failing on 2016.06.24 due to 8160376 on MacOS X so
+ * quarantine it on that platform:
+ * @requires os.family != "mac"
  * @modules java.base/jdk.internal.misc
  * @library /test/lib/share/classes
  * @library /testlibrary
--- a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -43,6 +43,9 @@
  * @bug 6313383
  * @key regression
  * @summary Regression test for hprof export issue due to large heaps (>2G)
+ * Started failing on 2016.06.24 due to 8160376 on MacOS X so quarantine
+ * it on that platform:
+ * @requires os.family != "mac"
  * @library /testlibrary
  * @modules java.base/jdk.internal.misc
  *          java.compiler
--- a/jaxp/.hgtags	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/.hgtags	Wed Jul 27 13:33:55 2016 +0000
@@ -370,3 +370,4 @@
 493eb91ec32a6dea7604cfbd86c10045ad9af15b jdk-9+125
 15722f71281f034bc696d8b96136da2ef34da44f jdk-9+126
 bdc3c0b737efbf899709eb3121ce760dcfb51151 jdk-9+127
+8a7681a9d70640ac7fbf05c28f53c1d51d8d00a1 jdk-9+128
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/XalanConstants.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/XalanConstants.java	Wed Jul 27 13:33:55 2016 +0000
@@ -80,6 +80,14 @@
      */
     public static final String JDK_GENERAL_ENTITY_SIZE_LIMIT =
             ORACLE_JAXP_PROPERTY_PREFIX + "maxGeneralEntitySizeLimit";
+
+    /**
+     * JDK node count limit in entities that limits the total number of nodes
+     * in all of entity references.
+     */
+    public static final String JDK_ENTITY_REPLACEMENT_LIMIT =
+            ORACLE_JAXP_PROPERTY_PREFIX + "entityReplacementLimit";
+
     /**
      * JDK maximum parameter entity size limit
      */
@@ -136,6 +144,13 @@
      * JDK maximum general entity size limit
      */
     public static final String SP_GENERAL_ENTITY_SIZE_LIMIT = "jdk.xml.maxGeneralEntitySizeLimit";
+
+    /**
+     * JDK node count limit in entities that limits the total number of nodes
+     * in all of entity references.
+     */
+    public static final String SP_ENTITY_REPLACEMENT_LIMIT = "jdk.xml.entityReplacementLimit";
+
     /**
      * JDK maximum parameter entity size limit
      */
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -82,7 +82,9 @@
         MAX_ELEMENT_DEPTH_LIMIT("MaxElementDepthLimit", XalanConstants.JDK_MAX_ELEMENT_DEPTH,
                 XalanConstants.SP_MAX_ELEMENT_DEPTH, 0, 0),
         MAX_NAME_LIMIT("MaxXMLNameLimit", XalanConstants.JDK_XML_NAME_LIMIT,
-                XalanConstants.SP_XML_NAME_LIMIT, 1000, 1000);
+                XalanConstants.SP_XML_NAME_LIMIT, 1000, 1000),
+        ENTITY_REPLACEMENT_LIMIT("EntityReplacementLimit", XalanConstants.JDK_ENTITY_REPLACEMENT_LIMIT,
+                XalanConstants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000);
 
         final String key;
         final String apiProperty;
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Constants.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Constants.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,15 +1,15 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * Copyright 2001-2004 The Apache Software Foundation.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -98,6 +98,10 @@
     public static final int ACC_STATIC
         = com.sun.org.apache.bcel.internal.Constants.ACC_STATIC;
 
+    public static final String MODULE_SIG
+        = "Ljava/lang/reflect/Module;";
+    public static final String CLASS_SIG
+        = "Ljava/lang/Class;";
     public static final String STRING_SIG
         = "Ljava/lang/String;";
     public static final String STRING_BUFFER_SIG
@@ -246,8 +250,12 @@
         = "com.sun.org.apache.xalan.internal.xsltc.DOM";
     public static final String DOM_IMPL
         = "com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl";
-        public static final String SAX_IMPL
+    public static final String SAX_IMPL
         = "com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl";
+    public static final String CLASS_CLASS
+        = "java.lang.Class";
+    public static final String MODULE_CLASS
+        = "java.lang.reflect.Module";
     public static final String STRING_CLASS
         = "java.lang.String";
     public static final String OBJECT_CLASS
@@ -293,7 +301,7 @@
         = "()D";
 
     public static final String DOM_PNAME
-  = "dom";
+        = "dom";
     public static final String NODE_PNAME
         = "node";
     public static final String TRANSLET_OUTPUT_PNAME
@@ -335,6 +343,19 @@
         = "setStartNode";
     public static final String RESET
         = "reset";
+    public static final String GET_MODULE
+        = "getModule";
+    public static final String FOR_NAME
+        = "forName";
+    public static final String ADD_READS
+        = "addReads";
+
+    public static final String GET_MODULE_SIG
+        = "()" + MODULE_SIG;
+    public static final String FOR_NAME_SIG
+        = "(" + STRING_SIG + ")" + CLASS_SIG;
+    public static final String ADD_READS_SIG
+        = "(" + MODULE_SIG + ")" + MODULE_SIG;
 
     public static final String ATTR_SET_SIG
         = "(" + DOM_INTF_SIG  + NODE_ITERATOR_SIG + TRANSLET_OUTPUT_SIG + "I)V";
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -17,9 +17,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/*
- * $Id: FunctionCall.java,v 1.2.4.1 2005/09/12 10:31:32 pvedula Exp $
- */
 
 package com.sun.org.apache.xalan.internal.xsltc.compiler;
 
@@ -32,6 +29,7 @@
 import com.sun.org.apache.bcel.internal.generic.InstructionConstants;
 import com.sun.org.apache.bcel.internal.generic.InstructionList;
 import com.sun.org.apache.bcel.internal.generic.InvokeInstruction;
+import com.sun.org.apache.bcel.internal.generic.LDC;
 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
 import com.sun.org.apache.bcel.internal.generic.NEW;
 import com.sun.org.apache.bcel.internal.generic.PUSH;
@@ -792,6 +790,11 @@
 
             final String clazz =
                 _chosenConstructor.getDeclaringClass().getName();
+
+            // Generate call to Module.addReads:
+            //   <TransletClass>.class.getModule().addReads(
+            generateAddReads(classGen, methodGen, clazz);
+
             Class[] paramTypes = _chosenConstructor.getParameterTypes();
             LocalVariableGen[] paramTemp = new LocalVariableGen[n];
 
@@ -855,6 +858,12 @@
             final String clazz = _chosenMethod.getDeclaringClass().getName();
             Class[] paramTypes = _chosenMethod.getParameterTypes();
 
+
+            // Generate call to Module.addReads:
+            //   <TransletClass>.class.getModule().addReads(
+            //        Class.forName(<clazz>).getModule());
+            generateAddReads(classGen, methodGen, clazz);
+
             // Push "this" if it is an instance method
             if (_thisArgument != null) {
                 _thisArgument.translate(classGen, methodGen);
@@ -896,6 +905,41 @@
         }
     }
 
+    private void generateAddReads(ClassGenerator classGen, MethodGenerator methodGen,
+                          String clazz) {
+        final ConstantPoolGen cpg = classGen.getConstantPool();
+        final InstructionList il = methodGen.getInstructionList();
+
+        // Generate call to Module.addReads:
+        //   <TransletClass>.class.getModule().addReads(
+        //        Class.forName(<clazz>).getModule());
+        // Class.forName may throw ClassNotFoundException.
+        // This is OK as it will caught higher up the stack in
+        // TransformerImpl.transform() and wrapped into a
+        // TransformerException.
+        methodGen.markChunkStart();
+
+        int index = cpg.addMethodref(CLASS_CLASS,
+                                     GET_MODULE,
+                                     GET_MODULE_SIG);
+        int index2 = cpg.addMethodref(CLASS_CLASS,
+                                      FOR_NAME,
+                                      FOR_NAME_SIG);
+        il.append(new LDC(cpg.addString(classGen.getClassName())));
+        il.append(new INVOKESTATIC(index2));
+        il.append(new INVOKEVIRTUAL(index));
+        il.append(new LDC(cpg.addString(clazz)));
+        il.append(new INVOKESTATIC(index2));
+        il.append(new INVOKEVIRTUAL(index));
+        index = cpg.addMethodref(MODULE_CLASS,
+                                 ADD_READS,
+                                 ADD_READS_SIG);
+        il.append(new INVOKEVIRTUAL(index));
+        il.append(InstructionConstants.POP);
+
+        methodGen.markChunkEnd();
+    }
+
     @Override
     public String toString() {
         return "funcall(" + _fname + ", " + _arguments + ')';
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -58,7 +58,6 @@
 import javax.xml.transform.TransformerConfigurationException;
 import javax.xml.transform.URIResolver;
 
-import jdk.internal.module.Modules;
 
 /**
  * @author Morten Jorgensen
@@ -486,10 +485,6 @@
                 thisModule.addExports(p, m);
             });
 
-            // For now, the module reads all unnnamed modules. This will be changed once
-            // the XSLT compiler is updated to generate code to invoke addReads.
-            Modules.addReadsAllUnnamed(m);
-
             // java.xml needs to instanitate the translet class
             thisModule.addReads(m);
 
@@ -513,7 +508,7 @@
         }
         catch (ClassFormatError e) {
             ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_CLASS_ERR, _name);
-            throw new TransformerConfigurationException(err.toString());
+            throw new TransformerConfigurationException(err.toString(), e);
         }
         catch (LinkageError e) {
             ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Constants.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Constants.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -239,6 +239,14 @@
      */
     public static final String JDK_GENERAL_ENTITY_SIZE_LIMIT =
             ORACLE_JAXP_PROPERTY_PREFIX + "maxGeneralEntitySizeLimit";
+
+    /**
+     * JDK node count limit in entities that limits the total number of nodes
+     * in all of entity references.
+     */
+    public static final String JDK_ENTITY_REPLACEMENT_LIMIT =
+            ORACLE_JAXP_PROPERTY_PREFIX + "entityReplacementLimit";
+
     /**
      * JDK maximum parameter entity size limit
      */
@@ -292,6 +300,13 @@
      * JDK maximum general entity size limit
      */
     public static final String SP_GENERAL_ENTITY_SIZE_LIMIT = "jdk.xml.maxGeneralEntitySizeLimit";
+
+    /**
+     * JDK node count limit in entities that limits the total number of nodes
+     * in all of entity references.
+     */
+    public static final String SP_ENTITY_REPLACEMENT_LIMIT = "jdk.xml.entityReplacementLimit";
+
     /**
      * JDK maximum parameter entity size limit
      */
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,62 +1,21 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 1999-2004 The Apache Software Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
- * 4. The names "Xerces" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
- * Business Machines, Inc., http://www.apache.org.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package com.sun.org.apache.xerces.internal.impl;
@@ -146,7 +105,7 @@
     protected boolean scanPubidLiteral(XMLString literal)
         throws IOException, XNIException
     {
-        int quote = fEntityScanner.scanChar();
+        int quote = fEntityScanner.scanChar(null);
         if (quote != '\'' && quote != '"') {
             reportFatalError("QuoteRequiredInPublicID", null);
             return false;
@@ -157,7 +116,7 @@
         boolean skipSpace = true;
         boolean dataok = true;
         while (true) {
-            int c = fEntityScanner.scanChar();
+            int c = fEntityScanner.scanChar(null);
             // REVISIT:  it could really only be \n or 0x20; all else is normalized, no?  - neilg
             if (c == ' ' || c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
                 if (!skipSpace) {
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DocumentScannerImpl.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DocumentScannerImpl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,62 +1,21 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 1999-2004 The Apache Software Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
- * 4. The names "Xerces" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
- * Business Machines, Inc., http://www.apache.org.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package com.sun.org.apache.xerces.internal.impl;
@@ -134,7 +93,7 @@
             // happens when there is the character reference &#13;
             // but scanContent doesn't do entity expansions...
             // is this *really* necessary???  - NG
-            fEntityScanner.scanChar();
+            fEntityScanner.scanChar(null);
             content.append((char)c);
             c = -1;
         }
@@ -143,7 +102,7 @@
         } */
 
         if (c == ']') {
-            content.append((char)fEntityScanner.scanChar());
+            content.append((char)fEntityScanner.scanChar(null));
             // remember where we are in case we get an endEntity before we
             // could flush the buffer out - this happens when we're parsing an
             // entity which ends with a ]
@@ -152,12 +111,12 @@
             // We work on a single character basis to handle cases such as:
             // ']]]>' which we might otherwise miss.
             //
-            if (fEntityScanner.skipChar(']')) {
+            if (fEntityScanner.skipChar(']', null)) {
                 content.append(']');
-                while (fEntityScanner.skipChar(']')) {
+                while (fEntityScanner.skipChar(']', null)) {
                     content.append(']');
                 }
-                if (fEntityScanner.skipChar('>')) {
+                if (fEntityScanner.skipChar('>', null)) {
                     reportFatalError("CDEndInContent", null);
                 }
             }
@@ -184,6 +143,7 @@
      * @param checkEntities true if undeclared entities should be reported as VC violation,
      *                      false if undeclared entities should be reported as WFC violation.
      * @param eleName The name of element to which this attribute belongs.
+     * @param isNSURI The flag indicating whether the content is a namespace URI
      *
      * @return true if the non-normalized and normalized value are the same
      *
@@ -193,7 +153,7 @@
     protected boolean scanAttributeValue(XMLString value,
                                       XMLString nonNormalizedValue,
                                       String atName,
-                                      boolean checkEntities,String eleName)
+                                      boolean checkEntities,String eleName, boolean isNSURI)
         throws IOException, XNIException
     {
         // quote
@@ -202,10 +162,10 @@
             reportFatalError("OpenQuoteExpected", new Object[]{eleName,atName});
         }
 
-        fEntityScanner.scanChar();
+        fEntityScanner.scanChar(NameType.ATTRIBUTE);
         int entityDepth = fEntityDepth;
 
-        int c = fEntityScanner.scanLiteral(quote, value);
+        int c = fEntityScanner.scanLiteral(quote, value, isNSURI);
         if (DEBUG_ATTR_NORMALIZATION) {
             System.out.println("** scanLiteral -> \""
                                + value.toString() + "\"");
@@ -215,7 +175,7 @@
         if (c == quote && (fromIndex = isUnchangedByNormalization(value)) == -1) {
             /** Both the non-normalized and normalized attribute values are equal. **/
             nonNormalizedValue.setValues(value);
-            int cquote = fEntityScanner.scanChar();
+            int cquote = fEntityScanner.scanChar(NameType.ATTRIBUTE);
             if (cquote != quote) {
                 reportFatalError("CloseQuoteExpected", new Object[]{eleName,atName});
             }
@@ -238,11 +198,11 @@
                                        + fStringBuffer.toString() + "\"");
                 }
                 if (c == '&') {
-                    fEntityScanner.skipChar('&');
+                    fEntityScanner.skipChar('&', NameType.REFERENCE);
                     if (entityDepth == fEntityDepth) {
                         fStringBuffer2.append('&');
                     }
-                    if (fEntityScanner.skipChar('#')) {
+                    if (fEntityScanner.skipChar('#', NameType.REFERENCE)) {
                         if (entityDepth == fEntityDepth) {
                             fStringBuffer2.append('#');
                         }
@@ -256,59 +216,22 @@
                         }
                     }
                     else {
-                        String entityName = fEntityScanner.scanName();
+                        String entityName = fEntityScanner.scanName(NameType.REFERENCE);
                         if (entityName == null) {
                             reportFatalError("NameRequiredInReference", null);
                         }
                         else if (entityDepth == fEntityDepth) {
                             fStringBuffer2.append(entityName);
                         }
-                        if (!fEntityScanner.skipChar(';')) {
+                        if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
                             reportFatalError("SemicolonRequiredInReference",
                                              new Object []{entityName});
                         }
                         else if (entityDepth == fEntityDepth) {
                             fStringBuffer2.append(';');
                         }
-                        if (entityName == fAmpSymbol) {
-                            fStringBuffer.append('&');
-                            if (DEBUG_ATTR_NORMALIZATION) {
-                                System.out.println("** value5: \""
-                                                   + fStringBuffer.toString()
-                                                   + "\"");
-                            }
-                        }
-                        else if (entityName == fAposSymbol) {
-                            fStringBuffer.append('\'');
-                            if (DEBUG_ATTR_NORMALIZATION) {
-                                System.out.println("** value7: \""
-                                                   + fStringBuffer.toString()
-                                                   + "\"");
-                            }
-                        }
-                        else if (entityName == fLtSymbol) {
-                            fStringBuffer.append('<');
-                            if (DEBUG_ATTR_NORMALIZATION) {
-                                System.out.println("** value9: \""
-                                                   + fStringBuffer.toString()
-                                                   + "\"");
-                            }
-                        }
-                        else if (entityName == fGtSymbol) {
-                            fStringBuffer.append('>');
-                            if (DEBUG_ATTR_NORMALIZATION) {
-                                System.out.println("** valueB: \""
-                                                   + fStringBuffer.toString()
-                                                   + "\"");
-                            }
-                        }
-                        else if (entityName == fQuotSymbol) {
-                            fStringBuffer.append('"');
-                            if (DEBUG_ATTR_NORMALIZATION) {
-                                System.out.println("** valueD: \""
-                                                   + fStringBuffer.toString()
-                                                   + "\"");
-                            }
+                        if (resolveCharacter(entityName, fStringBuffer)) {
+                            checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1);
                         }
                         else {
                             if (fEntityManager.isExternalEntity(entityName)) {
@@ -339,13 +262,13 @@
                 else if (c == '<') {
                     reportFatalError("LessthanInAttValue",
                                      new Object[] { eleName, atName });
-                    fEntityScanner.scanChar();
+                    fEntityScanner.scanChar(null);
                     if (entityDepth == fEntityDepth) {
                         fStringBuffer2.append((char)c);
                     }
                 }
                 else if (c == '%' || c == ']') {
-                    fEntityScanner.scanChar();
+                    fEntityScanner.scanChar(null);
                     fStringBuffer.append((char)c);
                     if (entityDepth == fEntityDepth) {
                         fStringBuffer2.append((char)c);
@@ -359,7 +282,7 @@
                 // XML11EntityScanner.  Not sure why
                 // this check was originally necessary.  - NG
                 else if (c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
-                    fEntityScanner.scanChar();
+                    fEntityScanner.scanChar(null);
                     fStringBuffer.append(' ');
                     if (entityDepth == fEntityDepth) {
                         fStringBuffer2.append('\n');
@@ -382,12 +305,12 @@
                 else if (c != -1 && isInvalidLiteral(c)) {
                     reportFatalError("InvalidCharInAttValue",
                                      new Object[] {eleName, atName, Integer.toString(c, 16)});
-                    fEntityScanner.scanChar();
+                    fEntityScanner.scanChar(null);
                     if (entityDepth == fEntityDepth) {
                         fStringBuffer2.append((char)c);
                     }
                 }
-                c = fEntityScanner.scanLiteral(quote, value);
+                c = fEntityScanner.scanLiteral(quote, value, isNSURI);
                 if (entityDepth == fEntityDepth) {
                     fStringBuffer2.append(value);
                 }
@@ -404,7 +327,7 @@
         nonNormalizedValue.setValues(fStringBuffer2);
 
         // quote
-        int cquote = fEntityScanner.scanChar();
+        int cquote = fEntityScanner.scanChar(null);
         if (cquote != quote) {
             reportFatalError("CloseQuoteExpected", new Object[]{eleName,atName});
         }
@@ -439,7 +362,7 @@
     protected boolean scanPubidLiteral(XMLString literal)
         throws IOException, XNIException
     {
-        int quote = fEntityScanner.scanChar();
+        int quote = fEntityScanner.scanChar(null);
         if (quote != '\'' && quote != '"') {
             reportFatalError("QuoteRequiredInPublicID", null);
             return false;
@@ -450,7 +373,7 @@
         boolean skipSpace = true;
         boolean dataok = true;
         while (true) {
-            int c = fEntityScanner.scanChar();
+            int c = fEntityScanner.scanChar(null);
             // REVISIT:  none of these except \n and 0x20 should make it past the entity scanner
             if (c == ' ' || c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
                 if (!skipSpace) {
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java	Wed Jul 27 13:33:55 2016 +0000
@@ -21,6 +21,7 @@
 
 package com.sun.org.apache.xerces.internal.impl;
 
+import com.sun.org.apache.xerces.internal.impl.XMLScanner.NameType;
 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
 import com.sun.org.apache.xerces.internal.util.XML11Char;
 import com.sun.org.apache.xerces.internal.util.XMLChar;
@@ -92,7 +93,7 @@
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public int scanChar() throws IOException {
+    protected int scanChar(NameType nt) throws IOException {
 
         // load more characters, if needed
         if (fCurrentEntity.position == fCurrentEntity.count) {
@@ -100,6 +101,7 @@
         }
 
         // scan character
+        int offset = fCurrentEntity.position;
         int c = fCurrentEntity.ch[fCurrentEntity.position++];
         boolean external = false;
         if (c == '\n' ||
@@ -110,6 +112,7 @@
                 invokeListeners(1);
                 fCurrentEntity.ch[0] = (char)c;
                 load(1, false, false);
+                offset = 0;
             }
             if (c == '\r' && external) {
                 int cc = fCurrentEntity.ch[fCurrentEntity.position++];
@@ -122,6 +125,9 @@
 
         // return character that was scanned
         fCurrentEntity.columnNumber++;
+        if (!detectingVersion) {
+            checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset);
+        }
         return c;
 
     } // scanChar():int
@@ -141,7 +147,7 @@
      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Name
      */
-    public String scanNmtoken() throws IOException {
+    protected String scanNmtoken() throws IOException {
         // load more characters, if needed
         if (fCurrentEntity.position == fCurrentEntity.count) {
             load(0, true, true);
@@ -248,6 +254,8 @@
      * <strong>Note:</strong> The string returned must be a symbol. The
      * SymbolTable can be used for this purpose.
      *
+     * @param nt The type of the name (element or attribute)
+     *
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      *
@@ -255,7 +263,7 @@
      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Name
      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NameStart
      */
-    public String scanName() throws IOException {
+    protected String scanName(NameType nt) throws IOException {
         // load more characters, if needed
         if (fCurrentEntity.position == fCurrentEntity.count) {
             load(0, true, true);
@@ -310,23 +318,11 @@
             return null;
         }
 
+        int length = 0;
         do {
             ch = fCurrentEntity.ch[fCurrentEntity.position];
             if (XML11Char.isXML11Name(ch)) {
-                if (++fCurrentEntity.position == fCurrentEntity.count) {
-                    int length = fCurrentEntity.position - offset;
-                    invokeListeners(length);
-                    if (length == fCurrentEntity.ch.length) {
-                        // bad luck we have to resize our buffer
-                        char[] tmp = new char[fCurrentEntity.ch.length << 1];
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         tmp, 0, length);
-                        fCurrentEntity.ch = tmp;
-                    }
-                    else {
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         fCurrentEntity.ch, 0, length);
-                    }
+                if ((length = checkBeforeLoad(fCurrentEntity, offset, offset)) > 0) {
                     offset = 0;
                     if (load(length, false, false)) {
                         break;
@@ -334,20 +330,7 @@
                 }
             }
             else if (XML11Char.isXML11NameHighSurrogate(ch)) {
-                if (++fCurrentEntity.position == fCurrentEntity.count) {
-                    int length = fCurrentEntity.position - offset;
-                    invokeListeners(length);
-                    if (length == fCurrentEntity.ch.length) {
-                        // bad luck we have to resize our buffer
-                        char[] tmp = new char[fCurrentEntity.ch.length << 1];
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         tmp, 0, length);
-                        fCurrentEntity.ch = tmp;
-                    }
-                    else {
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         fCurrentEntity.ch, 0, length);
-                    }
+                if ((length = checkBeforeLoad(fCurrentEntity, offset, offset)) > 0) {
                     offset = 0;
                     if (load(length, false, false)) {
                         --fCurrentEntity.position;
@@ -361,20 +344,7 @@
                     --fCurrentEntity.position;
                     break;
                 }
-                if (++fCurrentEntity.position == fCurrentEntity.count) {
-                    int length = fCurrentEntity.position - offset;
-                    invokeListeners(length);
-                    if (length == fCurrentEntity.ch.length) {
-                        // bad luck we have to resize our buffer
-                        char[] tmp = new char[fCurrentEntity.ch.length << 1];
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         tmp, 0, length);
-                        fCurrentEntity.ch = tmp;
-                    }
-                    else {
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         fCurrentEntity.ch, 0, length);
-                    }
+                if ((length = checkBeforeLoad(fCurrentEntity, offset, offset)) > 0) {
                     offset = 0;
                     if (load(length, false, false)) {
                         break;
@@ -387,12 +357,14 @@
         }
         while (true);
 
-        int length = fCurrentEntity.position - offset;
+        length = fCurrentEntity.position - offset;
         fCurrentEntity.columnNumber += length;
 
         // return name
         String symbol = null;
         if (length > 0) {
+            checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length);
+            checkEntityLimit(nt, fCurrentEntity, offset, length);
             symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
         }
         return symbol;
@@ -415,7 +387,7 @@
      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NCName
      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NCNameStart
      */
-    public String scanNCName() throws IOException {
+    protected String scanNCName() throws IOException {
 
         // load more characters, if needed
         if (fCurrentEntity.position == fCurrentEntity.count) {
@@ -571,6 +543,7 @@
      * this purpose.
      *
      * @param qname The qualified name structure to fill.
+     * @param nt The type of the name (element or attribute)
      *
      * @return Returns true if a qualified name appeared immediately on
      *         the input and was scanned, false otherwise.
@@ -582,7 +555,7 @@
      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Name
      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NameStart
      */
-    public boolean scanQName(QName qname) throws IOException {
+    protected boolean scanQName(QName qname, XMLScanner.NameType nt) throws IOException {
 
         // load more characters, if needed
         if (fCurrentEntity.position == fCurrentEntity.count) {
@@ -602,6 +575,7 @@
                     fCurrentEntity.columnNumber++;
                     String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
                     qname.setValues(null, name, name, null);
+                    checkEntityLimit(nt, fCurrentEntity, 0, 1);
                     return true;
                 }
             }
@@ -632,6 +606,7 @@
                     fCurrentEntity.columnNumber += 2;
                     String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
                     qname.setValues(null, name, name, null);
+                    checkEntityLimit(nt, fCurrentEntity, 0, 2);
                     return true;
                 }
             }
@@ -641,6 +616,7 @@
         }
 
         int index = -1;
+        int length = 0;
         boolean sawIncompleteSurrogatePair = false;
         do {
             ch = fCurrentEntity.ch[fCurrentEntity.position];
@@ -653,22 +629,7 @@
                     //check prefix before further read
                     checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, index - offset);
                 }
-                if (++fCurrentEntity.position == fCurrentEntity.count) {
-                    int length = fCurrentEntity.position - offset;
-                    //check localpart before loading more data
-                    checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length - index - 1);
-                    invokeListeners(length);
-                    if (length == fCurrentEntity.ch.length) {
-                        // bad luck we have to resize our buffer
-                        char[] tmp = new char[fCurrentEntity.ch.length << 1];
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         tmp, 0, length);
-                        fCurrentEntity.ch = tmp;
-                    }
-                    else {
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         fCurrentEntity.ch, 0, length);
-                    }
+                if ((length = checkBeforeLoad(fCurrentEntity, offset, index)) > 0) {
                     if (index != -1) {
                         index = index - offset;
                     }
@@ -679,20 +640,7 @@
                 }
             }
             else if (XML11Char.isXML11NameHighSurrogate(ch)) {
-                if (++fCurrentEntity.position == fCurrentEntity.count) {
-                    int length = fCurrentEntity.position - offset;
-                    invokeListeners(length);
-                    if (length == fCurrentEntity.ch.length) {
-                        // bad luck we have to resize our buffer
-                        char[] tmp = new char[fCurrentEntity.ch.length << 1];
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         tmp, 0, length);
-                        fCurrentEntity.ch = tmp;
-                    }
-                    else {
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         fCurrentEntity.ch, 0, length);
-                    }
+                if ((length = checkBeforeLoad(fCurrentEntity, offset, index)) > 0) {
                     if (index != -1) {
                         index = index - offset;
                     }
@@ -711,20 +659,7 @@
                     --fCurrentEntity.position;
                     break;
                 }
-                if (++fCurrentEntity.position == fCurrentEntity.count) {
-                    int length = fCurrentEntity.position - offset;
-                    invokeListeners(length);
-                    if (length == fCurrentEntity.ch.length) {
-                        // bad luck we have to resize our buffer
-                        char[] tmp = new char[fCurrentEntity.ch.length << 1];
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         tmp, 0, length);
-                        fCurrentEntity.ch = tmp;
-                    }
-                    else {
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                         fCurrentEntity.ch, 0, length);
-                    }
+                if ((length = checkBeforeLoad(fCurrentEntity, offset, index)) > 0) {
                     if (index != -1) {
                         index = index - offset;
                     }
@@ -740,7 +675,7 @@
         }
         while (true);
 
-        int length = fCurrentEntity.position - offset;
+        length = fCurrentEntity.position - offset;
         fCurrentEntity.columnNumber += length;
 
         if (length > 0) {
@@ -776,6 +711,7 @@
                 checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length);
             }
             qname.setValues(prefix, localpart, rawname, null);
+            checkEntityLimit(nt, fCurrentEntity, offset, length);
             return true;
         }
         return false;
@@ -808,7 +744,7 @@
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public int scanContent(XMLString content) throws IOException {
+    protected int scanContent(XMLString content) throws IOException {
 
         // load more characters, if needed
         if (fCurrentEntity.position == fCurrentEntity.count) {
@@ -826,6 +762,7 @@
         int offset = fCurrentEntity.position;
         int c = fCurrentEntity.ch[offset];
         int newlines = 0;
+        boolean counted = false;
         boolean external = fCurrentEntity.isExternal();
         if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
             do {
@@ -835,11 +772,13 @@
                     fCurrentEntity.lineNumber++;
                     fCurrentEntity.columnNumber = 1;
                     if (fCurrentEntity.position == fCurrentEntity.count) {
+                        checkEntityLimit(null, fCurrentEntity, offset, newlines);
                         offset = 0;
                         fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
                         fCurrentEntity.position = newlines;
                         fCurrentEntity.startPosition = newlines;
                         if (load(newlines, false, true)) {
+                            counted = true;
                             break;
                         }
                     }
@@ -858,11 +797,13 @@
                     fCurrentEntity.lineNumber++;
                     fCurrentEntity.columnNumber = 1;
                     if (fCurrentEntity.position == fCurrentEntity.count) {
+                        checkEntityLimit(null, fCurrentEntity, offset, newlines);
                         offset = 0;
                         fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
                         fCurrentEntity.position = newlines;
                         fCurrentEntity.startPosition = newlines;
                         if (load(newlines, false, true)) {
+                            counted = true;
                             break;
                         }
                     }
@@ -877,6 +818,7 @@
             }
             int length = fCurrentEntity.position - offset;
             if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+                checkEntityLimit(null, fCurrentEntity, offset, length);
                 content.setValues(fCurrentEntity.ch, offset, length);
                 return -1;
             }
@@ -904,8 +846,8 @@
         }
         int length = fCurrentEntity.position - offset;
         fCurrentEntity.columnNumber += length - newlines;
-        if (fCurrentEntity.isGE) {
-            checkLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fCurrentEntity, offset, length);
+        if (!counted) {
+            checkEntityLimit(null, fCurrentEntity, offset, length);
         }
         content.setValues(fCurrentEntity.ch, offset, length);
 
@@ -945,6 +887,7 @@
      * @param quote   The quote character that signifies the end of the
      *                attribute value data.
      * @param content The content structure to fill.
+     * @param isNSURI a flag indicating whether the content is a Namespace URI
      *
      * @return Returns the next character on the input, if known. This
      *         value may be -1 but this does <em>note</em> designate
@@ -953,7 +896,7 @@
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public int scanLiteral(int quote, XMLString content)
+    protected int scanLiteral(int quote, XMLString content, boolean isNSURI)
         throws IOException {
         // load more characters, if needed
         if (fCurrentEntity.position == fCurrentEntity.count) {
@@ -1051,8 +994,10 @@
         }
         int length = fCurrentEntity.position - offset;
         fCurrentEntity.columnNumber += length - newlines;
-        if (fCurrentEntity.isGE) {
-            checkLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fCurrentEntity, offset, length);
+
+        checkEntityLimit(null, fCurrentEntity, offset, length);
+        if (isNSURI) {
+            checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length);
         }
         content.setValues(fCurrentEntity.ch, offset, length);
 
@@ -1103,7 +1048,7 @@
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public boolean scanData(String delimiter, XMLStringBuffer buffer)
+    protected boolean scanData(String delimiter, XMLStringBuffer buffer)
         throws IOException {
 
         boolean done = false;
@@ -1135,6 +1080,7 @@
             if (fCurrentEntity.position >= fCurrentEntity.count - delimLen) {
                 // something must be wrong with the input:  e.g., file ends  an unterminated comment
                 int length = fCurrentEntity.count - fCurrentEntity.position;
+                checkEntityLimit(NameType.COMMENT, fCurrentEntity, fCurrentEntity.position, length);
                 buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length);
                 fCurrentEntity.columnNumber += fCurrentEntity.count;
                 fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
@@ -1199,6 +1145,7 @@
                 }
                 int length = fCurrentEntity.position - offset;
                 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+                    checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length);
                     buffer.append(fCurrentEntity.ch, offset, length);
                     return true;
                 }
@@ -1237,6 +1184,7 @@
                         fCurrentEntity.position--;
                         int length = fCurrentEntity.position - offset;
                         fCurrentEntity.columnNumber += length - newlines;
+                        checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length);
                         buffer.append(fCurrentEntity.ch, offset, length);
                         return true;
                     }
@@ -1274,6 +1222,7 @@
                         fCurrentEntity.position--;
                         int length = fCurrentEntity.position - offset;
                         fCurrentEntity.columnNumber += length - newlines;
+                        checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length);
                         buffer.append(fCurrentEntity.ch, offset, length);
                         return true;
                     }
@@ -1281,6 +1230,7 @@
             }
             int length = fCurrentEntity.position - offset;
             fCurrentEntity.columnNumber += length - newlines;
+            checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length);
             if (done) {
                 length -= delimLen;
             }
@@ -1305,7 +1255,7 @@
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public boolean skipChar(int c) throws IOException {
+    protected boolean skipChar(int c, NameType nt) throws IOException {
 
         // load more characters, if needed
         if (fCurrentEntity.position == fCurrentEntity.count) {
@@ -1313,6 +1263,7 @@
         }
 
         // skip character
+        int offset = fCurrentEntity.position;
         int cc = fCurrentEntity.ch[fCurrentEntity.position];
         if (cc == c) {
             fCurrentEntity.position++;
@@ -1323,12 +1274,14 @@
             else {
                 fCurrentEntity.columnNumber++;
             }
+            checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset);
             return true;
         }
         else if (c == '\n' && ((cc == 0x2028 || cc == 0x85) && fCurrentEntity.isExternal())) {
             fCurrentEntity.position++;
             fCurrentEntity.lineNumber++;
             fCurrentEntity.columnNumber = 1;
+            checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset);
             return true;
         }
         else if (c == '\n' && (cc == '\r' ) && fCurrentEntity.isExternal()) {
@@ -1344,6 +1297,7 @@
             }
             fCurrentEntity.lineNumber++;
             fCurrentEntity.columnNumber = 1;
+            checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset);
             return true;
         }
 
@@ -1366,7 +1320,7 @@
      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Space
      */
-    public boolean skipSpaces() throws IOException {
+    protected boolean skipSpaces() throws IOException {
 
         // load more characters, if needed
         if (fCurrentEntity.position == fCurrentEntity.count) {
@@ -1386,7 +1340,7 @@
 
         // skip spaces
         int c = fCurrentEntity.ch[fCurrentEntity.position];
-
+        int offset = fCurrentEntity.position - 1;
         // External --  Match: S + 0x85 + 0x2028, and perform end of line normalization
         if (fCurrentEntity.isExternal()) {
             if (XML11Char.isXML11Space(c)) {
@@ -1422,6 +1376,11 @@
                     else {
                         fCurrentEntity.columnNumber++;
                     }
+
+                    //If this is a general entity, spaces within a start element should be counted
+                    checkEntityLimit(null, fCurrentEntity, offset, fCurrentEntity.position - offset);
+                    offset = fCurrentEntity.position;
+
                     // load more characters, if needed
                     if (!entityChanged)
                         fCurrentEntity.position++;
@@ -1462,6 +1421,11 @@
                 else {
                     fCurrentEntity.columnNumber++;
                 }
+
+                //If this is a general entity, spaces within a start element should be counted
+                checkEntityLimit(null, fCurrentEntity, offset, fCurrentEntity.position - offset);
+                offset = fCurrentEntity.position;
+
                 // load more characters, if needed
                 if (!entityChanged)
                     fCurrentEntity.position++;
@@ -1495,7 +1459,7 @@
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public boolean skipString(String s) throws IOException {
+    protected boolean skipString(String s) throws IOException {
 
         // load more characters, if needed
         if (fCurrentEntity.position == fCurrentEntity.count) {
@@ -1504,6 +1468,7 @@
 
         // skip string
         final int length = s.length();
+        final int beforeSkip = fCurrentEntity.position ;
         for (int i = 0; i < length; i++) {
             char c = fCurrentEntity.ch[fCurrentEntity.position++];
             if (c != s.charAt(i)) {
@@ -1523,6 +1488,9 @@
             }
         }
         fCurrentEntity.columnNumber += length;
+        if (!detectingVersion) {
+            checkEntityLimit(null, fCurrentEntity, beforeSkip, length);
+        }
         return true;
 
     } // skipString(String):boolean
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11NSDocumentScannerImpl.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11NSDocumentScannerImpl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -135,7 +135,7 @@
         if (DEBUG_START_END_ELEMENT)
             System.out.println(">>> scanStartElementNS()");
                 // Note: namespace processing is on by default
-        fEntityScanner.scanQName(fElementQName);
+        fEntityScanner.scanQName(fElementQName, NameType.ATTRIBUTE);
         // REVISIT - [Q] Why do we need this local variable? -- mrglavas
         String rawname = fElementQName.rawname;
         if (fBindNamespaces) {
@@ -173,11 +173,11 @@
             // end tag?
             int c = fEntityScanner.peekChar();
             if (c == '>') {
-                fEntityScanner.scanChar();
+                fEntityScanner.scanChar(null);
                 break;
             } else if (c == '/') {
-                fEntityScanner.scanChar();
-                if (!fEntityScanner.skipChar('>')) {
+                fEntityScanner.scanChar(null);
+                if (!fEntityScanner.skipChar('>', null)) {
                     reportFatalError(
                         "ElementUnterminated",
                         new Object[] { rawname });
@@ -345,7 +345,7 @@
     protected void scanStartElementName ()
         throws IOException, XNIException {
         // Note: namespace processing is on by default
-        fEntityScanner.scanQName(fElementQName);
+        fEntityScanner.scanQName(fElementQName, NameType.ATTRIBUTE);
         // Must skip spaces here because the DTD scanner
         // would consume them at the end of the external subset.
         fSawSpace = fEntityScanner.skipSpaces();
@@ -395,11 +395,11 @@
             // end tag?
             int c = fEntityScanner.peekChar();
             if (c == '>') {
-                fEntityScanner.scanChar();
+                fEntityScanner.scanChar(null);
                 break;
             } else if (c == '/') {
-                fEntityScanner.scanChar();
-                if (!fEntityScanner.skipChar('>')) {
+                fEntityScanner.scanChar(null);
+                if (!fEntityScanner.skipChar('>', null)) {
                     reportFatalError(
                         "ElementUnterminated",
                         new Object[] { rawname });
@@ -571,11 +571,11 @@
             System.out.println(">>> scanAttribute()");
 
         // name
-        fEntityScanner.scanQName(fAttributeQName);
+        fEntityScanner.scanQName(fAttributeQName, NameType.ATTRIBUTE);
 
         // equals
         fEntityScanner.skipSpaces();
-        if (!fEntityScanner.skipChar('=')) {
+        if (!fEntityScanner.skipChar('=', NameType.ATTRIBUTE)) {
             reportFatalError(
                 "EqRequiredInAttribute",
                 new Object[] {
@@ -614,13 +614,20 @@
         //REVISIT: one more case needs to be included: external PE and standalone is no
         boolean isVC = fHasExternalDTD && !fStandalone;
 
-        // REVISIT: it seems that this function should not take attributes, and length
-        scanAttributeValue(
-            this.fTempString,
-            fTempString2,
-            fAttributeQName.rawname,
-            isVC,
-            fCurrentElement.rawname);
+        /**
+         * Determine whether this is a namespace declaration that will be subject
+         * to the name limit check in the scanAttributeValue operation.
+         * Namespace declaration format: xmlns="..." or xmlns:prefix="..."
+         * Note that prefix:xmlns="..." isn't a namespace.
+         */
+        String localpart = fAttributeQName.localpart;
+        String prefix = fAttributeQName.prefix != null
+                ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
+        boolean isNSDecl = fBindNamespaces & (prefix == XMLSymbols.PREFIX_XMLNS ||
+                    prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS);
+
+        scanAttributeValue(this.fTempString, fTempString2, fAttributeQName.rawname,
+            isVC, fCurrentElement.rawname, isNSDecl);
         String value = fTempString.toString();
         attributes.setValue(attrIndex, value);
         attributes.setNonNormalizedValue(attrIndex, fTempString2.toString());
@@ -628,17 +635,7 @@
 
         // record namespace declarations if any.
         if (fBindNamespaces) {
-
-            String localpart = fAttributeQName.localpart;
-            String prefix =
-                fAttributeQName.prefix != null
-                    ? fAttributeQName.prefix
-                    : XMLSymbols.EMPTY_STRING;
-            // when it's of form xmlns="..." or xmlns:prefix="...",
-            // it's a namespace declaration. but prefix:xmlns="..." isn't.
-            if (prefix == XMLSymbols.PREFIX_XMLNS
-                || prefix == XMLSymbols.EMPTY_STRING
-                && localpart == XMLSymbols.PREFIX_XMLNS) {
+            if (isNSDecl) {
                 if (value.length() > fXMLNameLimit) {
                     fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                             "MaxXMLNameLimit",
@@ -758,7 +755,7 @@
 
         // end
         fEntityScanner.skipSpaces();
-        if (!fEntityScanner.skipChar('>')) {
+        if (!fEntityScanner.skipChar('>', NameType.ELEMENTEND)) {
             reportFatalError(
                 "ETagUnterminated",
                 new Object[] { endElementName.rawname });
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -21,10 +21,7 @@
 
 package com.sun.org.apache.xerces.internal.impl;
 
-import com.sun.org.apache.xerces.internal.impl.Constants;
 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
-import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
-import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler;
 import com.sun.org.apache.xerces.internal.util.SymbolTable;
 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
 import com.sun.org.apache.xerces.internal.util.XMLChar;
@@ -367,6 +364,7 @@
                 // we're done, set starting state for external subset
                 setScannerState(SCANNER_STATE_TEXT_DECL);
                 // we're done scanning DTD.
+                fLimitAnalyzer.reset(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT);
                 fLimitAnalyzer.reset(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT);
                 return false;
             }
@@ -399,7 +397,7 @@
                 if (isInvalidLiteral(c)) {
                     reportFatalError("InvalidCharInDTD",
                         new Object[] { Integer.toHexString(c) });
-                    fEntityScanner.scanChar();
+                    fEntityScanner.scanChar(null);
                 }
             }
         }
@@ -767,7 +765,7 @@
                 fStringBuffer.clear();
                 fStringBuffer.append("xml");
                 while (isValidNameChar(fEntityScanner.peekChar())) {
-                    fStringBuffer.append((char)fEntityScanner.scanChar());
+                    fStringBuffer.append((char)fEntityScanner.scanChar(null));
                 }
                 String target =
                 fSymbolTable.addSymbol(fStringBuffer.ch,
@@ -867,7 +865,7 @@
         }
 
         // element name
-        String name = fEntityScanner.scanName();
+        String name = fEntityScanner.scanName(NameType.ELEMENTSTART);
         if (name == null) {
             reportFatalError("MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL",
             null);
@@ -900,7 +898,7 @@
             }
         }
         else {
-            if (!fEntityScanner.skipChar('(')) {
+            if (!fEntityScanner.skipChar('(', null)) {
                 reportFatalError("MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN",
                 new Object[]{name});
             }
@@ -930,7 +928,7 @@
         fReportEntity = false;
         skipSeparator(false, !scanningInternalSubset());
         // end
-        if (!fEntityScanner.skipChar('>')) {
+        if (!fEntityScanner.skipChar('>', null)) {
             reportFatalError("ElementDeclUnterminated", new Object[]{name});
         }
         fReportEntity = true;
@@ -967,7 +965,7 @@
             fDTDContentModelHandler.pcdata(null);
         }
         skipSeparator(false, !scanningInternalSubset());
-        while (fEntityScanner.skipChar('|')) {
+        while (fEntityScanner.skipChar('|', null)) {
             fStringBuffer.append('|');
             // call handler
             if (fDTDContentModelHandler != null) {
@@ -976,7 +974,7 @@
             }
             skipSeparator(false, !scanningInternalSubset());
 
-            childName = fEntityScanner.scanName();
+            childName = fEntityScanner.scanName(NameType.ENTITY);
             if (childName == null) {
                 reportFatalError("MSG_ELEMENT_TYPE_REQUIRED_IN_MIXED_CONTENT",
                 new Object[]{elName});
@@ -1005,7 +1003,7 @@
             reportFatalError("MixedContentUnterminated",
             new Object[]{elName});
         }
-        else if (fEntityScanner.skipChar(')')){
+        else if (fEntityScanner.skipChar(')', null)){
             fStringBuffer.append(')');
             // call handler
             if (fDTDContentModelHandler != null) {
@@ -1043,7 +1041,7 @@
         int currentOp = 0;
         int c;
         while (true) {
-            if (fEntityScanner.skipChar('(')) {
+            if (fEntityScanner.skipChar('(', null)) {
                 fMarkUpDepth++;
                 fStringBuffer.append('(');
                 // call handler
@@ -1057,7 +1055,7 @@
                 continue;
             }
             skipSeparator(false, !scanningInternalSubset());
-            String childName = fEntityScanner.scanName();
+            String childName = fEntityScanner.scanName(NameType.ELEMENTSTART);
             if (childName == null) {
                 reportFatalError("MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN",
                 new Object[]{elName});
@@ -1084,7 +1082,7 @@
                     }
                     fDTDContentModelHandler.occurrence(oc, null);
                 }
-                fEntityScanner.scanChar();
+                fEntityScanner.scanChar(null);
                 fStringBuffer.append((char)c);
             }
             while (true) {
@@ -1097,7 +1095,7 @@
                         fDTDContentModelHandler.separator(XMLDTDContentModelHandler.SEPARATOR_SEQUENCE,
                         null);
                     }
-                    fEntityScanner.scanChar();
+                    fEntityScanner.scanChar(null);
                     fStringBuffer.append(',');
                     break;
                 }
@@ -1108,7 +1106,7 @@
                         fDTDContentModelHandler.separator(XMLDTDContentModelHandler.SEPARATOR_CHOICE,
                         null);
                     }
-                    fEntityScanner.scanChar();
+                    fEntityScanner.scanChar(null);
                     fStringBuffer.append('|');
                     break;
                 }
@@ -1154,7 +1152,7 @@
                 }
                 else {
                     // no occurrence specified
-                    fEntityScanner.scanChar();
+                    fEntityScanner.scanChar(null);
                     fStringBuffer.append(')');
                 }
                 fMarkUpDepth--;
@@ -1186,7 +1184,7 @@
         }
 
         // element name
-        String elName = fEntityScanner.scanName();
+        String elName = fEntityScanner.scanName(NameType.ELEMENTSTART);
         if (elName == null) {
             reportFatalError("MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL",
             null);
@@ -1200,7 +1198,7 @@
         // spaces
         if (!skipSeparator(true, !scanningInternalSubset())) {
             // no space, is it the end yet?
-            if (fEntityScanner.skipChar('>')) {
+            if (fEntityScanner.skipChar('>', null)) {
                 // yes, stop here
                 // call handler
                 if (fDTDHandler != null) {
@@ -1216,8 +1214,8 @@
         }
 
         // definitions
-        while (!fEntityScanner.skipChar('>')) {
-            String name = fEntityScanner.scanName();
+        while (!fEntityScanner.skipChar('>', null)) {
+            String name = fEntityScanner.scanName(NameType.ATTRIBUTE);
             if (name == null) {
                 reportFatalError("AttNameRequiredInAttDef",
                 new Object[]{elName});
@@ -1353,7 +1351,7 @@
                 new Object[]{elName, atName});
             }
             // open paren
-            int c = fEntityScanner.scanChar();
+            int c = fEntityScanner.scanChar(null);
             if (c != '(') {
                 reportFatalError("MSG_OPEN_PAREN_REQUIRED_IN_NOTATIONTYPE",
                 new Object[]{elName, atName});
@@ -1361,7 +1359,7 @@
             fMarkUpDepth++;
             do {
                 skipSeparator(false, !scanningInternalSubset());
-                String aName = fEntityScanner.scanName();
+                String aName = fEntityScanner.scanName(NameType.ATTRIBUTE);
                 if (aName == null) {
                     reportFatalError("MSG_NAME_REQUIRED_IN_NOTATIONTYPE",
                     new Object[]{elName, atName});
@@ -1369,7 +1367,7 @@
                 ensureEnumerationSize(fEnumerationCount + 1);
                 fEnumeration[fEnumerationCount++] = aName;
                 skipSeparator(false, !scanningInternalSubset());
-                c = fEntityScanner.scanChar();
+                c = fEntityScanner.scanChar(null);
             } while (c == '|');
             if (c != ')') {
                 reportFatalError("NotationTypeUnterminated",
@@ -1380,7 +1378,7 @@
         else {              // Enumeration
             type = "ENUMERATION";
             // open paren
-            int c = fEntityScanner.scanChar();
+            int c = fEntityScanner.scanChar(null);
             if (c != '(') {
                 //                       "OPEN_PAREN_REQUIRED_BEFORE_ENUMERATION_IN_ATTRDECL",
                 reportFatalError("AttTypeRequiredInAttDef",
@@ -1397,7 +1395,7 @@
                 ensureEnumerationSize(fEnumerationCount + 1);
                 fEnumeration[fEnumerationCount++] = token;
                 skipSeparator(false, !scanningInternalSubset());
-                c = fEntityScanner.scanChar();
+                c = fEntityScanner.scanChar(null);
             } while (c == '|');
             if (c != ')') {
                 reportFatalError("EnumerationUnterminated",
@@ -1447,7 +1445,7 @@
             // AttValue
             boolean isVC = !fStandalone  &&  (fSeenExternalDTD || fSeenExternalPE) ;
             scanAttributeValue(defaultVal, nonNormalizedDefaultVal, atName,
-            fAttributes, 0, isVC, elName);
+            fAttributes, 0, isVC, elName, false);
         }
         return defaultType;
 
@@ -1475,7 +1473,7 @@
         boolean sawPERef = false;
         fReportEntity = false;
         if (fEntityScanner.skipSpaces()) {
-            if (!fEntityScanner.skipChar('%')) {
+            if (!fEntityScanner.skipChar('%', NameType.REFERENCE)) {
                 isPEDecl = false; // <!ENTITY x "x">
             }
             else if (skipSeparator(true, !scanningInternalSubset())) {
@@ -1496,7 +1494,7 @@
                 sawPERef = true;
             }
         }
-        else if (scanningInternalSubset() || !fEntityScanner.skipChar('%')) {
+        else if (scanningInternalSubset() || !fEntityScanner.skipChar('%', NameType.REFERENCE)) {
             // <!ENTITY[^ ]...> or <!ENTITY[^ %]...>
             reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_ENTITYDECL",
             null);
@@ -1513,11 +1511,11 @@
         }
         if (sawPERef) {
             while (true) {
-                String peName = fEntityScanner.scanName();
+                String peName = fEntityScanner.scanName(NameType.REFERENCE);
                 if (peName == null) {
                     reportFatalError("NameRequiredInPEReference", null);
                 }
-                else if (!fEntityScanner.skipChar(';')) {
+                else if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
                     reportFatalError("SemicolonRequiredInPEReference",
                     new Object[]{peName});
                 }
@@ -1525,20 +1523,20 @@
                     startPE(peName, false);
                 }
                 fEntityScanner.skipSpaces();
-                if (!fEntityScanner.skipChar('%'))
+                if (!fEntityScanner.skipChar('%', NameType.REFERENCE))
                     break;
                 if (!isPEDecl) {
                     if (skipSeparator(true, !scanningInternalSubset())) {
                         isPEDecl = true;
                         break;
                     }
-                    isPEDecl = fEntityScanner.skipChar('%');
+                    isPEDecl = fEntityScanner.skipChar('%', NameType.REFERENCE);
                 }
             }
         }
 
         // name
-        String name = fEntityScanner.scanName();
+        String name = fEntityScanner.scanName(NameType.ENTITY);
         if (name == null) {
             reportFatalError("MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL", null);
         }
@@ -1573,7 +1571,7 @@
                 reportFatalError("MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_UNPARSED_ENTITYDECL",
                 new Object[]{name});
             }
-            notation = fEntityScanner.scanName();
+            notation = fEntityScanner.scanName(NameType.NOTATION);
             if (notation == null) {
                 reportFatalError("MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL",
                 new Object[]{name});
@@ -1595,7 +1593,7 @@
         skipSeparator(false, !scanningInternalSubset());
 
         // end
-        if (!fEntityScanner.skipChar('>')) {
+        if (!fEntityScanner.skipChar('>', null)) {
             reportFatalError("EntityDeclUnterminated", new Object[]{name});
         }
         fMarkUpDepth--;
@@ -1650,7 +1648,7 @@
     protected final void scanEntityValue(String entityName, boolean isPEDecl, XMLString value,
     XMLString nonNormalizedValue)
     throws IOException, XNIException {
-        int quote = fEntityScanner.scanChar();
+        int quote = fEntityScanner.scanChar(null);
         if (quote != '\'' && quote != '"') {
             reportFatalError("OpenQuoteMissingInDecl", null);
         }
@@ -1665,23 +1663,24 @@
          }
         fLimitAnalyzer.startEntity(entityName);
 
-        if (fEntityScanner.scanLiteral(quote, fString) != quote) {
+        if (fEntityScanner.scanLiteral(quote, fString, false) != quote) {
             fStringBuffer.clear();
             fStringBuffer2.clear();
+            int offset;
             do {
-                checkEntityLimit(isPEDecl, entityName, fString.length + countChar);
                 countChar = 0;
+                offset = fStringBuffer.length;
                 fStringBuffer.append(fString);
                 fStringBuffer2.append(fString);
-                if (fEntityScanner.skipChar('&')) {
-                    if (fEntityScanner.skipChar('#')) {
+                if (fEntityScanner.skipChar('&', NameType.REFERENCE)) {
+                    if (fEntityScanner.skipChar('#', NameType.REFERENCE)) {
                         fStringBuffer2.append("&#");
                         scanCharReferenceValue(fStringBuffer, fStringBuffer2);
                     }
                     else {
                         fStringBuffer.append('&');
                         fStringBuffer2.append('&');
-                        String eName = fEntityScanner.scanName();
+                        String eName = fEntityScanner.scanName(NameType.REFERENCE);
                         if (eName == null) {
                             reportFatalError("NameRequiredInReference",
                             null);
@@ -1690,7 +1689,7 @@
                             fStringBuffer.append(eName);
                             fStringBuffer2.append(eName);
                         }
-                        if (!fEntityScanner.skipChar(';')) {
+                        if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
                             reportFatalError("SemicolonRequiredInReference",
                             new Object[]{eName});
                         }
@@ -1700,15 +1699,15 @@
                         }
                     }
                 }
-                else if (fEntityScanner.skipChar('%')) {
+                else if (fEntityScanner.skipChar('%', NameType.REFERENCE)) {
                     while (true) {
                         fStringBuffer2.append('%');
-                        String peName = fEntityScanner.scanName();
+                        String peName = fEntityScanner.scanName(NameType.REFERENCE);
                         if (peName == null) {
                             reportFatalError("NameRequiredInPEReference",
                             null);
                         }
-                        else if (!fEntityScanner.skipChar(';')) {
+                        else if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
                             reportFatalError("SemicolonRequiredInPEReference",
                             new Object[]{peName});
                         }
@@ -1725,20 +1724,20 @@
                         // REVISIT: This will make returning the non-
                         //          normalized value harder. -Ac
                         fEntityScanner.skipSpaces();
-                        if (!fEntityScanner.skipChar('%'))
+                        if (!fEntityScanner.skipChar('%', NameType.REFERENCE))
                             break;
                     }
                 }
                 else {
-                    countChar++;
                     int c = fEntityScanner.peekChar();
                     if (XMLChar.isHighSurrogate(c)) {
+                        countChar++;
                         scanSurrogates(fStringBuffer2);
                     }
                     else if (isInvalidLiteral(c)) {
                         reportFatalError("InvalidCharInLiteral",
                         new Object[]{Integer.toHexString(c)});
-                        fEntityScanner.scanChar();
+                        fEntityScanner.scanChar(null);
                     }
                     // if it's not the delimiting quote or if it is but from a
                     // different entity than the one this literal started from,
@@ -1746,10 +1745,12 @@
                     else if (c != quote || entityDepth != fEntityDepth) {
                         fStringBuffer.append((char)c);
                         fStringBuffer2.append((char)c);
-                        fEntityScanner.scanChar();
+                        fEntityScanner.scanChar(null);
                     }
                 }
-            } while (fEntityScanner.scanLiteral(quote, fString) != quote);
+                checkEntityLimit(isPEDecl, entityName, fStringBuffer.length - offset + countChar);
+            } while (fEntityScanner.scanLiteral(quote, fString, false) != quote);
+            checkEntityLimit(isPEDecl, entityName, fString.length);
             fStringBuffer.append(fString);
             fStringBuffer2.append(fString);
             literal = fStringBuffer;
@@ -1760,10 +1761,14 @@
         value.setValues(literal);
         nonNormalizedValue.setValues(literal2);
         if (fLimitAnalyzer != null) {
-            fLimitAnalyzer.endEntity(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, entityName);
+            if (isPEDecl) {
+                fLimitAnalyzer.endEntity(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, entityName);
+            } else {
+                fLimitAnalyzer.endEntity(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT, entityName);
+            }
         }
 
-        if (!fEntityScanner.skipChar(quote)) {
+        if (!fEntityScanner.skipChar(quote, null)) {
             reportFatalError("CloseQuoteMissingInDecl", null);
         }
     } // scanEntityValue(XMLString,XMLString):void
@@ -1788,7 +1793,7 @@
         }
 
         // notation name
-        String name = fEntityScanner.scanName();
+        String name = fEntityScanner.scanName(NameType.NOTATION);
         if (name == null) {
             reportFatalError("MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL",
             null);
@@ -1815,7 +1820,7 @@
         skipSeparator(false, !scanningInternalSubset());
 
         // end
-        if (!fEntityScanner.skipChar('>')) {
+        if (!fEntityScanner.skipChar('>', null)) {
             reportFatalError("NotationDeclUnterminated", new Object[]{name});
         }
         fMarkUpDepth--;
@@ -1863,7 +1868,7 @@
                 XMLErrorReporter.SEVERITY_ERROR);
             }
             // call handler
-            if (!fEntityScanner.skipChar('[')) {
+            if (!fEntityScanner.skipChar('[', null)) {
                 reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null);
             }
 
@@ -1888,7 +1893,7 @@
                 fDTDHandler.startConditional(XMLDTDHandler.CONDITIONAL_IGNORE,
                 null);
             }
-            if (!fEntityScanner.skipChar('[')) {
+            if (!fEntityScanner.skipChar('[', null)) {
                 reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null);
             }
             fReportEntity = true;
@@ -1897,7 +1902,7 @@
                 fIgnoreConditionalBuffer.clear();
             }
             while (true) {
-                if (fEntityScanner.skipChar('<')) {
+                if (fEntityScanner.skipChar('<', null)) {
                     if (fDTDHandler != null) {
                         fIgnoreConditionalBuffer.append('<');
                     }
@@ -1905,8 +1910,8 @@
                     // These tests are split so that we handle cases like
                     // '<<![' and '<!<![' which we might otherwise miss.
                     //
-                    if (fEntityScanner.skipChar('!')) {
-                        if(fEntityScanner.skipChar('[')) {
+                    if (fEntityScanner.skipChar('!', null)) {
+                        if(fEntityScanner.skipChar('[', null)) {
                             if (fDTDHandler != null) {
                                 fIgnoreConditionalBuffer.append("![");
                             }
@@ -1918,24 +1923,24 @@
                         }
                     }
                 }
-                else if (fEntityScanner.skipChar(']')) {
+                else if (fEntityScanner.skipChar(']', null)) {
                     if (fDTDHandler != null) {
                         fIgnoreConditionalBuffer.append(']');
                     }
                     //
                     // The same thing goes for ']<![' and '<]]>', etc.
                     //
-                    if (fEntityScanner.skipChar(']')) {
+                    if (fEntityScanner.skipChar(']', null)) {
                         if (fDTDHandler != null) {
                             fIgnoreConditionalBuffer.append(']');
                         }
-                        while (fEntityScanner.skipChar(']')) {
+                        while (fEntityScanner.skipChar(']', null)) {
                             /* empty loop body */
                             if (fDTDHandler != null) {
                                 fIgnoreConditionalBuffer.append(']');
                             }
                         }
-                        if (fEntityScanner.skipChar('>')) {
+                        if (fEntityScanner.skipChar('>', null)) {
                             if (fIncludeSectDepth-- == initialDepth) {
                                 fMarkUpDepth--;
                                 // call handler
@@ -1953,7 +1958,7 @@
                     }
                 }
                 else {
-                    int c = fEntityScanner.scanChar();
+                    int c = fEntityScanner.scanChar(null);
                     if (fScannerState == SCANNER_STATE_END_OF_INPUT) {
                         reportFatalError("IgnoreSectUnterminated", null);
                         return;
@@ -1990,16 +1995,16 @@
         //System.out.println("scanDecls"+fScannerState);
         while (again && fScannerState == SCANNER_STATE_MARKUP_DECL) {
             again = complete;
-            if (fEntityScanner.skipChar('<')) {
+            if (fEntityScanner.skipChar('<', null)) {
                 fMarkUpDepth++;
-                if (fEntityScanner.skipChar('?')) {
+                if (fEntityScanner.skipChar('?', null)) {
                     fStringBuffer.clear();
                     scanPI(fStringBuffer);
                     fMarkUpDepth--; // we're done with this decl
                 }
-                else if (fEntityScanner.skipChar('!')) {
-                    if (fEntityScanner.skipChar('-')) {
-                        if (!fEntityScanner.skipChar('-')) {
+                else if (fEntityScanner.skipChar('!', null)) {
+                    if (fEntityScanner.skipChar('-', null)) {
+                        if (!fEntityScanner.skipChar('-', null)) {
                             reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD",
                             null);
                         } else {
@@ -2018,7 +2023,7 @@
                     else if (fEntityScanner.skipString("NOTATION")) {
                         scanNotationDecl();
                     }
-                    else if (fEntityScanner.skipChar('[') &&
+                    else if (fEntityScanner.skipChar('[', null) &&
                     !scanningInternalSubset()) {
                         scanConditionalSect(fPEDepth);
                     }
@@ -2033,10 +2038,10 @@
                     reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null);
                 }
             }
-            else if (fIncludeSectDepth > 0 && fEntityScanner.skipChar(']')) {
+            else if (fIncludeSectDepth > 0 && fEntityScanner.skipChar(']', null)) {
                 // end of conditional section?
-                if (!fEntityScanner.skipChar(']')
-                || !fEntityScanner.skipChar('>')) {
+                if (!fEntityScanner.skipChar(']', null)
+                || !fEntityScanner.skipChar('>', null)) {
                     reportFatalError("IncludeSectUnterminated", null);
                 }
                 // call handler
@@ -2083,21 +2088,21 @@
     throws IOException, XNIException {
         int depth = fPEDepth;
         boolean sawSpace = fEntityScanner.skipSpaces();
-        if (!lookForPERefs || !fEntityScanner.skipChar('%')) {
+        if (!lookForPERefs || !fEntityScanner.skipChar('%', NameType.REFERENCE)) {
             return !spaceRequired || sawSpace || (depth != fPEDepth);
         }
         while (true) {
-            String name = fEntityScanner.scanName();
+            String name = fEntityScanner.scanName(NameType.ENTITY);
             if (name == null) {
                 reportFatalError("NameRequiredInPEReference", null);
             }
-            else if (!fEntityScanner.skipChar(';')) {
+            else if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
                 reportFatalError("SemicolonRequiredInPEReference",
                 new Object[]{name});
             }
             startPE(name, false);
             fEntityScanner.skipSpaces();
-            if (!fEntityScanner.skipChar('%'))
+            if (!fEntityScanner.skipChar('%', NameType.REFERENCE))
                 return true;
         }
     }
@@ -2181,56 +2186,6 @@
         fSecurityManager = fEntityManager.fSecurityManager;
     }
 
-    /**
-     * Add the count of the content buffer and check if the accumulated
-     * value exceeds the limit
-     * @param isPEDecl a flag to indicate whether the entity is parameter
-     * @param entityName entity name
-     * @param buffer content buffer
-     */
-    private void checkEntityLimit(boolean isPEDecl, String entityName, XMLString buffer) {
-        checkEntityLimit(isPEDecl, entityName, buffer.length);
-    }
-
-    /**
-     * Add the count and check limit
-     * @param isPEDecl a flag to indicate whether the entity is parameter
-     * @param entityName entity name
-     * @param len length of the buffer
-     */
-    private void checkEntityLimit(boolean isPEDecl, String entityName, int len) {
-        if (fLimitAnalyzer == null) {
-            fLimitAnalyzer = fEntityManager.fLimitAnalyzer;
-        }
-        if (isPEDecl) {
-            fLimitAnalyzer.addValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, "%" + entityName, len);
-            if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
-                        fSecurityManager.debugPrint(fLimitAnalyzer);
-                reportFatalError("MaxEntitySizeLimit", new Object[]{"%" + entityName,
-                    fLimitAnalyzer.getValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT),
-                    fSecurityManager.getLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT),
-                    fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT)});
-            }
-        } else {
-            fLimitAnalyzer.addValue(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT, entityName, len);
-            if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
-                        fSecurityManager.debugPrint(fLimitAnalyzer);
-                reportFatalError("MaxEntitySizeLimit", new Object[]{entityName,
-                    fLimitAnalyzer.getValue(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT),
-                    fSecurityManager.getLimit(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT),
-                    fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT)});
-            }
-        }
-        if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
-            fSecurityManager.debugPrint(fLimitAnalyzer);
-            reportFatalError("TotalEntitySizeLimit",
-                new Object[]{fLimitAnalyzer.getTotalValue(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT),
-                fSecurityManager.getLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT),
-                fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT)});
-        }
-
-    }
-
     public DTDGrammar getGrammar(){
         return nvGrammarInfo;
     }
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -21,14 +21,6 @@
 
 package com.sun.org.apache.xerces.internal.impl;
 
-import com.sun.xml.internal.stream.XMLBufferListener;
-import com.sun.xml.internal.stream.XMLEntityStorage;
-import com.sun.xml.internal.stream.dtd.DTDGrammarUtil;
-
-import java.io.EOFException;
-import java.io.IOException;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.events.XMLEvent;
 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
 import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
 import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl;
@@ -47,13 +39,18 @@
 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentScanner;
 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
 import com.sun.org.apache.xerces.internal.xni.Augmentations;
-import com.sun.org.apache.xerces.internal.impl.Constants;
-import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler;
 import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit;
 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
+import com.sun.xml.internal.stream.XMLBufferListener;
+import com.sun.xml.internal.stream.XMLEntityStorage;
+import com.sun.xml.internal.stream.dtd.DTDGrammarUtil;
+import java.io.EOFException;
+import java.io.IOException;
+import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.events.XMLEvent;
 
 /**
  *
@@ -454,6 +451,7 @@
                     //fDocumentHandler.startElement(getElementQName(),fAttributes,null);
                     break;
                 case XMLStreamConstants.CHARACTERS :
+                    fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                     fDocumentHandler.characters(getCharacterData(),null);
                     break;
                 case XMLStreamConstants.SPACE:
@@ -462,13 +460,15 @@
                     //fDocumentHandler.ignorableWhitespace(getCharacterData(), null);
                     break;
                 case XMLStreamConstants.ENTITY_REFERENCE :
+                    fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                     //entity reference callback are given in startEntity
                     break;
                 case XMLStreamConstants.PROCESSING_INSTRUCTION :
+                    fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                     fDocumentHandler.processingInstruction(getPITarget(),getPIData(),null);
                     break;
                 case XMLStreamConstants.COMMENT :
-                    //System.out.println(" in COMMENT of the XMLNSDocumentScannerImpl");
+                    fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                     fDocumentHandler.comment(getCharacterData(),null);
                     break;
                 case XMLStreamConstants.DTD :
@@ -477,6 +477,7 @@
                     //therefore we don't need to take care of anything here. So Just break;
                     break;
                 case XMLStreamConstants.CDATA:
+                    fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                     fDocumentHandler.startCDATA(null);
                     //xxx: check if CDATA values comes from getCharacterData() function
                     fDocumentHandler.characters(getCharacterData(),null);
@@ -1273,9 +1274,9 @@
             fElementQName = fElementStack.nextElement();
             // name
             if (fNamespaces) {
-                fEntityScanner.scanQName(fElementQName);
+                fEntityScanner.scanQName(fElementQName, NameType.ELEMENTSTART);
             } else {
-                String name = fEntityScanner.scanName();
+                String name = fEntityScanner.scanName(NameType.ELEMENTSTART);
                 fElementQName.setValues(null, name, name, null);
             }
 
@@ -1376,11 +1377,11 @@
         // end tag?
         final int c = fEntityScanner.peekChar();
         if (c == '>') {
-            fEntityScanner.scanChar();
+            fEntityScanner.scanChar(null);
             return true;
         } else if (c == '/') {
-            fEntityScanner.scanChar();
-            if (!fEntityScanner.skipChar('>')) {
+            fEntityScanner.scanChar(null);
+            if (!fEntityScanner.skipChar('>', NameType.ELEMENTEND)) {
                 reportFatalError("ElementUnterminated",
                         new Object[]{fElementQName.rawname});
             }
@@ -1518,15 +1519,15 @@
 
         // name
         if (fNamespaces) {
-            fEntityScanner.scanQName(fAttributeQName);
+            fEntityScanner.scanQName(fAttributeQName, NameType.ATTRIBUTENAME);
         } else {
-            String name = fEntityScanner.scanName();
+            String name = fEntityScanner.scanName(NameType.ATTRIBUTENAME);
             fAttributeQName.setValues(null, name, name, null);
         }
 
         // equals
         fEntityScanner.skipSpaces();
-        if (!fEntityScanner.skipChar('=')) {
+        if (!fEntityScanner.skipChar('=', NameType.ATTRIBUTE)) {
             reportFatalError("EqRequiredInAttribute",
                 new Object[] {fCurrentElement.rawname, fAttributeQName.rawname});
         }
@@ -1544,9 +1545,8 @@
         //can safely add the attribute later..
         XMLString tmpStr = getString();
 
-        scanAttributeValue(tmpStr, fTempString2,
-                fAttributeQName.rawname, attributes,
-                attIndex, isVC, fCurrentElement.rawname);
+        scanAttributeValue(tmpStr, fTempString2, fAttributeQName.rawname, attributes,
+                attIndex, isVC, fCurrentElement.rawname, false);
 
         // content
         int oldLen = attributes.getLength();
@@ -1594,13 +1594,13 @@
         if (c == '\r') {
             // happens when there is the character reference &#13;
             //xxx: We know the next chracter.. we should just skip it and add ']' directlry
-            fEntityScanner.scanChar();
+            fEntityScanner.scanChar(null);
             content.append((char)c);
             c = -1;
         } else if (c == ']') {
             //fStringBuffer.clear();
             //xxx: We know the next chracter.. we should just skip it and add ']' directlry
-            content.append((char)fEntityScanner.scanChar());
+            content.append((char)fEntityScanner.scanChar(null));
             // remember where we are in case we get an endEntity before we
             // could flush the buffer out - this happens when we're parsing an
             // entity which ends with a ]
@@ -1609,12 +1609,12 @@
             // We work on a single character basis to handle cases such as:
             // ']]]>' which we might otherwise miss.
             //
-            if (fEntityScanner.skipChar(']')) {
+            if (fEntityScanner.skipChar(']', null)) {
                 content.append(']');
-                while (fEntityScanner.skipChar(']')) {
+                while (fEntityScanner.skipChar(']', null)) {
                     content.append(']');
                 }
-                if (fEntityScanner.skipChar('>')) {
+                if (fEntityScanner.skipChar('>', null)) {
                     reportFatalError("CDEndInContent", null);
                 }
             }
@@ -1689,7 +1689,7 @@
                     } else {
                         reportFatalError("InvalidCharInCDSect",
                                 new Object[]{Integer.toString(c,16)});
-                                fEntityScanner.scanChar();
+                                fEntityScanner.scanChar(null);
                     }
                 }
                 //by this time we have also read surrogate contents if any...
@@ -1751,7 +1751,7 @@
 
         // end
         fEntityScanner.skipSpaces();
-        if (!fEntityScanner.skipChar('>')) {
+        if (!fEntityScanner.skipChar('>', NameType.ELEMENTEND)) {
             reportFatalError("ETagUnterminated",
                     new Object[]{rawname});
         }
@@ -1841,12 +1841,12 @@
      *                      notification.
      */
     protected void scanEntityReference(XMLStringBuffer content) throws IOException, XNIException {
-        String name = fEntityScanner.scanName();
+        String name = fEntityScanner.scanName(NameType.REFERENCE);
         if (name == null) {
             reportFatalError("NameRequiredInReference", null);
             return;
         }
-        if (!fEntityScanner.skipChar(';')) {
+        if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
             reportFatalError("SemicolonRequiredInReference", new Object []{name});
         }
         if (fEntityStore.isUnparsedEntity(name)) {
@@ -1943,6 +1943,7 @@
      */
     private void handleCharacter(char c, String entity, XMLStringBuffer content) throws XNIException {
         foundBuiltInRefs = true;
+        checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1);
         content.append(c);
         if (fDocumentHandler != null) {
             fSingleChar[0] = c;
@@ -2608,13 +2609,13 @@
                 switch(ch){
                     case '?' :{
                         setScannerState(SCANNER_STATE_PI);
-                        fEntityScanner.skipChar(ch);
+                        fEntityScanner.skipChar(ch, null);
                         break;
                     }
                     case '!' :{
-                        fEntityScanner.skipChar(ch);
-                        if (fEntityScanner.skipChar('-')) {
-                            if (!fEntityScanner.skipChar('-')) {
+                        fEntityScanner.skipChar(ch, null);
+                        if (fEntityScanner.skipChar('-', null)) {
+                            if (!fEntityScanner.skipChar('-', NameType.COMMENT)) {
                                 reportFatalError("InvalidCommentStart",
                                         null);
                             }
@@ -2629,7 +2630,7 @@
                     }
                     case '/' :{
                         setScannerState(SCANNER_STATE_END_ELEMENT_TAG);
-                        fEntityScanner.skipChar(ch);
+                        fEntityScanner.skipChar(ch, NameType.ELEMENTEND);
                         break;
                     }
                     default :{
@@ -2641,9 +2642,9 @@
         }//startOfMarkup
 
         private void startOfContent() throws IOException {
-            if (fEntityScanner.skipChar('<')) {
+            if (fEntityScanner.skipChar('<', null)) {
                 setScannerState(SCANNER_STATE_START_OF_MARKUP);
-            } else if (fEntityScanner.skipChar('&')) {
+            } else if (fEntityScanner.skipChar('&', NameType.REFERENCE)) {
                 setScannerState(SCANNER_STATE_REFERENCE) ; //XMLEvent.ENTITY_REFERENCE ); //SCANNER_STATE_REFERENCE
             } else {
                 //element content is there..
@@ -2716,10 +2717,10 @@
                     case SCANNER_STATE_CONTENT: {
                         final int ch = fEntityScanner.peekChar();
                         if (ch == '<') {
-                            fEntityScanner.scanChar();
+                            fEntityScanner.scanChar(null);
                             setScannerState(SCANNER_STATE_START_OF_MARKUP);
                         } else if (ch == '&') {
-                            fEntityScanner.scanChar();
+                            fEntityScanner.scanChar(NameType.REFERENCE);
                             setScannerState(SCANNER_STATE_REFERENCE) ; //XMLEvent.ENTITY_REFERENCE ); //SCANNER_STATE_REFERENCE
                             break;
                         } else {
@@ -2819,9 +2820,9 @@
                         if(DEBUG){
                             System.out.println("fTempString = " + fTempString);
                         }
-                        if(fEntityScanner.skipChar('<')){
+                        if(fEntityScanner.skipChar('<', null)){
                             //check if we have reached end of element
-                            if(fEntityScanner.skipChar('/')){
+                            if(fEntityScanner.skipChar('/', NameType.ELEMENTEND)){
                                 //increase the mark up depth
                                 fMarkupDepth++;
                                 fLastSectionWasCharacterData = false;
@@ -2871,7 +2872,7 @@
                             }
                             // happens when there is the character reference &#13;
                             //xxx: We know the next chracter.. we should just skip it and add ']' directlry
-                            fEntityScanner.scanChar();
+                            fEntityScanner.scanChar(null);
                             fUsebuffer = true;
                             fContentBuffer.append((char)c);
                             c = -1 ;
@@ -2879,7 +2880,7 @@
                             //fStringBuffer.clear();
                             //xxx: We know the next chracter.. we should just skip it and add ']' directlry
                             fUsebuffer = true;
-                            fContentBuffer.append((char)fEntityScanner.scanChar());
+                            fContentBuffer.append((char)fEntityScanner.scanChar(null));
                             // remember where we are in case we get an endEntity before we
                             // could flush the buffer out - this happens when we're parsing an
                             // entity which ends with a ]
@@ -2888,12 +2889,12 @@
                             // We work on a single character basis to handle cases such as:
                             // ']]]>' which we might otherwise miss.
                             //
-                            if (fEntityScanner.skipChar(']')) {
+                            if (fEntityScanner.skipChar(']', null)) {
                                 fContentBuffer.append(']');
-                                while (fEntityScanner.skipChar(']')) {
+                                while (fEntityScanner.skipChar(']', null)) {
                                     fContentBuffer.append(']');
                                 }
-                                if (fEntityScanner.skipChar('>')) {
+                                if (fEntityScanner.skipChar('>', null)) {
                                     reportFatalError("CDEndInContent", null);
                                 }
                             }
@@ -2906,12 +2907,12 @@
                             // we need not to grow the buffer only when isCoalesce() is not true;
 
                             if (c == '<') {
-                                fEntityScanner.scanChar();
+                                fEntityScanner.scanChar(null);
                                 setScannerState(SCANNER_STATE_START_OF_MARKUP);
                                 break;
                             }//xxx what should be the behavior if entity reference is present in the content ?
                             else if (c == '&') {
-                                fEntityScanner.scanChar();
+                                fEntityScanner.scanChar(NameType.REFERENCE);
                                 setScannerState(SCANNER_STATE_REFERENCE);
                                 break;
                             }///xxx since this part is also characters, it should be merged...
@@ -2924,7 +2925,7 @@
                                     reportFatalError("InvalidCharInContent",
                                             new Object[] {
                                         Integer.toString(c, 16)});
-                                        fEntityScanner.scanChar();
+                                        fEntityScanner.scanChar(null);
                                 }
                                 break;
                             }
@@ -3050,7 +3051,7 @@
                         }
                         fUsebuffer = true ;
                         //take care of character reference
-                        if (fEntityScanner.skipChar('#')) {
+                        if (fEntityScanner.skipChar('#', NameType.REFERENCE)) {
                             scanCharReferenceValue(fContentBuffer, null);
                             fMarkupDepth--;
                             if(!fIsCoalesce){
@@ -3106,11 +3107,11 @@
 
                                 if (fNamespaces) {
                                     while (isValidNCName(fEntityScanner.peekChar())) {
-                                        fStringBuffer.append((char)fEntityScanner.scanChar());
+                                        fStringBuffer.append((char)fEntityScanner.scanChar(null));
                                     }
                                 } else {
                                     while (isValidNameChar(fEntityScanner.peekChar())) {
-                                        fStringBuffer.append((char)fEntityScanner.scanChar());
+                                        fStringBuffer.append((char)fEntityScanner.scanChar(null));
                                     }
                                 }
                                 String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -631,7 +631,7 @@
         }
 
         // root element name
-        fDoctypeName = fEntityScanner.scanName();
+        fDoctypeName = fEntityScanner.scanName(NameType.DOCTYPE);
         if (fDoctypeName == null) {
             reportFatalError("MSG_ROOT_ELEMENT_TYPE_REQUIRED", null);
         }
@@ -671,10 +671,10 @@
 
         // is there an internal subset?
         boolean internalSubset = true;
-        if (!fEntityScanner.skipChar('[')) {
+        if (!fEntityScanner.skipChar('[', null)) {
             internalSubset = false;
             fEntityScanner.skipSpaces();
-            if (!fEntityScanner.skipChar('>')) {
+            if (!fEntityScanner.skipChar('>', null)) {
                 reportFatalError("DoctypedeclUnterminated", new Object[]{fDoctypeName});
             }
             fMarkupDepth--;
@@ -753,7 +753,7 @@
                         fStringBuffer.clear();
                         fStringBuffer.append("xml");
                         while (XMLChar.isName(fEntityScanner.peekChar())) {
-                            fStringBuffer.append((char)fEntityScanner.scanChar());
+                            fStringBuffer.append((char)fEntityScanner.scanChar(null));
                         }
                         String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
                         //this function should fill the data.. and set the fEvent object to this event.
@@ -831,9 +831,9 @@
                     switch (fScannerState) {
                         case SCANNER_STATE_PROLOG: {
                             fEntityScanner.skipSpaces();
-                            if (fEntityScanner.skipChar('<')) {
+                            if (fEntityScanner.skipChar('<', null)) {
                                 setScannerState(SCANNER_STATE_START_OF_MARKUP);
-                            } else if (fEntityScanner.skipChar('&')) {
+                            } else if (fEntityScanner.skipChar('&', NameType.REFERENCE)) {
                                 setScannerState(SCANNER_STATE_REFERENCE);
                             } else {
                                 setScannerState(SCANNER_STATE_CONTENT);
@@ -849,9 +849,9 @@
                                 setDriver(fContentDriver);
                                 //from now onwards this would be handled by fContentDriver,in the same next() call
                                 return fContentDriver.next();
-                            } else if (fEntityScanner.skipChar('!')) {
-                                if (fEntityScanner.skipChar('-')) {
-                                    if (!fEntityScanner.skipChar('-')) {
+                            } else if (fEntityScanner.skipChar('!', null)) {
+                                if (fEntityScanner.skipChar('-', null)) {
+                                    if (!fEntityScanner.skipChar('-', null)) {
                                         reportFatalError("InvalidCommentStart",
                                                 null);
                                     }
@@ -871,7 +871,7 @@
                                     reportFatalError("MarkupNotRecognizedInProlog",
                                             null);
                                 }
-                            } else if (fEntityScanner.skipChar('?')) {
+                            } else if (fEntityScanner.skipChar('?', null)) {
                                 setScannerState(SCANNER_STATE_PI);
                             } else {
                                 reportFatalError("MarkupNotRecognizedInProlog",
@@ -991,7 +991,7 @@
 
                     case SCANNER_STATE_CONTENT: {
                         reportFatalError("ContentIllegalInProlog", null);
-                        fEntityScanner.scanChar();
+                        fEntityScanner.scanChar(null);
                     }
                     case SCANNER_STATE_REFERENCE: {
                         reportFatalError("ReferenceIllegalInProlog", null);
@@ -1105,11 +1105,11 @@
                             fReadingDTD=false;
                             if (!moreToScan) {
                                 // end doctype declaration
-                                if (!fEntityScanner.skipChar(']')) {
+                                if (!fEntityScanner.skipChar(']', null)) {
                                     reportFatalError("DoctypedeclNotClosed", new Object[]{fDoctypeName});
                                 }
                                 fEntityScanner.skipSpaces();
-                                if (!fEntityScanner.skipChar('>')) {
+                                if (!fEntityScanner.skipChar('>', null)) {
                                     reportFatalError("DoctypedeclUnterminated", new Object[]{fDoctypeName});
                                 }
                                 fMarkupDepth--;
@@ -1373,7 +1373,7 @@
                             if(fScannerState == SCANNER_STATE_TERMINATED ){
                                 return XMLEvent.END_DOCUMENT ;
                             }
-                            if (fEntityScanner.skipChar('<')) {
+                            if (fEntityScanner.skipChar('<', null)) {
                                 setScannerState(SCANNER_STATE_START_OF_MARKUP);
                             } else {
                                 setScannerState(SCANNER_STATE_CONTENT);
@@ -1382,11 +1382,11 @@
                         }
                         case SCANNER_STATE_START_OF_MARKUP: {
                             fMarkupDepth++;
-                            if (fEntityScanner.skipChar('?')) {
+                            if (fEntityScanner.skipChar('?', null)) {
                                 setScannerState(SCANNER_STATE_PI);
-                            } else if (fEntityScanner.skipChar('!')) {
+                            } else if (fEntityScanner.skipChar('!', null)) {
                                 setScannerState(SCANNER_STATE_COMMENT);
-                            } else if (fEntityScanner.skipChar('/')) {
+                            } else if (fEntityScanner.skipChar('/', null)) {
                                 reportFatalError("MarkupNotRecognizedInMisc",
                                         null);
                             } else if (isValidNameStartChar(fEntityScanner.peekChar()) ||
@@ -1429,7 +1429,7 @@
                         } else{
                             reportFatalError("ContentIllegalInTrailingMisc",
                                     null);
-                            fEntityScanner.scanChar();
+                            fEntityScanner.scanChar(null);
                             setScannerState(SCANNER_STATE_TRAILING_MISC);
                             return XMLEvent.CHARACTERS;
                         }
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java	Wed Jul 27 13:33:55 2016 +0000
@@ -2066,6 +2066,7 @@
 
         // system id has to be a valid URI
         if (strict) {
+
             try {
                 // if it's already an absolute one, return it
                 new URI(systemId);
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java	Wed Jul 27 13:33:55 2016 +0000
@@ -21,6 +21,7 @@
 
 package com.sun.org.apache.xerces.internal.impl;
 
+import com.sun.org.apache.xerces.internal.impl.XMLScanner.NameType;
 import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader;
 import com.sun.org.apache.xerces.internal.impl.io.UCSReader;
 import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader;
@@ -144,6 +145,9 @@
     // so that XMLStreamReader.getVersion() can find that out.
     protected boolean xmlVersionSetExplicitly = false;
 
+    // indicates that the operation is for detecting XML version
+    boolean detectingVersion = false;
+
     //
     // Constructors
     //
@@ -530,10 +534,12 @@
      * <p>
      * <strong>Note:</strong> The character is consumed.
      *
+     * @param nt The type of the name (element or attribute)
+     *
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public int scanChar() throws IOException {
+    protected int scanChar(NameType nt) throws IOException {
         if (DEBUG_BUFFER) {
             System.out.print("(scanChar: ");
             print();
@@ -546,6 +552,7 @@
         }
 
         // scan character
+        int offset = fCurrentEntity.position;
         int c = fCurrentEntity.ch[fCurrentEntity.position++];
         if (c == '\n' || (c == '\r' && isExternal)) {
             fCurrentEntity.lineNumber++;
@@ -554,6 +561,7 @@
                 invokeListeners(1);
                 fCurrentEntity.ch[0] = (char)c;
                 load(1, false, false);
+                offset = 0;
             }
             if (c == '\r' && isExternal) {
                 if (fCurrentEntity.ch[fCurrentEntity.position++] != '\n') {
@@ -570,6 +578,9 @@
             System.out.println(" -> '"+(char)c+"'");
         }
         fCurrentEntity.columnNumber++;
+        if (!detectingVersion) {
+            checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset);
+        }
         return c;
 
     } // scanChar():int
@@ -589,7 +600,7 @@
      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
      */
-    public String scanNmtoken() throws IOException {
+    protected String scanNmtoken() throws IOException {
         if (DEBUG_BUFFER) {
             System.out.print("(scanNmtoken: ");
             print();
@@ -661,6 +672,8 @@
      * <strong>Note:</strong> The string returned must be a symbol. The
      * SymbolTable can be used for this purpose.
      *
+     * @param nt The type of the name (element or attribute)
+     *
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      *
@@ -668,7 +681,7 @@
      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart
      */
-    public String scanName() throws IOException {
+    protected String scanName(NameType nt) throws IOException {
         if (DEBUG_BUFFER) {
             System.out.print("(scanName: ");
             print();
@@ -682,6 +695,7 @@
 
         // scan name
         int offset = fCurrentEntity.position;
+        int length;
         if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) {
             if (++fCurrentEntity.position == fCurrentEntity.count) {
                 invokeListeners(1);
@@ -709,20 +723,7 @@
                     vc = XMLChar.isName(c);
                 }
                 if(!vc)break;
-                if (++fCurrentEntity.position == fCurrentEntity.count) {
-                    int length = fCurrentEntity.position - offset;
-                    invokeListeners(length);
-                    if (length == fCurrentEntity.fBufferSize) {
-                        // bad luck we have to resize our buffer
-                        char[] tmp = new char[fCurrentEntity.fBufferSize * 2];
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                tmp, 0, length);
-                        fCurrentEntity.ch = tmp;
-                        fCurrentEntity.fBufferSize *= 2;
-                    } else {
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                fCurrentEntity.ch, 0, length);
-                    }
+                if ((length = checkBeforeLoad(fCurrentEntity, offset, offset)) > 0) {
                     offset = 0;
                     if (load(length, false, false)) {
                         break;
@@ -730,12 +731,14 @@
                 }
             }
         }
-        int length = fCurrentEntity.position - offset;
+        length = fCurrentEntity.position - offset;
         fCurrentEntity.columnNumber += length;
 
         // return name
         String symbol;
         if (length > 0) {
+            checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length);
+            checkEntityLimit(nt, fCurrentEntity, offset, length);
             symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
         } else
             symbol = null;
@@ -759,6 +762,7 @@
      * this purpose.
      *
      * @param qname The qualified name structure to fill.
+     * @param nt The type of the name (element or attribute)
      *
      * @return Returns true if a qualified name appeared immediately on
      *         the input and was scanned, false otherwise.
@@ -770,7 +774,7 @@
      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart
      */
-    public boolean scanQName(QName qname) throws IOException {
+    protected boolean scanQName(QName qname, NameType nt) throws IOException {
         if (DEBUG_BUFFER) {
             System.out.print("(scanQName, "+qname+": ");
             print();
@@ -806,11 +810,13 @@
                         print();
                         System.out.println(" -> true");
                     }
+                    checkEntityLimit(nt, fCurrentEntity, 0, 1);
                     return true;
                 }
             }
             int index = -1;
             boolean vc = false;
+            int length;
             while ( true){
 
                 //XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) ;
@@ -829,22 +835,7 @@
                     //check prefix before further read
                     checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, index - offset);
                 }
-                if (++fCurrentEntity.position == fCurrentEntity.count) {
-                    int length = fCurrentEntity.position - offset;
-                    //check localpart before loading more data
-                    checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length - index - 1);
-                    invokeListeners(length);
-                    if (length == fCurrentEntity.fBufferSize) {
-                        // bad luck we have to resize our buffer
-                        char[] tmp = new char[fCurrentEntity.fBufferSize * 2];
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                tmp, 0, length);
-                        fCurrentEntity.ch = tmp;
-                        fCurrentEntity.fBufferSize *= 2;
-                    } else {
-                        System.arraycopy(fCurrentEntity.ch, offset,
-                                fCurrentEntity.ch, 0, length);
-                    }
+                if ((length = checkBeforeLoad(fCurrentEntity, offset, index)) > 0) {
                     if (index != -1) {
                         index = index - offset;
                     }
@@ -854,7 +845,7 @@
                     }
                 }
             }
-            int length = fCurrentEntity.position - offset;
+            length = fCurrentEntity.position - offset;
             fCurrentEntity.columnNumber += length;
             if (length > 0) {
                 String prefix = null;
@@ -885,6 +876,7 @@
                     print();
                     System.out.println(" -> true");
                 }
+                checkEntityLimit(nt, fCurrentEntity, offset, length);
                 return true;
             }
         }
@@ -900,22 +892,104 @@
     } // scanQName(QName):boolean
 
     /**
+     * Checks whether the end of the entity buffer has been reached. If yes,
+     * checks against the limit and buffer size before loading more characters.
+     *
+     * @param entity the current entity
+     * @param offset the offset from which the current read was started
+     * @param nameOffset the offset from which the current name starts
+     * @return the length of characters scanned before the end of the buffer,
+     * zero if there is more to be read in the buffer
+     */
+    protected int checkBeforeLoad(Entity.ScannedEntity entity, int offset,
+            int nameOffset) throws IOException {
+        int length = 0;
+        if (++entity.position == entity.count) {
+            length = entity.position - offset;
+            int nameLength = length;
+            if (nameOffset != -1) {
+                nameOffset = nameOffset - offset;
+                nameLength = length - nameOffset;
+            } else {
+                nameOffset = offset;
+            }
+            //check limit before loading more data
+            checkLimit(Limit.MAX_NAME_LIMIT, entity, nameOffset, nameLength);
+            invokeListeners(length);
+            if (length == entity.ch.length) {
+                // bad luck we have to resize our buffer
+                char[] tmp = new char[entity.fBufferSize * 2];
+                System.arraycopy(entity.ch, offset, tmp, 0, length);
+                entity.ch = tmp;
+                entity.fBufferSize *= 2;
+            }
+            else {
+                System.arraycopy(entity.ch, offset, entity.ch, 0, length);
+            }
+        }
+        return length;
+    }
+
+    /**
+     * If the current entity is an Entity reference, check the accumulated size
+     * against the limit.
+     *
+     * @param nt type of name (element, attribute or entity)
+     * @param entity The current entity
+     * @param offset The index of the first byte
+     * @param length The length of the entity scanned
+     */
+    protected void checkEntityLimit(NameType nt, ScannedEntity entity, int offset, int length) {
+        if (entity == null || !entity.isGE) {
+            return;
+        }
+
+        if (nt != NameType.REFERENCE) {
+            checkLimit(Limit.GENERAL_ENTITY_SIZE_LIMIT, entity, offset, length);
+        }
+        if (nt == NameType.ELEMENTSTART || nt == NameType.ATTRIBUTENAME) {
+            checkNodeCount(entity);
+        }
+    }
+
+    /**
+     * If the current entity is an Entity reference, counts the total nodes in
+     * the entity and checks the accumulated value against the limit.
+     *
+     * @param entity The current entity
+     */
+    protected void checkNodeCount(ScannedEntity entity) {
+        if (entity != null && entity.isGE) {
+            checkLimit(Limit.ENTITY_REPLACEMENT_LIMIT, entity, 0, 1);
+        }
+    }
+
+    /**
      * Checks whether the value of the specified Limit exceeds its limit
      *
-     * @param limit The Limit to be checked.
-     * @param entity The current entity.
+     * @param limit The Limit to be checked
+     * @param entity The current entity
      * @param offset The index of the first byte
-     * @param length The length of the entity scanned.
+     * @param length The length of the entity scanned
      */
     protected void checkLimit(Limit limit, ScannedEntity entity, int offset, int length) {
-        fLimitAnalyzer.addValue(limit, null, length);
+        fLimitAnalyzer.addValue(limit, entity.name, length);
         if (fSecurityManager.isOverLimit(limit, fLimitAnalyzer)) {
             fSecurityManager.debugPrint(fLimitAnalyzer);
+            Object[] e = (limit == Limit.ENTITY_REPLACEMENT_LIMIT) ?
+                    new Object[]{fLimitAnalyzer.getValue(limit),
+                        fSecurityManager.getLimit(limit), fSecurityManager.getStateLiteral(limit)} :
+                    new Object[]{entity.name, fLimitAnalyzer.getValue(limit),
+                        fSecurityManager.getLimit(limit), fSecurityManager.getStateLiteral(limit)};
             fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, limit.key(),
-                    new Object[]{new String(entity.ch, offset, length),
-                fLimitAnalyzer.getTotalValue(limit),
-                fSecurityManager.getLimit(limit),
-                fSecurityManager.getStateLiteral(limit)},
+                    e, XMLErrorReporter.SEVERITY_FATAL_ERROR);
+        }
+        if (fSecurityManager.isOverLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
+            fSecurityManager.debugPrint(fLimitAnalyzer);
+            fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, "TotalEntitySizeLimit",
+                    new Object[]{fLimitAnalyzer.getTotalValue(Limit.TOTAL_ENTITY_SIZE_LIMIT),
+                fSecurityManager.getLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT),
+                fSecurityManager.getStateLiteral(Limit.TOTAL_ENTITY_SIZE_LIMIT)},
                     XMLErrorReporter.SEVERITY_FATAL_ERROR);
         }
     }
@@ -942,7 +1016,7 @@
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public int scanContent(XMLString content) throws IOException {
+    protected int scanContent(XMLString content) throws IOException {
         if (DEBUG_BUFFER) {
             System.out.print("(scanContent: ");
             print();
@@ -963,6 +1037,7 @@
         int offset = fCurrentEntity.position;
         int c = fCurrentEntity.ch[offset];
         int newlines = 0;
+        boolean counted = false;
         if (c == '\n' || (c == '\r' && isExternal)) {
             if (DEBUG_BUFFER) {
                 System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
@@ -976,9 +1051,11 @@
                     fCurrentEntity.lineNumber++;
                     fCurrentEntity.columnNumber = 1;
                     if (fCurrentEntity.position == fCurrentEntity.count) {
+                        checkEntityLimit(null, fCurrentEntity, offset, newlines);
                         offset = 0;
                         fCurrentEntity.position = newlines;
                         if (load(newlines, false, true)) {
+                            counted = true;
                             break;
                         }
                     }
@@ -995,9 +1072,11 @@
                     fCurrentEntity.lineNumber++;
                     fCurrentEntity.columnNumber = 1;
                     if (fCurrentEntity.position == fCurrentEntity.count) {
+                        checkEntityLimit(null, fCurrentEntity, offset, newlines);
                         offset = 0;
                         fCurrentEntity.position = newlines;
                         if (load(newlines, false, true)) {
+                            counted = true;
                             break;
                         }
                     }
@@ -1011,6 +1090,7 @@
             }
             int length = fCurrentEntity.position - offset;
             if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+                checkEntityLimit(null, fCurrentEntity, offset, length);
                 //CHANGED: dont replace the value.. append to the buffer. This gives control to the callee
                 //on buffering the data..
                 content.setValues(fCurrentEntity.ch, offset, length);
@@ -1038,8 +1118,8 @@
         }
         int length = fCurrentEntity.position - offset;
         fCurrentEntity.columnNumber += length - newlines;
-        if (fCurrentEntity.isGE) {
-            checkLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fCurrentEntity, offset, length);
+        if (!counted) {
+            checkEntityLimit(null, fCurrentEntity, offset, length);
         }
 
         //CHANGED: dont replace the value.. append to the buffer. This gives control to the callee
@@ -1086,6 +1166,7 @@
      * @param quote   The quote character that signifies the end of the
      *                attribute value data.
      * @param content The content structure to fill.
+     * @param isNSURI a flag indicating whether the content is a Namespace URI
      *
      * @return Returns the next character on the input, if known. This
      *         value may be -1 but this does <em>note</em> designate
@@ -1094,7 +1175,7 @@
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public int scanLiteral(int quote, XMLString content)
+    protected int scanLiteral(int quote, XMLString content, boolean isNSURI)
     throws IOException {
         if (DEBUG_BUFFER) {
             System.out.print("(scanLiteral, '"+(char)quote+"': ");
@@ -1205,8 +1286,10 @@
         }
         int length = fCurrentEntity.position - offset;
         fCurrentEntity.columnNumber += length - newlines;
-        if (fCurrentEntity.isGE) {
-            checkLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fCurrentEntity, offset, length);
+
+        checkEntityLimit(null, fCurrentEntity, offset, length);
+        if (isNSURI) {
+            checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length);
         }
         content.setValues(fCurrentEntity.ch, offset, length);
 
@@ -1273,7 +1356,7 @@
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public boolean scanData(String delimiter, XMLStringBuffer buffer)
+    protected boolean scanData(String delimiter, XMLStringBuffer buffer)
     throws IOException {
 
         boolean done = false;
@@ -1311,6 +1394,7 @@
             if (fCurrentEntity.position > fCurrentEntity.count - delimLen) {
                 // something must be wrong with the input:  e.g., file ends in an unterminated comment
                 int length = fCurrentEntity.count - fCurrentEntity.position;
+                checkEntityLimit(NameType.COMMENT, fCurrentEntity, fCurrentEntity.position, length);
                 buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length);
                 fCurrentEntity.columnNumber += fCurrentEntity.count;
                 fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
@@ -1373,6 +1457,7 @@
                 }
                 int length = fCurrentEntity.position - offset;
                 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+                    checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length);
                     buffer.append(fCurrentEntity.ch, offset, length);
                     if (DEBUG_BUFFER) {
                         System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
@@ -1416,12 +1501,14 @@
                     fCurrentEntity.position--;
                     int length = fCurrentEntity.position - offset;
                     fCurrentEntity.columnNumber += length - newlines;
+                    checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length);
                     buffer.append(fCurrentEntity.ch, offset, length);
                     return true;
                 }
             }
             int length = fCurrentEntity.position - offset;
             fCurrentEntity.columnNumber += length - newlines;
+            checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length);
             if (done) {
                 length -= delimLen;
             }
@@ -1445,13 +1532,14 @@
      * the specified character.
      *
      * @param c The character to skip.
+     * @param nt The type of the name (element or attribute)
      *
      * @return Returns true if the character was skipped.
      *
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public boolean skipChar(int c) throws IOException {
+    protected boolean skipChar(int c, NameType nt) throws IOException {
         if (DEBUG_BUFFER) {
             System.out.print("(skipChar, '"+(char)c+"': ");
             print();
@@ -1464,6 +1552,7 @@
         }
 
         // skip character
+        int offset = fCurrentEntity.position;
         int cc = fCurrentEntity.ch[fCurrentEntity.position];
         if (cc == c) {
             fCurrentEntity.position++;
@@ -1478,6 +1567,7 @@
                 print();
                 System.out.println(" -> true");
             }
+            checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset);
             return true;
         } else if (c == '\n' && cc == '\r' && isExternal) {
             // handle newlines
@@ -1497,6 +1587,7 @@
                 print();
                 System.out.println(" -> true");
             }
+            checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset);
             return true;
         }
 
@@ -1526,7 +1617,7 @@
      *
      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
      */
-    public boolean skipSpaces() throws IOException {
+    protected boolean skipSpaces() throws IOException {
         if (DEBUG_BUFFER) {
             System.out.print("(skipSpaces: ");
             print();
@@ -1550,6 +1641,7 @@
 
         // skip spaces
         int c = fCurrentEntity.ch[fCurrentEntity.position];
+        int offset = fCurrentEntity.position - 1;
         if (XMLChar.isSpace(c)) {
             do {
                 boolean entityChanged = false;
@@ -1579,6 +1671,11 @@
                 } else {
                     fCurrentEntity.columnNumber++;
                 }
+
+                //If this is a general entity, spaces within a start element should be counted
+                checkEntityLimit(null, fCurrentEntity, offset, fCurrentEntity.position - offset);
+                offset = fCurrentEntity.position;
+
                 // load more characters, if needed
                 if (!entityChanged){
                     fCurrentEntity.position++;
@@ -1620,7 +1717,7 @@
 
 
     /**
-     * @param legnth This function checks that following number of characters are available.
+     * @param length This function checks that following number of characters are available.
      * to the underlying buffer.
      * @return This function returns true if capacity asked is available.
      */
@@ -1629,9 +1726,9 @@
     }
 
     /**
-     * @param legnth This function checks that following number of characters are available.
+     * @param length This function checks that following number of characters are available.
      * to the underlying buffer.
-     * @param if the underlying function should change the entity
+     * @param changeEntity a flag to indicate that the underlying function should change the entity
      * @return This function returns true if capacity asked is available.
      *
      */
@@ -1694,7 +1791,7 @@
      * @throws IOException  Thrown if i/o error occurs.
      * @throws EOFException Thrown on end of file.
      */
-    public boolean skipString(String s) throws IOException {
+    protected boolean skipString(String s) throws IOException {
 
         final int length = s.length();
 
@@ -1714,6 +1811,9 @@
                 if(afterSkip-- == beforeSkip){
                     fCurrentEntity.position = fCurrentEntity.position + length ;
                     fCurrentEntity.columnNumber += length;
+                    if (!detectingVersion) {
+                        checkEntityLimit(null, fCurrentEntity, beforeSkip, length);
+                    }
                     return true;
                 }
             }
@@ -1722,7 +1822,7 @@
         return false;
     } // skipString(String):boolean
 
-    public boolean skipString(char [] s) throws IOException {
+    protected boolean skipString(char [] s) throws IOException {
 
         final int length = s.length;
         //first make sure that required capacity is avaible
@@ -1741,6 +1841,9 @@
             }
             fCurrentEntity.position = fCurrentEntity.position + length ;
             fCurrentEntity.columnNumber += length;
+            if (!detectingVersion) {
+                checkEntityLimit(null, fCurrentEntity, beforeSkip, length);
+            }
             return true;
 
         }
@@ -2138,7 +2241,7 @@
      *
      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
      */
-    public final boolean skipDeclSpaces() throws IOException {
+    protected final boolean skipDeclSpaces() throws IOException {
         if (DEBUG_BUFFER) {
             System.out.print("(skipDeclSpaces: ");
             //XMLEntityManager.print(fCurrentEntity);
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -189,9 +189,9 @@
             // There are two variables,fNamespaces and fBindNamespaces
             //StAX uses XMLNSDocumentScannerImpl so this distinction needs to be maintained
             if (fNamespaces) {
-                fEntityScanner.scanQName(fElementQName);
+                fEntityScanner.scanQName(fElementQName, NameType.ELEMENTSTART);
             } else {
-                String name = fEntityScanner.scanName();
+                String name = fEntityScanner.scanName(NameType.ELEMENTSTART);
                 fElementQName.setValues(null, name, name, null);
             }
 
@@ -404,11 +404,11 @@
         if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanAttribute()");
 
         // name
-        fEntityScanner.scanQName(fAttributeQName);
+        fEntityScanner.scanQName(fAttributeQName, NameType.ATTRIBUTE);
 
         // equals
         fEntityScanner.skipSpaces();
-        if (!fEntityScanner.skipChar('=')) {
+        if (!fEntityScanner.skipChar('=', NameType.ATTRIBUTE)) {
             reportFatalError("EqRequiredInAttribute",
                     new Object[]{fCurrentElement.rawname,fAttributeQName.rawname});
         }
@@ -430,23 +430,28 @@
         //since scanAttributeValue doesn't use attIndex parameter therefore we
         //can safely add the attribute later..
         XMLString tmpStr = getString();
-        scanAttributeValue(tmpStr, fTempString2,
-                fAttributeQName.rawname, attributes,
-                attrIndex, isVC, fCurrentElement.rawname);
+
+        /**
+         * Determine whether this is a namespace declaration that will be subject
+         * to the name limit check in the scanAttributeValue operation.
+         * Namespace declaration format: xmlns="..." or xmlns:prefix="..."
+         * Note that prefix:xmlns="..." isn't a namespace.
+         */
+        String localpart = fAttributeQName.localpart;
+        String prefix = fAttributeQName.prefix != null
+                ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
+        boolean isNSDecl = fBindNamespaces & (prefix == XMLSymbols.PREFIX_XMLNS ||
+                    prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS);
+
+        scanAttributeValue(tmpStr, fTempString2, fAttributeQName.rawname, attributes,
+                attrIndex, isVC, fCurrentElement.rawname, isNSDecl);
 
         String value = null;
         //fTempString.toString();
 
         // record namespace declarations if any.
         if (fBindNamespaces) {
-
-            String localpart = fAttributeQName.localpart;
-            String prefix = fAttributeQName.prefix != null
-                    ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
-            // when it's of form xmlns="..." or xmlns:prefix="...",
-            // it's a namespace declaration. but prefix:xmlns="..." isn't.
-            if (prefix == XMLSymbols.PREFIX_XMLNS ||
-                    prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {
+            if (isNSDecl) {
                 //check the length of URI
                 if (tmpStr.length > fXMLNameLimit) {
                     fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java	Wed Jul 27 13:33:55 2016 +0000
@@ -114,6 +114,30 @@
     /** Debug attribute normalization. */
     protected static final boolean DEBUG_ATTR_NORMALIZATION = false;
 
+    /**
+     * Type of names
+     */
+    public static enum NameType {
+        ATTRIBUTE("attribute"),
+        ATTRIBUTENAME("attribute name"),
+        COMMENT("comment"),
+        DOCTYPE("doctype"),
+        ELEMENTSTART("startelement"),
+        ELEMENTEND("endelement"),
+        ENTITY("entity"),
+        NOTATION("notation"),
+        PI("pi"),
+        REFERENCE("reference");
+
+        final String literal;
+        NameType(String literal) {
+            this.literal = literal;
+        }
+
+        String literal() {
+            return literal;
+        }
+    }
 
     //xxx: setting the default value as false, as we dont need to calculate this value
     //we should have a feature when set to true computes this value
@@ -144,7 +168,7 @@
     protected boolean fNotifyCharRefs = false;
 
     /** Internal parser-settings feature */
-        protected boolean fParserSettings = true;
+    protected boolean fParserSettings = true;
 
     // properties
 
@@ -173,13 +197,13 @@
     /** event type */
     protected XMLEvent fEvent ;
 
-    /** Entity scanner, this alwasy works on last entity that was opened. */
+    /** Entity scanner, this always works on last entity that was opened. */
     protected XMLEntityScanner fEntityScanner = null;
 
     /** Entity depth. */
     protected int fEntityDepth;
 
-    /** Literal value of the last character refence scanned. */
+    /** Literal value of the last character reference scanned. */
     protected String fCharRefLiteral = null;
 
     /** Scanning attribute. */
@@ -547,10 +571,10 @@
         }
 
         // end
-        if (!fEntityScanner.skipChar('?')) {
+        if (!fEntityScanner.skipChar('?', null)) {
             reportFatalError("XMLDeclUnterminated", null);
         }
-        if (!fEntityScanner.skipChar('>')) {
+        if (!fEntityScanner.skipChar('>', null)) {
             reportFatalError("XMLDeclUnterminated", null);
 
         }
@@ -577,7 +601,7 @@
      * <strong>Note:</strong> This method uses fStringBuffer2, anything in it
      * at the time of calling is lost.
      */
-    public String scanPseudoAttribute(boolean scanningTextDecl,
+    protected String scanPseudoAttribute(boolean scanningTextDecl,
             XMLString value)
             throws IOException, XNIException {
 
@@ -588,7 +612,7 @@
             reportFatalError("PseudoAttrNameExpected", null);
         }
         fEntityScanner.skipSpaces();
-        if (!fEntityScanner.skipChar('=')) {
+        if (!fEntityScanner.skipChar('=', null)) {
             reportFatalError(scanningTextDecl ? "EqRequiredInTextDecl"
                     : "EqRequiredInXMLDecl", new Object[]{name});
         }
@@ -598,15 +622,15 @@
             reportFatalError(scanningTextDecl ? "QuoteRequiredInTextDecl"
                     : "QuoteRequiredInXMLDecl" , new Object[]{name});
         }
-        fEntityScanner.scanChar();
-        int c = fEntityScanner.scanLiteral(quote, value);
+        fEntityScanner.scanChar(NameType.ATTRIBUTE);
+        int c = fEntityScanner.scanLiteral(quote, value, false);
         if (c != quote) {
             fStringBuffer2.clear();
             do {
                 fStringBuffer2.append(value);
                 if (c != -1) {
                     if (c == '&' || c == '%' || c == '<' || c == ']') {
-                        fStringBuffer2.append((char)fEntityScanner.scanChar());
+                        fStringBuffer2.append((char)fEntityScanner.scanChar(NameType.ATTRIBUTE));
                     } else if (XMLChar.isHighSurrogate(c)) {
                         scanSurrogates(fStringBuffer2);
                     } else if (isInvalidLiteral(c)) {
@@ -614,15 +638,15 @@
                                 ? "InvalidCharInTextDecl" : "InvalidCharInXMLDecl";
                         reportFatalError(key,
                                 new Object[] {Integer.toString(c, 16)});
-                                fEntityScanner.scanChar();
+                                fEntityScanner.scanChar(null);
                     }
                 }
-                c = fEntityScanner.scanLiteral(quote, value);
+                c = fEntityScanner.scanLiteral(quote, value, false);
             } while (c != quote);
             fStringBuffer2.append(value);
             value.setValues(fStringBuffer2);
         }
-        if (!fEntityScanner.skipChar(quote)) {
+        if (!fEntityScanner.skipChar(quote, null)) {
             reportFatalError(scanningTextDecl ? "CloseQuoteMissingInTextDecl"
                     : "CloseQuoteMissingInXMLDecl",
                     new Object[]{name});
@@ -680,7 +704,7 @@
 
         // target
         fReportEntity = false;
-        String target = fEntityScanner.scanName();
+        String target = fEntityScanner.scanName(NameType.PI);
         if (target == null) {
             reportFatalError("PITargetRequired", null);
         }
@@ -745,7 +769,7 @@
                     } else if (isInvalidLiteral(c)) {
                         reportFatalError("InvalidCharInPI",
                                 new Object[]{Integer.toHexString(c)});
-                                fEntityScanner.scanChar();
+                                fEntityScanner.scanChar(null);
                     }
                 }
             } while (fEntityScanner.scanData("?>", data));
@@ -786,11 +810,11 @@
                 else if (isInvalidLiteral(c)) {
                     reportFatalError("InvalidCharInComment",
                             new Object[] { Integer.toHexString(c) });
-                            fEntityScanner.scanChar();
+                            fEntityScanner.scanChar(NameType.COMMENT);
                 }
             }
         }
-        if (!fEntityScanner.skipChar('>')) {
+        if (!fEntityScanner.skipChar('>', NameType.COMMENT)) {
             reportFatalError("DashDashInComment", null);
         }
 
@@ -811,15 +835,14 @@
      * @param checkEntities true if undeclared entities should be reported as VC violation,
      *                      false if undeclared entities should be reported as WFC violation.
      * @param eleName The name of element to which this attribute belongs.
+     * @param isNSURI a flag indicating whether the content is a Namespace URI
      *
      * <strong>Note:</strong> This method uses fStringBuffer2, anything in it
      * at the time of calling is lost.
      **/
-    protected void scanAttributeValue(XMLString value,
-            XMLString nonNormalizedValue,
-            String atName,
-            XMLAttributes attributes, int attrIndex,
-            boolean checkEntities, String eleName)
+    protected void scanAttributeValue(XMLString value, XMLString nonNormalizedValue,
+            String atName, XMLAttributes attributes, int attrIndex, boolean checkEntities,
+            String eleName, boolean isNSURI)
             throws IOException, XNIException {
         XMLStringBuffer stringBuffer = null;
         // quote
@@ -828,10 +851,10 @@
             reportFatalError("OpenQuoteExpected", new Object[]{eleName, atName});
         }
 
-        fEntityScanner.scanChar();
+        fEntityScanner.scanChar(NameType.ATTRIBUTE);
         int entityDepth = fEntityDepth;
 
-        int c = fEntityScanner.scanLiteral(quote, value);
+        int c = fEntityScanner.scanLiteral(quote, value, isNSURI);
         if (DEBUG_ATTR_NORMALIZATION) {
             System.out.println("** scanLiteral -> \""
                     + value.toString() + "\"");
@@ -857,11 +880,11 @@
                             + stringBuffer.toString() + "\"");
                 }
                 if (c == '&') {
-                    fEntityScanner.skipChar('&');
+                    fEntityScanner.skipChar('&', NameType.REFERENCE);
                     if (entityDepth == fEntityDepth && fNeedNonNormalizedValue ) {
                         fStringBuffer2.append('&');
                     }
-                    if (fEntityScanner.skipChar('#')) {
+                    if (fEntityScanner.skipChar('#', NameType.REFERENCE)) {
                         if (entityDepth == fEntityDepth && fNeedNonNormalizedValue ) {
                             fStringBuffer2.append('#');
                         }
@@ -879,53 +902,20 @@
                             }
                         }
                     } else {
-                        String entityName = fEntityScanner.scanName();
+                        String entityName = fEntityScanner.scanName(NameType.ENTITY);
                         if (entityName == null) {
                             reportFatalError("NameRequiredInReference", null);
                         } else if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                             fStringBuffer2.append(entityName);
                         }
-                        if (!fEntityScanner.skipChar(';')) {
+                        if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
                             reportFatalError("SemicolonRequiredInReference",
                                     new Object []{entityName});
                         } else if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                             fStringBuffer2.append(';');
                         }
-                        if (entityName == fAmpSymbol) {
-                            stringBuffer.append('&');
-                            if (DEBUG_ATTR_NORMALIZATION) {
-                                System.out.println("** value5: \""
-                                        + stringBuffer.toString()
-                                        + "\"");
-                            }
-                        } else if (entityName == fAposSymbol) {
-                            stringBuffer.append('\'');
-                            if (DEBUG_ATTR_NORMALIZATION) {
-                                System.out.println("** value7: \""
-                                        + stringBuffer.toString()
-                                        + "\"");
-                            }
-                        } else if (entityName == fLtSymbol) {
-                            stringBuffer.append('<');
-                            if (DEBUG_ATTR_NORMALIZATION) {
-                                System.out.println("** value9: \""
-                                        + stringBuffer.toString()
-                                        + "\"");
-                            }
-                        } else if (entityName == fGtSymbol) {
-                            stringBuffer.append('>');
-                            if (DEBUG_ATTR_NORMALIZATION) {
-                                System.out.println("** valueB: \""
-                                        + stringBuffer.toString()
-                                        + "\"");
-                            }
-                        } else if (entityName == fQuotSymbol) {
-                            stringBuffer.append('"');
-                            if (DEBUG_ATTR_NORMALIZATION) {
-                                System.out.println("** valueD: \""
-                                        + stringBuffer.toString()
-                                        + "\"");
-                            }
+                        if (resolveCharacter(entityName, stringBuffer)) {
+                            checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1);
                         } else {
                             if (fEntityStore.isExternalEntity(entityName)) {
                                 reportFatalError("ReferenceToExternalEntity",
@@ -952,12 +942,12 @@
                 } else if (c == '<') {
                     reportFatalError("LessthanInAttValue",
                             new Object[] { eleName, atName });
-                            fEntityScanner.scanChar();
+                            fEntityScanner.scanChar(null);
                             if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                                 fStringBuffer2.append((char)c);
                             }
                 } else if (c == '%' || c == ']') {
-                    fEntityScanner.scanChar();
+                    fEntityScanner.scanChar(null);
                     stringBuffer.append((char)c);
                     if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                         fStringBuffer2.append((char)c);
@@ -967,7 +957,7 @@
                                 + stringBuffer.toString() + "\"");
                     }
                 } else if (c == '\n' || c == '\r') {
-                    fEntityScanner.scanChar();
+                    fEntityScanner.scanChar(null);
                     stringBuffer.append(' ');
                     if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                         fStringBuffer2.append('\n');
@@ -988,12 +978,12 @@
                 } else if (c != -1 && isInvalidLiteral(c)) {
                     reportFatalError("InvalidCharInAttValue",
                             new Object[] {eleName, atName, Integer.toString(c, 16)});
-                            fEntityScanner.scanChar();
+                            fEntityScanner.scanChar(null);
                             if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                                 fStringBuffer2.append((char)c);
                             }
                 }
-                c = fEntityScanner.scanLiteral(quote, value);
+                c = fEntityScanner.scanLiteral(quote, value, isNSURI);
                 if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                     fStringBuffer2.append(value);
                 }
@@ -1014,7 +1004,7 @@
             nonNormalizedValue.setValues(fStringBuffer2);
 
         // quote
-        int cquote = fEntityScanner.scanChar();
+        int cquote = fEntityScanner.scanChar(NameType.ATTRIBUTE);
         if (cquote != quote) {
             reportFatalError("CloseQuoteExpected", new Object[]{eleName, atName});
         }
@@ -1022,6 +1012,39 @@
 
 
     /**
+     * Resolves character entity references.
+     * @param entityName the name of the entity
+     * @param stringBuffer the current XMLStringBuffer to append the character to.
+     * @return true if resolved, false otherwise
+     */
+    protected boolean resolveCharacter(String entityName, XMLStringBuffer stringBuffer) {
+        /**
+         * entityNames (symbols) are interned. The equals method would do the same,
+         * but I'm leaving it as comparisons by references are common in the impl
+         * and it made it explicit to others who read this code.
+         */
+        if (entityName == fAmpSymbol) {
+            stringBuffer.append('&');
+            return true;
+        } else if (entityName == fAposSymbol) {
+            stringBuffer.append('\'');
+            return true;
+        } else if (entityName == fLtSymbol) {
+            stringBuffer.append('<');
+            return true;
+        } else if (entityName == fGtSymbol) {
+            checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1);
+            stringBuffer.append('>');
+            return true;
+        } else if (entityName == fQuotSymbol) {
+            checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1);
+            stringBuffer.append('"');
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Scans External ID and return the public and system IDs.
      *
      * @param identifiers An array of size 2 to return the system id,
@@ -1064,25 +1087,25 @@
                 }
                 reportFatalError("QuoteRequiredInSystemID", null);
             }
-            fEntityScanner.scanChar();
+            fEntityScanner.scanChar(null);
             XMLString ident = fString;
-            if (fEntityScanner.scanLiteral(quote, ident) != quote) {
+            if (fEntityScanner.scanLiteral(quote, ident, false) != quote) {
                 fStringBuffer.clear();
                 do {
                     fStringBuffer.append(ident);
                     int c = fEntityScanner.peekChar();
                     if (XMLChar.isMarkup(c) || c == ']') {
-                        fStringBuffer.append((char)fEntityScanner.scanChar());
+                        fStringBuffer.append((char)fEntityScanner.scanChar(null));
                     } else if (c != -1 && isInvalidLiteral(c)) {
                         reportFatalError("InvalidCharInSystemID",
                             new Object[] {Integer.toString(c, 16)});
                     }
-                } while (fEntityScanner.scanLiteral(quote, ident) != quote);
+                } while (fEntityScanner.scanLiteral(quote, ident, false) != quote);
                 fStringBuffer.append(ident);
                 ident = fStringBuffer;
             }
             systemId = ident.toString();
-            if (!fEntityScanner.skipChar(quote)) {
+            if (!fEntityScanner.skipChar(quote, null)) {
                 reportFatalError("SystemIDUnterminated", null);
             }
         }
@@ -1114,7 +1137,7 @@
      */
     protected boolean scanPubidLiteral(XMLString literal)
     throws IOException, XNIException {
-        int quote = fEntityScanner.scanChar();
+        int quote = fEntityScanner.scanChar(null);
         if (quote != '\'' && quote != '"') {
             reportFatalError("QuoteRequiredInPublicID", null);
             return false;
@@ -1125,7 +1148,7 @@
         boolean skipSpace = true;
         boolean dataok = true;
         while (true) {
-            int c = fEntityScanner.scanChar();
+            int c = fEntityScanner.scanChar(null);
             if (c == ' ' || c == '\n' || c == '\r') {
                 if (!skipSpace) {
                     // take the first whitespace as a space and skip the others
@@ -1241,9 +1264,10 @@
      */
     protected int scanCharReferenceValue(XMLStringBuffer buf, XMLStringBuffer buf2)
     throws IOException, XNIException {
+        int initLen = buf.length;
         // scan hexadecimal value
         boolean hex = false;
-        if (fEntityScanner.skipChar('x')) {
+        if (fEntityScanner.skipChar('x', NameType.REFERENCE)) {
             if (buf2 != null) { buf2.append('x'); }
             hex = true;
             fStringBuffer3.clear();
@@ -1255,7 +1279,7 @@
                     (c >= 'A' && c <= 'F');
             if (digit) {
                 if (buf2 != null) { buf2.append((char)c); }
-                fEntityScanner.scanChar();
+                fEntityScanner.scanChar(NameType.REFERENCE);
                 fStringBuffer3.append((char)c);
 
                 do {
@@ -1265,7 +1289,7 @@
                             (c >= 'A' && c <= 'F');
                     if (digit) {
                         if (buf2 != null) { buf2.append((char)c); }
-                        fEntityScanner.scanChar();
+                        fEntityScanner.scanChar(NameType.REFERENCE);
                         fStringBuffer3.append((char)c);
                     }
                 } while (digit);
@@ -1283,7 +1307,7 @@
             digit = c >= '0' && c <= '9';
             if (digit) {
                 if (buf2 != null) { buf2.append((char)c); }
-                fEntityScanner.scanChar();
+                fEntityScanner.scanChar(NameType.REFERENCE);
                 fStringBuffer3.append((char)c);
 
                 do {
@@ -1291,7 +1315,7 @@
                     digit = c >= '0' && c <= '9';
                     if (digit) {
                         if (buf2 != null) { buf2.append((char)c); }
-                        fEntityScanner.scanChar();
+                        fEntityScanner.scanChar(NameType.REFERENCE);
                         fStringBuffer3.append((char)c);
                     }
                 } while (digit);
@@ -1301,7 +1325,7 @@
         }
 
         // end
-        if (!fEntityScanner.skipChar(';')) {
+        if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
             reportFatalError("SemicolonRequiredInCharRef", null);
         }
         if (buf2 != null) { buf2.append(';'); }
@@ -1347,6 +1371,9 @@
             }
         }
 
+        if (fEntityScanner.fCurrentEntity.isGE) {
+            checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, buf.length - initLen);
+        }
         return value;
     }
     // returns true if the given character is not
@@ -1408,14 +1435,14 @@
     protected boolean scanSurrogates(XMLStringBuffer buf)
     throws IOException, XNIException {
 
-        int high = fEntityScanner.scanChar();
+        int high = fEntityScanner.scanChar(null);
         int low = fEntityScanner.peekChar();
         if (!XMLChar.isLowSurrogate(low)) {
             reportFatalError("InvalidCharInContent",
                     new Object[] {Integer.toString(high, 16)});
                     return false;
         }
-        fEntityScanner.scanChar();
+        fEntityScanner.scanChar(null);
 
         // convert surrogates to supplemental character
         int c = XMLChar.supplemental((char)high, (char)low);
@@ -1478,5 +1505,52 @@
         }
     }
 
+    /**
+     * Add the count of the content buffer and check if the accumulated
+     * value exceeds the limit
+     * @param isPEDecl a flag to indicate whether the entity is parameter
+     * @param entityName entity name
+     * @param buffer content buffer
+     */
+    void checkEntityLimit(boolean isPEDecl, String entityName, XMLString buffer) {
+        checkEntityLimit(isPEDecl, entityName, buffer.length);
+    }
 
+    /**
+     * Add the count and check limit
+     * @param isPEDecl a flag to indicate whether the entity is parameter
+     * @param entityName entity name
+     * @param len length of the buffer
+     */
+    void checkEntityLimit(boolean isPEDecl, String entityName, int len) {
+        if (fLimitAnalyzer == null) {
+            fLimitAnalyzer = fEntityManager.fLimitAnalyzer;
+        }
+        if (isPEDecl) {
+            fLimitAnalyzer.addValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, "%" + entityName, len);
+            if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
+                        fSecurityManager.debugPrint(fLimitAnalyzer);
+                reportFatalError("MaxEntitySizeLimit", new Object[]{"%" + entityName,
+                    fLimitAnalyzer.getValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT),
+                    fSecurityManager.getLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT),
+                    fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT)});
+            }
+        } else {
+            fLimitAnalyzer.addValue(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT, entityName, len);
+            if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
+                        fSecurityManager.debugPrint(fLimitAnalyzer);
+                reportFatalError("MaxEntitySizeLimit", new Object[]{entityName,
+                    fLimitAnalyzer.getValue(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT),
+                    fSecurityManager.getLimit(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT),
+                    fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.GENERAL_ENTITY_SIZE_LIMIT)});
+            }
+        }
+        if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
+            fSecurityManager.debugPrint(fLimitAnalyzer);
+            reportFatalError("TotalEntitySizeLimit",
+                new Object[]{fLimitAnalyzer.getTotalValue(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT),
+                fSecurityManager.getLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT),
+                fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT)});
+        }
+    }
 } // class XMLScanner
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,62 +1,21 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 1999-2003 The Apache Software Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
- * 4. The names "Xerces" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 2003, International
- * Business Machines, Inc., http://www.apache.org.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package com.sun.org.apache.xerces.internal.impl;
@@ -192,40 +151,46 @@
         // in the XML declaration.
         fEntityManager.setScannerVersion(Constants.XML_VERSION_1_0);
         XMLEntityScanner scanner = fEntityManager.getEntityScanner();
+        scanner.detectingVersion = true;
         try {
             if (!scanner.skipString("<?xml")) {
                 // definitely not a well-formed 1.1 doc!
+                scanner.detectingVersion = false;
                 return Constants.XML_VERSION_1_0;
             }
             if (!scanner.skipDeclSpaces()) {
                 fixupCurrentEntity(fEntityManager, fExpectedVersionString, 5);
+                scanner.detectingVersion = false;
                 return Constants.XML_VERSION_1_0;
             }
             if (!scanner.skipString("version")) {
                 fixupCurrentEntity(fEntityManager, fExpectedVersionString, 6);
+                scanner.detectingVersion = false;
                 return Constants.XML_VERSION_1_0;
             }
             scanner.skipDeclSpaces();
             // Check if the next character is '='. If it is then consume it.
             if (scanner.peekChar() != '=') {
                 fixupCurrentEntity(fEntityManager, fExpectedVersionString, 13);
+                scanner.detectingVersion = false;
                 return Constants.XML_VERSION_1_0;
             }
-            scanner.scanChar();
+            scanner.scanChar(null);
             scanner.skipDeclSpaces();
-            int quoteChar = scanner.scanChar();
+            int quoteChar = scanner.scanChar(null);
             fExpectedVersionString[14] = (char) quoteChar;
             for (int versionPos = 0; versionPos < XML11_VERSION.length; versionPos++) {
-                fExpectedVersionString[15 + versionPos] = (char) scanner.scanChar();
+                fExpectedVersionString[15 + versionPos] = (char) scanner.scanChar(null);
             }
             // REVISIT:  should we check whether this equals quoteChar?
-            fExpectedVersionString[18] = (char) scanner.scanChar();
+            fExpectedVersionString[18] = (char) scanner.scanChar(null);
             fixupCurrentEntity(fEntityManager, fExpectedVersionString, 19);
             int matched = 0;
             for (; matched < XML11_VERSION.length; matched++) {
                 if (fExpectedVersionString[15 + matched] != XML11_VERSION[matched])
                     break;
             }
+            scanner.detectingVersion = false;
             if (matched == XML11_VERSION.length)
                 return Constants.XML_VERSION_1_1;
             return Constants.XML_VERSION_1_0;
@@ -237,10 +202,9 @@
                 "PrematureEOF",
                 null,
                 XMLErrorReporter.SEVERITY_FATAL_ERROR);
+            scanner.detectingVersion = false;
             return Constants.XML_VERSION_1_0;
-
         }
-
     }
 
     // This method prepends "length" chars from the char array,
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties	Wed Jul 27 13:33:55 2016 +0000
@@ -298,7 +298,8 @@
         EntityExpansionLimit=JAXP00010001: The parser has encountered more than \"{0}\" entity expansions in this document; this is the limit imposed by the JDK.
         ElementAttributeLimit=JAXP00010002:  Element \"{0}\" has more than \"{1}\" attributes, \"{1}\" is the limit imposed by the JDK.
         MaxEntitySizeLimit=JAXP00010003: The length of entity \"{0}\" is \"{1}\" that exceeds the \"{2}\" limit set by \"{3}\".
-        TotalEntitySizeLimit=JAXP00010004: The accumulated size of entities is \"{1}\" that exceeded the \"{2}\" limit set by \"{3}\".
+        TotalEntitySizeLimit=JAXP00010004: The accumulated size of entities is \"{0}\" that exceeded the \"{1}\" limit set by \"{2}\".
         MaxXMLNameLimit=JAXP00010005: The length of entity \"{0}\" is \"{1}\" that exceeds the \"{2}\" limit set by \"{3}\".
         MaxElementDepthLimit=JAXP00010006: The element \"{0}\" has a depth of \"{1}\" that exceeds the limit \"{2}\" set by \"{3}\".
+        EntityReplacementLimit=JAXP00010007: The total number of nodes in entity references is \"{0}\" that is over the limit \"{1}\" set by \"{2}\".
 
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/utils/XMLLimitAnalyzer.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/utils/XMLLimitAnalyzer.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -129,13 +129,15 @@
         if (index == Limit.ENTITY_EXPANSION_LIMIT.ordinal() ||
                 index == Limit.MAX_OCCUR_NODE_LIMIT.ordinal() ||
                 index == Limit.ELEMENT_ATTRIBUTE_LIMIT.ordinal() ||
-                index == Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal()
+                index == Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal() ||
+                index == Limit.ENTITY_REPLACEMENT_LIMIT.ordinal()
                 ) {
             totalValue[index] += value;
             return;
         }
         if (index == Limit.MAX_ELEMENT_DEPTH_LIMIT.ordinal() ||
                 index == Limit.MAX_NAME_LIMIT.ordinal()) {
+            values[index] = value;
             totalValue[index] = value;
             return;
         }
@@ -175,10 +177,13 @@
      * @return the value of the property
      */
     public int getValue(Limit limit) {
-        return values[limit.ordinal()];
+        return getValue(limit.ordinal());
     }
 
     public int getValue(int index) {
+        if (index == Limit.ENTITY_REPLACEMENT_LIMIT.ordinal()) {
+            return totalValue[index];
+        }
         return values[index];
     }
     /**
@@ -233,6 +238,11 @@
     public void reset(Limit limit) {
         if (limit.ordinal() == Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal()) {
             totalValue[limit.ordinal()] = 0;
+        } else if (limit.ordinal() == Limit.GENERAL_ENTITY_SIZE_LIMIT.ordinal()) {
+            names[limit.ordinal()] = null;
+            values[limit.ordinal()] = 0;
+            caches[limit.ordinal()] = null;
+            totalValue[limit.ordinal()] = 0;
         }
     }
 
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/utils/XMLSecurityManager.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/utils/XMLSecurityManager.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -78,7 +78,9 @@
         MAX_ELEMENT_DEPTH_LIMIT("MaxElementDepthLimit",
                 Constants.JDK_MAX_ELEMENT_DEPTH, Constants.SP_MAX_ELEMENT_DEPTH, 0, 0),
         MAX_NAME_LIMIT("MaxXMLNameLimit",
-                Constants.JDK_XML_NAME_LIMIT, Constants.SP_XML_NAME_LIMIT, 1000, 1000);
+                Constants.JDK_XML_NAME_LIMIT, Constants.SP_XML_NAME_LIMIT, 1000, 1000),
+        ENTITY_REPLACEMENT_LIMIT("EntityReplacementLimit",
+                Constants.JDK_ENTITY_REPLACEMENT_LIMIT, Constants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000);
 
         final String key;
         final String apiProperty;
@@ -450,6 +452,7 @@
         if (index == Limit.ELEMENT_ATTRIBUTE_LIMIT.ordinal() ||
                 index == Limit.ENTITY_EXPANSION_LIMIT.ordinal() ||
                 index == Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal() ||
+                index == Limit.ENTITY_REPLACEMENT_LIMIT.ordinal() ||
                 index == Limit.MAX_ELEMENT_DEPTH_LIMIT.ordinal() ||
                 index == Limit.MAX_NAME_LIMIT.ordinal()
                 ) {
--- a/jaxp/test/javax/xml/jaxp/unittest/transform/XSLTFunctionsTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/XSLTFunctionsTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -46,7 +46,7 @@
 public class XSLTFunctionsTest {
 
     /**
-     * @bug 8062518
+     * @bug 8062518 8153082
      * Verifies that a reference to the DTM created by XSLT document function is
      * actually read from the DTM by an extension function.
      * @param xml Content of xml file to process
--- a/jaxws/.hgtags	Wed Jul 27 08:33:15 2016 -0400
+++ b/jaxws/.hgtags	Wed Jul 27 13:33:55 2016 +0000
@@ -373,3 +373,4 @@
 5b0570e3db29f6b8c80a4beac70d51284507b203 jdk-9+125
 264a44128cd6286e598d5a849ceeb613c06269d0 jdk-9+126
 06d706c70634775418dc79a2671780ba1c624fd2 jdk-9+127
+fe4e11bd2423635dc0f5f5cb9a64eb2f2cce7f4c jdk-9+128
--- a/jdk/make/lib/Awt2dLibraries.gmk	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/make/lib/Awt2dLibraries.gmk	Wed Jul 27 13:33:55 2016 +0000
@@ -350,8 +350,6 @@
       BUILD_LIBAWT_XAWT_awt_Font.c_CFLAGS := -w
       # initializing a declared 'extern'
       BUILD_LIBAWT_XAWT_debug_mem.c_CFLAGS := -w
-      # decimal constant is unsigned only in ISO C90 (JAVASE_EMBEDDED)
-      BUILD_LIBAWT_XAWT_XToolkit.c_CFLAGS := -w
    endif
 
     $(eval $(call SetupNativeCompilation,BUILD_LIBAWT_XAWT, \
--- a/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template	Wed Jul 27 13:33:55 2016 +0000
@@ -166,10 +166,6 @@
 
         ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version);
 
-        if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
-            // embedded builds report headless state
-            ps.print(", headless");
-        }
         ps.println(')');
 
         /* Third line: JVM information. */
--- a/jdk/src/java.base/share/classes/java/net/URLPermission.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/net/URLPermission.java	Wed Jul 27 13:33:55 2016 +0000
@@ -461,11 +461,10 @@
     }
 
     private String actions() {
-        String b = String.join(",", methods);
-        if (!requestHeaders.isEmpty()) {
-            b += ":" + String.join(",", requestHeaders);
-        }
-        return b;
+        // The colon separator is optional when the request headers list is
+        // empty.This implementation chooses to include it even when the request
+        // headers list is empty.
+        return String.join(",", methods) + ":" + String.join(",", requestHeaders);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Wed Jul 27 13:33:55 2016 +0000
@@ -221,7 +221,10 @@
      *   across both while pushing actions.  The second completion is
      *   a CoCompletion pointing to the first, shared so that at most
      *   one performs the action.  The multiple-arity methods allOf
-     *   and anyOf do this pairwise to form trees of completions.
+     *   does this pairwise to form trees of completions.  Method
+     *   anyOf is handled differently from allOf because completion of
+     *   any source should trigger a cleanStack of other sources.
+     *   Each AnyOf completion can reach others via a shared array.
      *
      * Note that the generic type parameters of methods vary according
      * to whether "this" is a source, dependent, or completion.
@@ -588,9 +591,9 @@
     }
 
     /**
-     * Post-processing by dependent after successful UniCompletion
-     * tryFire.  Tries to clean stack of source a, and then either runs
-     * postComplete or returns this to caller, depending on mode.
+     * Post-processing by dependent after successful UniCompletion tryFire.
+     * Tries to clean stack of source a, and then either runs postComplete
+     * or returns this to caller, depending on mode.
      */
     final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
         if (a != null && a.stack != null) {
@@ -1003,12 +1006,12 @@
     }
 
     @SuppressWarnings("serial")
-    static final class UniRelay<T> extends UniCompletion<T,T> {
-        UniRelay(CompletableFuture<T> dep, CompletableFuture<T> src) {
+    static final class UniRelay<U, T extends U> extends UniCompletion<T,U> {
+        UniRelay(CompletableFuture<U> dep, CompletableFuture<T> src) {
             super(null, dep, src);
         }
-        final CompletableFuture<T> tryFire(int mode) {
-            CompletableFuture<T> d; CompletableFuture<T> a; Object r;
+        final CompletableFuture<U> tryFire(int mode) {
+            CompletableFuture<U> d; CompletableFuture<T> a; Object r;
             if ((d = dep) == null
                 || (a = src) == null || (r = a.result) == null)
                 return null;
@@ -1019,13 +1022,14 @@
         }
     }
 
-    private CompletableFuture<T> uniCopyStage() {
+    private static <U, T extends U> CompletableFuture<U> uniCopyStage(
+        CompletableFuture<T> src) {
         Object r;
-        CompletableFuture<T> d = newIncompleteFuture();
-        if ((r = result) != null)
+        CompletableFuture<U> d = src.newIncompleteFuture();
+        if ((r = src.result) != null)
             d.result = encodeRelay(r);
         else
-            unipush(new UniRelay<T>(d, this));
+            src.unipush(new UniRelay<U,T>(d, src));
         return d;
     }
 
@@ -1034,7 +1038,7 @@
         if ((r = result) != null)
             return new MinimalStage<T>(encodeRelay(r));
         MinimalStage<T> d = new MinimalStage<T>();
-        unipush(new UniRelay<T>(d, this));
+        unipush(new UniRelay<T,T>(d, this));
         return d;
     }
 
@@ -1069,7 +1073,7 @@
                     if ((r = g.result) != null)
                         d.completeRelay(r);
                     else {
-                        g.unipush(new UniRelay<V>(d, g));
+                        g.unipush(new UniRelay<V,V>(d, g));
                         if (d.result == null)
                             return null;
                     }
@@ -1103,7 +1107,7 @@
                 if ((s = g.result) != null)
                     d.result = encodeRelay(s);
                 else {
-                    g.unipush(new UniRelay<V>(d, g));
+                    g.unipush(new UniRelay<V,V>(d, g));
                 }
             } catch (Throwable ex) {
                 d.result = encodeThrowable(ex);
@@ -1637,45 +1641,40 @@
         return d;
     }
 
+    /** Completion for an anyOf input future. */
     @SuppressWarnings("serial")
-    static final class OrRelay<T,U> extends BiCompletion<T,U,Object> { // for Or
-        OrRelay(CompletableFuture<Object> dep,
-                CompletableFuture<T> src, CompletableFuture<U> snd) {
-            super(null, dep, src, snd);
+    static class AnyOf extends Completion {
+        CompletableFuture<Object> dep; CompletableFuture<?> src;
+        CompletableFuture<?>[] srcs;
+        AnyOf(CompletableFuture<Object> dep, CompletableFuture<?> src,
+              CompletableFuture<?>[] srcs) {
+            this.dep = dep; this.src = src; this.srcs = srcs;
         }
         final CompletableFuture<Object> tryFire(int mode) {
-            CompletableFuture<Object> d;
-            CompletableFuture<T> a;
-            CompletableFuture<U> b;
+            // assert mode != ASYNC;
+            CompletableFuture<Object> d; CompletableFuture<?> a;
+            CompletableFuture<?>[] as;
             Object r;
             if ((d = dep) == null
-                || (a = src) == null || (b = snd) == null
-                || ((r = a.result) == null && (r = b.result) == null))
+                || (a = src) == null || (r = a.result) == null
+                || (as = srcs) == null)
                 return null;
-            d.completeRelay(r);
-            src = null; snd = null; dep = null;
-            return d.postFire(a, b, mode);
+            dep = null; src = null; srcs = null;
+            if (d.completeRelay(r)) {
+                for (CompletableFuture<?> b : as)
+                    if (b != a)
+                        b.cleanStack();
+                if (mode < 0)
+                    return d;
+                else
+                    d.postComplete();
+            }
+            return null;
         }
-    }
-
-    /** Recursively constructs a tree of completions. */
-    static CompletableFuture<Object> orTree(CompletableFuture<?>[] cfs,
-                                            int lo, int hi) {
-        CompletableFuture<Object> d = new CompletableFuture<Object>();
-        if (lo <= hi) {
-            CompletableFuture<?> a, b; Object r;
-            int mid = (lo + hi) >>> 1;
-            if ((a = (lo == mid ? cfs[lo] :
-                      orTree(cfs, lo, mid))) == null ||
-                (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
-                      orTree(cfs, mid+1, hi))) == null)
-                throw new NullPointerException();
-            if ((r = a.result) != null && (r = b.result) != null)
-                d.result = encodeRelay(r);
-            else
-                a.orpush(b, new OrRelay<>(d, a, b));
+        final boolean isLive() {
+            CompletableFuture<Object> d;
+            return (d = dep) != null && d.result == null;
         }
-        return d;
     }
 
     /* ------------- Zero-input Async forms -------------- */
@@ -2354,7 +2353,28 @@
      * {@code null}
      */
     public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {
-        return orTree(cfs, 0, cfs.length - 1);
+        int n; Object r;
+        if ((n = cfs.length) <= 1)
+            return (n == 0)
+                ? new CompletableFuture<Object>()
+                : uniCopyStage(cfs[0]);
+        for (CompletableFuture<?> cf : cfs)
+            if ((r = cf.result) != null)
+                return new CompletableFuture<Object>(encodeRelay(r));
+        cfs = cfs.clone();
+        CompletableFuture<Object> d = new CompletableFuture<>();
+        for (CompletableFuture<?> cf : cfs)
+            cf.unipush(new AnyOf(d, cf, cfs));
+        // If d was completed while we were adding completions, we should
+        // clean the stack of any sources that may have had completions
+        // pushed on their stack after d was completed.
+        if (d.result != null)
+            for (int i = 0, len = cfs.length; i < len; i++)
+                if (cfs[i].result != null)
+                    for (i++; i < len; i++)
+                        if (cfs[i].result == null)
+                            cfs[i].cleanStack();
+        return d;
     }
 
     /* ------------- Control and status methods -------------- */
@@ -2526,7 +2546,7 @@
      * @since 9
      */
     public CompletableFuture<T> copy() {
-        return uniCopyStage();
+        return uniCopyStage(this);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1023,7 +1023,7 @@
         int hash = spread(key.hashCode());
         int binCount = 0;
         for (Node<K,V>[] tab = table;;) {
-            Node<K,V> f; int n, i, fh;
+            Node<K,V> f; int n, i, fh; K fk; V fv;
             if (tab == null || (n = tab.length) == 0)
                 tab = initTable();
             else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
@@ -1032,6 +1032,10 @@
             }
             else if ((fh = f.hash) == MOVED)
                 tab = helpTransfer(tab, f);
+            else if (onlyIfAbsent && fh == hash &&  // check first node
+                     ((fk = f.key) == key || fk != null && key.equals(fk)) &&
+                     (fv = f.val) != null)
+                return fv;
             else {
                 V oldVal = null;
                 synchronized (f) {
@@ -1702,7 +1706,7 @@
         V val = null;
         int binCount = 0;
         for (Node<K,V>[] tab = table;;) {
-            Node<K,V> f; int n, i, fh;
+            Node<K,V> f; int n, i, fh; K fk; V fv;
             if (tab == null || (n = tab.length) == 0)
                 tab = initTable();
             else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
@@ -1724,6 +1728,10 @@
             }
             else if ((fh = f.hash) == MOVED)
                 tab = helpTransfer(tab, f);
+            else if (fh == h &&                  // check first node
+                     ((fk = f.key) == key || fk != null && key.equals(fk)) &&
+                     (fv = f.val) != null)
+                return fv;
             else {
                 boolean added = false;
                 synchronized (f) {
@@ -4553,14 +4561,21 @@
             return true;
         }
 
-        public final boolean removeAll(Collection<?> c) {
+        public boolean removeAll(Collection<?> c) {
             if (c == null) throw new NullPointerException();
             boolean modified = false;
-            for (Iterator<E> it = iterator(); it.hasNext();) {
-                if (c.contains(it.next())) {
-                    it.remove();
-                    modified = true;
+            // Use (c instanceof Set) as a hint that lookup in c is as
+            // efficient as this view
+            if (c instanceof Set<?> && c.size() > map.table.length) {
+                for (Iterator<?> it = iterator(); it.hasNext(); ) {
+                    if (c.contains(it.next())) {
+                        it.remove();
+                        modified = true;
+                    }
                 }
+            } else {
+                for (Object e : c)
+                    modified |= remove(e);
             }
             return modified;
         }
@@ -4747,6 +4762,18 @@
             throw new UnsupportedOperationException();
         }
 
+        @Override public boolean removeAll(Collection<?> c) {
+            if (c == null) throw new NullPointerException();
+            boolean modified = false;
+            for (Iterator<V> it = iterator(); it.hasNext();) {
+                if (c.contains(it.next())) {
+                    it.remove();
+                    modified = true;
+                }
+            }
+            return modified;
+        }
+
         public boolean removeIf(Predicate<? super V> filter) {
             return map.removeValueIf(filter);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Wed Jul 27 13:33:55 2016 +0000
@@ -235,22 +235,16 @@
      * As is too common in this sort of code, methods are monolithic
      * because most of the logic relies on reads of fields that are
      * maintained as local variables so can't be nicely factored --
-     * mainly, here, bulky spin->yield->block/cancel code), and
-     * heavily dependent on intrinsics (VarHandles) to use inlined
-     * embedded CAS and related memory access operations (that tend
-     * not to be as readily inlined by dynamic compilers when they are
-     * hidden behind other methods that would more nicely name and
-     * encapsulate the intended effects). This includes the use of
-     * setRelease to clear fields of the per-thread Nodes between
-     * uses. Note that field Node.item is not declared as volatile
-     * even though it is read by releasing threads, because they only
-     * do so after CAS operations that must precede access, and all
-     * uses by the owning thread are otherwise acceptably ordered by
-     * other operations. (Because the actual points of atomicity are
-     * slot CASes, it would also be legal for the write to Node.match
-     * in a release to be weaker than a full volatile write. However,
-     * this is not done because it could allow further postponement of
-     * the write, delaying progress.)
+     * mainly, here, bulky spin->yield->block/cancel code.  Note that
+     * field Node.item is not declared as volatile even though it is
+     * read by releasing threads, because they only do so after CAS
+     * operations that must precede access, and all uses by the owning
+     * thread are otherwise acceptably ordered by other operations.
+     * (Because the actual points of atomicity are slot CASes, it
+     * would also be legal for the write to Node.match in a release to
+     * be weaker than a full volatile write. However, this is not done
+     * because it could allow further postponement of the write,
+     * delaying progress.)
      */
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Wed Jul 27 13:33:55 2016 +0000
@@ -35,7 +35,6 @@
 
 package java.util.concurrent.atomic;
 
-import java.lang.invoke.MethodHandles;
 import java.lang.invoke.VarHandle;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
@@ -54,11 +53,18 @@
  */
 public class AtomicInteger extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 6214790243416807050L;
-    private static final VarHandle VALUE;
+
+    /*
+     * This class intended to be implemented using VarHandles, but there
+     * are unresolved cyclic startup dependencies.
+     */
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+    private static final long VALUE;
+
     static {
         try {
-            MethodHandles.Lookup l = MethodHandles.lookup();
-            VALUE = l.findVarHandle(AtomicInteger.class, "value", int.class);
+            VALUE = U.objectFieldOffset
+                (AtomicInteger.class.getDeclaredField("value"));
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -109,7 +115,7 @@
      * @since 1.6
      */
     public final void lazySet(int newValue) {
-        VALUE.setRelease(this, newValue);
+        U.putIntRelease(this, VALUE, newValue);
     }
 
     /**
@@ -120,7 +126,7 @@
      * @return the previous value
      */
     public final int getAndSet(int newValue) {
-        return (int)VALUE.getAndSet(this, newValue);
+        return U.getAndSetInt(this, VALUE, newValue);
     }
 
     /**
@@ -134,7 +140,7 @@
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(int expectedValue, int newValue) {
-        return VALUE.compareAndSet(this, expectedValue, newValue);
+        return U.compareAndSwapInt(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -147,7 +153,7 @@
      * @return {@code true} if successful
      */
     public final boolean weakCompareAndSet(int expectedValue, int newValue) {
-        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
+        return U.weakCompareAndSwapInt(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -159,7 +165,7 @@
      * @return the previous value
      */
     public final int getAndIncrement() {
-        return (int)VALUE.getAndAdd(this, 1);
+        return U.getAndAddInt(this, VALUE, 1);
     }
 
     /**
@@ -171,7 +177,7 @@
      * @return the previous value
      */
     public final int getAndDecrement() {
-        return (int)VALUE.getAndAdd(this, -1);
+        return U.getAndAddInt(this, VALUE, -1);
     }
 
     /**
@@ -182,7 +188,7 @@
      * @return the previous value
      */
     public final int getAndAdd(int delta) {
-        return (int)VALUE.getAndAdd(this, delta);
+        return U.getAndAddInt(this, VALUE, delta);
     }
 
     /**
@@ -194,7 +200,7 @@
      * @return the updated value
      */
     public final int incrementAndGet() {
-        return (int)VALUE.addAndGet(this, 1);
+        return U.getAndAddInt(this, VALUE, 1) + 1;
     }
 
     /**
@@ -206,7 +212,7 @@
      * @return the updated value
      */
     public final int decrementAndGet() {
-        return (int)VALUE.addAndGet(this, -1);
+        return U.getAndAddInt(this, VALUE, -1) - 1;
     }
 
     /**
@@ -217,7 +223,7 @@
      * @return the updated value
      */
     public final int addAndGet(int delta) {
-        return (int)VALUE.addAndGet(this, delta);
+        return U.getAndAddInt(this, VALUE, delta) + delta;
     }
 
     /**
@@ -373,7 +379,7 @@
      * @since 9
      */
     public final int getPlain() {
-        return (int)VALUE.get(this);
+        return U.getInt(this, VALUE);
     }
 
     /**
@@ -385,7 +391,7 @@
      * @since 9
      */
     public final void setPlain(int newValue) {
-        VALUE.set(this, newValue);
+        U.putInt(this, VALUE, newValue);
     }
 
     /**
@@ -396,7 +402,7 @@
      * @since 9
      */
     public final int getOpaque() {
-        return (int)VALUE.getOpaque(this);
+        return U.getIntOpaque(this, VALUE);
     }
 
     /**
@@ -407,7 +413,7 @@
      * @since 9
      */
     public final void setOpaque(int newValue) {
-        VALUE.setOpaque(this, newValue);
+        U.putIntOpaque(this, VALUE, newValue);
     }
 
     /**
@@ -418,7 +424,7 @@
      * @since 9
      */
     public final int getAcquire() {
-        return (int)VALUE.getAcquire(this);
+        return U.getIntAcquire(this, VALUE);
     }
 
     /**
@@ -429,7 +435,7 @@
      * @since 9
      */
     public final void setRelease(int newValue) {
-        VALUE.setRelease(this, newValue);
+        U.putIntRelease(this, VALUE, newValue);
     }
 
     /**
@@ -445,7 +451,7 @@
      * @since 9
      */
     public final int compareAndExchange(int expectedValue, int newValue) {
-        return (int)VALUE.compareAndExchange(this, expectedValue, newValue);
+        return U.compareAndExchangeIntVolatile(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -461,7 +467,7 @@
      * @since 9
      */
     public final int compareAndExchangeAcquire(int expectedValue, int newValue) {
-        return (int)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+        return U.compareAndExchangeIntAcquire(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -477,7 +483,7 @@
      * @since 9
      */
     public final int compareAndExchangeRelease(int expectedValue, int newValue) {
-        return (int)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+        return U.compareAndExchangeIntRelease(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -492,7 +498,7 @@
      * @since 9
      */
     public final boolean weakCompareAndSetVolatile(int expectedValue, int newValue) {
-        return VALUE.weakCompareAndSetVolatile(this, expectedValue, newValue);
+        return U.weakCompareAndSwapIntVolatile(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -507,7 +513,7 @@
      * @since 9
      */
     public final boolean weakCompareAndSetAcquire(int expectedValue, int newValue) {
-        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+        return U.weakCompareAndSwapIntAcquire(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -522,7 +528,7 @@
      * @since 9
      */
     public final boolean weakCompareAndSetRelease(int expectedValue, int newValue) {
-        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+        return U.weakCompareAndSwapIntRelease(this, VALUE, expectedValue, newValue);
     }
 
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Wed Jul 27 13:33:55 2016 +0000
@@ -35,7 +35,6 @@
 
 package java.util.concurrent.atomic;
 
-import java.lang.invoke.MethodHandles;
 import java.lang.invoke.VarHandle;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
@@ -54,7 +53,6 @@
  */
 public class AtomicLong extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 1927816293512124184L;
-    private static final VarHandle VALUE;
 
     /**
      * Records whether the underlying JVM supports lockless
@@ -70,10 +68,17 @@
      */
     private static native boolean VMSupportsCS8();
 
+    /*
+     * This class intended to be implemented using VarHandles, but there
+     * are unresolved cyclic startup dependencies.
+     */
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+    private static final long VALUE;
+
     static {
         try {
-            MethodHandles.Lookup l = MethodHandles.lookup();
-            VALUE = l.findVarHandle(AtomicLong.class, "value", long.class);
+            VALUE = U.objectFieldOffset
+                (AtomicLong.class.getDeclaredField("value"));
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -113,7 +118,9 @@
      * @param newValue the new value
      */
     public final void set(long newValue) {
-        VALUE.setVolatile(this, newValue);
+        // Use putLongVolatile instead of ordinary volatile store when
+        // using compareAndSwapLong, for sake of some 32bit systems.
+        U.putLongVolatile(this, VALUE, newValue);
     }
 
     /**
@@ -124,7 +131,7 @@
      * @since 1.6
      */
     public final void lazySet(long newValue) {
-        VALUE.setRelease(this, newValue);
+        U.putLongRelease(this, VALUE, newValue);
     }
 
     /**
@@ -135,7 +142,7 @@
      * @return the previous value
      */
     public final long getAndSet(long newValue) {
-        return (long)VALUE.getAndSet(this, newValue);
+        return U.getAndSetLong(this, VALUE, newValue);
     }
 
     /**
@@ -149,7 +156,7 @@
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(long expectedValue, long newValue) {
-        return VALUE.compareAndSet(this, expectedValue, newValue);
+        return U.compareAndSwapLong(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -162,7 +169,7 @@
      * @return {@code true} if successful
      */
     public final boolean weakCompareAndSet(long expectedValue, long newValue) {
-        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
+        return U.weakCompareAndSwapLong(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -174,7 +181,7 @@
      * @return the previous value
      */
     public final long getAndIncrement() {
-        return (long)VALUE.getAndAdd(this, 1L);
+        return U.getAndAddLong(this, VALUE, 1L);
     }
 
     /**
@@ -186,7 +193,7 @@
      * @return the previous value
      */
     public final long getAndDecrement() {
-        return (long)VALUE.getAndAdd(this, -1L);
+        return U.getAndAddLong(this, VALUE, -1L);
     }
 
     /**
@@ -197,7 +204,7 @@
      * @return the previous value
      */
     public final long getAndAdd(long delta) {
-        return (long)VALUE.getAndAdd(this, delta);
+        return U.getAndAddLong(this, VALUE, delta);
     }
 
     /**
@@ -209,7 +216,7 @@
      * @return the updated value
      */
     public final long incrementAndGet() {
-        return (long)VALUE.addAndGet(this, 1L);
+        return U.getAndAddLong(this, VALUE, 1L) + 1L;
     }
 
     /**
@@ -221,7 +228,7 @@
      * @return the updated value
      */
     public final long decrementAndGet() {
-        return (long)VALUE.addAndGet(this, -1L);
+        return U.getAndAddLong(this, VALUE, -1L) - 1L;
     }
 
     /**
@@ -232,7 +239,7 @@
      * @return the updated value
      */
     public final long addAndGet(long delta) {
-        return (long)VALUE.addAndGet(this, delta);
+        return U.getAndAddLong(this, VALUE, delta) + delta;
     }
 
     /**
@@ -386,7 +393,7 @@
      * @since 9
      */
     public final long getPlain() {
-        return (long)VALUE.get(this);
+        return U.getLong(this, VALUE);
     }
 
     /**
@@ -398,7 +405,7 @@
      * @since 9
      */
     public final void setPlain(long newValue) {
-        VALUE.set(this, newValue);
+        U.putLong(this, VALUE, newValue);
     }
 
     /**
@@ -409,7 +416,7 @@
      * @since 9
      */
     public final long getOpaque() {
-        return (long)VALUE.getOpaque(this);
+        return U.getLongOpaque(this, VALUE);
     }
 
     /**
@@ -420,7 +427,7 @@
      * @since 9
      */
     public final void setOpaque(long newValue) {
-        VALUE.setOpaque(this, newValue);
+        U.putLongOpaque(this, VALUE, newValue);
     }
 
     /**
@@ -431,7 +438,7 @@
      * @since 9
      */
     public final long getAcquire() {
-        return (long)VALUE.getAcquire(this);
+        return U.getLongAcquire(this, VALUE);
     }
 
     /**
@@ -442,7 +449,7 @@
      * @since 9
      */
     public final void setRelease(long newValue) {
-        VALUE.setRelease(this, newValue);
+        U.putLongRelease(this, VALUE, newValue);
     }
 
     /**
@@ -458,7 +465,7 @@
      * @since 9
      */
     public final long compareAndExchange(long expectedValue, long newValue) {
-        return (long)VALUE.compareAndExchange(this, expectedValue, newValue);
+        return U.compareAndExchangeLongVolatile(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -474,7 +481,7 @@
      * @since 9
      */
     public final long compareAndExchangeAcquire(long expectedValue, long newValue) {
-        return (long)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+        return U.compareAndExchangeLongAcquire(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -490,7 +497,7 @@
      * @since 9
      */
     public final long compareAndExchangeRelease(long expectedValue, long newValue) {
-        return (long)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+        return U.compareAndExchangeLongRelease(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -505,7 +512,7 @@
      * @since 9
      */
     public final boolean weakCompareAndSetVolatile(long expectedValue, long newValue) {
-        return VALUE.weakCompareAndSetVolatile(this, expectedValue, newValue);
+        return U.weakCompareAndSwapLongVolatile(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -520,7 +527,7 @@
      * @since 9
      */
     public final boolean weakCompareAndSetAcquire(long expectedValue, long newValue) {
-        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+        return U.weakCompareAndSwapLongAcquire(this, VALUE, expectedValue, newValue);
     }
 
     /**
@@ -535,7 +542,7 @@
      * @since 9
      */
     public final boolean weakCompareAndSetRelease(long expectedValue, long newValue) {
-        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+        return U.weakCompareAndSwapLongRelease(this, VALUE, expectedValue, newValue);
     }
 
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Wed Jul 27 13:33:55 2016 +0000
@@ -60,7 +60,7 @@
         }
     }
 
-    private volatile Object value;
+    private volatile V value;
 
     /**
      * Creates a new AtomicReference with the given initial value.
@@ -83,9 +83,8 @@
      *
      * @return the current value
      */
-    @SuppressWarnings("unchecked")
     public final V get() {
-        return (V)value;
+        return value;
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Wed Jul 27 13:33:55 2016 +0000
@@ -256,8 +256,12 @@
      * method validate()) requires stricter ordering rules than apply
      * to normal volatile reads (of "state").  To force orderings of
      * reads before a validation and the validation itself in those
-     * cases where this is not already forced, we use
-     * VarHandle.acquireFence.
+     * cases where this is not already forced, we use acquireFence.
+     * Unlike in that paper, we allow writers to use plain writes.
+     * One would not expect reorderings of such writes with the lock
+     * acquisition CAS because there is a "control dependency", but it
+     * is theoretically possible, so we additionally add a
+     * storeStoreFence after lock acquisition CAS.
      *
      * The memory layout keeps lock state and queue pointers together
      * (normally on the same cache line). This usually works well for
@@ -355,6 +359,20 @@
         state = ORIGIN;
     }
 
+    private boolean casState(long expectedValue, long newValue) {
+        return STATE.compareAndSet(this, expectedValue, newValue);
+    }
+
+    private long tryWriteLock(long s) {
+        // assert (s & ABITS) == 0L;
+        long next;
+        if (casState(s, next = s | WBIT)) {
+            VarHandle.storeStoreFence();
+            return next;
+        }
+        return 0L;
+    }
+
     /**
      * Exclusively acquires the lock, blocking if necessary
      * until available.
@@ -363,10 +381,8 @@
      */
     @ReservedStackAccess
     public long writeLock() {
-        long s, next;  // bypass acquireWrite in fully unlocked case only
-        return ((((s = state) & ABITS) == 0L &&
-                 STATE.compareAndSet(this, s, next = s + WBIT)) ?
-                next : acquireWrite(false, 0L));
+        long next;
+        return ((next = tryWriteLock()) != 0L) ? next : acquireWrite(false, 0L);
     }
 
     /**
@@ -377,10 +393,8 @@
      */
     @ReservedStackAccess
     public long tryWriteLock() {
-        long s, next;
-        return ((((s = state) & ABITS) == 0L &&
-                 STATE.compareAndSet(this, s, next = s + WBIT)) ?
-                next : 0L);
+        long s;
+        return (((s = state) & ABITS) == 0L) ? tryWriteLock(s) : 0L;
     }
 
     /**
@@ -440,10 +454,13 @@
      */
     @ReservedStackAccess
     public long readLock() {
-        long s = state, next;  // bypass acquireRead on common uncontended case
-        return ((whead == wtail && (s & ABITS) < RFULL &&
-                 STATE.compareAndSet(this, s, next = s + RUNIT)) ?
-                next : acquireRead(false, 0L));
+        long s, next;
+        // bypass acquireRead on common uncontended case
+        return (whead == wtail
+                && ((s = state) & ABITS) < RFULL
+                && casState(s, next = s + RUNIT))
+            ? next
+            : acquireRead(false, 0L);
     }
 
     /**
@@ -457,7 +474,7 @@
         long s, m, next;
         while ((m = (s = state) & ABITS) != WBIT) {
             if (m < RFULL) {
-                if (STATE.compareAndSet(this, s, next = s + RUNIT))
+                if (casState(s, next = s + RUNIT))
                     return next;
             }
             else if ((next = tryIncReaderOverflow(s)) != 0L)
@@ -487,7 +504,7 @@
         if (!Thread.interrupted()) {
             if ((m = (s = state) & ABITS) != WBIT) {
                 if (m < RFULL) {
-                    if (STATE.compareAndSet(this, s, next = s + RUNIT))
+                    if (casState(s, next = s + RUNIT))
                         return next;
                 }
                 else if ((next = tryIncReaderOverflow(s)) != 0L)
@@ -514,10 +531,15 @@
      * before acquiring the lock
      */
     @ReservedStackAccess
-    public long readLockInterruptibly() throws InterruptedException {
-        long next;
-        if (!Thread.interrupted() &&
-            (next = acquireRead(true, 0L)) != INTERRUPTED)
+        public long readLockInterruptibly() throws InterruptedException {
+        long s, next;
+        if (!Thread.interrupted()
+            // bypass acquireRead on common uncontended case
+            && ((whead == wtail
+                 && ((s = state) & ABITS) < RFULL
+                 && casState(s, next = s + RUNIT))
+                ||
+                (next = acquireRead(true, 0L)) != INTERRUPTED))
             return next;
         throw new InterruptedException();
     }
@@ -598,7 +620,7 @@
                && (stamp & RBITS) > 0L
                && ((m = s & RBITS) > 0L)) {
             if (m < RFULL) {
-                if (STATE.compareAndSet(this, s, s - RUNIT)) {
+                if (casState(s, s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
                     return;
@@ -620,7 +642,7 @@
      */
     @ReservedStackAccess
     public void unlock(long stamp) {
-        if ((stamp & WBIT) != 0)
+        if ((stamp & WBIT) != 0L)
             unlockWrite(stamp);
         else
             unlockRead(stamp);
@@ -644,7 +666,7 @@
             if ((m = s & ABITS) == 0L) {
                 if (a != 0L)
                     break;
-                if (STATE.compareAndSet(this, s, next = s + WBIT))
+                if ((next = tryWriteLock(s)) != 0L)
                     return next;
             }
             else if (m == WBIT) {
@@ -653,8 +675,10 @@
                 return stamp;
             }
             else if (m == RUNIT && a != 0L) {
-                if (STATE.compareAndSet(this, s, next = s - RUNIT + WBIT))
+                if (casState(s, next = s - RUNIT + WBIT)) {
+                    VarHandle.storeStoreFence();
                     return next;
+                }
             }
             else
                 break;
@@ -688,7 +712,7 @@
             else if (a == 0L) {
                 // optimistic read stamp
                 if ((s & ABITS) < RFULL) {
-                    if (STATE.compareAndSet(this, s, next = s + RUNIT))
+                    if (casState(s, next = s + RUNIT))
                         return next;
                 }
                 else if ((next = tryIncReaderOverflow(s)) != 0L)
@@ -730,7 +754,7 @@
             else if ((m = s & ABITS) == 0L) // invalid read stamp
                 break;
             else if (m < RFULL) {
-                if (STATE.compareAndSet(this, s, next = s - RUNIT)) {
+                if (casState(s, next = s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
                     return next & SBITS;
@@ -771,7 +795,7 @@
         long s, m; WNode h;
         while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
             if (m < RFULL) {
-                if (STATE.compareAndSet(this, s, s - RUNIT)) {
+                if (casState(s, s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
                     return true;
@@ -940,7 +964,7 @@
         long s, m; WNode h;
         while ((m = (s = state) & RBITS) > 0L) {
             if (m < RFULL) {
-                if (STATE.compareAndSet(this, s, s - RUNIT)) {
+                if (casState(s, s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
                     return;
@@ -971,7 +995,7 @@
     private long tryIncReaderOverflow(long s) {
         // assert (s & ABITS) >= RFULL;
         if ((s & ABITS) == RFULL) {
-            if (STATE.compareAndSet(this, s, s | RBITS)) {
+            if (casState(s, s | RBITS)) {
                 ++readerOverflow;
                 STATE.setVolatile(this, s);
                 return s;
@@ -993,7 +1017,7 @@
     private long tryDecReaderOverflow(long s) {
         // assert (s & ABITS) >= RFULL;
         if ((s & ABITS) == RFULL) {
-            if (STATE.compareAndSet(this, s, s | RBITS)) {
+            if (casState(s, s | RBITS)) {
                 int r; long next;
                 if ((r = readerOverflow) > 0) {
                     readerOverflow = r - 1;
@@ -1047,7 +1071,7 @@
         for (int spins = -1;;) { // spin while enqueuing
             long m, s, ns;
             if ((m = (s = state) & ABITS) == 0L) {
-                if (STATE.compareAndSet(this, s, ns = s + WBIT))
+                if ((ns = tryWriteLock(s)) != 0L)
                     return ns;
             }
             else if (spins < 0)
@@ -1082,7 +1106,7 @@
                 for (int k = spins; k > 0; --k) { // spin at head
                     long s, ns;
                     if (((s = state) & ABITS) == 0L) {
-                        if (STATE.compareAndSet(this, s, ns = s + WBIT)) {
+                        if ((ns = tryWriteLock(s)) != 0L) {
                             whead = node;
                             node.prev = null;
                             if (wasInterrupted)
@@ -1158,7 +1182,7 @@
             if ((h = whead) == (p = wtail)) {
                 for (long m, s, ns;;) {
                     if ((m = (s = state) & ABITS) < RFULL ?
-                        STATE.compareAndSet(this, s, ns = s + RUNIT) :
+                        casState(s, ns = s + RUNIT) :
                         (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
                         if (wasInterrupted)
                             Thread.currentThread().interrupt();
@@ -1208,7 +1232,7 @@
                         long m, s, ns;
                         do {
                             if ((m = (s = state) & ABITS) < RFULL ?
-                                STATE.compareAndSet(this, s, ns = s + RUNIT) :
+                                casState(s, ns = s + RUNIT) :
                                 (m < WBIT &&
                                  (ns = tryIncReaderOverflow(s)) != 0L)) {
                                 if (wasInterrupted)
@@ -1260,7 +1284,7 @@
                 for (int k = spins;;) { // spin at head
                     long m, s, ns;
                     if ((m = (s = state) & ABITS) < RFULL ?
-                        STATE.compareAndSet(this, s, ns = s + RUNIT) :
+                        casState(s, ns = s + RUNIT) :
                         (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
                         WNode c; Thread w;
                         whead = node;
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, 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
@@ -568,9 +568,18 @@
                     int pos = off + 4;               // reserved 4 bytes
                     if (get16(extra, pos) !=  0x0001 || get16(extra, pos + 2) != 24)
                         break;
-                    mtime = winTimeToFileTime(get64(extra, pos + 4));
-                    atime = winTimeToFileTime(get64(extra, pos + 12));
-                    ctime = winTimeToFileTime(get64(extra, pos + 20));
+                    long wtime = get64(extra, pos + 4);
+                    if (wtime != WINDOWS_TIME_NOT_AVAILABLE) {
+                        mtime = winTimeToFileTime(wtime);
+                    }
+                    wtime = get64(extra, pos + 12);
+                    if (wtime != WINDOWS_TIME_NOT_AVAILABLE) {
+                        atime = winTimeToFileTime(wtime);
+                    }
+                    wtime = get64(extra, pos + 20);
+                    if (wtime != WINDOWS_TIME_NOT_AVAILABLE) {
+                        ctime = winTimeToFileTime(wtime);
+                    }
                     break;
                 case EXTID_EXTT:
                     int flag = Byte.toUnsignedInt(extra[off]);
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -421,22 +421,36 @@
         byte[] nameBytes = zc.getBytes(e.name);
         writeShort(nameBytes.length);
 
-        int elenEXTT = 0;               // info-zip extended timestamp
+        int elenEXTT = 0;         // info-zip extended timestamp
         int flagEXTT = 0;
+        long umtime = -1;
+        long uatime = -1;
+        long uctime = -1;
         if (e.mtime != null) {
             elenEXTT += 4;
             flagEXTT |= EXTT_FLAG_LMT;
+            umtime = fileTimeToUnixTime(e.mtime);
         }
         if (e.atime != null) {
             elenEXTT += 4;
             flagEXTT |= EXTT_FLAG_LAT;
+            uatime = fileTimeToUnixTime(e.atime);
         }
         if (e.ctime != null) {
             elenEXTT += 4;
             flagEXTT |= EXTT_FLAT_CT;
+            uctime = fileTimeToUnixTime(e.ctime);
         }
-        if (flagEXTT != 0)
-            elen += (elenEXTT + 5);    // headid(2) + size(2) + flag(1) + data
+        if (flagEXTT != 0) {
+            // to use ntfs time if any m/a/ctime is beyond unixtime upper bound
+            if (umtime > UPPER_UNIXTIME_BOUND ||
+                uatime > UPPER_UNIXTIME_BOUND ||
+                uctime > UPPER_UNIXTIME_BOUND) {
+                elen += 36;                // NTFS time, total 36 bytes
+            } else {
+                elen += (elenEXTT + 5);    // headid(2) + size(2) + flag(1) + data
+            }
+        }
         writeShort(elen);
         writeBytes(nameBytes, 0, nameBytes.length);
         if (hasZip64) {
@@ -446,15 +460,31 @@
             writeLong(e.csize);
         }
         if (flagEXTT != 0) {
-            writeShort(EXTID_EXTT);
-            writeShort(elenEXTT + 1);      // flag + data
-            writeByte(flagEXTT);
-            if (e.mtime != null)
-                writeInt(fileTimeToUnixTime(e.mtime));
-            if (e.atime != null)
-                writeInt(fileTimeToUnixTime(e.atime));
-            if (e.ctime != null)
-                writeInt(fileTimeToUnixTime(e.ctime));
+            if (umtime > UPPER_UNIXTIME_BOUND ||
+                uatime > UPPER_UNIXTIME_BOUND ||
+                uctime > UPPER_UNIXTIME_BOUND) {
+                writeShort(EXTID_NTFS);    // id
+                writeShort(32);            // data size
+                writeInt(0);               // reserved
+                writeShort(0x0001);        // NTFS attr tag
+                writeShort(24);
+                writeLong(e.mtime == null ? WINDOWS_TIME_NOT_AVAILABLE
+                                          : fileTimeToWinTime(e.mtime));
+                writeLong(e.atime == null ? WINDOWS_TIME_NOT_AVAILABLE
+                                          : fileTimeToWinTime(e.atime));
+                writeLong(e.ctime == null ? WINDOWS_TIME_NOT_AVAILABLE
+                                          : fileTimeToWinTime(e.ctime));
+            } else {
+                writeShort(EXTID_EXTT);
+                writeShort(elenEXTT + 1);  // flag + data
+                writeByte(flagEXTT);
+                if (e.mtime != null)
+                    writeInt(umtime);
+                if (e.atime != null)
+                    writeInt(uatime);
+                if (e.ctime != null)
+                    writeInt(uctime);
+            }
         }
         writeExtra(e.extra);
         locoff = written;
@@ -528,18 +558,30 @@
         // cen info-zip extended timestamp only outputs mtime
         // but set the flag for a/ctime, if present in loc
         int flagEXTT = 0;
+        long umtime = -1;
+        long uatime = -1;
+        long uctime = -1;
         if (e.mtime != null) {
-            elen += 4;              // + mtime(4)
             flagEXTT |= EXTT_FLAG_LMT;
+            umtime = fileTimeToUnixTime(e.mtime);
         }
         if (e.atime != null) {
             flagEXTT |= EXTT_FLAG_LAT;
+            uatime = fileTimeToUnixTime(e.atime);
         }
         if (e.ctime != null) {
             flagEXTT |= EXTT_FLAT_CT;
+            uctime = fileTimeToUnixTime(e.ctime);
         }
         if (flagEXTT != 0) {
-            elen += 5;             // headid + sz + flag
+            // to use ntfs time if any m/a/ctime is beyond unixtime upper bound
+            if (umtime > UPPER_UNIXTIME_BOUND ||
+                uatime > UPPER_UNIXTIME_BOUND ||
+                uctime > UPPER_UNIXTIME_BOUND) {
+                elen += 36;         // NTFS time total 36 bytes
+            } else {
+                elen += 9;          // headid(2) + sz(2) + flag(1) + mtime (4)
+            }
         }
         writeShort(elen);
         byte[] commentBytes;
@@ -568,14 +610,30 @@
                 writeLong(xentry.offset);
         }
         if (flagEXTT != 0) {
-            writeShort(EXTID_EXTT);
-            if (e.mtime != null) {
-                writeShort(5);      // flag + mtime
-                writeByte(flagEXTT);
-                writeInt(fileTimeToUnixTime(e.mtime));
+            if (umtime > UPPER_UNIXTIME_BOUND ||
+                uatime > UPPER_UNIXTIME_BOUND ||
+                uctime > UPPER_UNIXTIME_BOUND) {
+                writeShort(EXTID_NTFS);    // id
+                writeShort(32);            // data size
+                writeInt(0);               // reserved
+                writeShort(0x0001);        // NTFS attr tag
+                writeShort(24);
+                writeLong(e.mtime == null ? WINDOWS_TIME_NOT_AVAILABLE
+                                          : fileTimeToWinTime(e.mtime));
+                writeLong(e.atime == null ? WINDOWS_TIME_NOT_AVAILABLE
+                                          : fileTimeToWinTime(e.atime));
+                writeLong(e.ctime == null ? WINDOWS_TIME_NOT_AVAILABLE
+                                          : fileTimeToWinTime(e.ctime));
             } else {
-                writeShort(1);      // flag only
-                writeByte(flagEXTT);
+                writeShort(EXTID_EXTT);
+                if (e.mtime != null) {
+                    writeShort(5);      // flag + mtime
+                    writeByte(flagEXTT);
+                    writeInt(umtime);
+                } else {
+                    writeShort(1);      // flag only
+                    writeByte(flagEXTT);
+                }
             }
         }
         writeExtra(e.extra);
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -38,6 +38,9 @@
     // used to adjust values between Windows and java epoch
     private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
 
+    // used to indicate the corresponding windows time is not available
+    public static final long WINDOWS_TIME_NOT_AVAILABLE = Long.MIN_VALUE;
+
     /**
      * Converts Windows time (in microseconds, UTC/GMT) time to FileTime.
      */
@@ -54,6 +57,11 @@
     }
 
     /**
+     * The upper bound of the 32-bit unix time, the "year 2038 problem".
+     */
+    public static final long UPPER_UNIXTIME_BOUND = 0x7fffffff;
+
+    /**
      * Converts "standard Unix time"(in seconds, UTC/GMT) to FileTime
      */
     public static final FileTime unixTimeToFileTime(long utime) {
--- a/jdk/src/java.base/share/classes/module-info.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/share/classes/module-info.java	Wed Jul 27 13:33:55 2016 +0000
@@ -149,7 +149,6 @@
     exports jdk.internal.module to
         java.instrument,
         java.management,
-        java.xml,
         jdk.dynalink,
         jdk.jartool,
         jdk.jlink;
@@ -309,4 +308,3 @@
     provides java.nio.file.spi.FileSystemProvider with
         jdk.internal.jrtfs.JrtFileSystemProvider;
 }
-
--- a/jdk/src/java.base/unix/native/libjava/java_props_md.c	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.base/unix/native/libjava/java_props_md.c	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -68,11 +68,6 @@
 #endif
 #endif /* !_ALLBSD_SOURCE */
 
-#ifdef JAVASE_EMBEDDED
-#include <dlfcn.h>
-#include <sys/stat.h>
-#endif
-
 /* Take an array of string pairs (map of key->value) and a string (key).
  * Examine each pair in the map to see if the first string (key) matches the
  * string.  If so, store the second string of the pair (value) in the value and
@@ -350,36 +345,6 @@
     return 1;
 }
 
-#ifdef JAVASE_EMBEDDED
-/* Determine the default embedded toolkit based on whether libawt_xawt
- * exists in the JRE. This can still be overridden by -Dawt.toolkit=XXX
- */
-static char* getEmbeddedToolkit() {
-    Dl_info dlinfo;
-    char buf[MAXPATHLEN];
-    int32_t len;
-    char *p;
-    struct stat statbuf;
-
-    /* Get address of this library and the directory containing it. */
-    dladdr((void *)getEmbeddedToolkit, &dlinfo);
-    realpath((char *)dlinfo.dli_fname, buf);
-    len = strlen(buf);
-    p = strrchr(buf, '/');
-    /* Default AWT Toolkit on Linux and Solaris is XAWT (libawt_xawt.so). */
-    strncpy(p, "/libawt_xawt.so", MAXPATHLEN-len-1);
-    /* Check if it exists */
-    if (stat(buf, &statbuf) == -1 && errno == ENOENT) {
-        /* No - this is a reduced-headless-jre so use special HToolkit */
-        return "sun.awt.HToolkit";
-    }
-    else {
-        /* Yes - this is a headful JRE so fallback to SE defaults */
-        return NULL;
-    }
-}
-#endif
-
 /* This function gets called very early, before VM_CALLS are setup.
  * Do not use any of the VM_CALLS entries!!!
  */
@@ -424,10 +389,6 @@
     sprops.awt_headless = isInAquaSession() ? NULL : "true";
 #else
     sprops.graphics_env = "sun.awt.X11GraphicsEnvironment";
-#ifdef JAVASE_EMBEDDED
-    sprops.awt_toolkit = getEmbeddedToolkit();
-    if (sprops.awt_toolkit == NULL) // default as below
-#endif
     sprops.awt_toolkit = "sun.awt.X11.XToolkit";
 #endif
 
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -122,11 +122,7 @@
 JNIEXPORT jlong JNICALL Java_sun_awt_X11_XToolkit_getTrayIconDisplayTimeout
   (JNIEnv *env, jclass clazz)
 {
-#ifndef JAVASE_EMBEDDED
     return (jlong) 2000;
-#else
-    return (jlong) 10000;
-#endif
 }
 
 /*
@@ -369,12 +365,7 @@
 #define AWT_READPIPE            (awt_pipe_fds[0])
 #define AWT_WRITEPIPE           (awt_pipe_fds[1])
 
-#ifdef JAVASE_EMBEDDED
-  #define DEF_AWT_MAX_POLL_TIMEOUT ((uint32_t)4000000000) /* milliseconds */
-#else
-  #define DEF_AWT_MAX_POLL_TIMEOUT ((uint32_t)500) /* milliseconds */
-#endif
-
+#define DEF_AWT_MAX_POLL_TIMEOUT ((uint32_t)500) /* milliseconds */
 #define DEF_AWT_FLUSH_TIMEOUT ((uint32_t)100) /* milliseconds */
 #define AWT_MIN_POLL_TIMEOUT ((uint32_t)0) /* milliseconds */
 
@@ -391,11 +382,7 @@
 
 // Static fields
 
-#ifdef JAVASE_EMBEDDED
-  static int          awt_poll_alg = AWT_POLL_AGING_FAST;
-#else
-  static int          awt_poll_alg = AWT_POLL_AGING_SLOW;
-#endif
+static int          awt_poll_alg = AWT_POLL_AGING_SLOW;
 
 static uint32_t AWT_FLUSH_TIMEOUT  =  DEF_AWT_FLUSH_TIMEOUT; /* milliseconds */
 static uint32_t AWT_MAX_POLL_TIMEOUT = DEF_AWT_MAX_POLL_TIMEOUT; /* milliseconds */
--- a/jdk/src/java.desktop/unix/native/libjawt/jawt.c	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/src/java.desktop/unix/native/libjawt/jawt.c	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -39,10 +39,6 @@
  */
 JNIEXPORT jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt)
 {
-#if defined(JAVASE_EMBEDDED) && defined(HEADLESS)
-    /* there are no AWT libs available at all */
-    return JNI_FALSE;
-#else
     if (awt == NULL) {
         return JNI_FALSE;
     }
@@ -62,5 +58,4 @@
     }
 
     return JNI_TRUE;
-#endif
 }
--- a/jdk/test/java/net/URLPermission/URLPermissionTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/java/net/URLPermission/URLPermissionTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -26,7 +26,7 @@
 
 /**
  * @test
- * @bug 8010464 8027570 8027687 8029354 8114860 8071660
+ * @bug 8010464 8027570 8027687 8029354 8114860 8071660 8161291
  */
 
 public class URLPermissionTest {
@@ -355,15 +355,16 @@
     };
 
     static Test[] actionsStringTest = {
-        actionstest("", ""),
+        actionstest("", ":"),
+        actionstest(":", ":"),
         actionstest(":X-Bar", ":X-Bar"),
-        actionstest("GET", "GET"),
-        actionstest("get", "GET"),
-        actionstest("GET,POST", "GET,POST"),
-        actionstest("GET,post", "GET,POST"),
-        actionstest("get,post", "GET,POST"),
-        actionstest("get,post,DELETE", "DELETE,GET,POST"),
-        actionstest("GET,POST:", "GET,POST"),
+        actionstest("GET", "GET:"),
+        actionstest("get", "GET:"),
+        actionstest("GET,POST", "GET,POST:"),
+        actionstest("GET,post", "GET,POST:"),
+        actionstest("get,post", "GET,POST:"),
+        actionstest("get,post,DELETE", "DELETE,GET,POST:"),
+        actionstest("GET,POST:", "GET,POST:"),
         actionstest("GET:X-Foo,X-bar", "GET:X-Bar,X-Foo"),
         actionstest("GET,POST,DELETE:X-Bar,X-Foo,X-Bar,Y-Foo", "DELETE,GET,POST:X-Bar,X-Bar,X-Foo,Y-Foo")
     };
--- a/jdk/test/java/security/Provider/SecurityProviderModularTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/java/security/Provider/SecurityProviderModularTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -63,8 +63,7 @@
             "TestSecurityProviderClient.java");
     private static final String C_PKG = "client";
     private static final String C_JAR_NAME = C_PKG + JAR_EXTN;
-    private static final String MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME = MODULAR
-            + C_PKG + AUTO + JAR_EXTN;
+    private static final String MCN_JAR_NAME = MODULAR + C_PKG + "N" + JAR_EXTN;
     private static final String MC_JAR_NAME = MODULAR + C_PKG + JAR_EXTN;
 
     private static final Path BUILD_DIR = Paths.get(".").resolve("build");
@@ -72,7 +71,7 @@
     private static final Path S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG);
     private static final Path S_WITH_META_DESCR_BUILD_DIR = COMPILE_DIR.resolve(
             S_PKG + DESCRIPTOR);
-    private static final Path C_BUILD_DIR = COMPILE_DIR.resolve(C_PKG);
+    private static final Path C_BLD_DIR = COMPILE_DIR.resolve(C_PKG);
     private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase");
     private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts");
 
@@ -88,8 +87,7 @@
     private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG);
     private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME);
     private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME);
-    private static final Path MC_DEPENDS_ON_AUTO_SERVICE_JAR = C_ARTIFACTS_DIR
-            .resolve(MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME);
+    private static final Path MCN_JAR = C_ARTIFACTS_DIR.resolve(MCN_JAR_NAME);
 
     private static final String MAIN = C_PKG + ".TestSecurityProviderClient";
     private static final String S_INTERFACE = "java.security.Provider";
@@ -102,8 +100,6 @@
 
     private static final boolean WITH_S_DESCR = true;
     private static final boolean WITHOUT_S_DESCR = false;
-    private static final String CLASS_NOT_FOUND_MSG = "NoClassDefFoundError:"
-            + " provider/TestSecurityProvider";
     private static final String PROVIDER_NOT_FOUND_MSG = "Unable to find Test"
             + " Security Provider";
     private static final String CAN_NOT_ACCESS_MSG = "cannot access class";
@@ -126,10 +122,10 @@
             boolean useCLoader = CLASS_LOADER.equals(mechanism);
             boolean useSLoader = SERVICE_LOADER.equals(mechanism);
             String[] args = new String[]{mechanism};
-            //PARAMETER ORDERS -
-            //client Module Type, Service Module Type,
-            //Service META Descriptor Required,
-            //Expected Failure message, mech used to find the provider
+            // PARAMETER ORDERS -
+            // Client Module Type, Service Module Type,
+            // If Service META Descriptor Required,
+            // Expected Failure message, mechanism used to find the provider
             params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
                     WITH_S_DESCR, NO_FAILURE, args));
             params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
@@ -138,7 +134,8 @@
                     WITH_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG
                             : NO_FAILURE), args));
             params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
-                    WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args));
+                    WITHOUT_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG
+                            : PROVIDER_NOT_FOUND_MSG), args));
             params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
                     WITH_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG
                             : NO_FAILURE), args));
@@ -150,11 +147,12 @@
             params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT,
                     WITH_S_DESCR, NO_FAILURE, args));
             params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT,
-                    WITH_S_DESCR, NO_FAILURE, args));
+                    WITHOUT_S_DESCR, NO_FAILURE, args));
             params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
                     WITH_S_DESCR, NO_FAILURE, args));
             params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
-                    WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args));
+                    WITHOUT_S_DESCR,
+                    (useCLoader) ? NO_FAILURE : PROVIDER_NOT_FOUND_MSG, args));
             params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
                     WITH_S_DESCR, NO_FAILURE, args));
             params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
@@ -168,7 +166,8 @@
             params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
                     WITH_S_DESCR, NO_FAILURE, args));
             params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
-                    WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args));
+                    WITHOUT_S_DESCR,
+                    (useCLoader) ? NO_FAILURE : PROVIDER_NOT_FOUND_MSG, args));
             params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
                     WITH_S_DESCR, NO_FAILURE, args));
             params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
@@ -191,22 +190,23 @@
             done &= CompilerUtils.compile(S_SRC, S_BUILD_DIR);
             done &= CompilerUtils.compile(S_SRC, S_WITH_META_DESCR_BUILD_DIR);
             done &= createMetaInfServiceDescriptor(S_META_DESCR_FPATH, S_IMPL);
-            //Generate regular/modular jars with(out) META-INF
-            //Service descriptor
+            // Generate modular/regular jars with(out) META-INF
+            // service descriptor
             generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false);
             generateJar(true, MODULE_TYPE.EXPLICIT, MS_WITH_DESCR_JAR,
                     S_WITH_META_DESCR_BUILD_DIR, false);
             generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false);
             generateJar(true, MODULE_TYPE.UNNAMED, S_WITH_DESCRIPTOR_JAR,
                     S_WITH_META_DESCR_BUILD_DIR, false);
-            //Generate regular/modular(depends on explicit/auto Service)
-            //jars for client
-            done &= CompilerUtils.compile(C_SRC, C_BUILD_DIR, "-cp",
+            // Compile client source codes.
+            done &= CompilerUtils.compile(C_SRC, C_BLD_DIR, "-cp",
                     S_JAR.toFile().getCanonicalPath());
-            generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BUILD_DIR, true);
-            generateJar(false, MODULE_TYPE.EXPLICIT,
-                    MC_DEPENDS_ON_AUTO_SERVICE_JAR, C_BUILD_DIR, false);
-            generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BUILD_DIR, false);
+            // Generate modular client jar with explicit dependency
+            generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BLD_DIR, true);
+            // Generate modular client jar without any dependency
+            generateJar(false, MODULE_TYPE.EXPLICIT, MCN_JAR, C_BLD_DIR, false);
+            // Generate regular client jar
+            generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BLD_DIR, false);
             System.out.format("%nArtifacts generated successfully? %s", done);
             if (!done) {
                 throw new RuntimeException("Artifacts generation failed");
@@ -244,10 +244,9 @@
 
         OutputAnalyzer output = null;
         try {
-
-            //For automated/explicit module type copy the corresponding
-            //jars to module base folder, which will be considered as
-            //module base path during execution.
+            // For automated/explicit module types, copy the corresponding
+            // jars to module base folder, which will be considered as
+            // module base path during execution.
             if (!(cModuleType == MODULE_TYPE.UNNAMED
                     && sModuletype == MODULE_TYPE.UNNAMED)) {
                 copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH);
@@ -262,15 +261,14 @@
             String cPath = buildClassPath(cModuleType, cJarPath, sModuletype,
                     sJarPath);
 
-            Map<String, String> VM_ARGS = getVMArgs(sModuletype, args);
+            Map<String, String> vmArgs = getVMArgs(sModuletype,
+                    getModuleName(sModuletype, sJarPath, S_PKG), args);
             output = ProcessTools.executeTestJava(
-                    getJavaCommand(cmBasePath, cPath, mName, MAIN, VM_ARGS,
+                    getJavaCommand(cmBasePath, cPath, mName, MAIN, vmArgs,
                             args)).outputTo(System.out).errorTo(System.out);
         } finally {
-            //clean module path so that the modulepath can hold only
-            //the required jars for next run.
+            // Clean module path to hold required jars for next run.
             cleanModuleBasePath(M_BASE_PATH);
-            System.out.println("--------------------------------------------");
         }
         return output;
     }
@@ -297,11 +295,12 @@
                 }
             }
         } else {
+            // Choose corresponding client jar to use dependent module
             if (moduleType == MODULE_TYPE.EXPLICIT) {
                 if (dependsOnServiceModule) {
                     return MC_JAR;
                 } else {
-                    return MC_DEPENDS_ON_AUTO_SERVICE_JAR;
+                    return MCN_JAR;
                 }
             } else {
                 return C_JAR;
@@ -313,13 +312,16 @@
      * VM argument required for the test.
      */
     private Map<String, String> getVMArgs(MODULE_TYPE sModuletype,
-            String... args) throws IOException {
-        final Map<String, String> VM_ARGS = new LinkedHashMap<>();
-        VM_ARGS.put("-Duser.language=", "en");
-        VM_ARGS.put("-Duser.region=", "US");
-        //If mechanism selected to find the provider through
-        //Security.getProvider() then use providerName/ProviderClassName based
-        //on modular/regular provider jar in security configuration file.
+            String addModName, String... args) throws IOException {
+        final Map<String, String> vmArgs = new LinkedHashMap<>();
+        vmArgs.put("-Duser.language=", "en");
+        vmArgs.put("-Duser.region=", "US");
+        if (addModName != null && sModuletype == MODULE_TYPE.AUTO) {
+            vmArgs.put("-addmods ", addModName);
+        }
+        // If mechanism selected to find the provider through
+        // Security.getProvider() then use providerName/ProviderClassName based
+        // on modular/regular provider jar in security configuration file.
         if (args != null && args.length > 0 && SECURITY_PROP.equals(args[0])) {
             if (sModuletype == MODULE_TYPE.UNNAMED) {
                 Files.write(SECURE_PROP_EXTN, ("security.provider.10=" + S_IMPL)
@@ -328,10 +330,10 @@
                 Files.write(SECURE_PROP_EXTN, "security.provider.10=TEST"
                         .getBytes());
             }
-            VM_ARGS.put("-Djava.security.properties=", SECURE_PROP_EXTN.toFile()
+            vmArgs.put("-Djava.security.properties=", SECURE_PROP_EXTN.toFile()
                     .getCanonicalPath());
         }
-        return VM_ARGS;
+        return vmArgs;
     }
 
 }
--- a/jdk/test/java/security/modules/ModularTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/java/security/modules/ModularTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -82,7 +82,7 @@
 
         String testName = new StringJoiner("_").add(cModuleType.toString())
                 .add(sModuletype.toString()).add(
-                        (addMetaDesc) ? "DESCRIPTOR" : "NO_DESCRIPTOR")
+                        (addMetaDesc) ? "WITH_SERVICE" : "NO_SERVICE")
                 .toString();
 
         System.out.format("%nStarting Test case: '%s'", testName);
@@ -165,10 +165,12 @@
         if (moduleType == MODULE_TYPE.EXPLICIT) {
             System.out.format(" %nGenerating ModuleDescriptor object");
             builder = new Builder(moduleName).exports(pkg);
-            if (isService) {
+            if (isService && serviceInterface != null && serviceImpl != null) {
                 builder.provides(serviceInterface, serviceImpl);
             } else {
-                builder.uses(serviceInterface);
+                if (serviceInterface != null) {
+                    builder.uses(serviceInterface);
+                }
                 if (depends) {
                     builder.requires(serviceModuleName);
                 }
@@ -261,7 +263,7 @@
         String jarName = jarPath.toFile().getName();
         return (moduleType == MODULE_TYPE.EXPLICIT) ? mName
                 : ((moduleType == MODULE_TYPE.AUTO) ? jarName.substring(0,
-                                jarName.indexOf(JAR_EXTN)) : "");
+                                jarName.indexOf(JAR_EXTN)) : null);
     }
 
     /**
--- a/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java	Wed Jul 27 13:33:55 2016 +0000
@@ -42,6 +42,7 @@
 
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.LinkedTransferQueue;
 import java.util.concurrent.SynchronousQueue;
@@ -50,9 +51,11 @@
 public class PollMemoryLeak {
     public static void main(String[] args) throws InterruptedException {
         final BlockingQueue[] qs = {
+            new LinkedBlockingDeque(10),
             new LinkedBlockingQueue(10),
             new LinkedTransferQueue(),
             new ArrayBlockingQueue(10),
+            new ArrayBlockingQueue(10, true),
             new SynchronousQueue(),
             new SynchronousQueue(true),
         };
--- a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -4269,12 +4269,11 @@
         }
     }
 
-    /*
-     * Tests below currently fail in stress mode due to memory retention.
-     * ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest tck
+    /**
+     * Reproduction recipe for:
+     * 8160402: Garbage retention with CompletableFuture.anyOf
+     * cvs update -D '2016-05-01' ./src/main/java/util/concurrent/CompletableFuture.java && ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest -Djsr166.methodFilter=testAnyOfGarbageRetention tck; cvs update -A
      */
-
-    /** Checks for garbage retention with anyOf. */
     public void testAnyOfGarbageRetention() throws Throwable {
         for (Integer v : new Integer[] { 1, null })
     {
@@ -4288,7 +4287,12 @@
             checkCompletedNormally(CompletableFuture.anyOf(fs), v);
     }}
 
-    /** Checks for garbage retention with allOf. */
+    /**
+     * Checks for garbage retention with allOf.
+     *
+     * As of 2016-07, fails with OOME:
+     * ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest -Djsr166.methodFilter=testCancelledAllOfGarbageRetention tck
+     */
     public void testCancelledAllOfGarbageRetention() throws Throwable {
         final int n = expensiveTests ? 100_000 : 10;
         CompletableFuture<Integer>[] fs
@@ -4299,6 +4303,21 @@
             assertTrue(CompletableFuture.allOf(fs).cancel(false));
     }
 
+    /**
+     * Checks for garbage retention when a dependent future is
+     * cancelled and garbage-collected.
+     * 8161600: Garbage retention when source CompletableFutures are never completed
+     *
+     * As of 2016-07, fails with OOME:
+     * ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest -Djsr166.methodFilter=testCancelledGarbageRetention tck
+     */
+    public void testCancelledGarbageRetention() throws Throwable {
+        final int n = expensiveTests ? 100_000 : 10;
+        CompletableFuture<Integer> neverCompleted = new CompletableFuture<>();
+        for (int i = 0; i < n; i++)
+            assertTrue(neverCompleted.thenRun(() -> {}).cancel(true));
+    }
+
 //     static <U> U join(CompletionStage<U> stage) {
 //         CompletableFuture<U> f = new CompletableFuture<>();
 //         stage.whenComplete((v, ex) -> {
--- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -43,6 +43,8 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -830,4 +832,47 @@
         }
     }
 
+    /**
+     * Tests performance of removeAll when the other collection is much smaller.
+     * ant -Djsr166.tckTestClass=ConcurrentHashMapTest -Djsr166.methodFilter=testRemoveAll_performance -Djsr166.expensiveTests=true tck
+     */
+    public void testRemoveAll_performance() {
+        final int mapSize = expensiveTests ? 1_000_000 : 100;
+        final int iterations = expensiveTests ? 500 : 2;
+        final ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
+        for (int i = 0; i < mapSize; i++)
+            map.put(i, i);
+        Set<Integer> keySet = map.keySet();
+        Collection<Integer> removeMe = Arrays.asList(new Integer[] { -99, -86 });
+        for (int i = 0; i < iterations; i++)
+            assertFalse(keySet.removeAll(removeMe));
+        assertEquals(mapSize, map.size());
+    }
+
+    /**
+     * Tests performance of computeIfAbsent when the element is present.
+     * See JDK-8161372
+     * ant -Djsr166.tckTestClass=ConcurrentHashMapTest -Djsr166.methodFilter=testcomputeIfAbsent_performance -Djsr166.expensiveTests=true tck
+     */
+    public void testcomputeIfAbsent_performance() {
+        final int mapSize = 20;
+        final int iterations = expensiveTests ? (1 << 23) : mapSize * 2;
+        final int threads = expensiveTests ? 10 : 2;
+        final ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
+        for (int i = 0; i < mapSize; i++)
+            map.put(i, i);
+        final ExecutorService pool = Executors.newFixedThreadPool(2);
+        try (PoolCleaner cleaner = cleaner(pool)) {
+            Runnable r = new CheckedRunnable() {
+                public void realRun() {
+                    int result = 0;
+                    for (int i = 0; i < iterations; i++)
+                        result += map.computeIfAbsent(i % mapSize, (k) -> k + k);
+                    if (result == -42) throw new Error();
+                }};
+            for (int i = 0; i < threads; i++)
+                pool.execute(r);
+        }
+    }
+
 }
--- a/jdk/test/java/util/concurrent/tck/StampedLockTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/java/util/concurrent/tck/StampedLockTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -32,11 +32,18 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+import static java.util.concurrent.TimeUnit.DAYS;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.StampedLock;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -1078,4 +1085,121 @@
         assertThrows(IllegalMonitorStateException.class, actions);
     }
 
+    static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
+        try { return sl.writeLockInterruptibly(); }
+        catch (InterruptedException ex) { throw new AssertionError(ex); }
+    }
+
+    static long tryWriteLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
+        try { return sl.tryWriteLock(time, unit); }
+        catch (InterruptedException ex) { throw new AssertionError(ex); }
+    }
+
+    static long readLockInterruptiblyUninterrupted(StampedLock sl) {
+        try { return sl.readLockInterruptibly(); }
+        catch (InterruptedException ex) { throw new AssertionError(ex); }
+    }
+
+    static long tryReadLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
+        try { return sl.tryReadLock(time, unit); }
+        catch (InterruptedException ex) { throw new AssertionError(ex); }
+    }
+
+    /**
+     * Invalid write stamps result in IllegalMonitorStateException
+     */
+    public void testInvalidWriteStampsThrowIllegalMonitorStateException() {
+        List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
+        writeLockers.add((sl) -> sl.writeLock());
+        writeLockers.add((sl) -> writeLockInterruptiblyUninterrupted(sl));
+        writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
+        writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, 0, DAYS));
+
+        List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>();
+        writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp));
+        writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite()));
+        writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock());
+        writeUnlockers.add((sl, stamp) -> sl.unlock(stamp));
+
+        List<Consumer<StampedLock>> mutaters = new ArrayList<>();
+        mutaters.add((sl) -> {});
+        mutaters.add((sl) -> sl.readLock());
+        for (Function<StampedLock, Long> writeLocker : writeLockers)
+            mutaters.add((sl) -> writeLocker.apply(sl));
+
+        for (Function<StampedLock, Long> writeLocker : writeLockers)
+        for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers)
+        for (Consumer<StampedLock> mutater : mutaters) {
+            final StampedLock sl = new StampedLock();
+            final long stamp = writeLocker.apply(sl);
+            assertTrue(stamp != 0L);
+            assertThrows(IllegalMonitorStateException.class,
+                         () -> sl.unlockRead(stamp));
+            writeUnlocker.accept(sl, stamp);
+            mutater.accept(sl);
+            assertThrows(IllegalMonitorStateException.class,
+                         () -> sl.unlock(stamp),
+                         () -> sl.unlockRead(stamp),
+                         () -> sl.unlockWrite(stamp));
+        }
+    }
+
+    /**
+     * Invalid read stamps result in IllegalMonitorStateException
+     */
+    public void testInvalidReadStampsThrowIllegalMonitorStateException() {
+        List<Function<StampedLock, Long>> readLockers = new ArrayList<>();
+        readLockers.add((sl) -> sl.readLock());
+        readLockers.add((sl) -> readLockInterruptiblyUninterrupted(sl));
+        readLockers.add((sl) -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
+        readLockers.add((sl) -> tryReadLockUninterrupted(sl, 0, DAYS));
+
+        List<BiConsumer<StampedLock, Long>> readUnlockers = new ArrayList<>();
+        readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp));
+        readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead()));
+        readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock());
+        readUnlockers.add((sl, stamp) -> sl.unlock(stamp));
+
+        List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
+        writeLockers.add((sl) -> sl.writeLock());
+        writeLockers.add((sl) -> writeLockInterruptiblyUninterrupted(sl));
+        writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
+        writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, 0, DAYS));
+
+        List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>();
+        writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp));
+        writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite()));
+        writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock());
+        writeUnlockers.add((sl, stamp) -> sl.unlock(stamp));
+
+
+        for (Function<StampedLock, Long> readLocker : readLockers)
+        for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers)
+        for (Function<StampedLock, Long> writeLocker : writeLockers)
+        for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers) {
+            final StampedLock sl = new StampedLock();
+            final long stamp = readLocker.apply(sl);
+            assertTrue(stamp != 0L);
+            assertThrows(IllegalMonitorStateException.class,
+                         () -> sl.unlockWrite(stamp));
+            readUnlocker.accept(sl, stamp);
+            assertThrows(IllegalMonitorStateException.class,
+                         () -> sl.unlock(stamp),
+                         () -> sl.unlockRead(stamp),
+                         () -> sl.unlockWrite(stamp));
+            final long writeStamp = writeLocker.apply(sl);
+            assertTrue(writeStamp != 0L);
+            assertTrue(writeStamp != stamp);
+            assertThrows(IllegalMonitorStateException.class,
+                         () -> sl.unlock(stamp),
+                         () -> sl.unlockRead(stamp),
+                         () -> sl.unlockWrite(stamp));
+            writeUnlocker.accept(sl, writeStamp);
+            assertThrows(IllegalMonitorStateException.class,
+                         () -> sl.unlock(stamp),
+                         () -> sl.unlockRead(stamp),
+                         () -> sl.unlockWrite(stamp));
+        }
+    }
+
 }
--- a/jdk/test/java/util/zip/TestExtraTime.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/java/util/zip/TestExtraTime.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4759491 6303183 7012868 8015666 8023713 8068790 8076641 8075526 8130914
+ * @bug 4759491 6303183 7012868 8015666 8023713 8068790 8076641 8075526 8130914 8161942
  * @summary Test ZOS and ZIS timestamp in extra field correctly
  */
 
@@ -32,6 +32,7 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.attribute.FileTime;
+import java.time.Instant;
 import java.util.Arrays;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
@@ -40,37 +41,52 @@
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
 
+
+
 public class TestExtraTime {
 
     public static void main(String[] args) throws Throwable{
 
         File src = new File(System.getProperty("test.src", "."), "TestExtraTime.java");
-        if (src.exists()) {
+        if (!src.exists()) {
+            return;
+        }
+
+        TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
+
+        for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) {
+
+            // ms-dos 1980 epoch problem
+            test0(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra);
+            // negative epoch time
+            test0(FileTime.from(-100, TimeUnit.DAYS), null, null, null, extra);
+
             long time = src.lastModified();
-            FileTime mtime = FileTime.from(time, TimeUnit.MILLISECONDS);
-            FileTime atime = FileTime.from(time + 300000, TimeUnit.MILLISECONDS);
-            FileTime ctime = FileTime.from(time - 300000, TimeUnit.MILLISECONDS);
-            TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
-
-            for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) {
-                test(mtime, null, null, null, extra);
+            test(FileTime.from(time, TimeUnit.MILLISECONDS),
+                 FileTime.from(time + 300000, TimeUnit.MILLISECONDS),
+                 FileTime.from(time - 300000, TimeUnit.MILLISECONDS),
+                 tz, extra);
 
-                // ms-dos 1980 epoch problem
-                test(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra);
-                // negative epoch time
-                test(FileTime.from(-100, TimeUnit.DAYS), null, null, null, extra);
-
-                // non-default tz
-                test(mtime, null, null, tz, extra);
+            // now
+            time = Instant.now().toEpochMilli();
+            test(FileTime.from(time, TimeUnit.MILLISECONDS),
+                 FileTime.from(time + 300000, TimeUnit.MILLISECONDS),
+                 FileTime.from(time - 300000, TimeUnit.MILLISECONDS),
+                 tz, extra);
 
-                test(mtime, atime, null, null, extra);
-                test(mtime, null, ctime, null, extra);
-                test(mtime, atime, ctime, null, extra);
+            // unix 2038
+            time = 0x80000000L;
+            test(FileTime.from(time, TimeUnit.SECONDS),
+                 FileTime.from(time, TimeUnit.SECONDS),
+                 FileTime.from(time, TimeUnit.SECONDS),
+                 tz, extra);
 
-                test(mtime, atime, null, tz, extra);
-                test(mtime, null, ctime, tz, extra);
-                test(mtime, atime, ctime, tz, extra);
-            }
+            // mtime < unix 2038
+            time = 0x7fffffffL;
+            test(FileTime.from(time, TimeUnit.SECONDS),
+                 FileTime.from(time + 30000, TimeUnit.SECONDS),
+                 FileTime.from(time + 30000, TimeUnit.SECONDS),
+                 tz, extra);
         }
 
         testNullHandling();
@@ -80,6 +96,18 @@
 
     static void test(FileTime mtime, FileTime atime, FileTime ctime,
                      TimeZone tz, byte[] extra) throws Throwable {
+        test0(mtime, null, null, null, extra);
+        test0(mtime, null, null, tz, extra);    // non-default tz
+        test0(mtime, atime, null, null, extra);
+        test0(mtime, null, ctime, null, extra);
+        test0(mtime, atime, ctime, null, extra);
+        test0(mtime, atime, null, tz, extra);
+        test0(mtime, null, ctime, tz, extra);
+        test0(mtime, atime, ctime, tz, extra);
+    }
+
+    static void test0(FileTime mtime, FileTime atime, FileTime ctime,
+                     TimeZone tz, byte[] extra) throws Throwable {
         System.out.printf("--------------------%nTesting: [%s]/[%s]/[%s]%n",
                           mtime, atime, ctime);
         TimeZone tz0 = TimeZone.getDefault();
@@ -120,13 +148,14 @@
         Path zpath = Paths.get(System.getProperty("test.dir", "."),
                                "TestExtraTime.zip");
         Files.copy(new ByteArrayInputStream(baos.toByteArray()), zpath);
-        ZipFile zf = new ZipFile(zpath.toFile());
-        ze = zf.getEntry("TestExtraTime.java");
-        // ZipFile read entry from cen, which does not have a/ctime,
-        // for now.
-        check(mtime, null, null, ze, extra);
-        zf.close();
-        Files.delete(zpath);
+        try (ZipFile zf = new ZipFile(zpath.toFile())) {
+            ze = zf.getEntry("TestExtraTime.java");
+            // ZipFile read entry from cen, which does not have a/ctime,
+            // for now.
+            check(mtime, null, null, ze, extra);
+        } finally {
+            Files.delete(zpath);
+        }
     }
 
     static void check(FileTime mtime, FileTime atime, FileTime ctime,
--- a/jdk/test/java/util/zip/TestLocalTime.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/java/util/zip/TestLocalTime.java	Wed Jul 27 13:33:55 2016 +0000
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8075526 8135108 8155616
+ * @bug 8075526 8135108 8155616 8161942
  * @summary Test timestamp via ZipEntry.get/setTimeLocal()
  */
 
@@ -65,6 +65,9 @@
             test(LocalDateTime.of(1968, 04, 28, 2, 51, 25));
             test(LocalDateTime.of(1970, 04, 26, 2, 31, 52));
 
+            // for #8161942
+            test(LocalDateTime.of(2200, 04, 26, 2, 31, 52));  // unix 2038
+
         } finally {
             TimeZone.setDefault(tz0);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/net/ssl/templates/SSLSocketSample.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// Please run in othervm mode.  SunJSSE does not support dynamic system
+// properties, no way to re-use system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8161106
+ * @summary Improve SSLSocket test template
+ * @run main/othervm SSLSocketSample
+ */
+
+import java.io.*;
+import javax.net.ssl.*;
+import java.net.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Template to help speed your client/server tests.
+ */
+public final class SSLSocketSample {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    private static final boolean separateServerThread = false;
+
+    /*
+     * Where do we find the keystores?
+     */
+    private static final String pathToStores = "../etc";
+    private static final String keyStoreFile = "keystore";
+    private static final String trustStoreFile = "truststore";
+    private static final String passwd = "passphrase";
+
+    /*
+     * Turn on SSL debugging?
+     */
+    private static final boolean debug = false;
+
+    /*
+     * Is the server ready to serve?
+     */
+    private static final CountDownLatch serverCondition = new CountDownLatch(1);
+
+    /*
+     * Is the client ready to handshake?
+     */
+    private static final CountDownLatch clientCondition = new CountDownLatch(1);
+
+    /*
+     * What's the server port?  Use any free port by default
+     */
+    private volatile int serverPort = 0;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * Define the server side of the test.
+     */
+    void doServerSide() throws Exception {
+        SSLServerSocket sslServerSocket;
+
+        // kick start the server side service
+        SSLServerSocketFactory sslssf =
+                (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
+        sslServerSocket =
+                (SSLServerSocket)sslssf.createServerSocket(serverPort);
+
+        serverPort = sslServerSocket.getLocalPort();
+
+        // Signal the client, the server is ready to accept connection.
+        serverCondition.countDown();
+
+
+        // Try to accept a connection in 30 seconds.
+        SSLSocket sslSocket;
+        try {
+            sslServerSocket.setSoTimeout(30000);
+            sslSocket = (SSLSocket)sslServerSocket.accept();
+        } catch (SocketTimeoutException ste) {
+            sslServerSocket.close();
+
+            // Ignore the test case if no connection within 30 seconds.
+            System.out.println(
+                "No incoming client connection in 30 seconds. " +
+                "Ignore in server side.");
+            return;
+        }
+
+        // handle the connection
+        try {
+            // Is it the expected client connection?
+            //
+            // Naughty test cases or third party routines may try to
+            // connection to this server port unintentionally.  In
+            // order to mitigate the impact of unexpected client
+            // connections and avoid intermittent failure, it should
+            // be checked that the accepted connection is really linked
+            // to the expected client.
+            boolean clientIsReady =
+                    clientCondition.await(30L, TimeUnit.SECONDS);
+
+            if (clientIsReady) {
+                // Run the application in server side.
+                runServerApplication(sslSocket);
+            } else {    // Otherwise, ignore
+                // We don't actually care about plain socket connections
+                // for TLS communication testing generally.  Just ignore
+                // the test if the accepted connection is not linked to
+                // the expected client or the client connection timeout
+                // in 30 seconds.
+                System.out.println(
+                        "The client is not the expected one or timeout. " +
+                        "Ignore in server side.");
+            }
+        } finally {
+            sslSocket.close();
+            sslServerSocket.close();
+        }
+    }
+
+    /*
+     * Define the server side application of the test for the specified socket.
+     */
+    void runServerApplication(SSLSocket socket) throws Exception {
+        // here comes the test logic
+        InputStream sslIS = socket.getInputStream();
+        OutputStream sslOS = socket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        sslOS.flush();
+    }
+
+    /*
+     * Define the client side of the test.
+     */
+    void doClientSide() throws Exception {
+
+        // Wait for server to get started.
+        //
+        // The server side takes care of the issue if the server cannot
+        // get started in 90 seconds.  The client side would just ignore
+        // the test case if the serer is not ready.
+        boolean serverIsReady =
+                serverCondition.await(90L, TimeUnit.SECONDS);
+        if (!serverIsReady) {
+            System.out.println(
+                    "The server is not ready yet in 90 seconds. " +
+                    "Ignore in client side.");
+            return;
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory)SSLSocketFactory.getDefault();
+        try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) {
+            try {
+                sslSocket.connect(
+                        new InetSocketAddress("localhost", serverPort), 15000);
+            } catch (IOException ioe) {
+                // The server side may be impacted by naughty test cases or
+                // third party routines, and cannot accept connections.
+                //
+                // Just ignore the test if the connection cannot be
+                // established.
+                System.out.println(
+                        "Cannot make a connection in 15 seconds. " +
+                        "Ignore in client side.");
+                return;
+            }
+
+            // OK, here the client and server get connected.
+
+            // Signal the server, the client is ready to communicate.
+            clientCondition.countDown();
+
+            // There is still a chance in theory that the server thread may
+            // wait client-ready timeout and then quit.  The chance should
+            // be really rare so we don't consider it until it becomes a
+            // real problem.
+
+            // Run the application in client side.
+            runClientApplication(sslSocket);
+        }
+    }
+
+    /*
+     * Define the server side application of the test for the specified socket.
+     */
+    void runClientApplication(SSLSocket socket) throws Exception {
+        InputStream sslIS = socket.getInputStream();
+        OutputStream sslOS = socket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    private volatile Exception serverException = null;
+    private volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug) {
+            System.setProperty("javax.net.debug", "all");
+        }
+
+        /*
+         * Start the tests.
+         */
+        new SSLSocketSample();
+    }
+
+    private Thread clientThread = null;
+    private Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    SSLSocketSample() throws Exception {
+        Exception startException = null;
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            startException = e;
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            if (serverThread != null) {
+                serverThread.join();
+            }
+        } else {
+            if (clientThread != null) {
+                clientThread.join();
+            }
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+        } else {
+            remote = clientException;
+            local = serverException;
+        }
+
+        Exception exception = null;
+
+        /*
+         * Check various exception conditions.
+         */
+        if ((local != null) && (remote != null)) {
+            // If both failed, return the curthread's exception.
+            local.initCause(remote);
+            exception = local;
+        } else if (local != null) {
+            exception = local;
+        } else if (remote != null) {
+            exception = remote;
+        } else if (startException != null) {
+            exception = startException;
+        }
+
+        /*
+         * If there was an exception *AND* a startException,
+         * output it.
+         */
+        if (exception != null) {
+            if (exception != startException && startException != null) {
+                exception.addSuppressed(startException);
+            }
+            throw exception;
+        }
+
+        // Fall-through: no exception to throw!
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                @Override
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.out.println("Server died: " + e);
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                System.out.println("Server failed: " + e);
+                serverException = e;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                @Override
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.out.println("Client died: " + e);
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                System.out.println("Client failed: " + e);
+                clientException = e;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/modules/JaasClientWithDefaultHandler.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+package login;
+
+import java.security.Principal;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import com.sun.security.auth.UnixPrincipal;
+
+public class JaasClientWithDefaultHandler {
+
+    private static final String USER_NAME = "testUser";
+    private static final String LOGIN_CONTEXT = "ModularLoginConf";
+    private static final String CBH_PROP = "auth.login.defaultCallbackHandler";
+
+    public static void main(String[] args) {
+        try {
+            java.security.Security.setProperty(CBH_PROP, args[0]);
+            LoginContext lc = new LoginContext(LOGIN_CONTEXT);
+            lc.login();
+            checkPrincipal(lc, true);
+            lc.logout();
+            checkPrincipal(lc, false);
+        } catch (LoginException le) {
+            throw new RuntimeException(le);
+        }
+        System.out.println("Test passed.");
+
+    }
+
+    /*
+     * Verify principal for the test user.
+     */
+    private static void checkPrincipal(LoginContext loginContext,
+            boolean principalShouldExist) {
+        if (!principalShouldExist) {
+            if (loginContext.getSubject().getPrincipals().size() != 0) {
+                throw new RuntimeException("Test failed. Principal was not "
+                        + "cleared.");
+            }
+            return;
+        }
+        for (Principal p : loginContext.getSubject().getPrincipals()) {
+            if (p instanceof UnixPrincipal
+                    && USER_NAME.equals(p.getName())) {
+                //Proper principal was found, return.
+                return;
+            }
+        }
+        throw new RuntimeException("Test failed. UnixPrincipal "
+                + USER_NAME + " expected.");
+    }
+
+}
--- a/jdk/test/javax/security/auth/login/modules/JaasModularClientTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/javax/security/auth/login/modules/JaasModularClientTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -59,8 +59,7 @@
     private static final Path C_SRC = SRC.resolve("JaasClient.java");
     private static final String C_PKG = "client";
     private static final String C_JAR_NAME = C_PKG + JAR_EXTN;
-    private static final String MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME = MODULAR
-            + C_PKG + AUTO + JAR_EXTN;
+    private static final String MCN_JAR_NAME = MODULAR + C_PKG + "N" + JAR_EXTN;
     private static final String MC_JAR_NAME = MODULAR + C_PKG + JAR_EXTN;
 
     private static final Path BUILD_DIR = Paths.get(".").resolve("build");
@@ -68,7 +67,7 @@
     private static final Path S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG);
     private static final Path S_WITH_META_DESCR_BUILD_DIR = COMPILE_DIR.resolve(
             S_PKG + DESCRIPTOR);
-    private static final Path C_BUILD_DIR = COMPILE_DIR.resolve(C_PKG);
+    private static final Path C_BLD_DIR = COMPILE_DIR.resolve(C_PKG);
     private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase");
     private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts");
 
@@ -83,8 +82,7 @@
     private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG);
     private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME);
     private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME);
-    private static final Path MC_DEPENDS_ON_AUTO_SERVICE_JAR = C_ARTIFACTS_DIR
-            .resolve(MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME);
+    private static final Path MCN_JAR = C_ARTIFACTS_DIR.resolve(MCN_JAR_NAME);
 
     private static final String MAIN = C_PKG + ".JaasClient";
     private static final String S_INTERFACE
@@ -99,10 +97,7 @@
 
     private static final boolean WITH_S_DESCR = true;
     private static final boolean WITHOUT_S_DESCR = false;
-    private static final String LOGIN_MODULE_NOT_FOUND_MSG
-            = "No LoginModule found";
     private static final String NO_FAILURE = null;
-    private static final Map<String, String> VM_ARGS = new LinkedHashMap<>();
 
     /**
      * Generates Test specific input parameters.
@@ -112,10 +107,10 @@
 
         List<List<Object>> params = new ArrayList<>();
         String[] args = new String[]{};
-        //PARAMETER ORDERS -
-        //client Module Type, Service Module Type,
-        //Service META Descriptor Required,
-        //Expected Failure message, mechanism used to find the provider
+        // PARAMETER ORDERS -
+        // Client Module Type, Service Module Type,
+        // If Service META descriptor Required,
+        // Expected Failure message, Client arguments
         params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
                 WITH_S_DESCR, NO_FAILURE, args));
         params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
@@ -123,7 +118,7 @@
         params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
                 WITH_S_DESCR, NO_FAILURE, args));
         params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
-                WITHOUT_S_DESCR, LOGIN_MODULE_NOT_FOUND_MSG, args));
+                WITHOUT_S_DESCR, NO_FAILURE, args));
         params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
                 WITH_S_DESCR, NO_FAILURE, args));
         params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
@@ -136,7 +131,7 @@
         params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
                 WITH_S_DESCR, NO_FAILURE, args));
         params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
-                WITHOUT_S_DESCR, LOGIN_MODULE_NOT_FOUND_MSG, args));
+                WITHOUT_S_DESCR, NO_FAILURE, args));
         params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
                 WITH_S_DESCR, NO_FAILURE, args));
         params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
@@ -149,7 +144,7 @@
         params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
                 WITH_S_DESCR, NO_FAILURE, args));
         params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
-                WITHOUT_S_DESCR, LOGIN_MODULE_NOT_FOUND_MSG, args));
+                WITHOUT_S_DESCR, NO_FAILURE, args));
         params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
                 WITH_S_DESCR, NO_FAILURE, args));
         params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
@@ -166,29 +161,25 @@
 
         boolean done = true;
         try {
-            VM_ARGS.put("-Duser.language=", "en");
-            VM_ARGS.put("-Duser.region", "US");
-            VM_ARGS.put("-Djava.security.auth.login.config=", SRC.resolve(
-                    "jaas.conf").toFile().getCanonicalPath());
-
             done = CompilerUtils.compile(S_SRC, S_BUILD_DIR);
             done &= CompilerUtils.compile(S_SRC, S_WITH_META_DESCR_BUILD_DIR);
             done &= createMetaInfServiceDescriptor(S_META_DESCR_FPATH, S_IMPL);
-            //Generate regular/modular jars with(out) META-INF
-            //service descriptor
+            // Generate modular/regular jars with(out) META-INF
+            // service descriptor
             generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false);
             generateJar(true, MODULE_TYPE.EXPLICIT, MS_WITH_DESCR_JAR,
                     S_WITH_META_DESCR_BUILD_DIR, false);
             generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false);
             generateJar(true, MODULE_TYPE.UNNAMED, S_WITH_DESCRIPTOR_JAR,
                     S_WITH_META_DESCR_BUILD_DIR, false);
-            //Generate regular/modular(depends on explicit/auto service)
-            //jars for client
-            done &= CompilerUtils.compile(C_SRC, C_BUILD_DIR);
-            generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BUILD_DIR, true);
-            generateJar(false, MODULE_TYPE.EXPLICIT,
-                    MC_DEPENDS_ON_AUTO_SERVICE_JAR, C_BUILD_DIR, false);
-            generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BUILD_DIR, false);
+            // Compile client source codes.
+            done &= CompilerUtils.compile(C_SRC, C_BLD_DIR);
+            // Generate modular client jar with explicit dependency
+            generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BLD_DIR, true);
+            // Generate modular client jar without any dependency
+            generateJar(false, MODULE_TYPE.EXPLICIT, MCN_JAR, C_BLD_DIR, false);
+            // Generate regular client jar
+            generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BLD_DIR, false);
             System.out.format("%nArtifacts generated successfully? %s", done);
             if (!done) {
                 throw new RuntimeException("Artifact generation failed");
@@ -226,9 +217,9 @@
 
         OutputAnalyzer output = null;
         try {
-            //For automated/explicit module type copy the corresponding
-            //jars to module base folder, which will be considered as
-            //module base path during execution.
+            // For automated/explicit module types, copy the corresponding
+            // jars to module base folder, which will be considered as
+            // module base path during execution.
             if (!(cModuleType == MODULE_TYPE.UNNAMED
                     && sModuletype == MODULE_TYPE.UNNAMED)) {
                 copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH);
@@ -237,20 +228,19 @@
 
             System.out.format("%nExecuting java client with required"
                     + " custom service in class/module path.");
-            String mName = getModuleName(cModuleType, cJarPath,
-                    C_PKG);
+            String mName = getModuleName(cModuleType, cJarPath, C_PKG);
             Path cmBasePath = (cModuleType != MODULE_TYPE.UNNAMED
                     || sModuletype != MODULE_TYPE.UNNAMED) ? M_BASE_PATH : null;
             String cPath = buildClassPath(cModuleType, cJarPath, sModuletype,
                     sJarPath);
+            Map<String, String> vmArgs = getVMArgs(sModuletype,
+                    getModuleName(sModuletype, sJarPath, S_PKG));
             output = ProcessTools.executeTestJava(
-                    getJavaCommand(cmBasePath, cPath, mName, MAIN, VM_ARGS,
+                    getJavaCommand(cmBasePath, cPath, mName, MAIN, vmArgs,
                             args)).outputTo(System.out).errorTo(System.out);
         } finally {
-            //clean module path so that the modulepath can hold only
-            //the required jars for next run.
+            // Clean module path to hold required jars for next run.
             cleanModuleBasePath(M_BASE_PATH);
-            System.out.println("--------------------------------------------");
         }
         return output;
     }
@@ -260,9 +250,9 @@
      * based on client/service module type.
      */
     @Override
-    public Path findJarPath(boolean service, MODULE_TYPE moduleType,
+    public Path findJarPath(boolean isService, MODULE_TYPE moduleType,
             boolean addMetaDesc, boolean dependsOnServiceModule) {
-        if (service) {
+        if (isService) {
             if (moduleType == MODULE_TYPE.EXPLICIT) {
                 if (addMetaDesc) {
                     return MS_WITH_DESCR_JAR;
@@ -277,11 +267,12 @@
                 }
             }
         } else {
+            // Choose corresponding client jar using dependent module
             if (moduleType == MODULE_TYPE.EXPLICIT) {
                 if (dependsOnServiceModule) {
                     return MC_JAR;
                 } else {
-                    return MC_DEPENDS_ON_AUTO_SERVICE_JAR;
+                    return MCN_JAR;
                 }
             } else {
                 return C_JAR;
@@ -289,4 +280,20 @@
         }
     }
 
+    /**
+     * VM argument required for the test.
+     */
+    private Map<String, String> getVMArgs(MODULE_TYPE sModuletype,
+            String addModName) throws IOException {
+        final Map<String, String> vmArgs = new LinkedHashMap<>();
+        vmArgs.put("-Duser.language=", "en");
+        vmArgs.put("-Duser.region=", "US");
+        vmArgs.put("-Djava.security.auth.login.config=", SRC.resolve(
+                "jaas.conf").toFile().getCanonicalPath());
+        if (addModName != null && sModuletype == MODULE_TYPE.AUTO) {
+            vmArgs.put("-addmods ", addModName);
+        }
+        return vmArgs;
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/modules/JaasModularDefaultHandlerTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2016, 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 java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Arrays;
+import java.io.IOException;
+import java.lang.module.ModuleDescriptor;
+import java.util.ArrayList;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.OutputAnalyzer;
+import org.testng.annotations.BeforeTest;
+
+/**
+ * @test
+ * @bug 8151654
+ * @library /lib/testlibrary
+ * @library /java/security/modules
+ * @build CompilerUtils JarUtils
+ * @summary Test custom JAAS callback handler with all possible modular option.
+ * @run testng JaasModularDefaultHandlerTest
+ */
+public class JaasModularDefaultHandlerTest extends ModularTest {
+
+    private static final Path S_SRC = SRC.resolve("TestCallbackHandler.java");
+    private static final String MODULAR = "M";
+    private static final String S_PKG = "handler";
+    private static final String S_JAR_NAME = S_PKG + JAR_EXTN;
+    private static final String MS_JAR_NAME = MODULAR + S_PKG + JAR_EXTN;
+    private static final String HANDLER = S_PKG + ".TestCallbackHandler";
+
+    private static final Path C_SRC
+            = SRC.resolve("JaasClientWithDefaultHandler.java");
+    private static final Path CL_SRC = SRC.resolve("TestLoginModule.java");
+    private static final String C_PKG = "login";
+    private static final String C_JAR_NAME = C_PKG + JAR_EXTN;
+    private static final String MCN_JAR_NAME
+            = MODULAR + C_PKG + "NoMUse" + JAR_EXTN;
+    private static final String MC_JAR_NAME = MODULAR + C_PKG + JAR_EXTN;
+
+    private static final Path BUILD_DIR = Paths.get(".").resolve("build");
+    private static final Path COMPILE_DIR = BUILD_DIR.resolve("bin");
+    private static final Path S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG);
+    private static final Path C_BLD_DIR = COMPILE_DIR.resolve(C_PKG);
+    private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase");
+    private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts");
+
+    private static final Path S_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(S_PKG);
+    private static final Path S_JAR = S_ARTIFACTS_DIR.resolve(S_JAR_NAME);
+    private static final Path MS_JAR = S_ARTIFACTS_DIR.resolve(MS_JAR_NAME);
+
+    private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG);
+    private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME);
+    private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME);
+    private static final Path MCN_JAR = C_ARTIFACTS_DIR.resolve(MCN_JAR_NAME);
+
+    private static final String MAIN = C_PKG + ".JaasClientWithDefaultHandler";
+    private static final List<String> M_REQUIRED = Arrays.asList("java.base",
+            "jdk.security.auth");
+
+    private static final String CLASS_NOT_FOUND_MSG
+            = "java.lang.ClassNotFoundException: handler.TestCallbackHandler";
+    private static final String NO_FAILURE = null;
+
+    /**
+     * Generates Test specific input parameters.
+     */
+    @Override
+    public Object[][] getTestInput() {
+
+        List<List<Object>> params = new ArrayList<>();
+        String[] args = new String[]{HANDLER};
+        // PARAMETER ORDERS -
+        // Client Module Type, Service Module Type,
+        // Service META Descriptor Required,
+        // Expected Failure message, Client arguments
+        params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
+                false, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
+                false, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
+                false, NO_FAILURE, args));
+
+        params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT,
+                false, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
+                false, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
+                false, NO_FAILURE, args));
+
+        params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT,
+                false, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
+                false, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
+                false, NO_FAILURE, args));
+        return params.stream().map(p -> p.toArray()).toArray(Object[][]::new);
+    }
+
+    /**
+     * Pre-compile and generate the artifacts required to run this test before
+     * running each test cases.
+     */
+    @BeforeTest
+    public void buildArtifacts() {
+
+        boolean done = true;
+        try {
+            done = CompilerUtils.compile(S_SRC, S_BUILD_DIR);
+            // Generate modular/regular handler jars.
+            generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false);
+            generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false);
+            // Compile client source codes.
+            done &= CompilerUtils.compile(C_SRC, C_BLD_DIR);
+            done &= CompilerUtils.compile(CL_SRC, C_BLD_DIR);
+            // Generate modular client jar with explicit dependency
+            generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BLD_DIR, true);
+            // Generate modular client jar without any dependency
+            generateJar(false, MODULE_TYPE.EXPLICIT, MCN_JAR, C_BLD_DIR, false);
+            // Generate regular client jar
+            generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BLD_DIR, false);
+            System.out.format("%nArtifacts generated successfully? %s", done);
+            if (!done) {
+                throw new RuntimeException("Artifact generation failed");
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Generate modular/regular jar based on module type for this test.
+     */
+    private void generateJar(boolean isService, MODULE_TYPE moduleType,
+            Path jar, Path compilePath, boolean depends) throws IOException {
+
+        ModuleDescriptor mDescriptor = null;
+        if (isService) {
+            mDescriptor = generateModuleDescriptor(isService, moduleType, S_PKG,
+                    S_PKG, null, null, null, M_REQUIRED, depends);
+        } else {
+            mDescriptor = generateModuleDescriptor(isService, moduleType, C_PKG,
+                    C_PKG, null, null, S_PKG, M_REQUIRED, depends);
+        }
+        generateJar(mDescriptor, jar, compilePath);
+    }
+
+    /**
+     * Holds Logic for the test client. This method will get called with each
+     * test parameter.
+     */
+    @Override
+    public OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType,
+            Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath,
+            String... args) throws Exception {
+
+        OutputAnalyzer output = null;
+        try {
+            // For automated/explicit module types, copy the corresponding
+            // jars to module base folder, which will be considered as
+            // module base path during execution.
+            if (!(cModuleType == MODULE_TYPE.UNNAMED
+                    && sModuletype == MODULE_TYPE.UNNAMED)) {
+                copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH);
+                copyJarsToModuleBase(sModuletype, sJarPath, M_BASE_PATH);
+            }
+
+            System.out.format("%nExecuting java client with required"
+                    + " custom service in class/module path.");
+            String mName = getModuleName(cModuleType, cJarPath, C_PKG);
+            Path cmBasePath = (cModuleType != MODULE_TYPE.UNNAMED
+                    || sModuletype != MODULE_TYPE.UNNAMED) ? M_BASE_PATH : null;
+            String cPath = buildClassPath(cModuleType, cJarPath, sModuletype,
+                    sJarPath);
+            Map<String, String> vmArgs = getVMArgs(sModuletype, cModuleType,
+                    getModuleName(sModuletype, sJarPath, S_PKG));
+            output = ProcessTools.executeTestJava(
+                    getJavaCommand(cmBasePath, cPath, mName, MAIN, vmArgs,
+                            args)).outputTo(System.out).errorTo(System.out);
+        } finally {
+            // Clean module path to hold required jars for next run.
+            cleanModuleBasePath(M_BASE_PATH);
+        }
+        return output;
+    }
+
+    /**
+     * Decide the pre-generated client/service jar path for each test case
+     * based on client/service module type.
+     */
+    @Override
+    public Path findJarPath(boolean depends, MODULE_TYPE moduleType,
+            boolean addMetaDesc, boolean dependsOnServiceModule) {
+        if (depends) {
+            if (moduleType == MODULE_TYPE.EXPLICIT) {
+                return MS_JAR;
+            } else {
+                return S_JAR;
+            }
+        } else {
+            // Choose corresponding client jar using dependent module
+            if (moduleType == MODULE_TYPE.EXPLICIT) {
+                if (dependsOnServiceModule) {
+                    return MC_JAR;
+                } else {
+                    return MCN_JAR;
+                }
+            } else {
+                return C_JAR;
+            }
+        }
+    }
+
+    /**
+     * VM argument required for the test.
+     */
+    private Map<String, String> getVMArgs(MODULE_TYPE sModuletype,
+            MODULE_TYPE cModuleType, String addModName) throws IOException {
+        final Map<String, String> vmArgs = new LinkedHashMap<>();
+        vmArgs.put("-Duser.language=", "en");
+        vmArgs.put("-Duser.region=", "US");
+        vmArgs.put("-Djava.security.auth.login.config=", SRC.resolve(
+                "jaas.conf").toFile().getCanonicalPath());
+        if (addModName != null
+                && !(cModuleType == MODULE_TYPE.EXPLICIT
+                && sModuletype == MODULE_TYPE.EXPLICIT)) {
+            vmArgs.put("-addmods ", addModName);
+        }
+        return vmArgs;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/modules/TestCallbackHandler.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+package handler;
+
+import java.io.IOException;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+public class TestCallbackHandler implements CallbackHandler {
+
+    private static final String USER_NAME = "testUser";
+    private static final String PASSWORD = "testPassword";
+
+    @Override
+    public void handle(Callback[] callbacks) throws IOException,
+            UnsupportedCallbackException {
+        System.out.println("TestCallbackHandler will get resolved through"
+                + " auth.login.defaultCallbackHandler property.");
+        for (Callback callback : callbacks) {
+            if (callback instanceof NameCallback) {
+                ((NameCallback) callback).setName(USER_NAME);
+            } else if (callback instanceof PasswordCallback) {
+                ((PasswordCallback) callback).setPassword(
+                        PASSWORD.toCharArray());
+            } else {
+                throw new UnsupportedCallbackException(callback);
+            }
+        }
+    }
+
+}
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/Platform.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Platform.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -58,10 +58,6 @@
         return vmName.endsWith(" Minimal VM");
     }
 
-    public static boolean isEmbedded() {
-        return vmName.contains("Embedded");
-    }
-
     public static boolean isTieredSupported() {
         return compiler.contains("Tiered Compilers");
     }
--- a/langtools/.hgtags	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/.hgtags	Wed Jul 27 13:33:55 2016 +0000
@@ -370,3 +370,4 @@
 2d65e127e93d5ff0df61bf78e57d7f46a2f1edeb jdk-9+125
 ea4eea2997b9e2f26cd7965839921710ff4065c8 jdk-9+126
 a42768b48cb0c5af9063e12093975baeeca3b5fa jdk-9+127
+2764986661b6d339ba73af52d69d3506ce12e648 jdk-9+128
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1900,7 +1900,8 @@
             Type qualifier = (tree.meth.hasTag(SELECT))
                     ? ((JCFieldAccess) tree.meth).selected.type
                     : env.enclClass.sym.type;
-            restype = adjustMethodReturnType(qualifier, methName, argtypes, restype);
+            Symbol msym = TreeInfo.symbol(tree.meth);
+            restype = adjustMethodReturnType(msym, qualifier, methName, argtypes, restype);
 
             chk.checkRefTypes(tree.typeargs, typeargtypes);
 
@@ -1912,19 +1913,25 @@
         chk.validate(tree.typeargs, localEnv);
     }
     //where
-        Type adjustMethodReturnType(Type qualifierType, Name methodName, List<Type> argtypes, Type restype) {
-            if (methodName == names.clone && types.isArray(qualifierType)) {
+        Type adjustMethodReturnType(Symbol msym, Type qualifierType, Name methodName, List<Type> argtypes, Type restype) {
+            if (msym != null &&
+                    msym.owner == syms.objectType.tsym &&
+                    methodName == names.getClass &&
+                    argtypes.isEmpty()) {
+                // as a special case, x.getClass() has type Class<? extends |X|>
+                return new ClassType(restype.getEnclosingType(),
+                        List.<Type>of(new WildcardType(types.erasure(qualifierType),
+                                BoundKind.EXTENDS,
+                                syms.boundClass)),
+                        restype.tsym,
+                        restype.getMetadata());
+            } else if (msym != null &&
+                    msym.owner == syms.arrayClass &&
+                    methodName == names.clone &&
+                    types.isArray(qualifierType)) {
                 // as a special case, array.clone() has a result that is
                 // the same as static type of the array being cloned
                 return qualifierType;
-            } else if (methodName == names.getClass && argtypes.isEmpty()) {
-                // as a special case, x.getClass() has type Class<? extends |X|>
-                return new ClassType(restype.getEnclosingType(),
-                              List.<Type>of(new WildcardType(types.erasure(qualifierType),
-                                                               BoundKind.EXTENDS,
-                                                             syms.boundClass)),
-                                     restype.tsym,
-                                     restype.getMetadata());
             } else {
                 return restype;
             }
@@ -2989,7 +2996,7 @@
 
             if (!refType.isErroneous()) {
                 refType = types.createMethodTypeWithReturn(refType,
-                        adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
+                        adjustMethodReturnType(refSym, lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
             }
 
             //go ahead with standard method reference compatibility check - note that param check
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Wed Jul 27 13:33:55 2016 +0000
@@ -902,13 +902,7 @@
     /** Return binary operator that corresponds to given access code.
      */
     private OperatorSymbol binaryAccessOperator(int acode) {
-        for (Symbol sym : syms.predefClass.members().getSymbols(NON_RECURSIVE)) {
-            if (sym instanceof OperatorSymbol) {
-                OperatorSymbol op = (OperatorSymbol)sym;
-                if (accessCode(op.opcode) == acode) return op;
-            }
-        }
-        return null;
+        return (OperatorSymbol)operators.lookupBinaryOp(sym -> accessCode(((OperatorSymbol)sym).opcode) == acode);
     }
 
     /** Return tree tag for assignment operation corresponding
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -798,6 +798,15 @@
                     .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, bool_or));
     }
 
+    Symbol lookupBinaryOp(Predicate<Symbol> applicabilityTest) {
+        return binaryOperators.values().stream()
+                .flatMap(List::stream)
+                .map(helper -> helper.doLookup(applicabilityTest))
+                .distinct()
+                .filter(sym -> sym != syms.noSymbol)
+                .findFirst().get();
+    }
+
     /**
      * Complete the initialization of an operator helper by storing it into the corresponding operator map.
      */
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Wed Jul 27 13:33:55 2016 +0000
@@ -449,7 +449,7 @@
             ? CompileState.valueOf(options.get("shouldstop.ifNoError"))
             : CompileState.GENERATE;
 
-        if (options.isUnset("oldDiags"))
+        if (options.isUnset("diags.legacy"))
             log.setDiagnosticFormatter(RichDiagnosticFormatter.instance(context));
 
         PlatformDescription platformProvider = context.get(PlatformDescription.class);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java	Wed Jul 27 13:33:55 2016 +0000
@@ -346,21 +346,6 @@
         }
     },
 
-    DIAGS("-XDdiags=", null, HIDDEN, INFO) {
-        @Override
-        public boolean process(OptionHelper helper, String option) {
-            option = option.substring(option.indexOf('=') + 1);
-            String diagsOption = option.contains("%") ?
-                "-XDdiagsFormat=" :
-                "-XDdiags=";
-            diagsOption += option;
-            if (XD.matches(diagsOption))
-                return XD.process(helper, diagsOption);
-            else
-                return false;
-        }
-    },
-
     HELP("-help", "opt.help", STANDARD, INFO) {
         @Override
         public boolean process(OptionHelper helper, String option) {
@@ -506,30 +491,6 @@
 
     XDIAGS("-Xdiags:", "opt.diags", EXTENDED, BASIC, ONEOF, "compact", "verbose"),
 
-    /* This is a back door to the compiler's option table.
-     * -XDx=y sets the option x to the value y.
-     * -XDx sets the option x to the value x.
-     */
-    XD("-XD", null, HIDDEN, BASIC) {
-        @Override
-        public boolean matches(String s) {
-            return s.startsWith(text);
-        }
-        @Override
-        public boolean process(OptionHelper helper, String option) {
-            return process(helper, option, option.substring(text.length()));
-        }
-
-        @Override
-        public boolean process(OptionHelper helper, String option, String arg) {
-            int eq = arg.indexOf('=');
-            String key = (eq < 0) ? arg : arg.substring(0, eq);
-            String value = (eq < 0) ? arg : arg.substring(eq+1);
-            helper.put(key, value);
-            return false;
-        }
-    },
-
     XDEBUG("-Xdebug:", null, HIDDEN, BASIC) {
         @Override
         public boolean process(OptionHelper helper, String option) {
@@ -556,6 +517,37 @@
         }
     },
 
+    DIAGS("-diags:", null, HIDDEN, BASIC, true) {
+        @Override
+        public boolean process(OptionHelper helper, String option) {
+            return HiddenGroup.DIAGS.process(helper, option);
+        }
+    },
+
+    /* This is a back door to the compiler's option table.
+     * -XDx=y sets the option x to the value y.
+     * -XDx sets the option x to the value x.
+     */
+    XD("-XD", null, HIDDEN, BASIC) {
+        @Override
+        public boolean matches(String s) {
+            return s.startsWith(text);
+        }
+        @Override
+        public boolean process(OptionHelper helper, String option) {
+            return process(helper, option, option.substring(text.length()));
+        }
+
+        @Override
+        public boolean process(OptionHelper helper, String option, String arg) {
+            int eq = arg.indexOf('=');
+            String key = (eq < 0) ? arg : arg.substring(0, eq);
+            String value = (eq < 0) ? arg : arg.substring(eq+1);
+            helper.put(key, value);
+            return false;
+        }
+    },
+
     XADDEXPORTS("-XaddExports:", "opt.arg.addExports", "opt.addExports", EXTENDED, BASIC) {
         @Override
         public boolean process(OptionHelper helper, String option) {
@@ -672,6 +664,26 @@
         ANYOF
     }
 
+    enum HiddenGroup {
+        DIAGS("diags");
+
+        final String text;
+
+        HiddenGroup(String text) {
+            this.text = text;
+        }
+
+        public boolean process(OptionHelper helper, String option) {
+            String p = option.substring(option.indexOf(':') + 1).trim();
+            String[] subOptions = p.split(";");
+            for (String subOption : subOptions) {
+                subOption = text + "." + subOption.trim();
+                XD.process(helper, subOption, subOption);
+            }
+            return false;
+        }
+    }
+
     public final String text;
 
     final OptionKind kind;
@@ -705,6 +717,12 @@
         this(text, null, descrKey, kind, group, null, null, false);
     }
 
+    Option(String text, String descrKey,
+            OptionKind kind, OptionGroup group,
+            boolean doHasSuffix) {
+        this(text, null, descrKey, kind, group, null, null, doHasSuffix);
+    }
+
     Option(String text, String argsNameKey, String descrKey,
             OptionKind kind, OptionGroup group) {
         this(text, argsNameKey, descrKey, kind, group, null, null, false);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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
@@ -403,13 +403,13 @@
         public SimpleConfiguration(Options options, Set<DiagnosticPart> parts) {
             this(parts);
             String showSource = null;
-            if ((showSource = options.get("showSource")) != null) {
+            if ((showSource = options.get("diags.showSource")) != null) {
                 if (showSource.equals("true"))
                     setVisiblePart(DiagnosticPart.SOURCE, true);
                 else if (showSource.equals("false"))
                     setVisiblePart(DiagnosticPart.SOURCE, false);
             }
-            String diagOpts = options.get("diags");
+            String diagOpts = options.get("diags.formatterOptions");
             if (diagOpts != null) {//override -XDshowSource
                 Collection<String> args = Arrays.asList(diagOpts.split(","));
                 if (args.contains("short")) {
@@ -422,7 +422,7 @@
                     setVisiblePart(DiagnosticPart.SOURCE, false);
             }
             String multiPolicy = null;
-            if ((multiPolicy = options.get("multilinePolicy")) != null) {
+            if ((multiPolicy = options.get("diags.multilinePolicy")) != null) {
                 if (multiPolicy.equals("disabled"))
                     setVisiblePart(DiagnosticPart.SUBDIAGNOSTICS, false);
                 else if (multiPolicy.startsWith("limit:")) {
@@ -447,7 +447,7 @@
                 }
             }
             String showCaret = null;
-            if (((showCaret = options.get("showCaret")) != null) &&
+            if (((showCaret = options.get("diags.showCaret")) != null) &&
                 showCaret.equals("false"))
                     setCaretEnabled(false);
             else
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -229,9 +229,9 @@
                             DiagnosticPart.SOURCE));
             initFormat();
             initIndentation();
-            if (options.isSet("oldDiags"))
+            if (options.isSet("diags.legacy"))
                 initOldFormat();
-            String fmt = options.get("diagsFormat");
+            String fmt = options.get("diags.layout");
             if (fmt != null) {
                 if (fmt.equals("OLD"))
                     initOldFormat();
@@ -239,12 +239,12 @@
                     initFormats(fmt);
             }
             String srcPos = null;
-            if ((((srcPos = options.get("sourcePosition")) != null)) &&
+            if ((((srcPos = options.get("diags.sourcePosition")) != null)) &&
                     srcPos.equals("bottom"))
                     setSourcePosition(SourcePosition.BOTTOM);
             else
                 setSourcePosition(SourcePosition.AFTER_SUMMARY);
-            String indent = options.get("diagsIndentation");
+            String indent = options.get("diags.indent");
             if (indent != null) {
                 String[] levels = indent.split("\\|");
                 try {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, 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
@@ -644,7 +644,7 @@
                 EnumSet.of(RichFormatterFeature.SIMPLE_NAMES,
                     RichFormatterFeature.WHERE_CLAUSES,
                     RichFormatterFeature.UNIQUE_TYPEVAR_NAMES);
-            String diagOpts = options.get("diags");
+            String diagOpts = options.get("diags.formatterOptions");
             if (diagOpts != null) {
                 for (String args: diagOpts.split(",")) {
                     if (args.equals("-where")) {
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/ClassTracker.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2016, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-package jdk.internal.jshell.jdi;
-
-import java.util.HashMap;
-import java.util.Objects;
-import com.sun.jdi.ReferenceType;
-import java.util.List;
-import com.sun.jdi.VirtualMachine;
-
-/**
- * Tracks the state of a class.
- */
-class ClassTracker {
-
-    private final VirtualMachine vm;
-    private final HashMap<String, ClassInfo> map;
-
-    ClassTracker(VirtualMachine vm) {
-        this.vm = vm;
-        this.map = new HashMap<>();
-    }
-
-    /**
-     * Associates a class name, class bytes, and ReferenceType.
-     */
-    class ClassInfo {
-
-        // The name of the class -- always set
-        private final String className;
-
-        // The corresponding compiled class bytes when a load or redefine
-        // is started.  May not be the loaded bytes.  May be null.
-        private byte[] bytes;
-
-        // The class bytes successfully loaded/redefined into the remote VM.
-        private byte[] loadedBytes;
-
-        // The corresponding JDI ReferenceType.  Used by redefineClasses and
-        // acts as indicator of successful load (null if not loaded).
-        private ReferenceType rt;
-
-        private ClassInfo(String className) {
-            this.className = className;
-        }
-
-        String getClassName() {
-            return className;
-        }
-
-        byte[] getLoadedBytes() {
-            return loadedBytes;
-        }
-
-        byte[] getBytes() {
-            return bytes;
-        }
-
-        private void setBytes(byte[] potentialBytes) {
-            this.bytes = potentialBytes;
-        }
-
-        // The class has been successful loaded redefined.  The class bytes
-        // sent are now actually loaded.
-        void markLoaded() {
-            loadedBytes = bytes;
-        }
-
-        // Ask JDI for the ReferenceType, null if not loaded.
-        ReferenceType getReferenceTypeOrNull() {
-            if (rt == null) {
-                rt = nameToRef(className);
-            }
-            return rt;
-        }
-
-        private ReferenceType nameToRef(String name) {
-            List<ReferenceType> rtl = vm.classesByName(name);
-            if (rtl.size() != 1) {
-                return null;
-            }
-            return rtl.get(0);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            return o instanceof ClassInfo
-                    && ((ClassInfo) o).className.equals(className);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hashCode(this.className);
-        }
-    }
-
-    // Map a class name to the current compiled class bytes.
-    ClassInfo classInfo(String className, byte[] bytes) {
-        ClassInfo ci = get(className);
-        ci.setBytes(bytes);
-        return ci;
-    }
-
-    // Lookup the ClassInfo by class name, create if it does not exist.
-    ClassInfo get(String className) {
-        return map.computeIfAbsent(className, k -> new ClassInfo(k));
-    }
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/FailOverExecutionControl.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2016, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-package jdk.internal.jshell.jdi;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import jdk.internal.jshell.debug.InternalDebugControl;
-import jdk.jshell.JShellException;
-import jdk.jshell.spi.ExecutionControl;
-import jdk.jshell.spi.ExecutionEnv;
-
-/**
- * A meta implementation of ExecutionControl which cycles through the specified
- * ExecutionControl instances until it finds one that starts.
- */
-public class FailOverExecutionControl implements ExecutionControl {
-
-    private final List<ExecutionControl> ecl = new ArrayList<>();
-    private ExecutionControl active = null;
-    private final List<Exception> thrown = new ArrayList<>();
-
-    /**
-     * Create the ExecutionControl instance with at least one actual
-     * ExecutionControl instance.
-     *
-     * @param ec0 the first instance to try
-     * @param ecs the second and on instance to try
-     */
-    public FailOverExecutionControl(ExecutionControl ec0, ExecutionControl... ecs) {
-        ecl.add(ec0);
-        for (ExecutionControl ec : ecs) {
-            ecl.add(ec);
-        }
-    }
-
-    @Override
-    public void start(ExecutionEnv env) throws Exception {
-        for (ExecutionControl ec : ecl) {
-            try {
-                ec.start(env);
-                // Success! This is our active ExecutionControl
-                active = ec;
-                return;
-            } catch (Exception ex) {
-                thrown.add(ex);
-            } catch (Throwable ex) {
-                thrown.add(new RuntimeException(ex));
-            }
-            InternalDebugControl.debug(env.state(), env.userErr(),
-                    thrown.get(thrown.size() - 1), "failed one in FailOverExecutionControl");
-        }
-        // They have all failed -- rethrow the first exception we encountered
-        throw thrown.get(0);
-    }
-
-    @Override
-    public void close() {
-        active.close();
-    }
-
-    @Override
-    public boolean addToClasspath(String path) {
-        return active.addToClasspath(path);
-    }
-
-    @Override
-    public String invoke(String classname, String methodname) throws JShellException {
-        return active.invoke(classname, methodname);
-    }
-
-    @Override
-    public boolean load(Collection<String> classes) {
-        return active.load(classes);
-    }
-
-    @Override
-    public boolean redefine(Collection<String> classes) {
-        return active.redefine(classes);
-    }
-
-    @Override
-    public ClassStatus getClassStatus(String classname) {
-        return active.getClassStatus(classname);
-    }
-
-    @Override
-    public void stop() {
-        active.stop();
-    }
-
-    @Override
-    public String varValue(String classname, String varname) {
-        return active.varValue(classname, varname);
-    }
-
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIConnection.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 1998, 2016, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package jdk.internal.jshell.jdi;
-
-import com.sun.jdi.*;
-import com.sun.jdi.connect.*;
-
-import java.util.*;
-import java.util.Map.Entry;
-import java.io.*;
-import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
-
-/**
- * Connection to a Java Debug Interface VirtualMachine instance.
- * Adapted from jdb VMConnection. Message handling, exception handling, and I/O
- * redirection changed.  Interface to JShell added.
- */
-class JDIConnection {
-
-    private static final String REMOTE_AGENT = "jdk.internal.jshell.remote.RemoteAgent";
-
-    private VirtualMachine vm;
-    private boolean active = true;
-    private Process process = null;
-    private int outputCompleteCount = 0;
-
-    private final JDIExecutionControl ec;
-    private final Connector connector;
-    private final Map<String, com.sun.jdi.connect.Connector.Argument> connectorArgs;
-    private final int traceFlags;
-
-    private synchronized void notifyOutputComplete() {
-        outputCompleteCount++;
-        notifyAll();
-    }
-
-    private synchronized void waitOutputComplete() {
-        // Wait for stderr and stdout
-        if (process != null) {
-            while (outputCompleteCount < 2) {
-                try {wait();} catch (InterruptedException e) {}
-            }
-        }
-    }
-
-    private Connector findConnector(String name) {
-        for (Connector cntor :
-                 Bootstrap.virtualMachineManager().allConnectors()) {
-            if (cntor.name().equals(name)) {
-                return cntor;
-            }
-        }
-        return null;
-    }
-
-    private Map <String, Connector.Argument> mergeConnectorArgs(Connector connector, Map<String, String> argumentName2Value) {
-        Map<String, Connector.Argument> arguments = connector.defaultArguments();
-
-        for (Entry<String, String> argumentEntry : argumentName2Value.entrySet()) {
-            String name = argumentEntry.getKey();
-            String value = argumentEntry.getValue();
-            Connector.Argument argument = arguments.get(name);
-
-            if (argument == null) {
-                throw new IllegalArgumentException("Argument is not defined for connector:" +
-                                          name + " -- " + connector.name());
-            }
-
-            argument.setValue(value);
-        }
-
-        return arguments;
-    }
-
-    /**
-     * The JShell specific Connector args for the LaunchingConnector.
-     *
-     * @param portthe socket port for (non-JDI) commands
-     * @param remoteVMOptions any user requested VM options
-     * @return the argument map
-     */
-    private static Map<String, String> launchArgs(int port, String remoteVMOptions) {
-        Map<String, String> argumentName2Value = new HashMap<>();
-        argumentName2Value.put("main", REMOTE_AGENT + " " + port);
-        argumentName2Value.put("options", remoteVMOptions);
-        return argumentName2Value;
-    }
-
-    /**
-     * Start the remote agent and establish a JDI connection to it.
-     *
-     * @param ec the execution control instance
-     * @param port the socket port for (non-JDI) commands
-     * @param remoteVMOptions any user requested VM options
-     * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
-     * otherwise we start explicitly and use ListeningConnector
-     */
-    JDIConnection(JDIExecutionControl ec, int port, List<String> remoteVMOptions, boolean isLaunch) {
-        this(ec,
-                isLaunch
-                        ? "com.sun.jdi.CommandLineLaunch"
-                        : "com.sun.jdi.SocketListen",
-                isLaunch
-                        ? launchArgs(port, String.join(" ", remoteVMOptions))
-                        : new HashMap<>(),
-                0);
-        if (isLaunch) {
-            vm = launchTarget();
-        } else {
-            vm = listenTarget(port, remoteVMOptions);
-        }
-
-        if (isOpen() && vm().canBeModified()) {
-            /*
-             * Connection opened on startup.
-             */
-            new JDIEventHandler(vm(), (b) -> ec.handleVMExit())
-                    .start();
-        }
-    }
-
-    /**
-     * Base constructor -- set-up a JDI connection.
-     *
-     * @param ec the execution control instance
-     * @param connectorName the standardized name of the connector
-     * @param argumentName2Value the argument map
-     * @param traceFlags should we trace JDI behavior
-     */
-    JDIConnection(JDIExecutionControl ec, String connectorName, Map<String, String> argumentName2Value, int traceFlags) {
-        this.ec = ec;
-        this.connector = findConnector(connectorName);
-        if (connector == null) {
-            throw new IllegalArgumentException("No connector named: " + connectorName);
-        }
-        connectorArgs = mergeConnectorArgs(connector, argumentName2Value);
-        this.traceFlags = traceFlags;
-    }
-
-    final synchronized VirtualMachine vm() {
-        if (vm == null) {
-            throw new JDINotConnectedException();
-        } else {
-            return vm;
-        }
-    }
-
-    private synchronized boolean isOpen() {
-        return (vm != null);
-    }
-
-    synchronized boolean isRunning() {
-        return process != null && process.isAlive();
-    }
-
-    // Beginning shutdown, ignore any random dying squeals
-    void beginShutdown() {
-        active = false;
-    }
-
-    synchronized void disposeVM() {
-        try {
-            if (vm != null) {
-                vm.dispose(); // This could NPE, so it is caught below
-                vm = null;
-            }
-        } catch (VMDisconnectedException ex) {
-            // Ignore if already closed
-        } catch (Throwable e) {
-            ec.debug(DBG_GEN, null, "disposeVM threw: " + e);
-        } finally {
-            if (process != null) {
-                process.destroy();
-                process = null;
-            }
-            waitOutputComplete();
-        }
-    }
-
-    private void dumpStream(InputStream inStream, final PrintStream pStream) throws IOException {
-        BufferedReader in =
-            new BufferedReader(new InputStreamReader(inStream));
-        int i;
-        try {
-            while ((i = in.read()) != -1) {
-                // directly copy input to output, but skip if asked to close
-                if (active) {
-                    pStream.print((char) i);
-                }
-            }
-        } catch (IOException ex) {
-            String s = ex.getMessage();
-            if (active && !s.startsWith("Bad file number")) {
-                throw ex;
-            }
-            // else we are being shutdown (and don't want any spurious death
-            // throws to ripple) or
-            // we got a Bad file number IOException which just means
-            // that the debuggee has gone away.  We'll just treat it the
-            // same as if we got an EOF.
-        }
-    }
-
-    /**
-     *  Create a Thread that will retrieve and display any output.
-     *  Needs to be high priority, else debugger may exit before
-     *  it can be displayed.
-     */
-    private void displayRemoteOutput(final InputStream inStream, final PrintStream pStream) {
-        Thread thr = new Thread("output reader") {
-            @Override
-            public void run() {
-                try {
-                    dumpStream(inStream, pStream);
-                } catch (IOException ex) {
-                    ec.debug(ex, "Failed reading output");
-                    ec.handleVMExit();
-                } finally {
-                    notifyOutputComplete();
-                }
-            }
-        };
-        thr.setPriority(Thread.MAX_PRIORITY-1);
-        thr.start();
-    }
-
-    /**
-     *  Create a Thread that will ship all input to remote.
-     *  Does it need be high priority?
-     */
-    private void readRemoteInput(final OutputStream outStream, final InputStream inputStream) {
-        Thread thr = new Thread("input reader") {
-            @Override
-            public void run() {
-                try {
-                    byte[] buf = new byte[256];
-                    int cnt;
-                    while ((cnt = inputStream.read(buf)) != -1) {
-                        outStream.write(buf, 0, cnt);
-                        outStream.flush();
-                    }
-                } catch (IOException ex) {
-                    ec.debug(ex, "Failed reading output");
-                    ec.handleVMExit();
-                }
-            }
-        };
-        thr.setPriority(Thread.MAX_PRIORITY-1);
-        thr.start();
-    }
-
-    private void forwardIO() {
-        displayRemoteOutput(process.getErrorStream(), ec.execEnv.userErr());
-        displayRemoteOutput(process.getInputStream(), ec.execEnv.userOut());
-        readRemoteInput(process.getOutputStream(), ec.execEnv.userIn());
-    }
-
-    /* launch child target vm */
-    private VirtualMachine launchTarget() {
-        LaunchingConnector launcher = (LaunchingConnector)connector;
-        try {
-            VirtualMachine new_vm = launcher.launch(connectorArgs);
-            process = new_vm.process();
-            forwardIO();
-            return new_vm;
-        } catch (Exception ex) {
-            reportLaunchFail(ex, "launch");
-        }
-        return null;
-    }
-
-    /**
-     * Directly launch the remote agent and connect JDI to it with a
-     * ListeningConnector.
-     */
-    private VirtualMachine listenTarget(int port, List<String> remoteVMOptions) {
-        ListeningConnector listener = (ListeningConnector) connector;
-        try {
-            // Start listening, get the JDI connection address
-            String addr = listener.startListening(connectorArgs);
-            ec.debug(DBG_GEN, "Listening at address: " + addr);
-
-            // Launch the RemoteAgent requesting a connection on that address
-            String javaHome = System.getProperty("java.home");
-            List<String> args = new ArrayList<>();
-            args.add(javaHome == null
-                    ? "java"
-                    : javaHome + File.separator + "bin" + File.separator + "java");
-            args.add("-agentlib:jdwp=transport=" + connector.transport().name() +
-                    ",address=" + addr);
-            args.addAll(remoteVMOptions);
-            args.add(REMOTE_AGENT);
-            args.add("" + port);
-            ProcessBuilder pb = new ProcessBuilder(args);
-            process = pb.start();
-
-            // Forward out, err, and in
-            forwardIO();
-
-            // Accept the connection from the remote agent
-            vm = listener.accept(connectorArgs);
-            listener.stopListening(connectorArgs);
-            return vm;
-        } catch (Exception ex) {
-            reportLaunchFail(ex, "listen");
-        }
-        return null;
-    }
-
-    private void reportLaunchFail(Exception ex, String context) {
-        throw new InternalError("Failed remote " + context + ": " + connector +
-                " -- " + connectorArgs, ex);
-    }
-}
\ No newline at end of file
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIEventHandler.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 1998, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.jshell.jdi;
-
-import java.util.function.Consumer;
-import com.sun.jdi.*;
-import com.sun.jdi.event.*;
-
-/**
- * Handler of Java Debug Interface events.
- * Adapted from jdb EventHandler; Handling of events not used by JShell stubbed out.
- */
-class JDIEventHandler implements Runnable {
-
-    private final Thread thread;
-    private volatile boolean connected = true;
-    private boolean completed = false;
-    private final VirtualMachine vm;
-    private final Consumer<Boolean> reportVMExit;
-
-    JDIEventHandler(VirtualMachine vm, Consumer<Boolean> reportVMExit) {
-        this.vm = vm;
-        this.reportVMExit = reportVMExit;
-        this.thread = new Thread(this, "event-handler");
-    }
-
-    void start() {
-        thread.start();
-    }
-
-    synchronized void shutdown() {
-        connected = false;  // force run() loop termination
-        thread.interrupt();
-        while (!completed) {
-            try {wait();} catch (InterruptedException exc) {}
-        }
-    }
-
-    @Override
-    public void run() {
-        EventQueue queue = vm.eventQueue();
-        while (connected) {
-            try {
-                EventSet eventSet = queue.remove();
-                boolean resumeStoppedApp = false;
-                EventIterator it = eventSet.eventIterator();
-                while (it.hasNext()) {
-                    resumeStoppedApp |= handleEvent(it.nextEvent());
-                }
-
-                if (resumeStoppedApp) {
-                    eventSet.resume();
-                }
-            } catch (InterruptedException exc) {
-                // Do nothing. Any changes will be seen at top of loop.
-            } catch (VMDisconnectedException discExc) {
-                handleDisconnectedException();
-                break;
-            }
-        }
-        synchronized (this) {
-            completed = true;
-            notifyAll();
-        }
-    }
-
-    private boolean handleEvent(Event event) {
-        if (event instanceof ExceptionEvent) {
-            exceptionEvent(event);
-        } else if (event instanceof WatchpointEvent) {
-            fieldWatchEvent(event);
-        } else if (event instanceof MethodEntryEvent) {
-            methodEntryEvent(event);
-        } else if (event instanceof MethodExitEvent) {
-            methodExitEvent(event);
-        } else if (event instanceof ClassPrepareEvent) {
-            classPrepareEvent(event);
-        } else if (event instanceof ThreadStartEvent) {
-            threadStartEvent(event);
-        } else if (event instanceof ThreadDeathEvent) {
-            threadDeathEvent(event);
-        } else if (event instanceof VMStartEvent) {
-            vmStartEvent(event);
-            return true;
-        } else {
-            handleExitEvent(event);
-        }
-        return true;
-    }
-
-    private boolean vmDied = false;
-
-    private void handleExitEvent(Event event) {
-        if (event instanceof VMDeathEvent) {
-            vmDied = true;
-        } else if (event instanceof VMDisconnectEvent) {
-            connected = false;
-        } else {
-            throw new InternalError("Unexpected event type: " +
-                    event.getClass());
-        }
-        reportVMExit.accept(vmDied);
-    }
-
-    private synchronized void handleDisconnectedException() {
-        /*
-         * A VMDisconnectedException has happened while dealing with
-         * another event. We need to flush the event queue, dealing only
-         * with exit events (VMDeath, VMDisconnect) so that we terminate
-         * correctly.
-         */
-        EventQueue queue = vm.eventQueue();
-        while (connected) {
-            try {
-                EventSet eventSet = queue.remove();
-                EventIterator iter = eventSet.eventIterator();
-                while (iter.hasNext()) {
-                    handleExitEvent(iter.next());
-                }
-            } catch (InterruptedException exc) {
-                // ignore
-            } catch (InternalError exc) {
-                // ignore
-            }
-        }
-    }
-
-    private void vmStartEvent(Event event)  {
-        VMStartEvent se = (VMStartEvent)event;
-    }
-
-    private void methodEntryEvent(Event event)  {
-        MethodEntryEvent me = (MethodEntryEvent)event;
-    }
-
-    private void methodExitEvent(Event event)  {
-        MethodExitEvent me = (MethodExitEvent)event;
-    }
-
-    private void fieldWatchEvent(Event event)  {
-        WatchpointEvent fwe = (WatchpointEvent)event;
-    }
-
-    private void classPrepareEvent(Event event)  {
-        ClassPrepareEvent cle = (ClassPrepareEvent)event;
-    }
-
-    private void exceptionEvent(Event event) {
-        ExceptionEvent ee = (ExceptionEvent)event;
-    }
-
-    private void threadDeathEvent(Event event) {
-        ThreadDeathEvent tee = (ThreadDeathEvent)event;
-    }
-
-    private void threadStartEvent(Event event) {
-        ThreadStartEvent tse = (ThreadStartEvent)event;
-    }
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDIExecutionControl.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,598 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.jshell.jdi;
-
-import static jdk.internal.jshell.remote.RemoteCodes.*;
-import java.io.DataInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.PrintStream;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.io.EOFException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import com.sun.jdi.BooleanValue;
-import com.sun.jdi.ClassNotLoadedException;
-import com.sun.jdi.IncompatibleThreadStateException;
-import com.sun.jdi.InvalidTypeException;
-import com.sun.jdi.ObjectReference;
-import com.sun.jdi.ReferenceType;
-import com.sun.jdi.StackFrame;
-import com.sun.jdi.ThreadReference;
-import com.sun.jdi.VirtualMachine;
-import static java.util.stream.Collectors.toList;
-import jdk.jshell.JShellException;
-import jdk.jshell.spi.ExecutionControl;
-import jdk.jshell.spi.ExecutionEnv;
-import jdk.internal.jshell.jdi.ClassTracker.ClassInfo;
-import static java.util.stream.Collectors.toMap;
-import jdk.internal.jshell.debug.InternalDebugControl;
-import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
-
-/**
- * Controls the remote execution environment.
- * Interfaces to the JShell-core by implementing ExecutionControl SPI.
- * Interfaces to RemoteAgent over a socket and via JDI.
- * Launches a remote process.
- */
-public class JDIExecutionControl implements ExecutionControl {
-
-    ExecutionEnv execEnv;
-    private final boolean isLaunch;
-    private JDIConnection connection;
-    private ClassTracker classTracker;
-    private Socket socket;
-    private ObjectInputStream remoteIn;
-    private ObjectOutputStream remoteOut;
-
-    /**
-     * Creates an ExecutionControl instance based on JDI.
-     *
-     * @param isLaunch true for LaunchingConnector; false for ListeningConnector
-     */
-    public JDIExecutionControl(boolean isLaunch) {
-        this.isLaunch = isLaunch;
-    }
-
-    /**
-     * Creates an ExecutionControl instance based on a JDI LaunchingConnector.
-     */
-    public JDIExecutionControl() {
-        this.isLaunch = true;
-    }
-
-    /**
-     * Initializes the launching JDI execution engine. Initialize JDI and use it
-     * to launch the remote JVM. Set-up control and result communications socket
-     * to the remote execution environment. This socket also transports the
-     * input/output channels.
-     *
-     * @param execEnv the execution environment provided by the JShell-core
-     * @throws IOException
-     */
-    @Override
-    public void start(ExecutionEnv execEnv) throws IOException {
-        this.execEnv = execEnv;
-        StringBuilder sb = new StringBuilder();
-        try (ServerSocket listener = new ServerSocket(0)) {
-            // timeout after 60 seconds
-            listener.setSoTimeout(60000);
-            int port = listener.getLocalPort();
-            connection = new JDIConnection(this, port, execEnv.extraRemoteVMOptions(), isLaunch);
-            this.socket = listener.accept();
-            // out before in -- match remote creation so we don't hang
-            this.remoteOut = new ObjectOutputStream(socket.getOutputStream());
-            PipeInputStream commandIn = new PipeInputStream();
-            new DemultiplexInput(socket.getInputStream(), commandIn, execEnv.userOut(), execEnv.userErr()).start();
-            this.remoteIn = new ObjectInputStream(commandIn);
-        }
-    }
-
-    /**
-     * Closes the execution engine. Send an exit command to the remote agent.
-     * Shuts down the JDI connection. Should this close the socket?
-     */
-    @Override
-    public void close() {
-        try {
-            if (connection != null) {
-                connection.beginShutdown();
-            }
-            if (remoteOut != null) {
-                remoteOut.writeInt(CMD_EXIT);
-                remoteOut.flush();
-            }
-            if (connection != null) {
-                connection.disposeVM();
-            }
-        } catch (IOException ex) {
-            debug(DBG_GEN, "Exception on JDI exit: %s\n", ex);
-        }
-    }
-
-    /**
-     * Loads the list of classes specified. Sends a load command to the remote
-     * agent with pairs of classname/bytes.
-     *
-     * @param classes the names of the wrapper classes to loaded
-     * @return true if all classes loaded successfully
-     */
-    @Override
-    public boolean load(Collection<String> classes) {
-        try {
-            // Create corresponding ClassInfo instances to track the classes.
-            // Each ClassInfo has the current class bytes associated with it.
-            List<ClassInfo> infos = withBytes(classes);
-            // Send a load command to the remote agent.
-            remoteOut.writeInt(CMD_LOAD);
-            remoteOut.writeInt(classes.size());
-            for (ClassInfo ci : infos) {
-                remoteOut.writeUTF(ci.getClassName());
-                remoteOut.writeObject(ci.getBytes());
-            }
-            remoteOut.flush();
-            // Retrieve and report results from the remote agent.
-            boolean result = readAndReportResult();
-            // For each class that now has a JDI ReferenceType, mark the bytes
-            // as loaded.
-            infos.stream()
-                    .filter(ci -> ci.getReferenceTypeOrNull() != null)
-                    .forEach(ci -> ci.markLoaded());
-            return result;
-        } catch (IOException ex) {
-            debug(DBG_GEN, "IOException on remote load operation: %s\n", ex);
-            return false;
-        }
-    }
-
-    /**
-     * Invoke the doit method on the specified class.
-     *
-     * @param classname name of the wrapper class whose doit should be invoked
-     * @return return the result value of the doit
-     * @throws JShellException if a user exception was thrown (EvalException) or
-     * an unresolved reference was encountered (UnresolvedReferenceException)
-     */
-    @Override
-    public String invoke(String classname, String methodname) throws JShellException {
-        try {
-            synchronized (STOP_LOCK) {
-                userCodeRunning = true;
-            }
-            // Send the invoke command to the remote agent.
-            remoteOut.writeInt(CMD_INVOKE);
-            remoteOut.writeUTF(classname);
-            remoteOut.writeUTF(methodname);
-            remoteOut.flush();
-            // Retrieve and report results from the remote agent.
-            if (readAndReportExecutionResult()) {
-                String result = remoteIn.readUTF();
-                return result;
-            }
-        } catch (IOException | RuntimeException ex) {
-            if (!connection.isRunning()) {
-                // The JDI connection is no longer live, shutdown.
-                handleVMExit();
-            } else {
-                debug(DBG_GEN, "Exception on remote invoke: %s\n", ex);
-                return "Execution failure: " + ex.getMessage();
-            }
-        } finally {
-            synchronized (STOP_LOCK) {
-                userCodeRunning = false;
-            }
-        }
-        return "";
-    }
-
-    /**
-     * Retrieves the value of a JShell variable.
-     *
-     * @param classname name of the wrapper class holding the variable
-     * @param varname name of the variable
-     * @return the value as a String
-     */
-    @Override
-    public String varValue(String classname, String varname) {
-        try {
-            // Send the variable-value command to the remote agent.
-            remoteOut.writeInt(CMD_VARVALUE);
-            remoteOut.writeUTF(classname);
-            remoteOut.writeUTF(varname);
-            remoteOut.flush();
-            // Retrieve and report results from the remote agent.
-            if (readAndReportResult()) {
-                String result = remoteIn.readUTF();
-                return result;
-            }
-        } catch (EOFException ex) {
-            handleVMExit();
-        } catch (IOException ex) {
-            debug(DBG_GEN, "Exception on remote var value: %s\n", ex);
-            return "Execution failure: " + ex.getMessage();
-        }
-        return "";
-    }
-
-    /**
-     * Adds a path to the remote classpath.
-     *
-     * @param cp the additional path element
-     * @return true if succesful
-     */
-    @Override
-    public boolean addToClasspath(String cp) {
-        try {
-            // Send the classpath addition command to the remote agent.
-            remoteOut.writeInt(CMD_CLASSPATH);
-            remoteOut.writeUTF(cp);
-            remoteOut.flush();
-            // Retrieve and report results from the remote agent.
-            return readAndReportResult();
-        } catch (IOException ex) {
-            throw new InternalError("Classpath addition failed: " + cp, ex);
-        }
-    }
-
-    /**
-     * Redefine the specified classes. Where 'redefine' is, as in JDI and JVMTI,
-     * an in-place replacement of the classes (preserving class identity) --
-     * that is, existing references to the class do not need to be recompiled.
-     * This implementation uses JDI redefineClasses. It will be unsuccessful if
-     * the signature of the class has changed (see the JDI spec). The
-     * JShell-core is designed to adapt to unsuccessful redefine.
-     *
-     * @param classes the names of the classes to redefine
-     * @return true if all the classes were redefined
-     */
-    @Override
-    public boolean redefine(Collection<String> classes) {
-        try {
-            // Create corresponding ClassInfo instances to track the classes.
-            // Each ClassInfo has the current class bytes associated with it.
-            List<ClassInfo> infos = withBytes(classes);
-            // Convert to the JDI ReferenceType to class bytes map form needed
-            // by JDI.
-            Map<ReferenceType, byte[]> rmp = infos.stream()
-                    .collect(toMap(
-                            ci -> ci.getReferenceTypeOrNull(),
-                            ci -> ci.getBytes()));
-            // Attempt redefine.  Throws exceptions on failure.
-            connection.vm().redefineClasses(rmp);
-            // Successful: mark the bytes as loaded.
-            infos.stream()
-                    .forEach(ci -> ci.markLoaded());
-            return true;
-        } catch (UnsupportedOperationException ex) {
-            // A form of class transformation not supported by JDI
-            return false;
-        } catch (Exception ex) {
-            debug(DBG_GEN, "Exception on JDI redefine: %s\n", ex);
-            return false;
-        }
-    }
-
-    // the VM has gone down in flames or because user evaled System.exit() or the like
-    void handleVMExit() {
-        if (connection != null) {
-            // If there is anything left dispose of it
-            connection.disposeVM();
-        }
-        // Tell JShell-core that the VM has died
-        execEnv.closeDown();
-    }
-
-    // Lazy init class tracker
-    private ClassTracker classTracker() {
-        if (classTracker == null) {
-            classTracker = new ClassTracker(connection.vm());
-        }
-        return classTracker;
-    }
-
-    /**
-     * Converts a collection of class names into ClassInfo instances associated
-     * with the most recently compiled class bytes.
-     *
-     * @param classes names of the classes
-     * @return a list of corresponding ClassInfo instances
-     */
-    private List<ClassInfo> withBytes(Collection<String> classes) {
-        return classes.stream()
-                .map(cn -> classTracker().classInfo(cn, execEnv.getClassBytes(cn)))
-                .collect(toList());
-    }
-
-    /**
-     * Reports the status of the named class. UNKNOWN if not loaded. CURRENT if
-     * the most recent successfully loaded/redefined bytes match the current
-     * compiled bytes.
-     *
-     * @param classname the name of the class to test
-     * @return the status
-     */
-    @Override
-    public ClassStatus getClassStatus(String classname) {
-        ClassInfo ci = classTracker().get(classname);
-        if (ci.getReferenceTypeOrNull() == null) {
-            // If the class does not have a JDI ReferenceType it has not been loaded
-            return ClassStatus.UNKNOWN;
-        }
-        // Compare successfully loaded with last compiled bytes.
-        return (Arrays.equals(execEnv.getClassBytes(classname), ci.getLoadedBytes()))
-                ? ClassStatus.CURRENT
-                : ClassStatus.NOT_CURRENT;
-    }
-
-    /**
-     * Reports results from a remote agent command that does not expect
-     * exceptions.
-     *
-     * @return true if successful
-     * @throws IOException if the connection has dropped
-     */
-    private boolean readAndReportResult() throws IOException {
-        int ok = remoteIn.readInt();
-        switch (ok) {
-            case RESULT_SUCCESS:
-                return true;
-            case RESULT_FAIL: {
-                String ex = remoteIn.readUTF();
-                debug(DBG_GEN, "Exception on remote operation: %s\n", ex);
-                return false;
-            }
-            default: {
-                debug(DBG_GEN, "Bad remote result code: %s\n", ok);
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Reports results from a remote agent command that expects runtime
-     * exceptions.
-     *
-     * @return true if successful
-     * @throws IOException if the connection has dropped
-     * @throws EvalException if a user exception was encountered on invoke
-     * @throws UnresolvedReferenceException if an unresolved reference was
-     * encountered
-     */
-    private boolean readAndReportExecutionResult() throws IOException, JShellException {
-        int ok = remoteIn.readInt();
-        switch (ok) {
-            case RESULT_SUCCESS:
-                return true;
-            case RESULT_FAIL: {
-                // An internal error has occurred.
-                String ex = remoteIn.readUTF();
-                return false;
-            }
-            case RESULT_EXCEPTION: {
-                // A user exception was encountered.
-                String exceptionClassName = remoteIn.readUTF();
-                String message = remoteIn.readUTF();
-                StackTraceElement[] elems = readStackTrace();
-                throw execEnv.createEvalException(message, exceptionClassName, elems);
-            }
-            case RESULT_CORRALLED: {
-                // An unresolved reference was encountered.
-                int id = remoteIn.readInt();
-                StackTraceElement[] elems = readStackTrace();
-                throw execEnv.createUnresolvedReferenceException(id, elems);
-            }
-            case RESULT_KILLED: {
-                // Execution was aborted by the stop()
-                debug(DBG_GEN, "Killed.");
-                return false;
-            }
-            default: {
-                debug(DBG_GEN, "Bad remote result code: %s\n", ok);
-                return false;
-            }
-        }
-    }
-
-    private StackTraceElement[] readStackTrace() throws IOException {
-        int elemCount = remoteIn.readInt();
-        StackTraceElement[] elems = new StackTraceElement[elemCount];
-        for (int i = 0; i < elemCount; ++i) {
-            String className = remoteIn.readUTF();
-            String methodName = remoteIn.readUTF();
-            String fileName = remoteIn.readUTF();
-            int line = remoteIn.readInt();
-            elems[i] = new StackTraceElement(className, methodName, fileName, line);
-        }
-        return elems;
-    }
-
-    private final Object STOP_LOCK = new Object();
-    private boolean userCodeRunning = false;
-
-    /**
-     * Interrupt a running invoke.
-     */
-    @Override
-    public void stop() {
-        synchronized (STOP_LOCK) {
-            if (!userCodeRunning) {
-                return;
-            }
-
-            VirtualMachine vm = connection.vm();
-            vm.suspend();
-            try {
-                OUTER:
-                for (ThreadReference thread : vm.allThreads()) {
-                    // could also tag the thread (e.g. using name), to find it easier
-                    for (StackFrame frame : thread.frames()) {
-                        String remoteAgentName = "jdk.internal.jshell.remote.RemoteAgent";
-                        if (remoteAgentName.equals(frame.location().declaringType().name())
-                                && "commandLoop".equals(frame.location().method().name())) {
-                            ObjectReference thiz = frame.thisObject();
-                            if (((BooleanValue) thiz.getValue(thiz.referenceType().fieldByName("inClientCode"))).value()) {
-                                thiz.setValue(thiz.referenceType().fieldByName("expectingStop"), vm.mirrorOf(true));
-                                ObjectReference stopInstance = (ObjectReference) thiz.getValue(thiz.referenceType().fieldByName("stopException"));
-
-                                vm.resume();
-                                debug(DBG_GEN, "Attempting to stop the client code...\n");
-                                thread.stop(stopInstance);
-                                thiz.setValue(thiz.referenceType().fieldByName("expectingStop"), vm.mirrorOf(false));
-                            }
-
-                            break OUTER;
-                        }
-                    }
-                }
-            } catch (ClassNotLoadedException | IncompatibleThreadStateException | InvalidTypeException ex) {
-                debug(DBG_GEN, "Exception on remote stop: %s\n", ex);
-            } finally {
-                vm.resume();
-            }
-        }
-    }
-
-    void debug(int flags, String format, Object... args) {
-        InternalDebugControl.debug(execEnv.state(), execEnv.userErr(), flags, format, args);
-    }
-
-    void debug(Exception ex, String where) {
-        InternalDebugControl.debug(execEnv.state(), execEnv.userErr(), ex, where);
-    }
-
-    private final class DemultiplexInput extends Thread {
-
-        private final DataInputStream delegate;
-        private final PipeInputStream command;
-        private final PrintStream out;
-        private final PrintStream err;
-
-        public DemultiplexInput(InputStream input,
-                PipeInputStream command,
-                PrintStream out,
-                PrintStream err) {
-            super("output reader");
-            this.delegate = new DataInputStream(input);
-            this.command = command;
-            this.out = out;
-            this.err = err;
-        }
-
-        public void run() {
-            try {
-                while (true) {
-                    int nameLen = delegate.read();
-                    if (nameLen == (-1))
-                        break;
-                    byte[] name = new byte[nameLen];
-                    DemultiplexInput.this.delegate.readFully(name);
-                    int dataLen = delegate.read();
-                    byte[] data = new byte[dataLen];
-                    DemultiplexInput.this.delegate.readFully(data);
-                    switch (new String(name, "UTF-8")) {
-                        case "err":
-                            err.write(data);
-                            break;
-                        case "out":
-                            out.write(data);
-                            break;
-                        case "command":
-                            for (byte b : data) {
-                                command.write(Byte.toUnsignedInt(b));
-                            }
-                            break;
-                    }
-                }
-            } catch (IOException ex) {
-                debug(ex, "Failed reading output");
-            } finally {
-                command.close();
-            }
-        }
-
-    }
-
-    public static final class PipeInputStream extends InputStream {
-        public static final int INITIAL_SIZE = 128;
-
-        private int[] buffer = new int[INITIAL_SIZE];
-        private int start;
-        private int end;
-        private boolean closed;
-
-        @Override
-        public synchronized int read() {
-            while (start == end) {
-                if (closed) {
-                    return -1;
-                }
-                try {
-                    wait();
-                } catch (InterruptedException ex) {
-                    //ignore
-                }
-            }
-            try {
-                return buffer[start];
-            } finally {
-                start = (start + 1) % buffer.length;
-            }
-        }
-
-        public synchronized void write(int b) {
-            if (closed)
-                throw new IllegalStateException("Already closed.");
-            int newEnd = (end + 1) % buffer.length;
-            if (newEnd == start) {
-                //overflow:
-                int[] newBuffer = new int[buffer.length * 2];
-                int rightPart = (end > start ? end : buffer.length) - start;
-                int leftPart = end > start ? 0 : start - 1;
-                System.arraycopy(buffer, start, newBuffer, 0, rightPart);
-                System.arraycopy(buffer, 0, newBuffer, rightPart, leftPart);
-                buffer = newBuffer;
-                start = 0;
-                end = rightPart + leftPart;
-                newEnd = end + 1;
-            }
-            buffer[end] = b;
-            end = newEnd;
-            notifyAll();
-        }
-
-        @Override
-        public synchronized void close() {
-            closed = true;
-            notifyAll();
-        }
-
-    }
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/jdi/JDINotConnectedException.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.jshell.jdi;
-
-/**
- * Internal exception when Java Debug Interface VirtualMacine is not connected.
- * Copy of jdb VMNotConnectedException.
- */
-class JDINotConnectedException extends RuntimeException {
-
-    private static final long serialVersionUID = -7433430494903950165L;
-
-    public JDINotConnectedException() {
-        super();
-    }
-
-    public JDINotConnectedException(String s) {
-        super(s);
-    }
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,326 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.jshell.remote;
-import jdk.jshell.spi.SPIResolutionException;
-import java.io.File;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.Socket;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static jdk.internal.jshell.remote.RemoteCodes.*;
-
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * The remote agent runs in the execution process (separate from the main JShell
- * process.  This agent loads code over a socket from the main JShell process,
- * executes the code, and other misc,
- * @author Robert Field
- */
-class RemoteAgent {
-
-    private final RemoteClassLoader loader = new RemoteClassLoader();
-    private final Map<String, Class<?>> klasses = new TreeMap<>();
-
-    public static void main(String[] args) throws Exception {
-        String loopBack = null;
-        Socket socket = new Socket(loopBack, Integer.parseInt(args[0]));
-        (new RemoteAgent()).commandLoop(socket);
-    }
-
-    void commandLoop(Socket socket) throws IOException {
-        // in before out -- so we don't hang the controlling process
-        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
-        OutputStream socketOut = socket.getOutputStream();
-        System.setOut(new PrintStream(new MultiplexingOutputStream("out", socketOut), true));
-        System.setErr(new PrintStream(new MultiplexingOutputStream("err", socketOut), true));
-        ObjectOutputStream out = new ObjectOutputStream(new MultiplexingOutputStream("command", socketOut));
-        while (true) {
-            int cmd = in.readInt();
-            switch (cmd) {
-                case CMD_EXIT:
-                    // Terminate this process
-                    return;
-                case CMD_LOAD:
-                    // Load a generated class file over the wire
-                    try {
-                        int count = in.readInt();
-                        List<String> names = new ArrayList<>(count);
-                        for (int i = 0; i < count; ++i) {
-                            String name = in.readUTF();
-                            byte[] kb = (byte[]) in.readObject();
-                            loader.delare(name, kb);
-                            names.add(name);
-                        }
-                        for (String name : names) {
-                            Class<?> klass = loader.loadClass(name);
-                            klasses.put(name, klass);
-                            // Get class loaded to the point of, at least, preparation
-                            klass.getDeclaredMethods();
-                        }
-                        out.writeInt(RESULT_SUCCESS);
-                        out.flush();
-                    } catch (IOException | ClassNotFoundException | ClassCastException ex) {
-                        debug("*** Load failure: %s\n", ex);
-                        out.writeInt(RESULT_FAIL);
-                        out.writeUTF(ex.toString());
-                        out.flush();
-                    }
-                    break;
-                case CMD_INVOKE: {
-                    // Invoke executable entry point in loaded code
-                    String name = in.readUTF();
-                    Class<?> klass = klasses.get(name);
-                    if (klass == null) {
-                        debug("*** Invoke failure: no such class loaded %s\n", name);
-                        out.writeInt(RESULT_FAIL);
-                        out.writeUTF("no such class loaded: " + name);
-                        out.flush();
-                        break;
-                    }
-                    String methodName = in.readUTF();
-                    Method doitMethod;
-                    try {
-                        this.getClass().getModule().addExports(SPIResolutionException.class.getPackage().getName(), klass.getModule());
-                        doitMethod = klass.getDeclaredMethod(methodName, new Class<?>[0]);
-                        doitMethod.setAccessible(true);
-                        Object res;
-                        try {
-                            clientCodeEnter();
-                            res = doitMethod.invoke(null, new Object[0]);
-                        } catch (InvocationTargetException ex) {
-                            if (ex.getCause() instanceof StopExecutionException) {
-                                expectingStop = false;
-                                throw (StopExecutionException) ex.getCause();
-                            }
-                            throw ex;
-                        } catch (StopExecutionException ex) {
-                            expectingStop = false;
-                            throw ex;
-                        } finally {
-                            clientCodeLeave();
-                        }
-                        out.writeInt(RESULT_SUCCESS);
-                        out.writeUTF(valueString(res));
-                        out.flush();
-                    } catch (InvocationTargetException ex) {
-                        Throwable cause = ex.getCause();
-                        StackTraceElement[] elems = cause.getStackTrace();
-                        if (cause instanceof SPIResolutionException) {
-                            out.writeInt(RESULT_CORRALLED);
-                            out.writeInt(((SPIResolutionException) cause).id());
-                        } else {
-                            out.writeInt(RESULT_EXCEPTION);
-                            out.writeUTF(cause.getClass().getName());
-                            out.writeUTF(cause.getMessage() == null ? "<none>" : cause.getMessage());
-                        }
-                        out.writeInt(elems.length);
-                        for (StackTraceElement ste : elems) {
-                            out.writeUTF(ste.getClassName());
-                            out.writeUTF(ste.getMethodName());
-                            out.writeUTF(ste.getFileName() == null ? "<none>" : ste.getFileName());
-                            out.writeInt(ste.getLineNumber());
-                        }
-                        out.flush();
-                    } catch (NoSuchMethodException | IllegalAccessException ex) {
-                        debug("*** Invoke failure: %s -- %s\n", ex, ex.getCause());
-                        out.writeInt(RESULT_FAIL);
-                        out.writeUTF(ex.toString());
-                        out.flush();
-                    } catch (StopExecutionException ex) {
-                        try {
-                            out.writeInt(RESULT_KILLED);
-                            out.flush();
-                        } catch (IOException err) {
-                            debug("*** Error writing killed result: %s -- %s\n", ex, ex.getCause());
-                        }
-                    }
-                    System.out.flush();
-                    break;
-                }
-                case CMD_VARVALUE: {
-                    // Retrieve a variable value
-                    String classname = in.readUTF();
-                    String varname = in.readUTF();
-                    Class<?> klass = klasses.get(classname);
-                    if (klass == null) {
-                        debug("*** Var value failure: no such class loaded %s\n", classname);
-                        out.writeInt(RESULT_FAIL);
-                        out.writeUTF("no such class loaded: " + classname);
-                        out.flush();
-                        break;
-                    }
-                    try {
-                        Field var = klass.getDeclaredField(varname);
-                        var.setAccessible(true);
-                        Object res = var.get(null);
-                        out.writeInt(RESULT_SUCCESS);
-                        out.writeUTF(valueString(res));
-                        out.flush();
-                    } catch (Exception ex) {
-                        debug("*** Var value failure: no such field %s.%s\n", classname, varname);
-                        out.writeInt(RESULT_FAIL);
-                        out.writeUTF("no such field loaded: " + varname + " in class: " + classname);
-                        out.flush();
-                    }
-                    break;
-                }
-                case CMD_CLASSPATH: {
-                    // Append to the claspath
-                    String cp = in.readUTF();
-                    for (String path : cp.split(File.pathSeparator)) {
-                        loader.addURL(new File(path).toURI().toURL());
-                    }
-                    out.writeInt(RESULT_SUCCESS);
-                    out.flush();
-                    break;
-                }
-                default:
-                    debug("*** Bad command code: %d\n", cmd);
-                    break;
-            }
-        }
-    }
-
-    // These three variables are used by the main JShell process in interrupting
-    // the running process.  Access is via JDI, so the reference is not visible
-    // to code inspection.
-    private boolean inClientCode; // Queried by the main process
-    private boolean expectingStop; // Set by the main process
-
-    // thrown by the main process via JDI:
-    private final StopExecutionException stopException = new StopExecutionException();
-
-    @SuppressWarnings("serial")             // serialVersionUID intentionally omitted
-    private class StopExecutionException extends ThreadDeath {
-        @Override public synchronized Throwable fillInStackTrace() {
-            return this;
-        }
-    }
-
-    void clientCodeEnter() {
-        expectingStop = false;
-        inClientCode = true;
-    }
-
-    void clientCodeLeave() {
-        inClientCode = false;
-        while (expectingStop) {
-            try {
-                Thread.sleep(0);
-            } catch (InterruptedException ex) {
-                debug("*** Sleep interrupted while waiting for stop exception: %s\n", ex);
-            }
-        }
-    }
-
-    private void debug(String format, Object... args) {
-        System.err.printf("REMOTE: "+format, args);
-    }
-
-    static String valueString(Object value) {
-        if (value == null) {
-            return "null";
-        } else if (value instanceof String) {
-            return "\"" + (String)value + "\"";
-        } else if (value instanceof Character) {
-            return "'" + value + "'";
-        } else {
-            return value.toString();
-        }
-    }
-
-    private static final class MultiplexingOutputStream extends OutputStream {
-
-        private static final int PACKET_SIZE = 127;
-
-        private final byte[] name;
-        private final OutputStream delegate;
-
-        public MultiplexingOutputStream(String name, OutputStream delegate) {
-            try {
-                this.name = name.getBytes("UTF-8");
-                this.delegate = delegate;
-            } catch (UnsupportedEncodingException ex) {
-                throw new IllegalStateException(ex); //should not happen
-            }
-        }
-
-        @Override
-        public void write(int b) throws IOException {
-            synchronized (delegate) {
-                delegate.write(name.length); //assuming the len is small enough to fit into byte
-                delegate.write(name);
-                delegate.write(1);
-                delegate.write(b);
-                delegate.flush();
-            }
-        }
-
-        @Override
-        public void write(byte[] b, int off, int len) throws IOException {
-            synchronized (delegate) {
-                int i = 0;
-                while (len > 0) {
-                    int size = Math.min(PACKET_SIZE, len);
-
-                    delegate.write(name.length); //assuming the len is small enough to fit into byte
-                    delegate.write(name);
-                    delegate.write(size);
-                    delegate.write(b, off + i, size);
-                    i += size;
-                    len -= size;
-                }
-
-                delegate.flush();
-            }
-        }
-
-        @Override
-        public void flush() throws IOException {
-            super.flush();
-            delegate.flush();
-        }
-
-        @Override
-        public void close() throws IOException {
-            super.close();
-            delegate.close();
-        }
-
-    }
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteClassLoader.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.jshell.remote;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.CodeSource;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * Class loader wrapper which caches class files by name until requested.
- * @author Robert Field
- */
-class RemoteClassLoader extends URLClassLoader {
-
-    private final Map<String, byte[]> classObjects = new TreeMap<>();
-
-    RemoteClassLoader() {
-        super(new URL[0]);
-    }
-
-    void delare(String name, byte[] bytes) {
-        classObjects.put(name, bytes);
-    }
-
-    @Override
-    protected Class<?> findClass(String name) throws ClassNotFoundException {
-        byte[] b = classObjects.get(name);
-        if (b == null) {
-            return super.findClass(name);
-        }
-        return super.defineClass(name, b, 0, b.length, (CodeSource) null);
-    }
-
-    @Override
-    public void addURL(URL url) {
-        super.addURL(url);
-    }
-
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.jshell.remote;
-
-/**
- * Communication constants shared between the main process and the remote
- * execution process
- * @author Robert Field
- */
-public class RemoteCodes {
-    // Command codes
-    public static final int CMD_EXIT       = 0;
-    public static final int CMD_LOAD       = 1;
-    public static final int CMD_INVOKE     = 3;
-    public static final int CMD_CLASSPATH  = 4;
-    public static final int CMD_VARVALUE   = 5;
-
-    // Return result codes
-    public static final int RESULT_SUCCESS   = 100;
-    public static final int RESULT_FAIL      = 101;
-    public static final int RESULT_EXCEPTION = 102;
-    public static final int RESULT_CORRALLED = 103;
-    public static final int RESULT_KILLED    = 104;
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Wed Jul 27 13:33:55 2016 +0000
@@ -233,6 +233,7 @@
     private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB
     private static final String[] SHORTCUT_FIXES = {
         "\033\015", //Alt-Enter (Linux)
+        "\033\012", //Alt-Enter (Linux)
         "\033\133\061\067\176", //F6/Alt-F1 (Mac)
         "\u001BO3P" //Alt-F1 (Linux)
     };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Objects;
+import jdk.jshell.spi.ExecutionControl.ClassBytecodes;
+
+/**
+ * Tracks the state of a class.
+ */
+class ClassTracker {
+
+    private final HashMap<String, ClassInfo> map;
+
+    ClassTracker() {
+        this.map = new HashMap<>();
+    }
+
+    /**
+     * Associates a class name, class bytes (current and loaded).
+     */
+    class ClassInfo {
+
+        // The name of the class
+        private final String className;
+
+        // The corresponding compiled class bytes when a load or redefine
+        // is started.  May not be the loaded bytes.  May be null.
+        private byte[] currentBytes;
+
+        // The class bytes successfully loaded/redefined into the remote VM.
+        private byte[] loadedBytes;
+
+        private ClassInfo(String className) {
+            this.className = className;
+        }
+
+        String getClassName() {
+            return className;
+        }
+
+        byte[] getLoadedBytes() {
+            return loadedBytes;
+        }
+
+        byte[] getCurrentBytes() {
+            return currentBytes;
+        }
+
+        void setCurrentBytes(byte[] bytes) {
+            this.currentBytes = bytes;
+        }
+
+        void setLoadedBytes(byte[] bytes) {
+            this.loadedBytes = bytes;
+        }
+
+        boolean isLoaded() {
+            return loadedBytes != null;
+        }
+
+        boolean isCurrent() {
+            return Arrays.equals(currentBytes, loadedBytes);
+        }
+
+        ClassBytecodes toClassBytecodes() {
+            return new ClassBytecodes(className, currentBytes);
+        }
+
+            @Override
+        public boolean equals(Object o) {
+            return o instanceof ClassInfo
+                    && ((ClassInfo) o).className.equals(className);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hashCode(this.className);
+        }
+    }
+
+    void markLoaded(ClassBytecodes[] cbcs) {
+        for (ClassBytecodes cbc : cbcs) {
+            get(cbc.name()).setLoadedBytes(cbc.bytecodes());
+        }
+    }
+
+    void markLoaded(ClassBytecodes[] cbcs, boolean[] isLoaded) {
+        for (int i = 0; i < cbcs.length; ++i) {
+            if (isLoaded[i]) {
+                ClassBytecodes cbc = cbcs[i];
+                get(cbc.name()).setLoadedBytes(cbc.bytecodes());
+            }
+        }
+    }
+
+    // Map a class name to the current compiled class bytes.
+    void setCurrentBytes(String className, byte[] bytes) {
+        ClassInfo ci = get(className);
+        ci.setCurrentBytes(bytes);
+    }
+
+    // Lookup the ClassInfo by class name, create if it does not exist.
+    ClassInfo get(String className) {
+        return map.computeIfAbsent(className, k -> new ClassInfo(k));
+    }
+}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java	Wed Jul 27 13:33:55 2016 +0000
@@ -61,6 +61,14 @@
 import jdk.jshell.TreeDissector.ExpressionInfo;
 import jdk.jshell.Wrap.Range;
 import jdk.jshell.Snippet.Status;
+import jdk.jshell.spi.ExecutionControl.ClassBytecodes;
+import jdk.jshell.spi.ExecutionControl.ClassInstallException;
+import jdk.jshell.spi.ExecutionControl.EngineTerminationException;
+import jdk.jshell.spi.ExecutionControl.InternalException;
+import jdk.jshell.spi.ExecutionControl.NotImplementedException;
+import jdk.jshell.spi.ExecutionControl.ResolutionException;
+import jdk.jshell.spi.ExecutionControl.RunException;
+import jdk.jshell.spi.ExecutionControl.UserException;
 import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toSet;
 import static java.util.Collections.singletonList;
@@ -541,15 +549,21 @@
         if (si.status().isDefined()) {
             if (si.isExecutable()) {
                 try {
-                value = state.executionControl().invoke(si.classFullName(), DOIT_METHOD_NAME);
+                    value = state.executionControl().invoke(si.classFullName(), DOIT_METHOD_NAME);
                     value = si.subKind().hasValue()
                             ? expunge(value)
                             : "";
-                } catch (EvalException ex) {
+                } catch (ResolutionException ex) {
+                    DeclarationSnippet sn = (DeclarationSnippet) state.maps.getSnippetDeadOrAlive(ex.id());
+                    exception = new UnresolvedReferenceException(sn, ex.getStackTrace());
+                } catch (UserException ex) {
                     exception = translateExecutionException(ex);
-                } catch (JShellException ex) {
-                    // UnresolvedReferenceException
-                    exception = ex;
+                } catch (RunException ex) {
+                    // StopException - no-op
+                } catch (InternalException ex) {
+                    state.debug(ex, "invoke");
+                } catch (EngineTerminationException ex) {
+                    state.closeDown();
                 }
             } else if (si.subKind() == SubKind.VAR_DECLARATION_SUBKIND) {
                 switch (((VarSnippet) si).typeName()) {
@@ -700,15 +714,25 @@
 
     /**
      * If there are classes to load, loads by calling the execution engine.
-     * @param classnames names of the classes to load.
+     * @param classbytecoes names of the classes to load.
      */
-    private void load(Collection<String> classnames) {
-        if (!classnames.isEmpty()) {
-            state.executionControl().load(classnames);
+    private void load(Collection<ClassBytecodes> classbytecoes) {
+        if (!classbytecoes.isEmpty()) {
+            ClassBytecodes[] cbcs = classbytecoes.toArray(new ClassBytecodes[classbytecoes.size()]);
+            try {
+                state.executionControl().load(cbcs);
+                state.classTracker.markLoaded(cbcs);
+            } catch (ClassInstallException ex) {
+                state.classTracker.markLoaded(cbcs, ex.installed());
+            } catch (NotImplementedException ex) {
+                state.debug(ex, "Seriously?!? load not implemented");
+            } catch (EngineTerminationException ex) {
+                state.closeDown();
+            }
         }
     }
 
-    private EvalException translateExecutionException(EvalException ex) {
+    private EvalException translateExecutionException(UserException ex) {
         StackTraceElement[] raw = ex.getStackTrace();
         int last = raw.length;
         do {
@@ -739,7 +763,7 @@
         if (msg.equals("<none>")) {
             msg = null;
         }
-        return new EvalException(msg, ex.getExceptionClassName(), elems);
+        return new EvalException(msg, ex.causeExceptionClass(), elems);
     }
 
     private boolean isWrap(StackTraceElement ste) {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java	Wed Jul 27 13:33:55 2016 +0000
@@ -44,13 +44,15 @@
 
 import java.util.function.Supplier;
 import jdk.internal.jshell.debug.InternalDebugControl;
-import jdk.internal.jshell.jdi.FailOverExecutionControl;
+import jdk.jshell.Snippet.Status;
+import jdk.jshell.execution.JDIDefaultExecutionControl;
+import jdk.jshell.spi.ExecutionControl.EngineTerminationException;
+import jdk.jshell.spi.ExecutionControl.ExecutionControlException;
+import jdk.jshell.spi.ExecutionEnv;
+import static jdk.jshell.execution.Util.failOverExecutionControlGenerator;
 import static java.util.stream.Collectors.collectingAndThen;
 import static java.util.stream.Collectors.toList;
 import static jdk.jshell.Util.expunge;
-import jdk.jshell.Snippet.Status;
-import jdk.internal.jshell.jdi.JDIExecutionControl;
-import jdk.jshell.spi.ExecutionEnv;
 
 /**
  * The JShell evaluation state engine.  This is the central class in the JShell
@@ -90,17 +92,17 @@
     final BiFunction<Snippet, Integer, String> idGenerator;
     final List<String> extraRemoteVMOptions;
     final List<String> extraCompilerOptions;
-    final ExecutionControl executionControl;
+    final ExecutionControl.Generator executionControlGenerator;
 
     private int nextKeyIndex = 1;
 
     final Eval eval;
-    private final Map<String, byte[]> classnameToBytes = new HashMap<>();
+    final ClassTracker classTracker;
     private final Map<Subscription, Consumer<JShell>> shutdownListeners = new HashMap<>();
     private final Map<Subscription, Consumer<SnippetEvent>> keyStatusListeners = new HashMap<>();
     private boolean closed = false;
 
-    private boolean executionControlLaunched = false;
+    private ExecutionControl executionControl = null;
     private SourceCodeAnalysisImpl sourceCodeAnalysis = null;
 
     private static final String L10N_RB_NAME    = "jdk.jshell.resources.l10n";
@@ -114,17 +116,18 @@
         this.idGenerator = b.idGenerator;
         this.extraRemoteVMOptions = b.extraRemoteVMOptions;
         this.extraCompilerOptions = b.extraCompilerOptions;
-        this.executionControl = b.executionControl==null
-                ? new FailOverExecutionControl(
-                        new JDIExecutionControl(),
-                        new JDIExecutionControl(false))
-                : b.executionControl;
+        this.executionControlGenerator = b.executionControlGenerator==null
+                ? failOverExecutionControlGenerator(
+                        JDIDefaultExecutionControl.launch(),
+                        JDIDefaultExecutionControl.listen())
+                : b.executionControlGenerator;
 
         this.maps = new SnippetMaps(this);
         this.keyMap = new KeyMap(this);
         this.outerMap = new OuterWrapMap(this);
         this.taskFactory = new TaskFactory(this);
         this.eval = new Eval(this);
+        this.classTracker = new ClassTracker();
     }
 
     /**
@@ -154,7 +157,7 @@
         BiFunction<Snippet, Integer, String> idGenerator = null;
         List<String> extraRemoteVMOptions = new ArrayList<>();
         List<String> extraCompilerOptions = new ArrayList<>();
-        ExecutionControl executionControl;
+        ExecutionControl.Generator executionControlGenerator;
 
         Builder() { }
 
@@ -310,12 +313,12 @@
          * Sets the custom engine for execution. Snippet execution will be
          * provided by the specified {@link ExecutionControl} instance.
          *
-         * @param execEngine the execution engine
+         * @param executionControlGenerator the execution engine generator
          * @return the {@code Builder} instance (for use in chained
          * initialization)
          */
-        public Builder executionEngine(ExecutionControl execEngine) {
-            this.executionControl = execEngine;
+        public Builder executionEngine(ExecutionControl.Generator executionControlGenerator) {
+            this.executionControlGenerator = executionControlGenerator;
             return this;
         }
 
@@ -397,7 +400,8 @@
      * be an event showing its status changed to OVERWRITTEN, this will not
      * occur for dropped, rejected, or already overwritten declarations.
      * <p>
-     * The execution environment is out of process.  If the evaluated code
+     * If execution environment is out of process, as is the default case, then
+     * if the evaluated code
      * causes the execution environment to terminate, this {@code JShell}
      * instance will be closed but the calling process and VM remain valid.
      * @param input The input String to evaluate
@@ -447,8 +451,14 @@
      * @param path the path to add to the classpath.
      */
     public void addToClasspath(String path) {
-        taskFactory.addToClasspath(path);  // Compiler
-        executionControl().addToClasspath(path);       // Runtime
+        // Compiler
+        taskFactory.addToClasspath(path);
+        // Runtime
+        try {
+            executionControl().addToClasspath(path);
+        } catch (ExecutionControlException ex) {
+            debug(ex, "on addToClasspath(" + path + ")");
+        }
         if (sourceCodeAnalysis != null) {
             sourceCodeAnalysis.classpathChanged();
         }
@@ -468,8 +478,13 @@
      * catching the {@link ThreadDeath} exception.
      */
     public void stop() {
-        if (executionControl != null)
-            executionControl.stop();
+        if (executionControl != null) {
+            try {
+                executionControl.stop();
+            } catch (ExecutionControlException ex) {
+                debug(ex, "on stop()");
+            }
+        }
     }
 
     /**
@@ -622,7 +637,15 @@
             throw new IllegalArgumentException(
                     messageFormat("jshell.exc.var.not.valid",  snippet, snippet.status()));
         }
-        String value = executionControl().varValue(snippet.classFullName(), snippet.name());
+        String value;
+        try {
+            value = executionControl().varValue(snippet.classFullName(), snippet.name());
+        } catch (EngineTerminationException ex) {
+            throw new IllegalStateException(ex.getMessage());
+        } catch (ExecutionControlException ex) {
+            debug(ex, "In varValue()");
+            return "[" + ex.getMessage() + "]";
+        }
         return expunge(value);
     }
 
@@ -696,43 +719,22 @@
         }
 
         @Override
-        public JShell state() {
-            return JShell.this;
-        }
-
-        @Override
         public List<String> extraRemoteVMOptions() {
             return extraRemoteVMOptions;
         }
 
         @Override
-        public byte[] getClassBytes(String classname) {
-            return classnameToBytes.get(classname);
-        }
-
-        @Override
-        public EvalException createEvalException(String message, String exceptionClass, StackTraceElement[] stackElements) {
-            return new EvalException(message, exceptionClass, stackElements);
-        }
-
-        @Override
-        public UnresolvedReferenceException createUnresolvedReferenceException(int id, StackTraceElement[] stackElements) {
-            DeclarationSnippet sn = (DeclarationSnippet) maps.getSnippetDeadOrAlive(id);
-            return new UnresolvedReferenceException(sn, stackElements);
-        }
-
-        @Override
         public void closeDown() {
             JShell.this.closeDown();
         }
+
     }
 
     // --- private / package-private implementation support ---
     ExecutionControl executionControl() {
-        if (!executionControlLaunched) {
+        if (executionControl == null) {
             try {
-                executionControlLaunched = true;
-                executionControl.start(new ExecutionEnvImpl());
+                executionControl =  executionControlGenerator.generate(new ExecutionEnvImpl());
             } catch (Throwable ex) {
                 throw new InternalError("Launching execution engine threw: " + ex.getMessage(), ex);
             }
@@ -740,10 +742,6 @@
         return executionControl;
     }
 
-    void setClassnameToBytes(String classname, byte[] bytes) {
-        classnameToBytes.put(classname, bytes);
-    }
-
     void debug(int flags, String format, Object... args) {
         InternalDebugControl.debug(this, err, flags, format, args);
     }
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java	Wed Jul 27 13:33:55 2016 +0000
@@ -82,7 +82,7 @@
             throw new UnsupportedOperationException("Compiler not available, must be run with full JDK 9.");
         }
         Version current = Version.parse(System.getProperty("java.specification.version"));
-        if (INITIAL_SUPPORTED_VER.compareToIgnoreOpt(current) > 0)  {
+        if (INITIAL_SUPPORTED_VER.compareToIgnoreOptional(current) > 0)  {
             throw new UnsupportedOperationException("Wrong compiler, must be run with full JDK 9.");
         }
         this.fileManager = new MemoryFileManager(
@@ -223,7 +223,6 @@
                     new WrapSourceHandler(),
                     Util.join(new String[] {
                         "-Xshouldstop:at=FLOW", "-Xlint:unchecked",
-                        "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED",
                         "-proc:none"
                     }, extraArgs));
         }
@@ -267,7 +266,7 @@
 
         CompileTask(final Collection<OuterWrap> wraps) {
             super(wraps.stream(), new WrapSourceHandler(),
-                    "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none", "-parameters");
+                    "-Xlint:unchecked", "-proc:none", "-parameters");
         }
 
         boolean compile() {
@@ -286,7 +285,7 @@
             }
             List<String> list = new ArrayList<>();
             for (OutputMemoryJavaFileObject fo : l) {
-                state.setClassnameToBytes(fo.getName(), fo.getBytes());
+                state.classTracker.setCurrentBytes(fo.getName(), fo.getBytes());
                 list.add(fo.getName());
             }
             return list;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java	Wed Jul 27 13:33:55 2016 +0000
@@ -32,11 +32,16 @@
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Stream;
+import jdk.jshell.ClassTracker.ClassInfo;
 import jdk.jshell.Snippet.Kind;
 import jdk.jshell.Snippet.Status;
 import jdk.jshell.Snippet.SubKind;
 import jdk.jshell.TaskFactory.AnalyzeTask;
 import jdk.jshell.TaskFactory.CompileTask;
+import jdk.jshell.spi.ExecutionControl.ClassBytecodes;
+import jdk.jshell.spi.ExecutionControl.ClassInstallException;
+import jdk.jshell.spi.ExecutionControl.EngineTerminationException;
+import jdk.jshell.spi.ExecutionControl.NotImplementedException;
 import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toSet;
 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_EVNT;
@@ -75,7 +80,7 @@
     private SnippetEvent replaceOldEvent;
     private List<SnippetEvent> secondaryEvents;
     private boolean isAttemptingCorral;
-    private List<String> toRedefine;
+    private List<ClassInfo> toRedefine;
     private boolean dependenciesNeeded;
 
     Unit(JShell state, Snippet si, Snippet causalSnippet,
@@ -261,30 +266,29 @@
     }
 
     /**
-     * Process the class information from the last compile.
-     * Requires loading of returned list.
+     * Process the class information from the last compile. Requires loading of
+     * returned list.
+     *
      * @return the list of classes to load
      */
-    Stream<String> classesToLoad(List<String> classnames) {
+    Stream<ClassBytecodes> classesToLoad(List<String> classnames) {
         toRedefine = new ArrayList<>();
-        List<String> toLoad = new ArrayList<>();
+        List<ClassBytecodes> toLoad = new ArrayList<>();
         if (status.isDefined() && !isImport()) {
             // Classes should only be loaded/redefined if the compile left them
             // in a defined state.  Imports do not have code and are not loaded.
             for (String cn : classnames) {
-                switch (state.executionControl().getClassStatus(cn)) {
-                    case UNKNOWN:
-                        // If not loaded, add to the list of classes to load.
-                        toLoad.add(cn);
-                        dependenciesNeeded = true;
-                        break;
-                    case NOT_CURRENT:
-                        // If loaded but out of date, add to the list of classes to attempt redefine.
-                        toRedefine.add(cn);
-                        break;
-                    case CURRENT:
-                        // Loaded and current, so nothing to do
-                        break;
+                ClassInfo ci = state.classTracker.get(cn);
+                if (ci.isLoaded()) {
+                    if (ci.isCurrent()) {
+                        // nothing to do
+                    } else {
+                        toRedefine.add(ci);
+                    }
+                } else {
+                    // If not loaded, add to the list of classes to load.
+                    toLoad.add(ci.toClassBytecodes());
+                    dependenciesNeeded = true;
                 }
             }
         }
@@ -292,14 +296,30 @@
     }
 
     /**
-     * Redefine classes needing redefine.
-     * classesToLoad() must be called first.
+     * Redefine classes needing redefine. classesToLoad() must be called first.
+     *
      * @return true if all redefines succeeded (can be vacuously true)
      */
     boolean doRedefines() {
-        return toRedefine.isEmpty()
-                ? true
-                : state.executionControl().redefine(toRedefine);
+        if (toRedefine.isEmpty()) {
+            return true;
+        }
+        ClassBytecodes[] cbcs = toRedefine.stream()
+                .map(ci -> ci.toClassBytecodes())
+                .toArray(size -> new ClassBytecodes[size]);
+        try {
+            state.executionControl().redefine(cbcs);
+            state.classTracker.markLoaded(cbcs);
+            return true;
+        } catch (ClassInstallException ex) {
+            state.classTracker.markLoaded(cbcs, ex.installed());
+            return false;
+        } catch (EngineTerminationException ex) {
+            state.closeDown();
+            return false;
+        } catch (NotImplementedException ex) {
+            return false;
+        }
     }
 
     void markForReplacement() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DefaultLoaderDelegate.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.CodeSource;
+import java.util.Map;
+import java.util.TreeMap;
+import jdk.jshell.spi.ExecutionControl.ClassBytecodes;
+import jdk.jshell.spi.ExecutionControl.ClassInstallException;
+import jdk.jshell.spi.ExecutionControl.EngineTerminationException;
+import jdk.jshell.spi.ExecutionControl.InternalException;
+import jdk.jshell.spi.ExecutionControl.NotImplementedException;
+
+/**
+ * The standard implementation of {@link LoaderDelegate} using
+ * a {@link URLClassLoader}.
+ *
+ * @author Robert Field
+ */
+class DefaultLoaderDelegate implements LoaderDelegate {
+
+    private final RemoteClassLoader loader;
+    private final Map<String, Class<?>> klasses = new TreeMap<>();
+
+    class RemoteClassLoader extends URLClassLoader {
+
+        private final Map<String, byte[]> classObjects = new TreeMap<>();
+
+        RemoteClassLoader() {
+            super(new URL[0]);
+        }
+
+        void delare(String name, byte[] bytes) {
+            classObjects.put(name, bytes);
+        }
+
+        @Override
+        protected Class<?> findClass(String name) throws ClassNotFoundException {
+            byte[] b = classObjects.get(name);
+            if (b == null) {
+                return super.findClass(name);
+            }
+            return super.defineClass(name, b, 0, b.length, (CodeSource) null);
+        }
+
+        @Override
+        public void addURL(URL url) {
+            super.addURL(url);
+        }
+
+    }
+
+    public DefaultLoaderDelegate() {
+        this.loader = new RemoteClassLoader();
+    }
+
+    @Override
+    public void load(ClassBytecodes[] cbcs)
+            throws ClassInstallException, EngineTerminationException {
+        boolean[] loaded = new boolean[cbcs.length];
+        try {
+            for (ClassBytecodes cbc : cbcs) {
+                loader.delare(cbc.name(), cbc.bytecodes());
+            }
+            for (int i = 0; i < cbcs.length; ++i) {
+                ClassBytecodes cbc = cbcs[i];
+                Class<?> klass = loader.loadClass(cbc.name());
+                klasses.put(cbc.name(), klass);
+                loaded[i] = true;
+                // Get class loaded to the point of, at least, preparation
+                klass.getDeclaredMethods();
+            }
+        } catch (Throwable ex) {
+            throw new ClassInstallException("load: " + ex.getMessage(), loaded);
+        }
+    }
+
+
+    @Override
+    public void addToClasspath(String cp)
+            throws EngineTerminationException, InternalException {
+        try {
+            for (String path : cp.split(File.pathSeparator)) {
+                loader.addURL(new File(path).toURI().toURL());
+            }
+        } catch (Exception ex) {
+            throw new InternalException(ex.toString());
+        }
+    }
+
+    @Override
+    public void setClasspath(String path)
+            throws EngineTerminationException, InternalException {
+        throw new NotImplementedException("setClasspath: Not supported yet.");
+    }
+
+    @Override
+    public Class<?> findClass(String name) throws ClassNotFoundException {
+        Class<?> klass = klasses.get(name);
+        if (klass == null) {
+            throw new ClassNotFoundException(name + " not found");
+        } else {
+            return klass;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DemultiplexInput.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+/**
+ * Read from an InputStream which has been packetized and write its contents
+ * to the named OutputStreams.
+ *
+ * @author Jan Lahoda
+ * @see Util#demultiplexInput(java.io.InputStream, java.io.OutputStream, java.io.OutputStream, java.io.OutputStream...)
+ */
+class DemultiplexInput extends Thread {
+
+    private final DataInputStream delegate;
+    private final PipeInputStream command;
+    private final Map<String, OutputStream> io;
+
+    DemultiplexInput(InputStream input, PipeInputStream command,
+            Map<String, OutputStream> io) {
+        super("output reader");
+        this.delegate = new DataInputStream(input);
+        this.command = command;
+        this.io = io;
+    }
+
+    @Override
+    public void run() {
+        try {
+            while (true) {
+                int nameLen = delegate.read();
+                if (nameLen == (-1)) {
+                    break;
+                }
+                byte[] name = new byte[nameLen];
+                DemultiplexInput.this.delegate.readFully(name);
+                int dataLen = delegate.read();
+                byte[] data = new byte[dataLen];
+                DemultiplexInput.this.delegate.readFully(data);
+                String chan = new String(name, "UTF-8");
+                if (chan.equals("command")) {
+                    for (byte b : data) {
+                        command.write(Byte.toUnsignedInt(b));
+                    }
+                } else {
+                    OutputStream out = io.get(chan);
+                    if (out == null) {
+                        debug("Unexpected channel name: %s", chan);
+                    } else {
+                        out.write(data);
+                    }
+                }
+            }
+        } catch (IOException ex) {
+            debug(ex, "Failed reading output");
+        } finally {
+            command.close();
+        }
+    }
+
+    /**
+     * Log debugging information. Arguments as for {@code printf}.
+     *
+     * @param format a format string as described in Format string syntax
+     * @param args arguments referenced by the format specifiers in the format
+     * string.
+     */
+    private void debug(String format, Object... args) {
+        // Reserved for future logging
+    }
+
+    /**
+     * Log a serious unexpected internal exception.
+     *
+     * @param ex the exception
+     * @param where a description of the context of the exception
+     */
+    private void debug(Throwable ex, String where) {
+        // Reserved for future logging
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import jdk.jshell.spi.ExecutionControl;
+import jdk.jshell.spi.SPIResolutionException;
+
+/**
+ * An {@link ExecutionControl} implementation that runs in the current process.
+ * May be used directly, or over a channel with
+ * {@link Util#forwardExecutionControl(ExecutionControl, java.io.ObjectInput, java.io.ObjectOutput) }.
+ *
+ * @author Robert Field
+ * @author Jan Lahoda
+ */
+public class DirectExecutionControl implements ExecutionControl {
+
+    private final LoaderDelegate loaderDelegate;
+
+    /**
+     * Creates an instance, delegating loader operations to the specified
+     * delegate.
+     *
+     * @param loaderDelegate the delegate to handle loading classes
+     */
+    public DirectExecutionControl(LoaderDelegate loaderDelegate) {
+        this.loaderDelegate = loaderDelegate;
+    }
+
+    /**
+     * Create an instance using the default class loading.
+     */
+    public DirectExecutionControl() {
+        this(new DefaultLoaderDelegate());
+    }
+
+    @Override
+    public void load(ClassBytecodes[] cbcs)
+            throws ClassInstallException, NotImplementedException, EngineTerminationException {
+        loaderDelegate.load(cbcs);
+    }
+
+    @Override
+    public void redefine(ClassBytecodes[] cbcs)
+            throws ClassInstallException, NotImplementedException, EngineTerminationException {
+        throw new NotImplementedException("redefine not supported");
+    }
+
+    @Override
+    public String invoke(String className, String methodName)
+            throws RunException, InternalException, EngineTerminationException {
+        Method doitMethod;
+        try {
+            Class<?> klass = findClass(className);
+            doitMethod = klass.getDeclaredMethod(methodName, new Class<?>[0]);
+            doitMethod.setAccessible(true);
+        } catch (Throwable ex) {
+            throw new InternalException(ex.toString());
+        }
+
+        try {
+            clientCodeEnter();
+            String result = invoke(doitMethod);
+            System.out.flush();
+            return result;
+        } catch (RunException | InternalException | EngineTerminationException ex) {
+            throw ex;
+        } catch (SPIResolutionException ex) {
+            return throwConvertedInvocationException(ex);
+        } catch (InvocationTargetException ex) {
+            return throwConvertedInvocationException(ex.getCause());
+        } catch (Throwable ex) {
+            return throwConvertedOtherException(ex);
+        } finally {
+            clientCodeLeave();
+        }
+    }
+
+    @Override
+    public String varValue(String className, String varName)
+            throws RunException, EngineTerminationException, InternalException {
+        Object val;
+        try {
+            Class<?> klass = findClass(className);
+            Field var = klass.getDeclaredField(varName);
+            var.setAccessible(true);
+            val = var.get(null);
+        } catch (Throwable ex) {
+            throw new InternalException(ex.toString());
+        }
+
+        try {
+            clientCodeEnter();
+            return valueString(val);
+        } catch (Throwable ex) {
+            return throwConvertedInvocationException(ex);
+        } finally {
+            clientCodeLeave();
+        }
+    }
+
+    @Override
+    public void addToClasspath(String cp)
+            throws EngineTerminationException, InternalException {
+        loaderDelegate.addToClasspath(cp);
+    }
+
+    @Override
+    public void setClasspath(String path)
+            throws EngineTerminationException, InternalException {
+        loaderDelegate.setClasspath(path);
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * Not supported.
+     */
+    @Override
+    public void stop()
+            throws EngineTerminationException, InternalException {
+        throw new NotImplementedException("stop: Not supported.");
+    }
+
+    @Override
+    public Object extensionCommand(String command, Object arg)
+            throws RunException, EngineTerminationException, InternalException {
+        throw new NotImplementedException("Unknown command: " + command);
+    }
+
+    @Override
+    public void close() {
+    }
+
+    /**
+     * Finds the class with the specified binary name.
+     *
+     * @param name the binary name of the class
+     * @return the Class Object
+     * @throws ClassNotFoundException if the class could not be found
+     */
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        return loaderDelegate.findClass(name);
+    }
+
+    /**
+     * Invoke the specified "doit-method", a static method with no parameters.
+     * The {@link DirectExecutionControl#invoke(java.lang.String, java.lang.String) }
+     * in this class will call this to invoke.
+     *
+     * @param doitMethod the Method to invoke
+     * @return the value or null
+     * @throws Exception any exceptions thrown by
+     * {@link java.lang.reflect.Method#invoke(Object, Object...) }
+     * or any {@link ExecutionControl.ExecutionControlException}
+     * to pass-through.
+     */
+    protected String invoke(Method doitMethod) throws Exception {
+        Object res = doitMethod.invoke(null, new Object[0]);
+        return valueString(res);
+    }
+
+    /**
+     * Converts the {@code Object} value from
+     * {@link ExecutionControl#invoke(String, String)  } or
+     * {@link ExecutionControl#varValue(String, String)   } to {@code String}.
+     *
+     * @param value the value to convert
+     * @return the {@code String} representation
+     */
+    protected static String valueString(Object value) {
+        if (value == null) {
+            return "null";
+        } else if (value instanceof String) {
+            return "\"" + (String) value + "\"";
+        } else if (value instanceof Character) {
+            return "'" + value + "'";
+        } else {
+            return value.toString();
+        }
+    }
+
+    /**
+     * Converts incoming exceptions in user code into instances of subtypes of
+     * {@link ExecutionControl.ExecutionControlException} and throws the
+     * converted exception.
+     *
+     * @param cause the exception to convert
+     * @return never returns as it always throws
+     * @throws ExecutionControl.RunException for normal exception occurrences
+     * @throws ExecutionControl.InternalException for internal problems
+     */
+    protected String throwConvertedInvocationException(Throwable cause) throws RunException, InternalException {
+        if (cause instanceof SPIResolutionException) {
+            SPIResolutionException spire = (SPIResolutionException) cause;
+            throw new ResolutionException(spire.id(), spire.getStackTrace());
+        } else {
+            throw new UserException(cause.getMessage(), cause.getClass().getName(), cause.getStackTrace());
+        }
+    }
+
+    /**
+     * Converts incoming exceptions in agent code into instances of subtypes of
+     * {@link ExecutionControl.ExecutionControlException} and throws the
+     * converted exception.
+     *
+     * @param ex the exception to convert
+     * @return never returns as it always throws
+     * @throws ExecutionControl.RunException for normal exception occurrences
+     * @throws ExecutionControl.InternalException for internal problems
+     */
+    protected String throwConvertedOtherException(Throwable ex) throws RunException, InternalException {
+        throw new InternalException(ex.toString());
+    }
+
+    /**
+     * Marks entry into user code.
+     *
+     * @throws ExecutionControl.InternalException in unexpected failure cases
+     */
+    protected void clientCodeEnter() throws InternalException {
+    }
+
+    /**
+     * Marks departure from user code.
+     *
+     * @throws ExecutionControl.InternalException in unexpected failure cases
+     */
+    protected void clientCodeLeave() throws InternalException {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/ExecutionControlForwarder.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import jdk.jshell.spi.ExecutionControl;
+import jdk.jshell.spi.ExecutionControl.ClassBytecodes;
+import jdk.jshell.spi.ExecutionControl.ClassInstallException;
+import jdk.jshell.spi.ExecutionControl.EngineTerminationException;
+import jdk.jshell.spi.ExecutionControl.InternalException;
+import jdk.jshell.spi.ExecutionControl.NotImplementedException;
+import jdk.jshell.spi.ExecutionControl.ResolutionException;
+import jdk.jshell.spi.ExecutionControl.StoppedException;
+import jdk.jshell.spi.ExecutionControl.UserException;
+import static jdk.jshell.execution.RemoteCodes.*;
+
+/**
+ * Forwards commands from the input to the specified {@link ExecutionControl}
+ * instance, then responses back on the output.
+ */
+class ExecutionControlForwarder {
+
+    private final ExecutionControl ec;
+    private final ObjectInput in;
+    private final ObjectOutput out;
+
+    ExecutionControlForwarder(ExecutionControl ec, ObjectInput in, ObjectOutput out) {
+        this.ec = ec;
+        this.in = in;
+        this.out = out;
+    }
+
+    private boolean writeSuccess() throws IOException {
+        writeStatus(RESULT_SUCCESS);
+        flush();
+        return true;
+    }
+
+    private boolean writeSuccessAndResult(String result) throws IOException {
+        writeStatus(RESULT_SUCCESS);
+        writeUTF(result);
+        flush();
+        return true;
+    }
+
+    private boolean writeSuccessAndResult(Object result) throws IOException {
+        writeStatus(RESULT_SUCCESS);
+        writeObject(result);
+        flush();
+        return true;
+    }
+
+    private void writeStatus(int status) throws IOException {
+        out.writeInt(status);
+    }
+
+    private void writeObject(Object o) throws IOException {
+        out.writeObject(o);
+    }
+
+    private void writeInt(int i) throws IOException {
+        out.writeInt(i);
+    }
+
+    private void writeUTF(String s) throws IOException {
+        if (s == null) {
+            s = "";
+        }
+        out.writeUTF(s);
+    }
+
+    private void flush() throws IOException {
+        out.flush();
+    }
+
+    private boolean processCommand() throws IOException {
+        try {
+            int prefix = in.readInt();
+            if (prefix != COMMAND_PREFIX) {
+                throw new EngineTerminationException("Invalid command prefix: " + prefix);
+            }
+            String cmd = in.readUTF();
+            switch (cmd) {
+                case CMD_LOAD: {
+                    // Load a generated class file over the wire
+                    ClassBytecodes[] cbcs = (ClassBytecodes[]) in.readObject();
+                    ec.load(cbcs);
+                    return writeSuccess();
+                }
+                case CMD_REDEFINE: {
+                    // Load a generated class file over the wire
+                    ClassBytecodes[] cbcs = (ClassBytecodes[]) in.readObject();
+                    ec.redefine(cbcs);
+                    return writeSuccess();
+                }
+                case CMD_INVOKE: {
+                    // Invoke executable entry point in loaded code
+                    String className = in.readUTF();
+                    String methodName = in.readUTF();
+                    String res = ec.invoke(className, methodName);
+                    return writeSuccessAndResult(res);
+                }
+                case CMD_VAR_VALUE: {
+                    // Retrieve a variable value
+                    String className = in.readUTF();
+                    String varName = in.readUTF();
+                    String res = ec.varValue(className, varName);
+                    return writeSuccessAndResult(res);
+                }
+                case CMD_ADD_CLASSPATH: {
+                    // Append to the claspath
+                    String cp = in.readUTF();
+                    ec.addToClasspath(cp);
+                    return writeSuccess();
+                }
+                case CMD_SET_CLASSPATH: {
+                    // Set the claspath
+                    String cp = in.readUTF();
+                    ec.setClasspath(cp);
+                    return writeSuccess();
+                }
+                case CMD_STOP: {
+                    // Stop the current execution
+                    try {
+                        ec.stop();
+                    } catch (Throwable ex) {
+                        // JShell-core not waiting for a result, ignore
+                    }
+                    return true;
+                }
+                case CMD_CLOSE: {
+                    // Terminate this process
+                    try {
+                        ec.close();
+                    } catch (Throwable ex) {
+                        // JShell-core not waiting for a result, ignore
+                    }
+                    return true;
+                }
+                default: {
+                    Object arg = in.readObject();
+                    Object res = ec.extensionCommand(cmd, arg);
+                    return writeSuccessAndResult(res);
+                }
+            }
+        } catch (IOException ex) {
+            // handled by the outer level
+            throw ex;
+        } catch (EngineTerminationException ex) {
+            writeStatus(RESULT_TERMINATED);
+            writeUTF(ex.getMessage());
+            flush();
+            return false;
+        } catch (NotImplementedException ex) {
+            writeStatus(RESULT_NOT_IMPLEMENTED);
+            writeUTF(ex.getMessage());
+            flush();
+            return true;
+        } catch (InternalException ex) {
+            writeStatus(RESULT_INTERNAL_PROBLEM);
+            writeUTF(ex.getMessage());
+            flush();
+            return true;
+        } catch (ClassInstallException ex) {
+            writeStatus(RESULT_CLASS_INSTALL_EXCEPTION);
+            writeUTF(ex.getMessage());
+            writeObject(ex.installed());
+            flush();
+            return true;
+        } catch (UserException ex) {
+            writeStatus(RESULT_USER_EXCEPTION);
+            writeUTF(ex.getMessage());
+            writeUTF(ex.causeExceptionClass());
+            writeObject(ex.getStackTrace());
+            flush();
+            return true;
+        } catch (ResolutionException ex) {
+            writeStatus(RESULT_CORRALLED);
+            writeInt(ex.id());
+            writeObject(ex.getStackTrace());
+            flush();
+            return true;
+        } catch (StoppedException ex) {
+            writeStatus(RESULT_STOPPED);
+            flush();
+            return true;
+        } catch (Throwable ex) {
+            writeStatus(RESULT_TERMINATED);
+            writeUTF(ex.getMessage());
+            flush();
+            return false;
+        }
+    }
+
+    void commandLoop() {
+        try {
+            while (processCommand()) {
+                // condition is loop action
+            }
+        } catch (IOException ex) {
+            // drop out of loop
+        }
+    }
+
+}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Internal.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2016, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-package jdk.jshell.execution;
-
-/**
- * Temp class needed so the package exists.
- */
-class Internal {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIDefaultExecutionControl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import com.sun.jdi.BooleanValue;
+import com.sun.jdi.ClassNotLoadedException;
+import com.sun.jdi.Field;
+import com.sun.jdi.IncompatibleThreadStateException;
+import com.sun.jdi.InvalidTypeException;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.StackFrame;
+import com.sun.jdi.ThreadReference;
+import com.sun.jdi.VMDisconnectedException;
+import com.sun.jdi.VirtualMachine;
+import jdk.jshell.spi.ExecutionControl;
+import jdk.jshell.spi.ExecutionEnv;
+import static jdk.jshell.execution.Util.remoteInput;
+
+/**
+ * The implementation of {@link jdk.jshell.spi.ExecutionControl} that the
+ * JShell-core uses by default.
+ * Launches a remote process -- the "remote agent".
+ * Interfaces to the remote agent over a socket and via JDI.
+ * Designed to work with {@link RemoteExecutionControl}.
+ *
+ * @author Robert Field
+ * @author Jan Lahoda
+ */
+public class JDIDefaultExecutionControl extends JDIExecutionControl {
+
+    private static final String REMOTE_AGENT = RemoteExecutionControl.class.getName();
+
+    private VirtualMachine vm;
+    private Process process;
+
+    private final Object STOP_LOCK = new Object();
+    private boolean userCodeRunning = false;
+
+    /**
+     * Creates an ExecutionControl instance based on a JDI
+     * {@code LaunchingConnector}.
+     *
+     * @return the generator
+     */
+    public static ExecutionControl.Generator launch() {
+        return env -> create(env, true);
+    }
+
+    /**
+     * Creates an ExecutionControl instance based on a JDI
+     * {@code ListeningConnector}.
+     *
+     * @return the generator
+     */
+    public static ExecutionControl.Generator listen() {
+        return env -> create(env, false);
+    }
+
+    /**
+     * Creates an ExecutionControl instance based on a JDI
+     * {@code ListeningConnector} or {@code LaunchingConnector}.
+     *
+     * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
+     * commands and results. This socket also transports the user
+     * input/output/error.
+     *
+     * @param env the context passed by
+     * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
+     * @return the channel
+     * @throws IOException if there are errors in set-up
+     */
+    private static JDIDefaultExecutionControl create(ExecutionEnv env, boolean isLaunch) throws IOException {
+        try (final ServerSocket listener = new ServerSocket(0)) {
+            // timeout after 60 seconds
+            listener.setSoTimeout(60000);
+            int port = listener.getLocalPort();
+
+            // Set-up the JDI connection
+            JDIInitiator jdii = new JDIInitiator(port,
+                    env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch);
+            VirtualMachine vm = jdii.vm();
+            Process process = jdii.process();
+
+            // Forward input to the remote agent
+            Util.forwardInputToRemote(env.userIn(), process.getOutputStream(),
+                    ex -> debug(ex, "input forwarding failure"));
+
+            List<Consumer<String>> deathListeners = new ArrayList<>();
+            deathListeners.add(s -> env.closeDown());
+            Util.detectJDIExitEvent(vm, s -> {
+                for (Consumer<String> h : deathListeners) {
+                    h.accept(s);
+                }
+            });
+
+            // Set-up the commands/reslts on the socket.  Piggy-back snippet
+            // output.
+            Socket socket = listener.accept();
+            // out before in -- match remote creation so we don't hang
+            ObjectOutput cmdout = new ObjectOutputStream(socket.getOutputStream());
+            Map<String, OutputStream> io = new HashMap<>();
+            io.put("out", env.userOut());
+            io.put("err", env.userErr());
+            ObjectInput cmdin = remoteInput(socket.getInputStream(), io);
+            return new JDIDefaultExecutionControl(cmdout, cmdin, vm, process, deathListeners);
+        }
+    }
+
+    /**
+     * Create an instance.
+     *
+     * @param cmdout the output for commands
+     * @param cmdin the input for responses
+     */
+    private JDIDefaultExecutionControl(ObjectOutput cmdout, ObjectInput cmdin,
+            VirtualMachine vm, Process process, List<Consumer<String>> deathListeners) {
+        super(cmdout, cmdin);
+        this.vm = vm;
+        this.process = process;
+        deathListeners.add(s -> disposeVM());
+    }
+
+    @Override
+    public String invoke(String classname, String methodname)
+            throws RunException,
+            EngineTerminationException, InternalException {
+        String res;
+        synchronized (STOP_LOCK) {
+            userCodeRunning = true;
+        }
+        try {
+            res = super.invoke(classname, methodname);
+        } finally {
+            synchronized (STOP_LOCK) {
+                userCodeRunning = false;
+            }
+        }
+        return res;
+    }
+
+    /**
+     * Interrupts a running remote invoke by manipulating remote variables
+     * and sending a stop via JDI.
+     *
+     * @throws EngineTerminationException the execution engine has terminated
+     * @throws InternalException an internal problem occurred
+     */
+    @Override
+    public void stop() throws EngineTerminationException, InternalException {
+        synchronized (STOP_LOCK) {
+            if (!userCodeRunning) {
+                return;
+            }
+
+            vm().suspend();
+            try {
+                OUTER:
+                for (ThreadReference thread : vm().allThreads()) {
+                    // could also tag the thread (e.g. using name), to find it easier
+                    for (StackFrame frame : thread.frames()) {
+                        if (REMOTE_AGENT.equals(frame.location().declaringType().name()) &&
+                                (    "invoke".equals(frame.location().method().name())
+                                || "varValue".equals(frame.location().method().name()))) {
+                            ObjectReference thiz = frame.thisObject();
+                            Field inClientCode = thiz.referenceType().fieldByName("inClientCode");
+                            Field expectingStop = thiz.referenceType().fieldByName("expectingStop");
+                            Field stopException = thiz.referenceType().fieldByName("stopException");
+                            if (((BooleanValue) thiz.getValue(inClientCode)).value()) {
+                                thiz.setValue(expectingStop, vm().mirrorOf(true));
+                                ObjectReference stopInstance = (ObjectReference) thiz.getValue(stopException);
+
+                                vm().resume();
+                                debug("Attempting to stop the client code...\n");
+                                thread.stop(stopInstance);
+                                thiz.setValue(expectingStop, vm().mirrorOf(false));
+                            }
+
+                            break OUTER;
+                        }
+                    }
+                }
+            } catch (ClassNotLoadedException | IncompatibleThreadStateException | InvalidTypeException ex) {
+                throw new InternalException("Exception on remote stop: " + ex);
+            } finally {
+                vm().resume();
+            }
+        }
+    }
+
+    @Override
+    public void close() {
+        super.close();
+        disposeVM();
+    }
+
+    private synchronized void disposeVM() {
+        try {
+            if (vm != null) {
+                vm.dispose(); // This could NPE, so it is caught below
+                vm = null;
+            }
+        } catch (VMDisconnectedException ex) {
+            // Ignore if already closed
+        } catch (Throwable ex) {
+            debug(ex, "disposeVM");
+        } finally {
+            if (process != null) {
+                process.destroy();
+                process = null;
+            }
+        }
+    }
+
+    @Override
+    protected synchronized VirtualMachine vm() throws EngineTerminationException {
+        if (vm == null) {
+            throw new EngineTerminationException("VM closed");
+        } else {
+            return vm;
+        }
+    }
+
+    /**
+     * Log debugging information. Arguments as for {@code printf}.
+     *
+     * @param format a format string as described in Format string syntax
+     * @param args arguments referenced by the format specifiers in the format
+     * string.
+     */
+    private static void debug(String format, Object... args) {
+        // Reserved for future logging
+    }
+
+    /**
+     * Log a serious unexpected internal exception.
+     *
+     * @param ex the exception
+     * @param where a description of the context of the exception
+     */
+    private static void debug(Throwable ex, String where) {
+        // Reserved for future logging
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIEventHandler.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 1998, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.jshell.execution;
+
+import java.util.function.Consumer;
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+
+/**
+ * Handler of Java Debug Interface events.
+ * Adapted from jdb EventHandler.
+ * Only exit and disconnect events processed.
+ */
+class JDIEventHandler implements Runnable {
+
+    private final Thread thread;
+    private volatile boolean connected = true;
+    private boolean completed = false;
+    private final VirtualMachine vm;
+    private final Consumer<String> reportVMExit;
+
+    /**
+     * Creates an event handler. Start with {@code start()}.
+     *
+     * @param vm the virtual machine for which to handle events
+     * @param reportVMExit callback to report exit/disconnect
+     * (passed true if the VM has died)
+     */
+    JDIEventHandler(VirtualMachine vm, Consumer<String> reportVMExit) {
+        this.vm = vm;
+        this.reportVMExit = reportVMExit;
+        this.thread = new Thread(this, "event-handler");
+    }
+
+    /**
+     * Starts the event handler.
+     */
+    void start() {
+        thread.start();
+    }
+
+    synchronized void shutdown() {
+        connected = false;  // force run() loop termination
+        thread.interrupt();
+        while (!completed) {
+            try {wait();} catch (InterruptedException exc) {}
+        }
+    }
+
+    @Override
+    public void run() {
+        EventQueue queue = vm.eventQueue();
+        while (connected) {
+            try {
+                EventSet eventSet = queue.remove();
+                boolean resumeStoppedApp = false;
+                EventIterator it = eventSet.eventIterator();
+                while (it.hasNext()) {
+                    resumeStoppedApp |= handleEvent(it.nextEvent());
+                }
+
+                if (resumeStoppedApp) {
+                    eventSet.resume();
+                }
+            } catch (InterruptedException exc) {
+                // Do nothing. Any changes will be seen at top of loop.
+            } catch (VMDisconnectedException discExc) {
+                handleDisconnectedException();
+                break;
+            }
+        }
+        synchronized (this) {
+            completed = true;
+            notifyAll();
+        }
+    }
+
+    private boolean handleEvent(Event event) {
+        handleExitEvent(event);
+        return true;
+    }
+
+    private void handleExitEvent(Event event) {
+        if (event instanceof VMDeathEvent) {
+            reportVMExit.accept("VM Died");
+        } else if (event instanceof VMDisconnectEvent) {
+            connected = false;
+            reportVMExit.accept("VM Disconnected");
+        } else {
+            // ignore everything else
+        }
+    }
+
+    private synchronized void handleDisconnectedException() {
+        /*
+         * A VMDisconnectedException has happened while dealing with
+         * another event. We need to flush the event queue, dealing only
+         * with exit events (VMDeath, VMDisconnect) so that we terminate
+         * correctly.
+         */
+        EventQueue queue = vm.eventQueue();
+        while (connected) {
+            try {
+                EventSet eventSet = queue.remove();
+                EventIterator iter = eventSet.eventIterator();
+                while (iter.hasNext()) {
+                    handleExitEvent(iter.next());
+                }
+            } catch (InterruptedException exc) {
+                // ignore
+            } catch (InternalError exc) {
+                // ignore
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIExecutionControl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2014, 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.jshell.execution;
+
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.VirtualMachine;
+import jdk.jshell.spi.ExecutionControl;
+import static java.util.stream.Collectors.toMap;
+
+/**
+ * Abstract JDI implementation of {@link jdk.jshell.spi.ExecutionControl}
+ */
+public abstract class JDIExecutionControl extends StreamingExecutionControl implements ExecutionControl {
+
+    /**
+     * Mapping from class names to JDI {@link ReferenceType}.
+     */
+    private final Map<String, ReferenceType> toReferenceType = new HashMap<>();
+
+    /**
+     * Create an instance.
+     * @param out the output from the remote agent
+     * @param in the input to the remote agent
+     */
+    protected JDIExecutionControl(ObjectOutput out, ObjectInput in) {
+        super(out, in);
+    }
+
+    /**
+     * Returns the JDI {@link VirtualMachine} instance.
+     *
+     * @return the virtual machine
+     * @throws EngineTerminationException if the VM is dead/disconnected
+     */
+    protected abstract VirtualMachine vm() throws EngineTerminationException;
+
+    /**
+     * Redefine the specified classes. Where 'redefine' is, as in JDI and JVMTI,
+     * an in-place replacement of the classes (preserving class identity) --
+     * that is, existing references to the class do not need to be recompiled.
+     * This implementation uses JDI
+     * {@link com.sun.jdi.VirtualMachine#redefineClasses(java.util.Map) }.
+     * It will be unsuccessful if
+     * the signature of the class has changed (see the JDI spec). The
+     * JShell-core is designed to adapt to unsuccessful redefine.
+     */
+    @Override
+    public void redefine(ClassBytecodes[] cbcs)
+            throws ClassInstallException, EngineTerminationException {
+        try {
+            // Convert to the JDI ReferenceType to class bytes map form needed
+            // by JDI.
+            VirtualMachine vm = vm();
+            Map<ReferenceType, byte[]> rmp = Stream.of(cbcs)
+                    .collect(toMap(
+                            cbc -> referenceType(vm, cbc.name()),
+                            cbc -> cbc.bytecodes()));
+            // Attempt redefine.  Throws exceptions on failure.
+            vm().redefineClasses(rmp);
+        } catch (EngineTerminationException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new ClassInstallException("redefine: " + ex.getMessage(), new boolean[cbcs.length]);
+        }
+    }
+
+    /**
+     * Returns the JDI {@link ReferenceType} corresponding to the specified
+     * class name.
+     *
+     * @param vm the current JDI {@link VirtualMachine} as returned by
+     * {@code vm()}
+     * @param name the class name to look-up
+     * @return the corresponding {@link ReferenceType}
+     */
+    protected ReferenceType referenceType(VirtualMachine vm, String name) {
+        return toReferenceType.computeIfAbsent(name, n -> nameToRef(vm, n));
+    }
+
+    private static ReferenceType nameToRef(VirtualMachine vm, String name) {
+        List<ReferenceType> rtl = vm.classesByName(name);
+        if (rtl.size() != 1) {
+            return null;
+        }
+        return rtl.get(0);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIInitiator.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.connect.Connector;
+import com.sun.jdi.connect.LaunchingConnector;
+import com.sun.jdi.connect.ListeningConnector;
+
+/**
+ * Sets up a JDI connection, providing the resulting JDI {@link VirtualMachine}
+ * and the {@link Process} the remote agent is running in.
+ */
+public class JDIInitiator {
+
+    private VirtualMachine vm;
+    private Process process = null;
+    private final Connector connector;
+    private final String remoteAgent;
+    private final Map<String, com.sun.jdi.connect.Connector.Argument> connectorArgs;
+
+    /**
+     * Start the remote agent and establish a JDI connection to it.
+     *
+     * @param port the socket port for (non-JDI) commands
+     * @param remoteVMOptions any user requested VM options
+     * @param remoteAgent full class name of remote agent to launch
+     * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
+     * otherwise we start explicitly and use ListeningConnector
+     */
+    public JDIInitiator(int port, List<String> remoteVMOptions,
+            String remoteAgent, boolean isLaunch) {
+        this.remoteAgent = remoteAgent;
+        String connectorName
+                = isLaunch
+                        ? "com.sun.jdi.CommandLineLaunch"
+                        : "com.sun.jdi.SocketListen";
+        this.connector = findConnector(connectorName);
+        if (connector == null) {
+            throw new IllegalArgumentException("No connector named: " + connectorName);
+        }
+        Map<String, String> argumentName2Value
+                = isLaunch
+                        ? launchArgs(port, String.join(" ", remoteVMOptions))
+                        : new HashMap<>();
+        this.connectorArgs = mergeConnectorArgs(connector, argumentName2Value);
+        this.vm = isLaunch
+                ? launchTarget()
+                : listenTarget(port, remoteVMOptions);
+
+    }
+
+    /**
+     * Returns the resulting {@code VirtualMachine} instance.
+     *
+     * @return the virtual machine
+     */
+    public VirtualMachine vm() {
+        return vm;
+    }
+
+    /**
+     * Returns the launched process.
+     *
+     * @return the remote agent process
+     */
+    public Process process() {
+        return process;
+    }
+
+    /* launch child target vm */
+    private VirtualMachine launchTarget() {
+        LaunchingConnector launcher = (LaunchingConnector) connector;
+        try {
+            VirtualMachine new_vm = launcher.launch(connectorArgs);
+            process = new_vm.process();
+            return new_vm;
+        } catch (Exception ex) {
+            reportLaunchFail(ex, "launch");
+        }
+        return null;
+    }
+
+    /**
+     * Directly launch the remote agent and connect JDI to it with a
+     * ListeningConnector.
+     */
+    private VirtualMachine listenTarget(int port, List<String> remoteVMOptions) {
+        ListeningConnector listener = (ListeningConnector) connector;
+        try {
+            // Start listening, get the JDI connection address
+            String addr = listener.startListening(connectorArgs);
+            debug("Listening at address: " + addr);
+
+            // Launch the RemoteAgent requesting a connection on that address
+            String javaHome = System.getProperty("java.home");
+            List<String> args = new ArrayList<>();
+            args.add(javaHome == null
+                    ? "java"
+                    : javaHome + File.separator + "bin" + File.separator + "java");
+            args.add("-agentlib:jdwp=transport=" + connector.transport().name() +
+                    ",address=" + addr);
+            args.addAll(remoteVMOptions);
+            args.add(remoteAgent);
+            args.add("" + port);
+            ProcessBuilder pb = new ProcessBuilder(args);
+            process = pb.start();
+
+            // Forward out, err, and in
+            // Accept the connection from the remote agent
+            vm = listener.accept(connectorArgs);
+            listener.stopListening(connectorArgs);
+            return vm;
+        } catch (Exception ex) {
+            reportLaunchFail(ex, "listen");
+        }
+        return null;
+    }
+
+    private Connector findConnector(String name) {
+        for (Connector cntor
+                : Bootstrap.virtualMachineManager().allConnectors()) {
+            if (cntor.name().equals(name)) {
+                return cntor;
+            }
+        }
+        return null;
+    }
+
+    private Map<String, Connector.Argument> mergeConnectorArgs(Connector connector, Map<String, String> argumentName2Value) {
+        Map<String, Connector.Argument> arguments = connector.defaultArguments();
+
+        for (Entry<String, String> argumentEntry : argumentName2Value.entrySet()) {
+            String name = argumentEntry.getKey();
+            String value = argumentEntry.getValue();
+            Connector.Argument argument = arguments.get(name);
+
+            if (argument == null) {
+                throw new IllegalArgumentException("Argument is not defined for connector:" +
+                        name + " -- " + connector.name());
+            }
+
+            argument.setValue(value);
+        }
+
+        return arguments;
+    }
+
+    /**
+     * The JShell specific Connector args for the LaunchingConnector.
+     *
+     * @param portthe socket port for (non-JDI) commands
+     * @param remoteVMOptions any user requested VM options
+     * @return the argument map
+     */
+    private Map<String, String> launchArgs(int port, String remoteVMOptions) {
+        Map<String, String> argumentName2Value = new HashMap<>();
+        argumentName2Value.put("main", remoteAgent + " " + port);
+        argumentName2Value.put("options", remoteVMOptions);
+        return argumentName2Value;
+    }
+
+    private void reportLaunchFail(Exception ex, String context) {
+        throw new InternalError("Failed remote " + context + ": " + connector +
+                " -- " + connectorArgs, ex);
+    }
+
+    /**
+     * Log debugging information. Arguments as for {@code printf}.
+     *
+     * @param format a format string as described in Format string syntax
+     * @param args arguments referenced by the format specifiers in the format
+     * string.
+     */
+    private void debug(String format, Object... args) {
+        // Reserved for future logging
+    }
+
+    /**
+     * Log a serious unexpected internal exception.
+     *
+     * @param ex the exception
+     * @param where a description of the context of the exception
+     */
+    private void debug(Throwable ex, String where) {
+        // Reserved for future logging
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/LoaderDelegate.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import jdk.jshell.spi.ExecutionControl.ClassBytecodes;
+import jdk.jshell.spi.ExecutionControl.ClassInstallException;
+import jdk.jshell.spi.ExecutionControl.EngineTerminationException;
+import jdk.jshell.spi.ExecutionControl.InternalException;
+import jdk.jshell.spi.ExecutionControl.NotImplementedException;
+
+/**
+ * This interface specifies the loading specific subset of
+ * {@link jdk.jshell.spi.ExecutionControl}.  For use in encapsulating the
+ * {@link java.lang.ClassLoader} implementation.
+ */
+public interface LoaderDelegate {
+
+    /**
+     * Attempts to load new classes.
+     *
+     * @param cbcs the class name and bytecodes to load
+     * @throws ClassInstallException exception occurred loading the classes,
+     * some or all were not loaded
+     * @throws NotImplementedException if not implemented
+     * @throws EngineTerminationException the execution engine has terminated
+     */
+    void load(ClassBytecodes[] cbcs)
+            throws ClassInstallException, NotImplementedException, EngineTerminationException;
+
+    /**
+     * Adds the path to the execution class path.
+     *
+     * @param path the path to add
+     * @throws EngineTerminationException the execution engine has terminated
+     * @throws InternalException an internal problem occurred
+     */
+    void addToClasspath(String path)
+            throws EngineTerminationException, InternalException;
+
+    /**
+     * Sets the execution class path to the specified path.
+     *
+     * @param path the path to add
+     * @throws EngineTerminationException the execution engine has terminated
+     * @throws InternalException an internal problem occurred
+     */
+    void setClasspath(String path)
+            throws EngineTerminationException, InternalException;
+
+    /**
+     * Finds the class with the specified binary name.
+     *
+     * @param name the binary name of the class
+     * @return the Class Object
+     * @throws ClassNotFoundException if the class could not be found
+     */
+    Class<?> findClass(String name) throws ClassNotFoundException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/LocalExecutionControl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.atomic.AtomicReference;
+import jdk.jshell.spi.ExecutionControl;
+
+/**
+ * An implementation of {@link jdk.jshell.spi.ExecutionControl} which executes
+ * in the same JVM as the JShell-core.
+ *
+ * @author Grigory Ptashko
+ */
+public class LocalExecutionControl extends DirectExecutionControl {
+
+    private final Object STOP_LOCK = new Object();
+    private boolean userCodeRunning = false;
+    private ThreadGroup execThreadGroup;
+
+    /**
+     * Creates a local ExecutionControl instance.
+     *
+     * @return the generator
+     */
+    public static ExecutionControl.Generator create() {
+        return env -> new LocalExecutionControl();
+    }
+
+    /**
+     * Creates an instance, delegating loader operations to the specified
+     * delegate.
+     *
+     * @param loaderDelegate the delegate to handle loading classes
+     */
+    public LocalExecutionControl(LoaderDelegate loaderDelegate) {
+        super(loaderDelegate);
+    }
+
+    /**
+     * Create an instance using the default class loading.
+     */
+    public LocalExecutionControl() {
+    }
+
+    @Override
+    protected String invoke(Method doitMethod) throws Exception {
+        execThreadGroup = new ThreadGroup("JShell process local execution");
+
+        AtomicReference<InvocationTargetException> iteEx = new AtomicReference<>();
+        AtomicReference<IllegalAccessException> iaeEx = new AtomicReference<>();
+        AtomicReference<NoSuchMethodException> nmeEx = new AtomicReference<>();
+        AtomicReference<Boolean> stopped = new AtomicReference<>(false);
+
+        Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
+            if (e instanceof InvocationTargetException) {
+                if (e.getCause() instanceof ThreadDeath) {
+                    stopped.set(true);
+                } else {
+                    iteEx.set((InvocationTargetException) e);
+                }
+            } else if (e instanceof IllegalAccessException) {
+                iaeEx.set((IllegalAccessException) e);
+            } else if (e instanceof NoSuchMethodException) {
+                nmeEx.set((NoSuchMethodException) e);
+            } else if (e instanceof ThreadDeath) {
+                stopped.set(true);
+            }
+        });
+
+        final Object[] res = new Object[1];
+        Thread snippetThread = new Thread(execThreadGroup, () -> {
+            try {
+                res[0] = doitMethod.invoke(null, new Object[0]);
+            } catch (InvocationTargetException e) {
+                if (e.getCause() instanceof ThreadDeath) {
+                    stopped.set(true);
+                } else {
+                    iteEx.set(e);
+                }
+            } catch (IllegalAccessException e) {
+                iaeEx.set(e);
+            } catch (ThreadDeath e) {
+                stopped.set(true);
+            }
+        });
+
+        snippetThread.start();
+        Thread[] threadList = new Thread[execThreadGroup.activeCount()];
+        execThreadGroup.enumerate(threadList);
+        for (Thread thread : threadList) {
+            if (thread != null) {
+                thread.join();
+            }
+        }
+
+        if (stopped.get()) {
+            throw new StoppedException();
+        }
+
+        if (iteEx.get() != null) {
+            throw iteEx.get();
+        } else if (nmeEx.get() != null) {
+            throw nmeEx.get();
+        } else if (iaeEx.get() != null) {
+            throw iaeEx.get();
+        }
+
+        return valueString(res[0]);
+    }
+
+    @Override
+    @SuppressWarnings("deprecation")
+    public void stop() throws EngineTerminationException, InternalException {
+        synchronized (STOP_LOCK) {
+            if (!userCodeRunning) {
+                return;
+            }
+            if (execThreadGroup == null) {
+                throw new InternalException("Process-local code snippets thread group is null. Aborting stop.");
+            }
+
+            execThreadGroup.stop();
+        }
+    }
+
+    @Override
+    protected void clientCodeEnter() {
+        synchronized (STOP_LOCK) {
+            userCodeRunning = true;
+        }
+    }
+
+    @Override
+    protected void clientCodeLeave() {
+        synchronized (STOP_LOCK) {
+            userCodeRunning = false;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/MultiplexingOutputStream.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Packetize an OutputStream, dividing it into named channels.
+ *
+ * @author Jan Lahoda
+ */
+class MultiplexingOutputStream extends OutputStream {
+
+    private static final int PACKET_SIZE = 127;
+    private final byte[] name;
+    private final OutputStream delegate;
+
+    MultiplexingOutputStream(String name, OutputStream delegate) {
+        try {
+            this.name = name.getBytes("UTF-8");
+            this.delegate = delegate;
+        } catch (UnsupportedEncodingException ex) {
+            throw new IllegalStateException(ex); //should not happen
+        }
+    }
+
+    @Override
+    public void write(int b) throws IOException {
+        synchronized (delegate) {
+            delegate.write(name.length); //assuming the len is small enough to fit into byte
+            delegate.write(name);
+            delegate.write(1);
+            delegate.write(b);
+            delegate.flush();
+        }
+    }
+
+    @Override
+    public void write(byte[] b, int off, int len) throws IOException {
+        synchronized (delegate) {
+            int i = 0;
+            while (len > 0) {
+                int size = Math.min(PACKET_SIZE, len);
+                delegate.write(name.length); //assuming the len is small enough to fit into byte
+                delegate.write(name);
+                delegate.write(size);
+                delegate.write(b, off + i, size);
+                i += size;
+                len -= size;
+            }
+            delegate.flush();
+        }
+    }
+
+    @Override
+    public void flush() throws IOException {
+        super.flush();
+        delegate.flush();
+    }
+
+    @Override
+    public void close() throws IOException {
+        super.close();
+        delegate.close();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/PipeInputStream.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.io.InputStream;
+
+/**
+ *
+ * @author Jan Lahoda
+ */
+class PipeInputStream extends InputStream {
+
+    private static final int INITIAL_SIZE = 128;
+    private int[] buffer = new int[INITIAL_SIZE];
+    private int start;
+    private int end;
+    private boolean closed;
+
+    @Override
+    public synchronized int read() {
+        while (start == end) {
+            if (closed) {
+                return -1;
+            }
+            try {
+                wait();
+            } catch (InterruptedException ex) {
+                //ignore
+            }
+        }
+        try {
+            return buffer[start];
+        } finally {
+            start = (start + 1) % buffer.length;
+        }
+    }
+
+    public synchronized void write(int b) {
+        if (closed) {
+            throw new IllegalStateException("Already closed.");
+        }
+        int newEnd = (end + 1) % buffer.length;
+        if (newEnd == start) {
+            //overflow:
+            int[] newBuffer = new int[buffer.length * 2];
+            int rightPart = (end > start ? end : buffer.length) - start;
+            int leftPart = end > start ? 0 : start - 1;
+            System.arraycopy(buffer, start, newBuffer, 0, rightPart);
+            System.arraycopy(buffer, 0, newBuffer, rightPart, leftPart);
+            buffer = newBuffer;
+            start = 0;
+            end = rightPart + leftPart;
+            newEnd = end + 1;
+        }
+        buffer[end] = b;
+        end = newEnd;
+        notifyAll();
+    }
+
+    @Override
+    public synchronized void close() {
+        closed = true;
+        notifyAll();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteCodes.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014, 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.jshell.execution;
+
+/**
+ * Communication constants shared between the main process and the remote
+ * execution process.  These are not enums to allow for future expansion, and
+ * remote/local of different versions.
+ *
+ * @author Robert Field
+ */
+class RemoteCodes {
+
+    /**
+     * Command prefix markers.
+     */
+    static final int COMMAND_PREFIX = 0xC03DC03D;
+
+    // Command codes
+
+    /**
+     * Exit the the agent.
+     */
+    static final String CMD_CLOSE          = "CMD_CLOSE";
+    /**
+     * Load classes.
+     */
+    static final String CMD_LOAD           = "CMD_LOAD";
+    /**
+     * Redefine classes.
+     */
+    static final String CMD_REDEFINE       = "CMD_REDEFINE";
+    /**
+     * Invoke a method.
+     */
+    static final String CMD_INVOKE         = "CMD_INVOKE";
+    /**
+     * Retrieve the value of a variable.
+     */
+    static final String CMD_VAR_VALUE      = "CMD_VAR_VALUE";
+    /**
+     * Add to the class-path.
+     */
+    static final String CMD_ADD_CLASSPATH  = "CMD_ADD_CLASSPATH";
+    /**
+     * Set the class-path.
+     */
+    static final String CMD_SET_CLASSPATH  = "CMD_SET_CLASSPATH";
+    /**
+     * Stop an invoke.
+     */
+    static final String CMD_STOP           = "CMD_STOP";
+
+    // Return result codes
+
+    /**
+     * The command succeeded.
+     */
+    static final int RESULT_SUCCESS                 = 100;
+    /**
+     * Unbidden execution engine termination.
+     */
+    static final int RESULT_TERMINATED              = 101;
+    /**
+     * Command not implemented.
+     */
+    static final int RESULT_NOT_IMPLEMENTED         = 102;
+    /**
+     * The command failed.
+     */
+    static final int RESULT_INTERNAL_PROBLEM        = 103;
+    /**
+     * User exception encountered.
+     */
+    static final int RESULT_USER_EXCEPTION          = 104;
+    /**
+     * Corralled code exception encountered.
+     */
+    static final int RESULT_CORRALLED               = 105;
+    /**
+     * Exception encountered during class load/redefine.
+     */
+    static final int RESULT_CLASS_INSTALL_EXCEPTION = 106;
+    /**
+     * The invoke has been stopped.
+     */
+    static final int RESULT_STOPPED                 = 107;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteExecutionControl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2014, 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.net.Socket;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+import jdk.jshell.spi.ExecutionControl;
+import static jdk.jshell.execution.Util.forwardExecutionControlAndIO;
+
+/**
+ * The remote agent runs in the execution process (separate from the main JShell
+ * process). This agent loads code over a socket from the main JShell process,
+ * executes the code, and other misc, Specialization of
+ * {@link DirectExecutionControl} which adds stop support controlled by
+ * an external process. Designed to work with {@link JDIDefaultExecutionControl}.
+ *
+ * @author Jan Lahoda
+ * @author Robert Field
+ */
+public class RemoteExecutionControl extends DirectExecutionControl implements ExecutionControl {
+
+    /**
+     * Launch the agent, connecting to the JShell-core over the socket specified
+     * in the command-line argument.
+     *
+     * @param args standard command-line arguments, expectation is the socket
+     * number is the only argument
+     * @throws Exception any unexpected exception
+     */
+    public static void main(String[] args) throws Exception {
+        String loopBack = null;
+        Socket socket = new Socket(loopBack, Integer.parseInt(args[0]));
+        InputStream inStream = socket.getInputStream();
+        OutputStream outStream = socket.getOutputStream();
+        Map<String, Consumer<OutputStream>> chans = new HashMap<>();
+        chans.put("out", st -> System.setOut(new PrintStream(st, true)));
+        chans.put("err", st -> System.setErr(new PrintStream(st, true)));
+        forwardExecutionControlAndIO(new RemoteExecutionControl(), inStream, outStream, chans);
+    }
+
+    // These three variables are used by the main JShell process in interrupting
+    // the running process.  Access is via JDI, so the reference is not visible
+    // to code inspection.
+    private boolean inClientCode; // Queried by the main process (in superclass)
+    private boolean expectingStop; // Set by the main process
+// Set by the main process
+
+    // thrown by the main process via JDI:
+    private final StopExecutionException stopException = new StopExecutionException();
+
+    /**
+     * Creates an instance, delegating loader operations to the specified
+     * delegate.
+     *
+     * @param loaderDelegate the delegate to handle loading classes
+     */
+    public RemoteExecutionControl(LoaderDelegate loaderDelegate) {
+        super(loaderDelegate);
+    }
+
+    /**
+     * Create an instance using the default class loading.
+     */
+    public RemoteExecutionControl() {
+    }
+
+    @Override
+    public void stop() throws EngineTerminationException, InternalException {
+        // handled by JDI
+    }
+
+    // Overridden only so this stack frame is seen
+    @Override
+    protected String invoke(Method doitMethod) throws Exception {
+        return super.invoke(doitMethod);
+    }
+
+    // Overridden only so this stack frame is seen
+    @Override
+    public String varValue(String className, String varName) throws RunException, EngineTerminationException, InternalException {
+        return super.varValue(className, varName);
+    }
+
+    @Override
+    protected String throwConvertedInvocationException(Throwable cause) throws RunException, InternalException {
+        if (cause instanceof StopExecutionException) {
+            expectingStop = false;
+            throw new StoppedException();
+        } else {
+            return super.throwConvertedInvocationException(cause);
+        }
+    }
+
+    @Override
+    protected String throwConvertedOtherException(Throwable ex) throws RunException, InternalException {
+        if (ex instanceof StopExecutionException ||
+                 ex.getCause() instanceof StopExecutionException) {
+            expectingStop = false;
+            throw new StoppedException();
+        }
+        return super.throwConvertedOtherException(ex);
+    }
+
+    @Override
+    protected void clientCodeEnter() {
+        expectingStop = false;
+        inClientCode = true;
+    }
+
+    @Override
+    protected void clientCodeLeave() throws InternalException {
+        inClientCode = false;
+        while (expectingStop) {
+            try {
+                Thread.sleep(0);
+            } catch (InterruptedException ex) {
+                throw new InternalException("*** Sleep interrupted while waiting for stop exception: " + ex);
+            }
+        }
+    }
+
+    @SuppressWarnings("serial")             // serialVersionUID intentionally omitted
+    private class StopExecutionException extends ThreadDeath {
+
+        @Override
+        public synchronized Throwable fillInStackTrace() {
+            return this;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/StreamingExecutionControl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import jdk.jshell.JShellException;
+import jdk.jshell.spi.ExecutionControl;
+import static jdk.jshell.execution.RemoteCodes.*;
+
+/**
+ * An implementation of the {@link jdk.jshell.spi.ExecutionControl}
+ * execution engine SPI which streams requests to a remote agent where
+ * execution takes place.
+ *
+ * @author Robert Field
+ */
+public class StreamingExecutionControl implements ExecutionControl {
+
+    private final ObjectOutput out;
+    private final ObjectInput in;
+
+    /**
+     * Creates an instance.
+     *
+     * @param out the output for commands
+     * @param in the input for command responses
+     */
+    public StreamingExecutionControl(ObjectOutput out, ObjectInput in) {
+        this.out = out;
+        this.in = in;
+    }
+
+    @Override
+    public void load(ClassBytecodes[] cbcs)
+            throws ClassInstallException, NotImplementedException, EngineTerminationException {
+        try {
+            // Send a load command to the remote agent.
+            writeCommand(CMD_LOAD);
+            out.writeObject(cbcs);
+            out.flush();
+            // Retrieve and report results from the remote agent.
+            readAndReportClassInstallResult();
+        } catch (IOException ex) {
+            throw new EngineTerminationException("Exception writing remote load: " + ex);
+        }
+    }
+
+    @Override
+    public void redefine(ClassBytecodes[] cbcs)
+            throws ClassInstallException, NotImplementedException, EngineTerminationException {
+        try {
+            // Send a load command to the remote agent.
+            writeCommand(CMD_REDEFINE);
+            out.writeObject(cbcs);
+            out.flush();
+            // Retrieve and report results from the remote agent.
+            readAndReportClassInstallResult();
+        } catch (IOException ex) {
+            throw new EngineTerminationException("Exception writing remote redefine: " + ex);
+        }
+    }
+
+    @Override
+    public String invoke(String classname, String methodname)
+            throws RunException, EngineTerminationException, InternalException {
+        try {
+            // Send the invoke command to the remote agent.
+            writeCommand(CMD_INVOKE);
+            out.writeUTF(classname);
+            out.writeUTF(methodname);
+            out.flush();
+            // Retrieve and report results from the remote agent.
+            readAndReportExecutionResult();
+            String result = in.readUTF();
+            return result;
+        } catch (IOException ex) {
+            throw new EngineTerminationException("Exception writing remote invoke: " + ex);
+        }
+    }
+
+    @Override
+    public String varValue(String classname, String varname)
+            throws RunException, EngineTerminationException, InternalException {
+        try {
+            // Send the variable-value command to the remote agent.
+            writeCommand(CMD_VAR_VALUE);
+            out.writeUTF(classname);
+            out.writeUTF(varname);
+            out.flush();
+            // Retrieve and report results from the remote agent.
+            readAndReportExecutionResult();
+            String result = in.readUTF();
+            return result;
+        } catch (IOException ex) {
+            throw new EngineTerminationException("Exception writing remote varValue: " + ex);
+        }
+    }
+
+
+    @Override
+    public void addToClasspath(String path)
+            throws EngineTerminationException, InternalException {
+        try {
+            // Send the classpath addition command to the remote agent.
+            writeCommand(CMD_ADD_CLASSPATH);
+            out.writeUTF(path);
+            out.flush();
+            // Retrieve and report results from the remote agent.
+            readAndReportClassSimpleResult();
+        } catch (IOException ex) {
+            throw new EngineTerminationException("Exception writing remote add to classpath: " + ex);
+        }
+    }
+
+    @Override
+    public void setClasspath(String path)
+            throws EngineTerminationException, InternalException {
+        try {
+            // Send the classpath addition command to the remote agent.
+            writeCommand(CMD_SET_CLASSPATH);
+            out.writeUTF(path);
+            out.flush();
+            // Retrieve and report results from the remote agent.
+            readAndReportClassSimpleResult();
+        } catch (IOException ex) {
+            throw new EngineTerminationException("Exception writing remote set classpath: " + ex);
+        }
+    }
+
+    @Override
+    public void stop()
+            throws EngineTerminationException, InternalException {
+        try {
+            // Send the variable-value command to the remote agent.
+            writeCommand(CMD_STOP);
+            out.flush();
+        } catch (IOException ex) {
+            throw new EngineTerminationException("Exception writing remote stop: " + ex);
+        }
+    }
+
+    @Override
+    public Object extensionCommand(String command, Object arg)
+            throws RunException, EngineTerminationException, InternalException {
+        try {
+            writeCommand(command);
+            out.writeObject(arg);
+            out.flush();
+            // Retrieve and report results from the remote agent.
+            readAndReportExecutionResult();
+            Object result = in.readObject();
+            return result;
+        } catch (IOException | ClassNotFoundException ex) {
+            throw new EngineTerminationException("Exception transmitting remote extensionCommand: "
+                    + command + " -- " + ex);
+        }
+    }
+
+    /**
+     * Closes the execution engine. Send an exit command to the remote agent.
+     */
+    @Override
+    public void close() {
+        try {
+            writeCommand(CMD_CLOSE);
+            out.flush();
+        } catch (IOException ex) {
+            // ignore;
+        }
+    }
+
+    private void writeCommand(String cmd) throws IOException {
+        out.writeInt(COMMAND_PREFIX);
+        out.writeUTF(cmd);
+    }
+
+    /**
+     * Reports results from a remote agent command that does not expect
+     * exceptions.
+     */
+    private void readAndReportClassSimpleResult() throws EngineTerminationException, InternalException {
+        try {
+            int status = in.readInt();
+            switch (status) {
+                case RESULT_SUCCESS:
+                    return;
+                case RESULT_NOT_IMPLEMENTED: {
+                    String message = in.readUTF();
+                    throw new NotImplementedException(message);
+                }
+                case RESULT_INTERNAL_PROBLEM: {
+                    String message = in.readUTF();
+                    throw new InternalException(message);
+                }
+                case RESULT_TERMINATED: {
+                    String message = in.readUTF();
+                    throw new EngineTerminationException(message);
+                }
+                default: {
+                    throw new EngineTerminationException("Bad remote result code: " + status);
+                }
+            }
+        } catch (IOException ex) {
+            throw new EngineTerminationException(ex.toString());
+        }
+    }
+
+    /**
+     * Reports results from a remote agent command that does not expect
+     * exceptions.
+     */
+    private void readAndReportClassInstallResult() throws ClassInstallException,
+            NotImplementedException, EngineTerminationException {
+        try {
+            int status = in.readInt();
+            switch (status) {
+                case RESULT_SUCCESS:
+                    return;
+                case RESULT_NOT_IMPLEMENTED: {
+                    String message = in.readUTF();
+                    throw new NotImplementedException(message);
+                }
+                case RESULT_CLASS_INSTALL_EXCEPTION: {
+                    String message = in.readUTF();
+                    boolean[] loaded = (boolean[]) in.readObject();
+                    throw new ClassInstallException(message, loaded);
+                }
+                case RESULT_TERMINATED: {
+                    String message = in.readUTF();
+                    throw new EngineTerminationException(message);
+                }
+                default: {
+                    throw new EngineTerminationException("Bad remote result code: " + status);
+                }
+            }
+        } catch (IOException | ClassNotFoundException ex) {
+            throw new EngineTerminationException(ex.toString());
+        }
+    }
+
+    /**
+     * Reports results from a remote agent command that expects runtime
+     * exceptions.
+     *
+     * @return true if successful
+     * @throws IOException if the connection has dropped
+     * @throws JShellException {@link jdk.jshell.EvalException}, if a user
+     * exception was encountered on invoke;
+     * {@link jdk.jshell.UnresolvedReferenceException}, if an unresolved
+     * reference was encountered
+     * @throws java.lang.ClassNotFoundException
+     */
+    private void readAndReportExecutionResult() throws RunException,
+            EngineTerminationException, InternalException {
+        try {
+            int status = in.readInt();
+            switch (status) {
+                case RESULT_SUCCESS:
+                    return;
+                case RESULT_NOT_IMPLEMENTED: {
+                    String message = in.readUTF();
+                    throw new NotImplementedException(message);
+                }
+                case RESULT_USER_EXCEPTION: {
+                    // A user exception was encountered.
+                    String message = in.readUTF();
+                    String exceptionClassName = in.readUTF();
+                    StackTraceElement[] elems = (StackTraceElement[]) in.readObject();
+                    throw new UserException(message, exceptionClassName, elems);
+                }
+                case RESULT_CORRALLED: {
+                    // An unresolved reference was encountered.
+                    int id = in.readInt();
+                    StackTraceElement[] elems = (StackTraceElement[]) in.readObject();
+                    ResolutionException re = new ResolutionException(id, elems);
+                    throw re;
+                }
+                case RESULT_STOPPED: {
+                    // Execution was aborted by the stop()
+                    throw new StoppedException();
+                }
+                case RESULT_INTERNAL_PROBLEM: {
+                    // An internal error has occurred.
+                    String message = in.readUTF();
+                    throw new InternalException(message);
+                }
+                case RESULT_TERMINATED: {
+                    String message = in.readUTF();
+                    throw new EngineTerminationException(message);
+                }
+                default: {
+                    throw new EngineTerminationException("Bad remote result code: " + status);
+                }
+            }
+        } catch (IOException | ClassNotFoundException ex) {
+            throw new EngineTerminationException(ex.toString());
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.jshell.execution;
+
+import jdk.jshell.spi.ExecutionEnv;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.function.Consumer;
+import com.sun.jdi.VirtualMachine;
+import jdk.jshell.spi.ExecutionControl;
+
+
+/**
+ * Miscellaneous utility methods for setting-up implementations of
+ * {@link ExecutionControl}. Particularly implementations with remote
+ * execution.
+ *
+ * @author Jan Lahoda
+ * @author Robert Field
+ */
+public class Util {
+
+    // never instanciated
+    private Util() {}
+
+    /**
+     * Create a composite {@link ExecutionControl.Generator} instance that, when
+     * generating, will try each specified generator until successfully creating
+     * an {@link ExecutionControl} instance, or, if all fail, will re-throw the
+     * first exception.
+     *
+     * @param gec0 the first instance to try
+     * @param gecs the second through Nth instance to try
+     * @return the fail-over generator
+     */
+    public static ExecutionControl.Generator failOverExecutionControlGenerator(
+            ExecutionControl.Generator gec0, ExecutionControl.Generator... gecs) {
+        return (ExecutionEnv env) -> {
+            Throwable thrown;
+            try {
+                return gec0.generate(env);
+            } catch (Throwable ex) {
+                thrown = ex;
+            }
+            for (ExecutionControl.Generator gec : gecs) {
+                try {
+                    return gec.generate(env);
+                } catch (Throwable ignore) {
+                    // only care about the first, and only if they all fail
+                }
+            }
+            throw thrown;
+        };
+    }
+
+    /**
+     * Forward commands from the input to the specified {@link ExecutionControl}
+     * instance, then responses back on the output.
+     * @param ec the direct instance of {@link ExecutionControl} to process commands
+     * @param in the command input
+     * @param out the command response output
+     */
+    public static void forwardExecutionControl(ExecutionControl ec,
+            ObjectInput in, ObjectOutput out) {
+        new ExecutionControlForwarder(ec, in, out).commandLoop();
+    }
+
+    /**
+     * Forward commands from the input to the specified {@link ExecutionControl}
+     * instance, then responses back on the output.
+     * @param ec the direct instance of {@link ExecutionControl} to process commands
+     * @param inStream the stream from which to create the command input
+     * @param outStream the stream that will carry {@code System.out},
+     * {@code System.err}, any specified auxiliary channels, and the
+     * command response output.
+     * @param streamMap a map between names of additional streams to carry and setters
+     * for the stream
+     * @throws IOException if there are errors using the passed streams
+     */
+    public static void forwardExecutionControlAndIO(ExecutionControl ec,
+            InputStream inStream, OutputStream outStream,
+            Map<String, Consumer<OutputStream>> streamMap) throws IOException {
+        ObjectInputStream cmdIn = new ObjectInputStream(inStream);
+        for (Entry<String, Consumer<OutputStream>> e : streamMap.entrySet()) {
+            e.getValue().accept(multiplexingOutputStream(e.getKey(), outStream));
+        }
+        ObjectOutputStream cmdOut = new ObjectOutputStream(multiplexingOutputStream("command", outStream));
+        forwardExecutionControl(ec, cmdIn, cmdOut);
+    }
+
+    static OutputStream multiplexingOutputStream(String label, OutputStream outputStream) {
+        return new MultiplexingOutputStream(label, outputStream);
+    }
+
+    /**
+     * Reads from an InputStream which has been packetized and write its contents
+     * to the out and err OutputStreams; Copies the command stream.
+     * @param input the packetized input stream
+     * @param streamMap a map between stream names and the output streams to forward
+     * @return the command stream
+     * @throws IOException if setting up the streams raised an exception
+     */
+    public static ObjectInput remoteInput(InputStream input,
+            Map<String, OutputStream> streamMap) throws IOException {
+        PipeInputStream commandIn = new PipeInputStream();
+        new DemultiplexInput(input, commandIn, streamMap).start();
+        return new ObjectInputStream(commandIn);
+    }
+
+    /**
+     * Monitor the JDI event stream for {@link com.sun.jdi.event.VMDeathEvent}
+     * and {@link com.sun.jdi.event.VMDisconnectEvent}. If encountered, invokes
+     * {@code unbiddenExitHandler}.
+     *
+     * @param vm the virtual machine to check
+     * @param unbiddenExitHandler the handler, which will accept the exit
+     * information
+     */
+    public static void detectJDIExitEvent(VirtualMachine vm, Consumer<String> unbiddenExitHandler) {
+        if (vm.canBeModified()) {
+            new JDIEventHandler(vm, unbiddenExitHandler).start();
+        }
+    }
+
+    /**
+     * Creates a Thread that will ship all input to the remote agent.
+     *
+     * @param inputStream the user input
+     * @param outStream the input to the remote agent
+     * @param handler a failure handler
+     */
+    public static void forwardInputToRemote(final InputStream inputStream,
+            final OutputStream outStream, final Consumer<Exception> handler) {
+        Thread thr = new Thread("input reader") {
+            @Override
+            public void run() {
+                try {
+                    byte[] buf = new byte[256];
+                    int cnt;
+                    while ((cnt = inputStream.read(buf)) != -1) {
+                        outStream.write(buf, 0, cnt);
+                        outStream.flush();
+                    }
+                } catch (Exception ex) {
+                    handler.accept(ex);
+                }
+            }
+        };
+        thr.setPriority(Thread.MAX_PRIORITY - 1);
+        thr.start();
+    }
+
+}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionControl.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionControl.java	Wed Jul 27 13:33:55 2016 +0000
@@ -22,62 +22,152 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.jshell.spi;
 
-import java.util.Collection;
-import jdk.jshell.JShellException;
+import java.io.Serializable;
 
 /**
- * This interface specifies the functionality that must provided to implement
- * a pluggable JShell execution engine.
+ * This interface specifies the functionality that must provided to implement a
+ * pluggable JShell execution engine.
  * <p>
- * The audience for this Service Provider Interface is engineers
- * wishing to implement their own version of the execution engine in support
- * of the JShell API.  This is NOT a part of the JShell API.
+ * The audience for this Service Provider Interface is engineers wishing to
+ * implement their own version of the execution engine in support of the JShell
+ * API.
  * <p>
- * A Snippet is compiled into code wrapped in a 'wrapper class'.  The execution
- * engine is used by the core JShell implementation to load and, for
- * executable Snippets, execute the Snippet.
+ * A Snippet is compiled into code wrapped in a 'wrapper class'. The execution
+ * engine is used by the core JShell implementation to load and, for executable
+ * Snippets, execute the Snippet.
  * <p>
  * Methods defined in this interface should only be called by the core JShell
  * implementation.
  * <p>
- * To install an instance of ExecutionControl, it is passed to
- * {@link jdk.jshell.JShell.Builder#executionEngine(jdk.jshell.spi.ExecutionControl) }.
+ * To install an {@code ExecutionControl}, its {@code Generator} is passed to
+ * {@link jdk.jshell.JShell.Builder#executionEngine(ExecutionControl.Generator)  }.
  */
 public interface ExecutionControl {
 
     /**
-     * Represents the current status of a class in the execution engine.
+     * Defines a functional interface for creating {@link ExecutionControl}
+     * instances.
      */
-    public enum ClassStatus {
-        /**
-         * Class is not known to the execution engine (not loaded).
-         */
-        UNKNOWN,
-
-        /**
-         * Class is loaded, but the loaded/redefined bytes do not match those
-         * returned by {@link ExecutionEnv#getClassBytes(java.lang.String) }.
-         */
-        NOT_CURRENT,
+    public interface Generator {
 
         /**
-         * Class is loaded and loaded/redefined bytes match those
-         * returned by {@link ExecutionEnv#getClassBytes(java.lang.String) }.
+         * Generates an execution engine, given an execution environment.
+         *
+         * @param env the context in which the {@link ExecutionControl} is to
+         * be created
+         * @return the created instance
+         * @throws Throwable if problems occurred
          */
-        CURRENT
-    };
+        ExecutionControl generate(ExecutionEnv env) throws Throwable;
+    }
+
+    /**
+     * Attempts to load new classes.
+     *
+     * @param cbcs the class name and bytecodes to load
+     * @throws ClassInstallException exception occurred loading the classes,
+     * some or all were not loaded
+     * @throws NotImplementedException if not implemented
+     * @throws EngineTerminationException the execution engine has terminated
+     */
+    void load(ClassBytecodes[] cbcs)
+            throws ClassInstallException, NotImplementedException, EngineTerminationException;
+
+    /**
+     * Attempts to redefine previously loaded classes.
+     *
+     * @param cbcs the class name and bytecodes to redefine
+     * @throws ClassInstallException exception occurred redefining the classes,
+     * some or all were not redefined
+     * @throws NotImplementedException if not implemented
+     * @throws EngineTerminationException the execution engine has terminated
+     */
+    void redefine(ClassBytecodes[] cbcs)
+            throws ClassInstallException, NotImplementedException, EngineTerminationException;
+
+    /**
+     * Invokes an executable Snippet by calling a method on the specified
+     * wrapper class. The method must have no arguments and return String.
+     *
+     * @param className the class whose method should be invoked
+     * @param methodName the name of method to invoke
+     * @return the result of the execution or null if no result
+     * @throws UserException the invoke raised a user exception
+     * @throws ResolutionException the invoke attempted to directly or
+     * indirectly invoke an unresolved snippet
+     * @throws StoppedException if the {@code invoke()} was canceled by
+     * {@link ExecutionControl#stop}
+     * @throws EngineTerminationException the execution engine has terminated
+     * @throws InternalException an internal problem occurred
+     */
+    String invoke(String className, String methodName)
+            throws RunException, EngineTerminationException, InternalException;
 
     /**
-     * Initializes the instance. No methods in this interface can be called
-     * before this.
+     * Returns the value of a variable.
+     *
+     * @param className the name of the wrapper class of the variable
+     * @param varName the name of the variable
+     * @return the value of the variable
+     * @throws UserException formatting the value raised a user exception
+     * @throws ResolutionException formatting the value attempted to directly or
+     * indirectly invoke an unresolved snippet
+     * @throws StoppedException if the formatting the value was canceled by
+     * {@link ExecutionControl#stop}
+     * @throws EngineTerminationException the execution engine has terminated
+     * @throws InternalException an internal problem occurred
+     */
+    String varValue(String className, String varName)
+            throws RunException, EngineTerminationException, InternalException;
+
+    /**
+     * Adds the path to the execution class path.
+     *
+     * @param path the path to add
+     * @throws EngineTerminationException the execution engine has terminated
+     * @throws InternalException an internal problem occurred
+     */
+    void addToClasspath(String path)
+            throws EngineTerminationException, InternalException;
+
+    /**
+     * Sets the execution class path to the specified path.
      *
-     * @param env the execution environment information provided by JShell
-     * @throws Exception if the instance is unable to initialize
+     * @param path the path to add
+     * @throws EngineTerminationException the execution engine has terminated
+     * @throws InternalException an internal problem occurred
+     */
+    void setClasspath(String path)
+            throws EngineTerminationException, InternalException;
+
+    /**
+     * Interrupts a running invoke.
+     *
+     * @throws EngineTerminationException the execution engine has terminated
+     * @throws InternalException an internal problem occurred
      */
-    void start(ExecutionEnv env) throws Exception;
+    void stop()
+            throws EngineTerminationException, InternalException;
+
+    /**
+     * Run a non-standard command (or a standard command from a newer version).
+     *
+     * @param command the non-standard command
+     * @param arg the commands argument
+     * @return the commands return value
+     * @throws UserException the command raised a user exception
+     * @throws ResolutionException the command attempted to directly or
+     * indirectly invoke an unresolved snippet
+     * @throws StoppedException if the command was canceled by
+     * {@link ExecutionControl#stop}
+     * @throws EngineTerminationException the execution engine has terminated
+     * @throws NotImplementedException if not implemented
+     * @throws InternalException an internal problem occurred
+     */
+    Object extensionCommand(String command, Object arg)
+            throws RunException, EngineTerminationException, InternalException;
 
     /**
      * Shuts down this execution engine. Implementation should free all
@@ -88,67 +178,206 @@
     void close();
 
     /**
-     * Adds the path to the execution class path.
-     *
-     * @param path the path to add
-     * @return true if successful
+     * Bundles class name with class bytecodes.
      */
-    boolean addToClasspath(String path);
+    public static final class ClassBytecodes implements Serializable {
+
+        private static final long serialVersionUID = 0xC1A55B47EC0DE5L;
+        private final String name;
+        private final byte[] bytecodes;
+
+        /**
+         * Creates a name/bytecode pair.
+         * @param name the class name
+         * @param bytecodes the class bytecodes
+         */
+        public ClassBytecodes(String name, byte[] bytecodes) {
+            this.name = name;
+            this.bytecodes = bytecodes;
+        }
+
+        /**
+         * The bytecodes for the class.
+         *
+         * @return the bytecodes
+         */
+        public byte[] bytecodes() {
+            return bytecodes;
+        }
+
+        /**
+         * The class name.
+         *
+         * @return the class name
+         */
+        public String name() {
+            return name;
+        }
+    }
 
     /**
-     * Invokes an executable Snippet by calling a method on the specified
-     * wrapper class. The method must have no arguments and return String.
-     *
-     * @param classname the class whose method should be invoked
-     * @param methodname the name of method to invoke
-     * @return the result of the execution or null if no result
-     * @throws JShellException if a user exception if thrown,
-     * {@link jdk.jshell.EvalException EvalException} will be thrown; if an
-     * unresolved reference is encountered,
-     * {@link jdk.jshell.UnresolvedReferenceException UnresolvedReferenceException}
-     * will be thrown
+     * The abstract base of all {@code ExecutionControl} exceptions.
      */
-    String invoke(String classname, String methodname) throws JShellException;
+    public static abstract class ExecutionControlException extends Exception {
+
+        private static final long serialVersionUID = 1L;
+
+        public ExecutionControlException(String message) {
+            super(message);
+        }
+    }
 
     /**
-     * Attempts to load new classes. Class bytes are retrieved from
-     * {@link ExecutionEnv#getClassBytes(java.lang.String) }
-     *
-     * @param classes list of class names to load
-     * @return true if load succeeded
+     * Unbidden execution engine termination has occurred.
+     */
+    public static class EngineTerminationException extends ExecutionControlException {
+
+        private static final long serialVersionUID = 1L;
+
+        public EngineTerminationException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * The command is not implemented.
      */
-    boolean load(Collection<String> classes);
+    public static class NotImplementedException extends InternalException {
+
+        private static final long serialVersionUID = 1L;
+
+        public NotImplementedException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * An internal problem has occurred.
+     */
+    public static class InternalException extends ExecutionControlException {
+
+        private static final long serialVersionUID = 1L;
+
+        public InternalException(String message) {
+            super(message);
+        }
+    }
 
     /**
-     * Attempts to redefine previously loaded classes. Class bytes are retrieved
-     * from {@link ExecutionEnv#getClassBytes(java.lang.String) }
-     *
-     * @param classes list of class names to redefine
-     * @return true if redefine succeeded
+     * A class install (load or redefine) encountered a problem.
      */
-    boolean redefine(Collection<String> classes);
+    public static class ClassInstallException extends ExecutionControlException {
+
+        private static final long serialVersionUID = 1L;
+
+        private final boolean[] installed;
+
+        public ClassInstallException(String message, boolean[] installed) {
+            super(message);
+            this.installed = installed;
+        }
+
+        /**
+         * Indicates which of the passed classes were successfully
+         * loaded/redefined.
+         * @return a one-to-one array with the {@link ClassBytecodes}{@code[]}
+         * array -- {@code true} if installed
+         */
+        public boolean[] installed() {
+            return installed;
+        }
+    }
+
+    /**
+     * The abstract base of of exceptions specific to running user code.
+     */
+    public static abstract class RunException extends ExecutionControlException {
+
+        private static final long serialVersionUID = 1L;
+
+        private RunException(String message) {
+            super(message);
+        }
+    }
 
     /**
-     * Queries if the class is loaded and the class bytes are current.
-     *
-     * @param classname name of the wrapper class to query
-     * @return {@code UNKNOWN} if the class is not loaded; {@code CURRENT} if
-     * the loaded/redefined bytes are equal to the most recent bytes for this
-     * wrapper class; otherwise {@code NOT_CURRENT}
+     * A 'normal' user exception occurred.
      */
-    ClassStatus getClassStatus(String classname);
+    public static class UserException extends RunException {
+
+        private static final long serialVersionUID = 1L;
+
+        private final String causeExceptionClass;
+
+        public UserException(String message, String causeExceptionClass, StackTraceElement[] stackElements) {
+            super(message);
+            this.causeExceptionClass = causeExceptionClass;
+            this.setStackTrace(stackElements);
+        }
+
+        /**
+         * Returns the class of the user exception.
+         * @return the name of the user exception class
+         */
+        public String causeExceptionClass() {
+            return causeExceptionClass;
+        }
+    }
 
     /**
-     * Interrupt a running invoke.
+     * An exception indicating that a {@code DeclarationSnippet} with unresolved
+     * references has been encountered.
+     * <p>
+     * Contrast this with the initiating {@link SPIResolutionException}
+     * (a {@code RuntimeException}) which is embedded in generated corralled
+     * code.  Also, contrast this with
+     * {@link jdk.jshell.UnresolvedReferenceException} the high-level
+     * exception (with {@code DeclarationSnippet} reference) provided in the
+     * main API.
      */
-    void stop();
+    public static class ResolutionException extends RunException {
+
+        private static final long serialVersionUID = 1L;
+
+        private final int id;
+
+        /**
+         * Constructs an exception indicating that a {@code DeclarationSnippet}
+         * with unresolved references has been encountered.
+         *
+         * @param id An internal identifier of the specific method
+         * @param stackElements the stack trace
+         */
+        public ResolutionException(int id, StackTraceElement[] stackElements) {
+            super("resolution exception: " + id);
+            this.id = id;
+            this.setStackTrace(stackElements);
+        }
+
+        /**
+         * Retrieves the internal identifier of the unresolved identifier.
+         *
+         * @return the internal identifier
+         */
+        public int id() {
+            return id;
+        }
+    }
 
     /**
-     * Returns the value of a variable.
-     *
-     * @param classname the name of the wrapper class of the variable
-     * @param varname the name of the variable
-     * @return the value of the variable
+     * An exception indicating that an
+     * {@link ExecutionControl#invoke(java.lang.String, java.lang.String) }
+     * (or theoretically a
+     * {@link ExecutionControl#varValue(java.lang.String, java.lang.String) })
+     * has been interrupted by a {@link ExecutionControl#stop() }.
      */
-    String varValue(String classname, String varname);
+    public static class StoppedException extends RunException {
+
+        private static final long serialVersionUID = 1L;
+
+        public StoppedException() {
+            super("stopped by stop()");
+        }
+    }
+
 }
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionEnv.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionEnv.java	Wed Jul 27 13:33:55 2016 +0000
@@ -28,14 +28,11 @@
 import java.io.InputStream;
 import java.io.PrintStream;
 import java.util.List;
-import jdk.jshell.EvalException;
 import jdk.jshell.JShell;
-import jdk.jshell.UnresolvedReferenceException;
 
 /**
  * Functionality made available to a pluggable JShell execution engine.  It is
- * provided to the execution engine by the core JShell implementation calling
- * {@link ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }.
+ * provided to the execution engine by the core JShell implementation.
  * <p>
  * This interface is designed to provide the access to core JShell functionality
  * needed to implement ExecutionControl.
@@ -66,11 +63,6 @@
     PrintStream userErr();
 
     /**
-     * @return the JShell instance
-     */
-    JShell state();
-
-    /**
      * Returns the additional VM options to be used when launching the remote
      * JVM. This is advice to the execution engine.
      * <p>
@@ -81,47 +73,8 @@
     List<String> extraRemoteVMOptions();
 
     /**
-     * Retrieves the class file bytes for the specified wrapper class.
-     *
-     * @param className the name of the wrapper class
-     * @return the current class file bytes as a byte array
-     */
-    byte[] getClassBytes(String className);
-
-    /**
-     * Creates an {@code EvalException} corresponding to a user exception. An
-     * user exception thrown during
-     * {@link ExecutionControl#invoke(java.lang.String, java.lang.String) }
-     * should be converted to an {@code EvalException} using this method.
-     *
-     * @param message the exception message to use (from the user exception)
-     * @param exceptionClass the class name of the user exception
-     * @param stackElements the stack trace elements to install
-     * @return a user API EvalException for the user exception
-     */
-    EvalException createEvalException(String message, String exceptionClass,
-            StackTraceElement[] stackElements);
-
-    /**
-     * Creates an {@code UnresolvedReferenceException} for the Snippet identifed
-     * by the specified identifier. An {@link SPIResolutionException} thrown
-     * during {@link ExecutionControl#invoke(java.lang.String, java.lang.String) }
-     * should be converted to an {@code UnresolvedReferenceException} using
-     * this method.
-     * <p>
-     * The identifier is an internal id, different from the id in the API. This
-     * internal id is returned by {@link SPIResolutionException#id()}.
-     *
-     * @param id the internal integer identifier
-     * @param stackElements the stack trace elements to install
-     * @return an {@code UnresolvedReferenceException} for the unresolved
-     * reference
-     */
-    UnresolvedReferenceException createUnresolvedReferenceException(int id,
-            StackTraceElement[] stackElements);
-
-    /**
      * Reports that the execution engine has shutdown.
      */
     void closeDown();
+
 }
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/SPIResolutionException.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/SPIResolutionException.java	Wed Jul 27 13:33:55 2016 +0000
@@ -33,9 +33,6 @@
  * <p>
  * This exception is seen by the execution engine, but not seen by
  * the end user nor through the JShell API.
- *
- * @see ExecutionEnv#createUnresolvedReferenceException(int,
- * java.lang.StackTraceElement[])
  */
 @SuppressWarnings("serial")             // serialVersionUID intentionally omitted
 public class SPIResolutionException extends RuntimeException {
@@ -57,11 +54,9 @@
     }
 
     /**
-     * Retrieves the internal identifer of the unresolved identifer.
+     * Retrieves the internal identifier of the unresolved identifier.
      *
-     * @return the internal identifer
-     * @see ExecutionEnv#createUnresolvedReferenceException(int,
-     * java.lang.StackTraceElement[])
+     * @return the internal identifier
      */
     public int id() {
         return id;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/package-info.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/package-info.java	Wed Jul 27 13:33:55 2016 +0000
@@ -31,9 +31,9 @@
  * implementation includes a default execution engine (currently a remote
  * process which is JDI controlled).  By implementing the
  * {@link jdk.jshell.spi.ExecutionControl} interface and installing it with
- * {@link jdk.jshell.JShell.Builder#executionEngine(jdk.jshell.spi.ExecutionControl) }
+ * {@link jdk.jshell.JShell.Builder#executionEngine(jdk.jshell.spi.ExecutionControl.Generator) }
  * other execution engines can be used.
  *
- * @see jdk.jshell.execution jdk.jshell.execution for execution implementation support
+ * @see jdk.jshell.execution for execution implementation support
  */
 package jdk.jshell.spi;
--- a/langtools/test/jdk/jshell/ComputeFQNsTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/jdk/jshell/ComputeFQNsTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -76,7 +76,7 @@
         assertInferredFQNs("class X { ArrayList", "ArrayList".length(), false, "java.util.ArrayList");
     }
 
-    @Test
+    @Test(enabled = false) //TODO 8161165
     public void testSuspendIndexing() throws Throwable {
         compiler.compile(outDir, "package test; public class FQNTest { }");
         String jarName = "test.jar";
--- a/langtools/test/jdk/jshell/FailOverExecutionControlTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/jdk/jshell/FailOverExecutionControlTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -23,23 +23,20 @@
 
 /*
  * @test
- * @bug 8131029
- * @summary Test that fail-over works for FailOverExecutionControl
- * @modules jdk.jshell/jdk.internal.jshell.jdi
+ * @bug 8131029 8160127 8159935
+ * @summary Test that fail-over works for fail-over ExecutionControl generators.
+ * @modules jdk.jshell/jdk.jshell.execution
  *          jdk.jshell/jdk.jshell.spi
  * @build KullaTesting ExecutionControlTestBase
  * @run testng FailOverExecutionControlTest
  */
 
-
-import java.util.Collection;
 import org.testng.annotations.Test;
 import org.testng.annotations.BeforeMethod;
-import jdk.internal.jshell.jdi.FailOverExecutionControl;
-import jdk.internal.jshell.jdi.JDIExecutionControl;
-import jdk.jshell.JShellException;
+import jdk.jshell.execution.JDIDefaultExecutionControl;
 import jdk.jshell.spi.ExecutionControl;
 import jdk.jshell.spi.ExecutionEnv;
+import static jdk.jshell.execution.Util.failOverExecutionControlGenerator;
 
 @Test
 public class FailOverExecutionControlTest extends ExecutionControlTestBase {
@@ -47,56 +44,16 @@
     @BeforeMethod
     @Override
     public void setUp() {
-        setUp(new FailOverExecutionControl(
-                new AlwaysFailingExecutionControl(),
-                new AlwaysFailingExecutionControl(),
-                new JDIExecutionControl()));
+        setUp(builder -> builder.executionEngine(failOverExecutionControlGenerator(
+                new AlwaysFailingGenerator(),
+                new AlwaysFailingGenerator(),
+                JDIDefaultExecutionControl.launch())));
     }
 
-    class AlwaysFailingExecutionControl implements ExecutionControl {
-
-        @Override
-        public void start(ExecutionEnv env) throws Exception {
-            throw new UnsupportedOperationException("This operation intentionally broken.");
-        }
-
-        @Override
-        public void close() {
-            throw new UnsupportedOperationException("This operation intentionally broken.");
-        }
-
-        @Override
-        public boolean addToClasspath(String path) {
-            throw new UnsupportedOperationException("This operation intentionally broken.");
-        }
+    class AlwaysFailingGenerator implements ExecutionControl.Generator {
 
         @Override
-        public String invoke(String classname, String methodname) throws JShellException {
-            throw new UnsupportedOperationException("This operation intentionally broken.");
-        }
-
-        @Override
-        public boolean load(Collection<String> classes) {
-            throw new UnsupportedOperationException("This operation intentionally broken.");
-        }
-
-        @Override
-        public boolean redefine(Collection<String> classes) {
-            throw new UnsupportedOperationException("This operation intentionally broken.");
-        }
-
-        @Override
-        public ClassStatus getClassStatus(String classname) {
-            throw new UnsupportedOperationException("This operation intentionally broken.");
-        }
-
-        @Override
-        public void stop() {
-            throw new UnsupportedOperationException("This operation intentionally broken.");
-        }
-
-        @Override
-        public String varValue(String classname, String varname) {
+        public ExecutionControl generate(ExecutionEnv env) throws UnsupportedOperationException {
             throw new UnsupportedOperationException("This operation intentionally broken.");
         }
 
--- a/langtools/test/jdk/jshell/JDIListeningExecutionControlTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/jdk/jshell/JDIListeningExecutionControlTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -23,9 +23,9 @@
 
 /*
  * @test
- * @bug 8131029
+ * @bug 8131029 8159935 8160127
  * @summary Tests for alternate JDI connector -- listening
- * @modules jdk.jshell/jdk.internal.jshell.jdi
+ * @modules jdk.jshell/jdk.jshell.execution
  * @build KullaTesting ExecutionControlTestBase
  * @run testng JDIListeningExecutionControlTest
  */
@@ -33,7 +33,7 @@
 
 import org.testng.annotations.Test;
 import org.testng.annotations.BeforeMethod;
-import jdk.internal.jshell.jdi.JDIExecutionControl;
+import jdk.jshell.execution.JDIDefaultExecutionControl;
 
 @Test
 public class JDIListeningExecutionControlTest extends ExecutionControlTestBase {
@@ -41,6 +41,6 @@
     @BeforeMethod
     @Override
     public void setUp() {
-        setUp(new JDIExecutionControl(false));
+        setUp(builder -> builder.executionEngine(JDIDefaultExecutionControl.listen()));
     }
 }
--- a/langtools/test/jdk/jshell/KullaTesting.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/jdk/jshell/KullaTesting.java	Wed Jul 27 13:33:55 2016 +0000
@@ -73,7 +73,6 @@
 import static jdk.jshell.Snippet.Status.*;
 import static org.testng.Assert.*;
 import static jdk.jshell.Snippet.SubKind.METHOD_SUBKIND;
-import jdk.jshell.spi.ExecutionControl;
 
 public class KullaTesting {
 
@@ -158,10 +157,6 @@
         setUp(b -> {});
     }
 
-    public void setUp(ExecutionControl ec) {
-        setUp(b -> b.executionEngine(ec));
-    }
-
     public void setUp(Consumer<JShell.Builder> bc) {
         inStream = new TestingInputStream();
         outStream = new ByteArrayOutputStream();
--- a/langtools/test/jdk/jshell/LocalExecutionControl.java	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,313 +0,0 @@
-/*
- * Copyright (c) 2016, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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 jdk.jshell.spi.ExecutionControl;
-import jdk.jshell.spi.ExecutionEnv;
-import jdk.jshell.spi.SPIResolutionException;
-import jdk.jshell.EvalException;
-import jdk.jshell.UnresolvedReferenceException;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.CodeSource;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * An implementation of ExecutionControl which executes in the same JVM as the
- * JShell core.
- *
- * @author Grigory Ptashko
- */
-class LocalExecutionControl implements ExecutionControl {
-    private class REPLClassLoader extends URLClassLoader {
-        REPLClassLoader() {
-            super(new URL[0]);
-        }
-
-        @Override
-        protected Class<?> findClass(String name) throws ClassNotFoundException {
-            debug("findClass %s\n", name);
-            byte[] b = execEnv.getClassBytes(name);
-            if (b == null) {
-                return super.findClass(name);
-            }
-            return super.defineClass(name, b, 0, b.length, (CodeSource)null);
-        }
-
-        @Override
-        public void addURL(URL url) {
-            super.addURL(url);
-        }
-    }
-
-    private ExecutionEnv execEnv;
-    private final Object STOP_LOCK = new Object();
-    private boolean userCodeRunning = false;
-    private REPLClassLoader loader = new REPLClassLoader();
-    private final Map<String, Class<?>> klasses = new TreeMap<>();
-    private final Map<String, byte[]> classBytes = new HashMap<>();
-    private ThreadGroup execThreadGroup;
-
-    @Override
-    public void start(ExecutionEnv execEnv) throws Exception {
-        this.execEnv = execEnv;
-
-        debug("Process-local code snippets execution control started");
-    }
-
-    @Override
-    public void close() {
-    }
-
-    @Override
-    public boolean load(Collection<String> classes) {
-        try {
-            loadLocal(classes);
-
-            return true;
-        } catch (ClassNotFoundException | ClassCastException ex) {
-            debug(ex, "Exception on load operation");
-        }
-
-        return false;
-    }
-
-    @Override
-    public String invoke(String classname, String methodname) throws EvalException, UnresolvedReferenceException {
-        try {
-            synchronized (STOP_LOCK) {
-                userCodeRunning = true;
-            }
-
-            // Invoke executable entry point in loaded code
-            Class<?> klass = klasses.get(classname);
-            if (klass == null) {
-                debug("Invoke failure: no such class loaded %s\n", classname);
-
-                return "";
-            }
-
-            Method doitMethod;
-            try {
-                this.getClass().getModule().addReads(klass.getModule());
-                this.getClass().getModule().addExports(SPIResolutionException.class.getPackage()
-                        .getName(), klass.getModule());
-                doitMethod = klass.getDeclaredMethod(methodname, new Class<?>[0]);
-                doitMethod.setAccessible(true);
-
-                execThreadGroup = new ThreadGroup("JShell process local execution");
-
-                AtomicReference<InvocationTargetException> iteEx = new AtomicReference<>();
-                AtomicReference<IllegalAccessException> iaeEx = new AtomicReference<>();
-                AtomicReference<NoSuchMethodException> nmeEx = new AtomicReference<>();
-                AtomicReference<Boolean> stopped = new AtomicReference<>(false);
-
-                Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
-                    if (e instanceof InvocationTargetException) {
-                        if (e.getCause() instanceof ThreadDeath) {
-                            stopped.set(true);
-                        } else {
-                            iteEx.set((InvocationTargetException)e);
-                        }
-                    } else if (e instanceof IllegalAccessException) {
-                        iaeEx.set((IllegalAccessException)e);
-                    } else if (e instanceof NoSuchMethodException) {
-                        nmeEx.set((NoSuchMethodException)e);
-                    } else if (e instanceof ThreadDeath) {
-                        stopped.set(true);
-                    }
-                });
-
-                final Object[] res = new Object[1];
-                Thread snippetThread = new Thread(execThreadGroup, () -> {
-                    try {
-                        res[0] = doitMethod.invoke(null, new Object[0]);
-                    } catch (InvocationTargetException e) {
-                        if (e.getCause() instanceof ThreadDeath) {
-                            stopped.set(true);
-                        } else {
-                            iteEx.set(e);
-                        }
-                    } catch (IllegalAccessException e) {
-                        iaeEx.set(e);
-                    } catch (ThreadDeath e) {
-                        stopped.set(true);
-                    }
-                });
-
-                snippetThread.start();
-                Thread[] threadList = new Thread[execThreadGroup.activeCount()];
-                execThreadGroup.enumerate(threadList);
-                for (Thread thread : threadList) {
-                    if (thread != null)
-                        thread.join();
-                }
-
-                if (stopped.get()) {
-                    debug("Killed.");
-
-                    return "";
-                }
-
-                if (iteEx.get() != null) {
-                    throw iteEx.get();
-                } else if (nmeEx.get() != null) {
-                    throw nmeEx.get();
-                } else if (iaeEx.get() != null) {
-                    throw iaeEx.get();
-                }
-
-                return valueString(res[0]);
-            } catch (InvocationTargetException ex) {
-                Throwable cause = ex.getCause();
-                StackTraceElement[] elems = cause.getStackTrace();
-                if (cause instanceof SPIResolutionException) {
-                    int id = ((SPIResolutionException)cause).id();
-
-                    throw execEnv.createUnresolvedReferenceException(id, elems);
-                } else {
-                    throw execEnv.createEvalException(cause.getMessage() == null ?
-                            "<none>" : cause.getMessage(), cause.getClass().getName(), elems);
-                }
-            } catch (NoSuchMethodException | IllegalAccessException | InterruptedException ex) {
-                debug(ex, "Invoke failure");
-            }
-        } finally {
-            synchronized (STOP_LOCK) {
-                userCodeRunning = false;
-            }
-        }
-
-        return "";
-    }
-
-    @Override
-    @SuppressWarnings("deprecation")
-    public void stop() {
-        synchronized (STOP_LOCK) {
-            if (!userCodeRunning)
-                return;
-
-            if (execThreadGroup == null) {
-                debug("Process-local code snippets thread group is null. Aborting stop.");
-
-                return;
-            }
-
-            execThreadGroup.stop();
-        }
-    }
-
-    @Override
-    public String varValue(String classname, String varname) {
-        Class<?> klass = klasses.get(classname);
-        if (klass == null) {
-            debug("Var value failure: no such class loaded %s\n", classname);
-
-            return "";
-        }
-        try {
-            this.getClass().getModule().addReads(klass.getModule());
-            Field var = klass.getDeclaredField(varname);
-            var.setAccessible(true);
-            Object res = var.get(null);
-
-            return valueString(res);
-        } catch (Exception ex) {
-            debug("Var value failure: no such field %s.%s\n", classname, varname);
-        }
-
-        return "";
-    }
-
-    @Override
-    public boolean addToClasspath(String cp) {
-        // Append to the claspath
-        for (String path : cp.split(File.pathSeparator)) {
-            try {
-                loader.addURL(new File(path).toURI().toURL());
-            } catch (MalformedURLException e) {
-                throw new InternalError("Classpath addition failed: " + cp, e);
-            }
-        }
-
-        return true;
-    }
-
-    @Override
-    public boolean redefine(Collection<String> classes) {
-        return false;
-    }
-
-    @Override
-    public ClassStatus getClassStatus(String classname) {
-        if (!classBytes.containsKey(classname)) {
-            return ClassStatus.UNKNOWN;
-        } else if (!Arrays.equals(classBytes.get(classname), execEnv.getClassBytes(classname))) {
-            return ClassStatus.NOT_CURRENT;
-        } else {
-            return ClassStatus.CURRENT;
-        }
-    }
-
-    private void loadLocal(Collection<String> classes) throws ClassNotFoundException {
-        for (String className : classes) {
-            Class<?> klass = loader.loadClass(className);
-            klasses.put(className, klass);
-            classBytes.put(className, execEnv.getClassBytes(className));
-            klass.getDeclaredMethods();
-        }
-    }
-
-    private void debug(String format, Object... args) {
-        //debug(execEnv.state(), execEnv.userErr(), flags, format, args);
-    }
-
-    private void debug(Exception ex, String where) {
-        //debug(execEnv.state(), execEnv.userErr(), ex, where);
-    }
-
-    private static String valueString(Object value) {
-        if (value == null) {
-            return "null";
-        } else if (value instanceof String) {
-            return "\"" + (String)value + "\"";
-        } else if (value instanceof Character) {
-            return "'" + value + "'";
-        } else {
-            return value.toString();
-        }
-    }
-}
--- a/langtools/test/jdk/jshell/UserExecutionControlTest.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/jdk/jshell/UserExecutionControlTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -23,13 +23,14 @@
 
 /*
  * @test
- * @bug 8156101
+ * @bug 8156101 8159935 8159122
  * @summary Tests for ExecutionControl SPI
- * @build KullaTesting LocalExecutionControl ExecutionControlTestBase
+ * @build KullaTesting ExecutionControlTestBase
  * @run testng UserExecutionControlTest
  */
 
 
+import jdk.jshell.execution.LocalExecutionControl;
 import org.testng.annotations.Test;
 import static org.testng.Assert.assertEquals;
 import org.testng.annotations.BeforeMethod;
@@ -40,7 +41,7 @@
     @BeforeMethod
     @Override
     public void setUp() {
-        setUp(new LocalExecutionControl());
+        setUp(builder -> builder.executionEngine(LocalExecutionControl.create()));
     }
 
     public void verifyLocal() throws ClassNotFoundException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/UserJDIUserRemoteTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2016, 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 8160128 8159935
+ * @summary Tests for Aux channel, custom remote agents, custom JDI implementations.
+ * @build KullaTesting ExecutionControlTestBase
+ * @run testng UserJDIUserRemoteTest
+ */
+import java.io.ByteArrayOutputStream;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+import jdk.jshell.Snippet;
+import static jdk.jshell.Snippet.Status.OVERWRITTEN;
+import static jdk.jshell.Snippet.Status.VALID;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.List;
+import com.sun.jdi.VMDisconnectedException;
+import com.sun.jdi.VirtualMachine;
+import jdk.jshell.VarSnippet;
+import jdk.jshell.execution.DirectExecutionControl;
+import jdk.jshell.execution.JDIExecutionControl;
+import jdk.jshell.execution.JDIInitiator;
+import jdk.jshell.execution.Util;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.Socket;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+import jdk.jshell.spi.ExecutionControl;
+import jdk.jshell.spi.ExecutionControl.ExecutionControlException;
+import jdk.jshell.spi.ExecutionEnv;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+import static jdk.jshell.execution.Util.forwardExecutionControlAndIO;
+import static jdk.jshell.execution.Util.remoteInput;
+
+@Test
+public class UserJDIUserRemoteTest extends ExecutionControlTestBase {
+
+    ExecutionControl currentEC;
+    ByteArrayOutputStream auxStream;
+
+    @BeforeMethod
+    @Override
+    public void setUp() {
+        auxStream = new ByteArrayOutputStream();
+        setUp(builder -> builder.executionEngine(MyExecutionControl.create(this)));
+    }
+
+    public void testVarValue() {
+        VarSnippet dv = varKey(assertEval("double aDouble = 1.5;"));
+        String vd = getState().varValue(dv);
+        assertEquals(vd, "1.5");
+        assertEquals(auxStream.toString(), "aDouble");
+    }
+
+    public void testExtension() throws ExecutionControlException {
+        assertEval("42;");
+        Object res = currentEC.extensionCommand("FROG", "test");
+        assertEquals(res, "ribbit");
+    }
+
+    public void testRedefine() {
+        Snippet vx = varKey(assertEval("int x;"));
+        Snippet mu = methodKey(assertEval("int mu() { return x * 4; }"));
+        Snippet c = classKey(assertEval("class C { String v() { return \"#\" + mu(); } }"));
+        assertEval("C c0  = new C();");
+        assertEval("c0.v();", "\"#0\"");
+        assertEval("int x = 10;", "10",
+                ste(MAIN_SNIPPET, VALID, VALID, false, null),
+                ste(vx, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+        assertEval("c0.v();", "\"#40\"");
+        assertEval("C c = new C();");
+        assertEval("c.v();", "\"#40\"");
+        assertEval("int mu() { return x * 3; }",
+                ste(MAIN_SNIPPET, VALID, VALID, false, null),
+                ste(mu, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+        assertEval("c.v();", "\"#30\"");
+        assertEval("class C { String v() { return \"@\" + mu(); } }",
+                ste(MAIN_SNIPPET, VALID, VALID, false, null),
+                ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+        assertEval("c0.v();", "\"@30\"");
+        assertEval("c = new C();");
+        assertEval("c.v();", "\"@30\"");
+        assertActiveKeys();
+    }
+}
+
+class MyExecutionControl extends JDIExecutionControl {
+
+    private static final String REMOTE_AGENT = MyRemoteExecutionControl.class.getName();
+
+    private VirtualMachine vm;
+    private Process process;
+
+    /**
+     * Creates an ExecutionControl instance based on a JDI
+     * {@code LaunchingConnector}.
+     *
+     * @return the generator
+     */
+    public static ExecutionControl.Generator create(UserJDIUserRemoteTest test) {
+        return env -> make(env, test);
+    }
+
+    /**
+     * Creates an ExecutionControl instance based on a JDI
+     * {@code ListeningConnector} or {@code LaunchingConnector}.
+     *
+     * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
+     * commands and results. This socket also transports the user
+     * input/output/error.
+     *
+     * @param env the context passed by
+         * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
+     * @return the channel
+     * @throws IOException if there are errors in set-up
+     */
+    static MyExecutionControl make(ExecutionEnv env, UserJDIUserRemoteTest test) throws IOException {
+        try (final ServerSocket listener = new ServerSocket(0)) {
+            // timeout after 60 seconds
+            listener.setSoTimeout(60000);
+            int port = listener.getLocalPort();
+
+            // Set-up the JDI connection
+            List<String> opts = new ArrayList<>(env.extraRemoteVMOptions());
+            opts.add("-classpath");
+            opts.add(System.getProperty("java.class.path")
+                    + System.getProperty("path.separator")
+                    + System.getProperty("user.dir"));
+            JDIInitiator jdii = new JDIInitiator(port,
+                    opts, REMOTE_AGENT, true);
+            VirtualMachine vm = jdii.vm();
+            Process process = jdii.process();
+
+            List<Consumer<String>> deathListeners = new ArrayList<>();
+            deathListeners.add(s -> env.closeDown());
+            Util.detectJDIExitEvent(vm, s -> {
+                for (Consumer<String> h : deathListeners) {
+                    h.accept(s);
+                }
+            });
+
+            // Set-up the commands/reslts on the socket.  Piggy-back snippet
+            // output.
+            Socket socket = listener.accept();
+            // out before in -- match remote creation so we don't hang
+            ObjectOutput cmdout = new ObjectOutputStream(socket.getOutputStream());
+            Map<String, OutputStream> io = new HashMap<>();
+            io.put("out", env.userOut());
+            io.put("err", env.userErr());
+            io.put("aux", test.auxStream);
+            ObjectInput cmdin = remoteInput(socket.getInputStream(), io);
+            MyExecutionControl myec = new MyExecutionControl(cmdout, cmdin, vm, process, deathListeners);
+            test.currentEC = myec;
+            return myec;
+        }
+    }
+
+    /**
+     * Create an instance.
+     *
+     * @param out the output for commands
+     * @param in the input for responses
+     */
+    private MyExecutionControl(ObjectOutput out, ObjectInput in,
+            VirtualMachine vm, Process process,
+            List<Consumer<String>> deathListeners) {
+        super(out, in);
+        this.vm = vm;
+        this.process = process;
+        deathListeners.add(s -> disposeVM());
+    }
+
+    @Override
+    public void close() {
+        super.close();
+        disposeVM();
+    }
+
+    private synchronized void disposeVM() {
+        try {
+            if (vm != null) {
+                vm.dispose(); // This could NPE, so it is caught below
+                vm = null;
+            }
+        } catch (VMDisconnectedException ex) {
+            // Ignore if already closed
+        } catch (Throwable e) {
+            fail("disposeVM threw: " + e);
+        } finally {
+            if (process != null) {
+                process.destroy();
+                process = null;
+            }
+        }
+    }
+
+    @Override
+    protected synchronized VirtualMachine vm() throws EngineTerminationException {
+        if (vm == null) {
+            throw new EngineTerminationException("VM closed");
+        } else {
+            return vm;
+        }
+    }
+
+}
+
+class MyRemoteExecutionControl extends DirectExecutionControl implements ExecutionControl {
+
+    static PrintStream auxPrint;
+
+    /**
+     * Launch the agent, connecting to the JShell-core over the socket specified
+     * in the command-line argument.
+     *
+     * @param args standard command-line arguments, expectation is the socket
+     * number is the only argument
+     * @throws Exception any unexpected exception
+     */
+    public static void main(String[] args) throws Exception {
+        try {
+            String loopBack = null;
+            Socket socket = new Socket(loopBack, Integer.parseInt(args[0]));
+            InputStream inStream = socket.getInputStream();
+            OutputStream outStream = socket.getOutputStream();
+            Map<String, Consumer<OutputStream>> chans = new HashMap<>();
+            chans.put("out", st -> System.setOut(new PrintStream(st, true)));
+            chans.put("err", st -> System.setErr(new PrintStream(st, true)));
+            chans.put("aux", st -> { auxPrint = new PrintStream(st, true); });
+            forwardExecutionControlAndIO(new MyRemoteExecutionControl(), inStream, outStream, chans);
+        } catch (Throwable ex) {
+            throw ex;
+        }
+    }
+
+    @Override
+    public String varValue(String className, String varName)
+            throws RunException, EngineTerminationException, InternalException {
+        auxPrint.print(varName);
+        return super.varValue(className, varName);
+    }
+
+    @Override
+    public Object extensionCommand(String className, Object arg)
+            throws RunException, EngineTerminationException, InternalException {
+        if (!arg.equals("test")) {
+            throw new InternalException("expected extensionCommand arg to be 'test' got: " + arg);
+        }
+        return "ribbit";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8161985/T8161985a.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8161985
+ * @summary Spurious override of Object.getClass leads to NPE
+ * @compile/fail/ref=T8161985a.out -XDrawDiagnostics T8161985a.java
+ */
+
+class T8161985 {
+    public static void main(String [] arg) {
+        T8161985 t = new T8161985();
+        t.getClass();
+
+    }
+    public void getClass() {
+        Fred1 f = new Fred1();
+        System.out.println( "fred classname: " + f.getClassName());
+    }
+
+
+    abstract class Fred {
+        public String getClassName() {
+            return this.getClass().getSimpleName();
+        }
+    }
+
+    class Fred1 extends Fred {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8161985/T8161985a.out	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,2 @@
+T8161985a.java:14:17: compiler.err.override.meth: (compiler.misc.cant.override: getClass(), T8161985, getClass(), java.lang.Object), final
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8161985/T8161985b.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8161985
+ * @summary Spurious override of Object.getClass leads to NPE
+ * @compile/fail/ref=T8161985b.out -XDrawDiagnostics T8161985b.java
+ */
+
+class T8161985b {
+   public String getClass() { return ""; }
+
+   void test() {
+      this.getClass().getSimpleName();
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8161985/T8161985b.out	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,3 @@
+T8161985b.java:9:18: compiler.err.override.meth: (compiler.misc.cant.override: getClass(), T8161985b, getClass(), java.lang.Object), final
+T8161985b.java:12:22: compiler.err.cant.resolve.location.args: kindname.method, getSimpleName, , , (compiler.misc.location: kindname.class, java.lang.String, null)
+2 errors
--- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234a.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234a.java	Wed Jul 27 13:33:55 2016 +0000
@@ -3,8 +3,8 @@
  * @bug     6722234
  * @summary javac diagnostics need better integration with the type-system
  * @author  mcimadamore
- * @compile/fail/ref=T6722234a_1.out -XDrawDiagnostics -XDdiags=disambiguateTvars T6722234a.java
- * @compile/fail/ref=T6722234a_2.out -XDrawDiagnostics -XDdiags=disambiguateTvars,where T6722234a.java
+ * @compile/fail/ref=T6722234a_1.out -XDrawDiagnostics -diags:formatterOptions=disambiguateTvars T6722234a.java
+ * @compile/fail/ref=T6722234a_2.out -XDrawDiagnostics -diags:formatterOptions=disambiguateTvars,where T6722234a.java
  */
 
 class T6722234a<T extends String> {
--- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234b.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234b.java	Wed Jul 27 13:33:55 2016 +0000
@@ -3,8 +3,8 @@
  * @bug     6722234 8078024
  * @summary javac diagnostics need better integration with the type-system
  * @author  mcimadamore
- * @compile/fail/ref=T6722234b_1.out -XDrawDiagnostics -XDdiags=simpleNames T6722234b.java
- * @compile/fail/ref=T6722234b_2.out -XDrawDiagnostics -XDdiags=simpleNames,where T6722234b.java
+ * @compile/fail/ref=T6722234b_1.out -XDrawDiagnostics -diags:formatterOptions=simpleNames T6722234b.java
+ * @compile/fail/ref=T6722234b_2.out -XDrawDiagnostics -diags:formatterOptions=simpleNames,where T6722234b.java
  */
 
 import java.util.*;
--- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234c.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234c.java	Wed Jul 27 13:33:55 2016 +0000
@@ -3,7 +3,7 @@
  * @bug     6722234
  * @summary javac diagnostics need better integration with the type-system
  * @author  mcimadamore
- * @compile/fail/ref=T6722234c.out -XDrawDiagnostics -XDdiags=simpleNames T6722234c.java
+ * @compile/fail/ref=T6722234c.out -XDrawDiagnostics -diags:formatterOptions=simpleNames T6722234c.java
  */
 
 class T6722234c {
--- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234d.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234d.java	Wed Jul 27 13:33:55 2016 +0000
@@ -3,8 +3,8 @@
  * @bug     6722234 8078024
  * @summary javac diagnostics need better integration with the type-system
  * @author  mcimadamore
- * @compile/fail/ref=T6722234d_1.out -XDrawDiagnostics -XDdiags=where T6722234d.java
- * @compile/fail/ref=T6722234d_2.out -XDrawDiagnostics -XDdiags=where,simpleNames T6722234d.java
+ * @compile/fail/ref=T6722234d_1.out -XDrawDiagnostics -diags:formatterOptions=where T6722234d.java
+ * @compile/fail/ref=T6722234d_2.out -XDrawDiagnostics -diags:formatterOptions=where,simpleNames T6722234d.java
  */
 
 class T6722234d {
--- a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, 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
@@ -59,8 +59,8 @@
 
     enum CaretKind {
         DEFAULT("", ""),
-        SHOW("showCaret","true"),
-        HIDE("showCaret","false");
+        SHOW("diags.showCaret","true"),
+        HIDE("diags.showCaret","false");
 
         String key;
         String value;
@@ -81,8 +81,8 @@
 
     enum SourceLineKind {
         DEFAULT("", ""),
-        AFTER_SUMMARY("sourcePosition", "top"),
-        BOTTOM("sourcePosition", "bottom");
+        AFTER_SUMMARY("diags.sourcePosition", "top"),
+        BOTTOM("diags.sourcePosition", "bottom");
 
         String key;
         String value;
@@ -110,9 +110,9 @@
 
         void init(Options opts) {
             if (this != DEFAULT) {
-                String flags = opts.get("diags");
+                String flags = opts.get("diags.formatterOptions");
                 flags = flags == null ? flag : flags + "," + flag;
-                opts.put("diags", flags);
+                opts.put("diags.formatterOptions", flags);
             }
         }
 
@@ -136,9 +136,9 @@
 
         void init(Options opts) {
             if (this != DEFAULT) {
-                String flags = opts.get("diags");
+                String flags = opts.get("diags.formatterOptions");
                 flags = flags == null ? flag : flags + "," + flag;
-                opts.put("diags", flags);
+                opts.put("diags.formatterOptions", flags);
             }
         }
 
@@ -243,11 +243,11 @@
     }
 
     enum MultilinePolicy {
-        ENABLED(0, "multilinePolicy", "enabled"),
-        DISABLED(1, "multilinePolicy", "disabled"),
-        LIMIT_LENGTH(2, "multilinePolicy", "limit:1:*"),
-        LIMIT_DEPTH(3, "multilinePolicy", "limit:*:1"),
-        LIMIT_BOTH(4, "multilinePolicy", "limit:1:1");
+        ENABLED(0, "diags.multilinePolicy", "enabled"),
+        DISABLED(1, "diags.multilinePolicy", "disabled"),
+        LIMIT_LENGTH(2, "diags.multilinePolicy", "limit:1:*"),
+        LIMIT_DEPTH(3, "diags.multilinePolicy", "limit:*:1"),
+        LIMIT_BOTH(4, "diags.multilinePolicy", "limit:1:1");
 
         String name;
         String value;
@@ -371,7 +371,7 @@
         indentString += (detailsIndent == IndentKind.CUSTOM) ? "|3" : "|0";
         indentString += (sourceIndent == IndentKind.CUSTOM) ? "|3" : "|0";
         indentString += (subdiagsIndent == IndentKind.CUSTOM) ? "|3" : "|0";
-        options.put("diagsIndentation", indentString);
+        options.put("diags.indent", indentString);
         MyLog log = new MyLog(ctx);
         JavacMessages messages = JavacMessages.instance(ctx);
         messages.add(locale -> ResourceBundle.getBundle("tester", locale));
--- a/langtools/test/tools/javac/Diagnostics/6862608/T6862608a.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/Diagnostics/6862608/T6862608a.java	Wed Jul 27 13:33:55 2016 +0000
@@ -3,7 +3,7 @@
  * @bug     6862608
  * @summary rich diagnostic sometimes contain wrong type variable numbering
  * @author  mcimadamore
- * @compile/fail/ref=T6862608a.out -XDrawDiagnostics -XDdiags=disambiguateTvars,where T6862608a.java
+ * @compile/fail/ref=T6862608a.out -XDrawDiagnostics -diags:formatterOptions=disambiguateTvars,where T6862608a.java
  */
 
 
--- a/langtools/test/tools/javac/Diagnostics/6862608/T6862608b.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/Diagnostics/6862608/T6862608b.java	Wed Jul 27 13:33:55 2016 +0000
@@ -3,7 +3,7 @@
  * @bug     6862608
  * @summary rich diagnostic sometimes contain wrong type variable numbering
  * @author  mcimadamore
- * @compile/fail/ref=T6862608b.out -XDrawDiagnostics -XDdiags=disambiguateTvars,where T6862608b.java
+ * @compile/fail/ref=T6862608b.out -XDrawDiagnostics -diags:formatterOptions=disambiguateTvars,where T6862608b.java
  */
 
 class T66862608b<T extends String, S> {
--- a/langtools/test/tools/javac/Diagnostics/7010608/Test.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/Diagnostics/7010608/Test.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -46,9 +46,9 @@
         try {
             test(Arrays.<String>asList(),
                     "myfo://test:1: error: cannot find symbol");
-            test(Arrays.asList("-XDdiagsFormat=OLD"),
+            test(Arrays.asList("-diags:layout=OLD"),
                     "myfo://test:1: cannot find symbol");
-            test(Arrays.asList("-XDoldDiags"),
+            test(Arrays.asList("-diags:legacy"),
                     "myfo://test:1: cannot find symbol");
         } finally {
             Locale.setDefault(prev);
--- a/langtools/test/tools/javac/Diagnostics/8010387/T8010387.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/Diagnostics/8010387/T8010387.java	Wed Jul 27 13:33:55 2016 +0000
@@ -2,7 +2,7 @@
  * @test /nodynamiccopyright/
  * @bug     8010387
  * @summary rich diagnostic sometimes contain wrong type variable numbering
- * @compile/fail/ref=T8010387.out -XDrawDiagnostics -XDdiags=disambiguateTvars,where T8010387.java
+ * @compile/fail/ref=T8010387.out -XDrawDiagnostics -diags:formatterOptions=disambiguateTvars,where T8010387.java
  */
 abstract class T8010387<X> {
 
--- a/langtools/test/tools/javac/InterfaceMemberClassModifiers.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/InterfaceMemberClassModifiers.java	Wed Jul 27 13:33:55 2016 +0000
@@ -4,7 +4,7 @@
  * @summary Verify that invalid access modifiers on interface members don't cause crash.
  * @author maddox
  *
- * @compile/fail/ref=InterfaceMemberClassModifiers.out -XDdiags=%b:%l:%_%m InterfaceMemberClassModifiers.java
+ * @compile/fail/ref=InterfaceMemberClassModifiers.out -diags:layout=%b:%l:%_%m InterfaceMemberClassModifiers.java
  */
 
 public interface InterfaceMemberClassModifiers {
--- a/langtools/test/tools/javac/T5003235/T5003235a.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/T5003235/T5003235a.java	Wed Jul 27 13:33:55 2016 +0000
@@ -3,7 +3,7 @@
  * @bug     5003235
  * @summary Private inner class accessible from subclasses
  * @author  Peter von der Ah\u00e9
- * @compile/fail/ref=T5003235a.out -XDdiags=%b:%l:%_%m T5003235a.java
+ * @compile/fail/ref=T5003235a.out -diags:layout=%b:%l:%_%m T5003235a.java
  */
 
 class Super {
--- a/langtools/test/tools/javac/T5003235/T5003235b.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/T5003235/T5003235b.java	Wed Jul 27 13:33:55 2016 +0000
@@ -3,7 +3,7 @@
  * @bug     5003235
  * @summary Accessibility of private inner class
  * @author  Peter von der Ah\u00e9
- * @compile/fail/ref=T5003235b.out -XDdiags=%b:%l:%_%m T5003235b.java
+ * @compile/fail/ref=T5003235b.out -diags:layout=%b:%l:%_%m T5003235b.java
  */
 
 class Outer {
--- a/langtools/test/tools/javac/T6214885.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/T6214885.java	Wed Jul 27 13:33:55 2016 +0000
@@ -2,8 +2,8 @@
  * @test  /nodynamiccopyright/
  * @bug 6214885
  * @summary This test exercises features provided by the new internal Diagnostics API
- * @compile/fail/ref=T6214885a.out -XDdiags=%b:%l%_%t%m|%p%m T6214885.java
- * @compile/fail/ref=T6214885b.out -XDdiags=%b:%l:%c%_%t%m|%p%m T6214885.java
+ * @compile/fail/ref=T6214885a.out -diags:layout=%b:%l%_%t%m|%p%m T6214885.java
+ * @compile/fail/ref=T6214885b.out -diags:layout=%b:%l:%c%_%t%m|%p%m T6214885.java
  */
 class T6214885
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T8161383/LookingForOperatorSymbolsAtWrongPlaceTest.java	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,18 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 8161383
+ * @summary javac is looking for operator symbols at the wrong place
+ * @compile LookingForOperatorSymbolsAtWrongPlaceTest.java
+ */
+
+public class LookingForOperatorSymbolsAtWrongPlaceTest {
+    class Base {
+        protected int i = 1;
+    }
+
+    class Sub extends Base {
+        void func(){
+            Sub.super.i += 10;
+        }
+    }
+}
--- a/langtools/test/tools/javac/api/6731573/T6731573.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/api/6731573/T6731573.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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
@@ -62,8 +62,8 @@
 
     enum SourceLine {
         STANDARD(null),
-        ENABLED("-XDshowSource=true"),
-        DISABLED("-XDshowSource=false");
+        ENABLED("-diags:showSource=true"),
+        DISABLED("-diags:showSource=false");
 
         String optValue;
 
--- a/langtools/test/tools/javac/diags/CheckResourceKeys.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java	Wed Jul 27 13:33:55 2016 +0000
@@ -263,6 +263,9 @@
                 // ignore shouldstop flag names
                 if (cs.startsWith("shouldstop."))
                     continue;
+                // ignore diagsformat flag names
+                if (cs.startsWith("diags."))
+                    continue;
                 // explicit known exceptions
                 if (noResourceRequired.contains(cs))
                     continue;
--- a/langtools/test/tools/javac/diags/examples/WhereCaptured.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/diags/examples/WhereCaptured.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, 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 @@
 // key: compiler.err.cant.apply.symbol
 // key: compiler.misc.incompatible.eq.bounds
 // key: compiler.misc.captured.type
-// options: -XDdiags=where,simpleNames
+// options: -diags:formatterOptions=where,simpleNames
 // run: simple
 
 import java.util.*;
--- a/langtools/test/tools/javac/diags/examples/WhereCaptured1.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/diags/examples/WhereCaptured1.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
 // key: compiler.misc.incompatible.eq.bounds
 // key: compiler.misc.captured.type
 // key: compiler.misc.type.null
-// options: -XDdiags=where,simpleNames
+// options: -diags:formatterOptions=where,simpleNames
 // run: simple
 
 import java.util.*;
--- a/langtools/test/tools/javac/diags/examples/WhereFreshTvar.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/diags/examples/WhereFreshTvar.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 // key: compiler.misc.where.description.typevar
 // key: compiler.err.prob.found.req
 // key: compiler.misc.inconvertible.types
-// options: -XDdiags=where,simpleNames
+// options: -diags:formatterOptions=where,simpleNames
 // run: simple
 
 import java.util.*;
--- a/langtools/test/tools/javac/diags/examples/WhereIntersection.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/diags/examples/WhereIntersection.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, 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
@@ -26,7 +26,7 @@
 // key: compiler.misc.where.description.intersection.1
 // key: compiler.misc.where.intersection
 // key: compiler.err.prob.found.req
-// options: -XDdiags=where
+// options: -diags:formatterOptions=where
 // run: simple
 
 class WhereIntersection {
--- a/langtools/test/tools/javac/diags/examples/WhereIntersection2.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/diags/examples/WhereIntersection2.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
 // key: compiler.misc.where.description.intersection
 // key: compiler.misc.where.intersection
 // key: compiler.err.prob.found.req
-// options: -XDdiags=where
+// options: -diags:formatterOptions=where
 // run: simple
 
 class WhereIntersection2 {
--- a/langtools/test/tools/javac/diags/examples/WhereTypeVar.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/diags/examples/WhereTypeVar.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, 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
@@ -27,7 +27,7 @@
 // key: compiler.err.cant.apply.symbol
 // key: compiler.misc.no.conforming.assignment.exists
 // key: compiler.misc.inconvertible.types
-// options: -XDdiags=where,disambiguateTvars
+// options: -diags:formatterOptions=where,disambiguateTvars
 // run: simple
 
 class WhereTypeVar<T extends String> {
--- a/langtools/test/tools/javac/diags/examples/WhereTypeVar2.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/diags/examples/WhereTypeVar2.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 // key: compiler.misc.where.description.typevar
 // key: compiler.misc.where.typevar
 // key: compiler.err.prob.found.req
-// options: -XDdiags=where
+// options: -diags:formatterOptions=where
 // run: simple
 
 class WhereTypeVar2 {
--- a/langtools/test/tools/javac/missingSuperRecovery/MissingSuperRecovery.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/missingSuperRecovery/MissingSuperRecovery.java	Wed Jul 27 13:33:55 2016 +0000
@@ -5,7 +5,7 @@
  * class is no longer available during a subsequent compilation.
  * @author maddox
  * @build impl
- * @compile/fail/ref=MissingSuperRecovery.out -XDdiags=%b:%l:%_%m MissingSuperRecovery.java
+ * @compile/fail/ref=MissingSuperRecovery.out -diags:layout=%b:%l:%_%m MissingSuperRecovery.java
  */
 
 // Requires "golden" class file 'impl.class', which contains
--- a/langtools/test/tools/javac/protectedAccess/ProtectedMemberAccess2.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/protectedAccess/ProtectedMemberAccess2.java	Wed Jul 27 13:33:55 2016 +0000
@@ -4,7 +4,7 @@
  * @summary Verify correct implementation of JLS2e 6.6.2.1
  * @author maddox
  *
- * @compile/fail/ref=ProtectedMemberAccess2.out -XDdiags=-simpleNames -XDdiagsFormat=%b:%l:%_%m ProtectedMemberAccess2.java
+ * @compile/fail/ref=ProtectedMemberAccess2.out -diags:formatterOptions=-simpleNames;layout=%b:%l:%_%m ProtectedMemberAccess2.java
  */
 
 // 71 errors expected.
--- a/langtools/test/tools/javac/protectedAccess/ProtectedMemberAccess3.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/protectedAccess/ProtectedMemberAccess3.java	Wed Jul 27 13:33:55 2016 +0000
@@ -4,7 +4,7 @@
  * @summary Verify correct implementation of JLS2e 6.6.2.1
  * @author maddox
  *
- * @compile/fail/ref=ProtectedMemberAccess3.out -XDdiags=-simpleNames -XDdiagsFormat=%b:%l:%_%m ProtectedMemberAccess3.java
+ * @compile/fail/ref=ProtectedMemberAccess3.out -diags:formatterOptions=-simpleNames;layout=%b:%l:%_%m ProtectedMemberAccess3.java
  */
 
 // 46 errors expected.
--- a/langtools/test/tools/javac/protectedAccess/ProtectedMemberAccess4.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/protectedAccess/ProtectedMemberAccess4.java	Wed Jul 27 13:33:55 2016 +0000
@@ -4,7 +4,7 @@
  * @summary Verify correct implementation of JLS2e 6.6.2.1
  * @author maddox
  *
- * @compile/fail/ref=ProtectedMemberAccess4.out -XDdiags=-simpleNames -XDdiagsFormat=%b:%l:%_%m ProtectedMemberAccess4.java
+ * @compile/fail/ref=ProtectedMemberAccess4.out -diags:formatterOptions=-simpleNames;layout=%b:%l:%_%m ProtectedMemberAccess4.java
  */
 
 // 33 errors expected.
--- a/langtools/test/tools/javac/unicode/UnicodeNewline.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/langtools/test/tools/javac/unicode/UnicodeNewline.java	Wed Jul 27 13:33:55 2016 +0000
@@ -3,7 +3,7 @@
  * @bug 4739428 4785453
  * @summary when \u000a is used, diagnostics are reported on the wrong line.
  *
- * @compile/fail/ref=UnicodeNewline.out -XDdiags=%b:%l:%_%m UnicodeNewline.java
+ * @compile/fail/ref=UnicodeNewline.out -diags:layout=%b:%l:%_%m UnicodeNewline.java
  */
 
 class UnicodeNewline {
--- a/nashorn/.hgtags	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/.hgtags	Wed Jul 27 13:33:55 2016 +0000
@@ -361,3 +361,4 @@
 a32d419d73fe881a935b567c57dab9bfe3ed5f92 jdk-9+125
 ee90c69a18409533df8f7b602044bf966a28381a jdk-9+126
 ff07be6106fa56b72c163244f45a3ecb4c995564 jdk-9+127
+5a189c5b396c353786343b590f6c19a5d929f01d jdk-9+128
--- a/nashorn/make/build-nasgen.xml	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/make/build-nasgen.xml	Wed Jul 27 13:33:55 2016 +0000
@@ -43,14 +43,14 @@
         </java>
     </target>
 
-    <target name="run-nasgen-eclipse">
+    <target name="run-nasgen-eclipse" depends="load-properties">
         <mkdir dir="${basedir}/build/eclipse/.nasgentmp"/>
 
         <java classname="jdk.nashorn.internal.tools.nasgen.Main" fork="true" failonerror="true">
             <classpath>
                 <pathelement location="${basedir}/buildtools/nasgen/dist/nasgen.jar"/>
             </classpath>
-            <jvmarg value="-Xbootclasspath/p:${basedir}/build/eclipse"/>
+            <jvmarg line="${nasgen.module.imports}"/>
             <arg value="${basedir}/build/eclipse"/>
             <arg value="jdk.nashorn.internal.objects"/>
             <arg value="${basedir}/build/eclipse/.nasgentmp"/>
--- a/nashorn/make/build.xml	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/make/build.xml	Wed Jul 27 13:33:55 2016 +0000
@@ -27,11 +27,14 @@
   <import file="build-nasgen.xml"/>
   <import file="code_coverage.xml"/>
 
-  <target name="init-conditions">
+  <target name="load-properties">
     <!-- loading locally defined resources and properties. NB they owerwrite default ones defined later -->
     <property file="${user.home}/.nashorn.project.local.properties"/>
 
     <loadproperties srcFile="make/project.properties"/>
+  </target>
+
+  <target name="init-conditions" depends="load-properties">
     <path id="nashorn.jar.path">
          <pathelement location="${nashorn.jar}"/>
     </path>
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java	Wed Jul 27 13:33:55 2016 +0000
@@ -108,15 +108,19 @@
      * language's objects to Java interfaces and classes by generating adapters
      * for them.
      * <p>
-     * The type of the invocation is {@code targetType(sourceType)}, while the
-     * type of the guard is {@code boolean(sourceType)}. You are allowed to
+     * The type of the invocation is <tt>(sourceType)&rarr;targetType</tt>, while the
+     * type of the guard is <tt>(sourceType)&rarr;boolean</tt>. You are allowed to
      * return unconditional invocations (with no guard) if the source type is
      * specific to your runtime and your runtime only.
-     * <p>Note that this method will never be invoked for type conversions
-     * allowed by the JLS 5.3 "Method Invocation Conversion", see
-     * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class)} for
-     * details. An implementation can assume it is never requested to produce a
-     * converter for these conversions.
+     * <p>Note that this method will never be invoked for
+     * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method
+     * invocation conversions} as those can be automatically applied by
+     * {@link java.lang.invoke.MethodHandle#asType(MethodType)}.
+     * An implementation can assume it is never requested to produce a
+     * converter for those conversions. If a language runtime needs to customize
+     * method invocation conversions, it should
+     * {@link jdk.dynalink.DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)
+     * set an autoconversion strategy in the dynamic linker factory} instead.
      * <p>Dynalink is at liberty to either cache some of the returned converters
      * or to repeatedly request the converter factory to create the same
      * conversion.
@@ -127,6 +131,9 @@
      * on whose behalf a type converter is requested. When a converter is
      * requested as part of linking an {@code invokedynamic} instruction the
      * supplier will return the lookup passed to the bootstrap method, otherwise
+     * if the method is invoked from within a
+     * {@link LinkerServices#getWithLookup(Supplier, jdk.dynalink.SecureLookupSupplier)}
+     * it will delegate to the secure lookup supplier. In any other case,
      * it will return the public lookup. A typical case where the lookup might
      * be needed is when the converter creates a Java adapter class on the fly
      * (e.g. to convert some object from the dynamic language into a Java
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/package-info.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/package-info.java	Wed Jul 27 13:33:55 2016 +0000
@@ -96,10 +96,8 @@
  * language-specific manner if no other linker managed to handle the operation.)
  * </p><p>
  * A language runtime that wishes to make at least some of its linkers available
- * to other language runtimes for interoperability will need to declare the
- * class names of those linkers in
- * {@code /META-INF/services/jdk.dynalink.linker.GuardingDynamicLinker} file in
- * its distribution (typically, JAR file).
+ * to other language runtimes for interoperability will need to use a
+ * {@link jdk.dynalink.linker.GuardingDynamicLinkerExporter}.
  * </p><p>
  * Most language runtimes will be able to implement their own linking logic by
  * implementing {@link jdk.dynalink.linker.TypeBasedGuardingDynamicLinker}
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java	Wed Jul 27 13:33:55 2016 +0000
@@ -138,7 +138,7 @@
      * Determines whether one type can be converted to another type using a method invocation conversion, as per JLS 5.3
      * "Method Invocation Conversion". This is basically all conversions allowed by subtyping (see
      * {@link #isSubtype(Class, Class)}) as well as boxing conversion (JLS 5.1.7) optionally followed by widening
-     * reference conversion and unboxing conversion (JLS 5.1.8) optionally followed by widening primitive conversion.
+     * reference conversion, and unboxing conversion (JLS 5.1.8) optionally followed by widening primitive conversion.
      *
      * @param sourceType the type being converted from (call site type for parameter types, method type for return types)
      * @param targetType the parameter type being converted to (method type for parameter types, call site type for return types)
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java	Wed Jul 27 13:33:55 2016 +0000
@@ -90,9 +90,10 @@
 
 /**
  * A relinkable call site that implements monomorphic inline caching strategy,
- * only being linked to a single {@link GuardedInvocation}. If that invocation
- * is invalidated, it will throw it away and ask its associated
- * {@link DynamicLinker} to relink it.
+ * only being linked to a single {@link GuardedInvocation} at any given time.
+ * If the guard of that single invocation fails, or it has an invalidated
+ * switch point, or its invalidating exception triggered, then the call site
+ * will throw it away and ask its associated {@link DynamicLinker} to relink it.
  */
 public class SimpleRelinkableCallSite extends AbstractRelinkableCallSite {
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java	Wed Jul 27 13:33:55 2016 +0000
@@ -1329,30 +1329,31 @@
             return ScriptRuntime.UNDEFINED;
         }
 
-        final Object start = args.length > 0 ? args[0] : ScriptRuntime.UNDEFINED;
-        final Object deleteCount = args.length > 1 ? args[1] : ScriptRuntime.UNDEFINED;
-
-        Object[] items;
-
-        if (args.length > 2) {
-            items = new Object[args.length - 2];
-            System.arraycopy(args, 2, items, 0, items.length);
-        } else {
-            items = ScriptRuntime.EMPTY_ARRAY;
-        }
-
-        final ScriptObject sobj                = (ScriptObject)obj;
-        final long         len                 = JSType.toUint32(sobj.getLength());
-        final long         relativeStart       = JSType.toLong(start);
+        final ScriptObject sobj          = (ScriptObject)obj;
+        final long         len           = JSType.toUint32(sobj.getLength());
+        final long         relativeStart = JSType.toLong(args.length > 0 ? args[0] : ScriptRuntime.UNDEFINED);
 
         final long actualStart = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
-        final long actualDeleteCount = Math.min(Math.max(JSType.toLong(deleteCount), 0), len - actualStart);
+        final long actualDeleteCount;
+        Object[] items = ScriptRuntime.EMPTY_ARRAY;
+
+        if (args.length == 0) {
+            actualDeleteCount = 0;
+        } else if (args.length == 1) {
+            actualDeleteCount = len - actualStart;
+        } else {
+            actualDeleteCount = Math.min(Math.max(JSType.toLong(args[1]), 0), len - actualStart);
+            if (args.length > 2) {
+                items = new Object[args.length - 2];
+                System.arraycopy(args, 2, items, 0, items.length);
+            }
+        }
 
         NativeArray returnValue;
 
         if (actualStart <= Integer.MAX_VALUE && actualDeleteCount <= Integer.MAX_VALUE && bulkable(sobj)) {
             try {
-                returnValue =  new NativeArray(sobj.getArray().fastSplice((int)actualStart, (int)actualDeleteCount, items.length));
+                returnValue = new NativeArray(sobj.getArray().fastSplice((int)actualStart, (int)actualDeleteCount, items.length));
 
                 // Since this is a dense bulkable array we can use faster defineOwnProperty to copy new elements
                 int k = (int) actualStart;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java	Wed Jul 27 13:33:55 2016 +0000
@@ -127,7 +127,7 @@
     // Fold an accessor getter into the method handle of a user accessor property.
     private MethodHandle insertAccessorsGetter(final UserAccessorProperty uap, final LinkRequest request, final MethodHandle mh) {
         MethodHandle superGetter = uap.getAccessorsGetter();
-        if (isInherited()) {
+        if (!isSelf()) {
             superGetter = ScriptObject.addProtoFilter(superGetter, getProtoChainLength());
         }
         if (request != null && !(request.getReceiver() instanceof ScriptObject)) {
@@ -183,11 +183,12 @@
     }
 
     /**
-     * Check if the property found was inherited, i.e. not directly in the self
-     * @return true if inherited property
+     * Check if the property found was inherited from a prototype and it is an ordinary
+     * property (one that has no accessor function).
+     * @return true if the found property is an inherited ordinary property
      */
-    public boolean isInherited() {
-        return self != prototype;
+    public boolean isInheritedOrdinaryProperty() {
+        return !isSelf() && !getProperty().isAccessorProperty();
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Jul 27 13:33:55 2016 +0000
@@ -796,7 +796,7 @@
      * @param start the object on which the lookup was originally initiated
      * @return FindPropertyData or null if not found.
      */
-    protected FindProperty findProperty(final Object key, final boolean deep, boolean isScope, final ScriptObject start) {
+    protected FindProperty findProperty(final Object key, final boolean deep, final boolean isScope, final ScriptObject start) {
 
         final PropertyMap selfMap  = getMap();
         final Property    property = selfMap.findProperty(key);
@@ -1108,7 +1108,7 @@
      *
      * @return value of property as a MethodHandle or null.
      */
-    protected MethodHandle getCallMethodHandle(final FindProperty find, final MethodType type, final String bindName) {
+    protected static MethodHandle getCallMethodHandle(final FindProperty find, final MethodType type, final String bindName) {
         return getCallMethodHandle(find.getObjectValue(), type, bindName);
     }
 
@@ -1121,7 +1121,7 @@
      *
      * @return value of property as a MethodHandle or null.
      */
-    protected static MethodHandle getCallMethodHandle(final Object value, final MethodType type, final String bindName) {
+    private static MethodHandle getCallMethodHandle(final Object value, final MethodType type, final String bindName) {
         return value instanceof ScriptFunction ? ((ScriptFunction)value).getCallMethodHandle(type, bindName) : null;
     }
 
@@ -2107,13 +2107,13 @@
      * @param desc           call site descriptor
      * @return method handle for getter
      */
-    protected MethodHandle findGetIndexMethodHandle(final Class<?> returnType, final String name, final Class<?> elementType, final CallSiteDescriptor desc) {
+    private static MethodHandle findGetIndexMethodHandle(final Class<?> returnType, final String name, final Class<?> elementType, final CallSiteDescriptor desc) {
         if (!returnType.isPrimitive()) {
-            return findOwnMH_V(getClass(), name, returnType, elementType);
+            return findOwnMH_V(name, returnType, elementType);
         }
 
         return MH.insertArguments(
-                findOwnMH_V(getClass(), name, returnType, elementType, int.class),
+                findOwnMH_V(name, returnType, elementType, int.class),
                 2,
                 NashornCallSiteDescriptor.isOptimistic(desc) ?
                         NashornCallSiteDescriptor.getProgramPoint(desc) :
@@ -2184,7 +2184,7 @@
         FindProperty find = findProperty(name, true, NashornCallSiteDescriptor.isScope(desc), this);
 
         // If it's not a scope search, then we don't want any inherited properties except those with user defined accessors.
-        if (find != null && find.isInherited() && !find.getProperty().isAccessorProperty()) {
+        if (find != null && find.isInheritedOrdinaryProperty()) {
             // We should still check if inherited data property is not writable
             if (isExtensible() && !find.getProperty().isWritable()) {
                 return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true);
@@ -2257,11 +2257,11 @@
         }
     }
 
-    private GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
+    private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
         Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic setter: ", desc, " ", name);
         final MethodType        type = desc.getMethodType().insertParameterTypes(1, Object.class);
         //never bother with ClassCastExceptionGuard for megamorphic callsites
-        final GuardedInvocation inv = findSetIndexMethod(getClass(), desc, false, type);
+        final GuardedInvocation inv = findSetIndexMethod(desc, false, type);
         return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
     }
 
@@ -2284,25 +2284,24 @@
      * @return GuardedInvocation to be invoked at call site.
      */
     protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
-        return findSetIndexMethod(getClass(), desc, explicitInstanceOfCheck(desc, request), desc.getMethodType());
+        return findSetIndexMethod(desc, explicitInstanceOfCheck(desc, request), desc.getMethodType());
     }
 
     /**
      * Find the appropriate SETINDEX method for an invoke dynamic call.
      *
-     * @param clazz the receiver class
      * @param desc  the call site descriptor
      * @param explicitInstanceOfCheck add an explicit instanceof check?
      * @param callType the method type at the call site
      *
      * @return GuardedInvocation to be invoked at call site.
      */
-    private static GuardedInvocation findSetIndexMethod(final Class<? extends ScriptObject> clazz, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final MethodType callType) {
+    private static GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final MethodType callType) {
         assert callType.parameterCount() == 3;
         final Class<?> keyClass   = callType.parameterType(1);
         final Class<?> valueClass = callType.parameterType(2);
 
-        MethodHandle methodHandle = findOwnMH_V(clazz, "set", void.class, keyClass, valueClass, int.class);
+        MethodHandle methodHandle = findOwnMH_V("set", void.class, keyClass, valueClass, int.class);
         methodHandle = MH.insertArguments(methodHandle, 3, NashornCallSiteDescriptor.getFlags(desc));
 
         return new GuardedInvocation(methodHandle, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
@@ -2953,18 +2952,6 @@
         return false;
     }
 
-    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final long value, final int callSiteFlags) {
-        if (getMap().containsArrayKeys()) {
-            final String       key  = JSType.toString(longIndex);
-            final FindProperty find = findProperty(key, true);
-            if (find != null) {
-                setObject(find, callSiteFlags, key, value);
-                return true;
-            }
-        }
-        return false;
-    }
-
     private boolean doesNotHaveCheckArrayKeys(final long longIndex, final double value, final int callSiteFlags) {
          if (getMap().containsArrayKeys()) {
             final String       key  = JSType.toString(longIndex);
@@ -3044,7 +3031,7 @@
 
         invalidateGlobalConstant(key);
 
-        if (f != null && f.isInherited() && !f.getProperty().isAccessorProperty()) {
+        if (f != null && f.isInheritedOrdinaryProperty()) {
             final boolean isScope = isScopeFlag(callSiteFlags);
             // If the start object of the find is not this object it means the property was found inside a
             // 'with' statement expression (see WithObject.findProperty()). In this case we forward the 'set'
@@ -3467,15 +3454,10 @@
         return this;
     }
 
-    private static MethodHandle findOwnMH_V(final Class<? extends ScriptObject> clazz, final String name, final Class<?> rtype, final Class<?>... types) {
-        // TODO: figure out how can it work for NativeArray$Prototype etc.
+    private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
         return MH.findVirtual(MethodHandles.lookup(), ScriptObject.class, name, MH.type(rtype, types));
     }
 
-    private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
-        return findOwnMH_V(ScriptObject.class, name, rtype, types);
-    }
-
     private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
         return MH.findStatic(MethodHandles.lookup(), ScriptObject.class, name, MH.type(rtype, types));
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java	Wed Jul 27 13:33:55 2016 +0000
@@ -170,7 +170,7 @@
         assert property     != null;
 
         final MethodHandle boundHandle;
-        if (!property.isAccessorProperty() && find.isInherited()) {
+        if (find.isInheritedOrdinaryProperty()) {
             boundHandle = ScriptObject.addProtoFilter(methodHandle, find.getProtoChainLength());
         } else {
             boundHandle = methodHandle;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java	Wed Jul 27 08:33:15 2016 -0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java	Wed Jul 27 13:33:55 2016 +0000
@@ -117,7 +117,7 @@
                     return new GuardedInvocation(GlobalConstants.staticConstantGetter(find.getObjectValue()), guard, sp, null);
                 }
 
-                if (find.isInherited() && !(find.getProperty().isAccessorProperty())) {
+                if (find.isInheritedOrdinaryProperty()) {
                     // If property is found in the prototype object bind the method handle directly to
                     // the proto filter instead of going through wrapper instantiation below.
                     final ScriptObject proto = wrappedReceiver.getProto();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8068972.js	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+/**
+ * JDK-8068972: Array.splice should follow the ES6 specification
+ *
+ * @test
+ * @run
+ */
+
+
+function assertEqualArrays(a, b) {
+    Assert.assertTrue(Array.isArray(a));
+    Assert.assertTrue(Array.isArray(b));
+    Assert.assertTrue(a.length === b.length);
+    Assert.assertTrue(a.every(function(v, j) {
+        return v === b[j];
+    }));
+}
+
+var array = [1, 2, 3, 4, 5, 6, 7];
+
+var result = array.splice();
+assertEqualArrays(array, [1, 2, 3, 4, 5, 6, 7]);
+assertEqualArrays(result, []);
+
+result = array.splice(4);
+assertEqualArrays(array, [1, 2, 3, 4]);
+assertEqualArrays(result, [5, 6, 7]);
+
+result = array.splice(1, 2, -2, -3);
+assertEqualArrays(array, [1, -2, -3, 4]);
+assertEqualArrays(result, [2, 3]);
--- a/nashorn/test/script/currently-failing/logcoverage.js	Wed Jul 27 08:33:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, 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.
- */
-
-/**
- * mh_coverage.js
- * Screen scrape various logs to ensure that we cover enough functionality,
- * e.g. method handle instrumentation
- *
- * @test
- * @run
- */
-
-/*
- * creates new script engine initialized with given options and
- * runs given code on it. Returns standard output captured.
- */
-
-function runScriptEngine(opts, name) {
-    var imports = new JavaImporter(
-        Packages.jdk.nashorn.api.scripting,
-        java.io, java.lang, java.util);
-
-    with(imports) {
-        var fac = new NashornScriptEngineFactory();
-        // get current System.err
-        var oldErr = System.err;
-    var oldOut = System.out;
-        var baosErr = new ByteArrayOutputStream();
-        var newErr = new PrintStream(baosErr);
-        var baosOut = new ByteArrayOutputStream();
-    var newOut = new PrintStream(baosOut);
-        try {
-            // set new standard err
-            System.setErr(newErr);
-            System.setOut(newOut);
-            var engine = fac.getScriptEngine(Java.to(opts, "java.lang.String[]"));
-        var reader = new java.io.FileReader(name);
-            engine.eval(reader);
-            newErr.flush();
-        newOut.flush();
-            return new java.lang.String(baosErr.toByteArray());
-        } finally {
-            // restore System.err to old value
-            System.setErr(oldErr);
-        System.setOut(oldOut);
-        }
-    }
-}
-
-var str;
-
-var methodsCalled = [
-   'asCollector',
-   'asType',
-   'bindTo',
-   'dropArguments',
-   'explicitCastArguments',
-   'filterArguments',
-   'filterReturnValue',
-   'findStatic',
-   'findVirtual',
-   'foldArguments',
-   'getter',
-   'guardWithTest',
-   'insertArguments',
-   'methodType',
-   'setter'
-];
-
-function check(str, strs) {
-    for each (s in strs) {
-       if (str.indexOf(s) !== -1) {
-       continue;
-       }
-       print(s + " not found");
-       return;
-    }
-    print("check ok!");
-}
-
-str = runScriptEngine([ "--log=codegen,compiler=finest,methodhandles=finest,fields=finest" ], __DIR__ + "../basic/NASHORN-19.js");
-str += runScriptEngine([ "--log=codegen,compiler=finest,methodhandles=finest,fields=finest" ], __DIR__ + "../basic/varargs.js");
-
-check(str, methodsCalled);
-check(str, ['return', 'get', 'set', '[fields]']);
-check(str, ['codegen']);
-
-print("hello, world!");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/logcoverage.js	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010, 2016, 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.
+ */
+
+/**
+ * Screen scrape various logs to ensure that we cover enough functionality,
+ * e.g. method handle instrumentation
+ *
+ * @test
+ * @fork
+ * @option -Dnashorn.debug=true
+ */
+
+/*
+ * creates new script engine initialized with given options and
+ * runs given code on it. Returns standard output captured.
+ */
+
+function runScriptEngine(opts, name) {
+    var imports = new JavaImporter(
+            Packages.jdk.nashorn.api.scripting,
+            java.io, java.lang, java.util);
+
+    with (imports) {
+        var fac = new NashornScriptEngineFactory();
+        // get current System.err
+        var oldErr = System.err;
+        var oldOut = System.out;
+        var baosErr = new ByteArrayOutputStream();
+        var newErr = new PrintStream(baosErr);
+        var baosOut = new ByteArrayOutputStream();
+        var newOut = new PrintStream(baosOut);
+        try {
+            // set new standard err
+            System.setErr(newErr);
+            System.setOut(newOut);
+            var engine = fac.getScriptEngine(Java.to(opts, "java.lang.String[]"));
+            var reader = new java.io.FileReader(name);
+            engine.eval(reader);
+            newErr.flush();
+            newOut.flush();
+            return new java.lang.String(baosErr.toByteArray());
+        } finally {
+            // restore System.err to old value
+            System.setErr(oldErr);
+            System.setOut(oldOut);
+        }
+    }
+}
+
+var str;
+
+var methodsCalled = [
+    'asCollector',
+    'asType',
+    'bindTo',
+    'dropArguments',
+    'explicitCastArguments',
+    'filterArguments',
+    'filterReturnValue',
+    'findStatic',
+    'findVirtual',
+    'foldArguments',
+    'getter',
+    'guardWithTest',
+    'insertArguments',
+    'methodType',
+    'setter'
+];
+
+function check(str, strs) {
+    for each (s in strs) {
+        if (str.indexOf(s) !== -1) {
+            continue;
+        }
+        print(s + " not found");
+        return;
+    }
+    print("check ok!");
+}
+
+str = runScriptEngine(["--log=codegen,compiler=finest,methodhandles=finest,fields=finest"], __DIR__ + "../basic/NASHORN-19.js");
+str += runScriptEngine(["--log=codegen,compiler=finest,methodhandles=finest,fields=finest"], __DIR__ + "../basic/varargs.js");
+
+check(str, methodsCalled);
+check(str, ['return', 'get', 'set', '[fields]']);
+check(str, ['codegen']);
+
+print("hello, world!");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/logcoverage.js.EXPECTED	Wed Jul 27 13:33:55 2016 +0000
@@ -0,0 +1,4 @@
+check ok!
+check ok!
+check ok!
+hello, world!