changeset 14777:216b0ecea3af

Merge
author prr
date Wed, 18 May 2016 12:04:26 -0700
parents 3dc009028cab 6b5c8b0f6b74
children 49ad64d12e8f
files src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/libsoftcrypto.h src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginContextImpl.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PoolImpl.java src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java test/sun/tools/jinfo/JInfoHelper.java test/sun/tools/jinfo/JInfoLauncherTest.java test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java test/sun/tools/jinfo/JInfoRunningProcessTest.java test/sun/tools/jinfo/JInfoSanityTest.java test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java
diffstat 284 files changed, 10816 insertions(+), 8621 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed May 18 20:40:17 2016 +0300
+++ b/.hgtags	Wed May 18 12:04:26 2016 -0700
@@ -360,3 +360,4 @@
 35225b837d66582037eeadeb471c13235dfd793d jdk-9+115
 baeb5edb38939cdb78ae0ac6f4fd368465cbf188 jdk-9+116
 4da0f73ce03aaf245b92cc040cc0ab0e3fa54dc2 jdk-9+117
+e1eba5cfa5cc8c66d524396a05323dc93568730a jdk-9+118
--- a/make/Import.gmk	Wed May 18 20:40:17 2016 +0300
+++ b/make/Import.gmk	Wed May 18 12:04:26 2016 -0700
@@ -112,7 +112,7 @@
 	$(LN) -s ../$(@F) $@
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
-  $(BASE_INSTALL_LIBRARIES_HERE)/server/%.dSYM : $(BASE_INSTALL_LIBRARIES_HERE)/%.dSYM
+  $(BASE_INSTALL_LIBRARIES_HERE)/server/%.dSYM:
 	$(MKDIR) -p $(@D)
 	$(RM) $@
 	$(LN) -s ../$(@F) $@
--- a/make/launcher/Launcher-java.base.gmk	Wed May 18 20:40:17 2016 +0300
+++ b/make/launcher/Launcher-java.base.gmk	Wed May 18 12:04:26 2016 -0700
@@ -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
@@ -25,11 +25,11 @@
 
 include LauncherCommon.gmk
 
-JAVA_RC_FLAGS += -i $(JDK_TOPDIR)/src/java.base/windows/native/common
+JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/java.base/windows/native/common
 ifdef OPENJDK
-  JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons"
+  JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons
 else
-  JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons"
+  JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons
 endif
 
 ################################################################################
--- a/make/lib/Awt2dLibraries.gmk	Wed May 18 20:40:17 2016 +0300
+++ b/make/lib/Awt2dLibraries.gmk	Wed May 18 12:04:26 2016 -0700
@@ -213,9 +213,9 @@
   endif
 
   ifdef OPENJDK
-    LIBAWT_RC_FLAGS := -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons"
+    LIBAWT_RC_FLAGS := -I $(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons
   else
-    LIBAWT_RC_FLAGS := -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons"
+    LIBAWT_RC_FLAGS := -I $(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons
   endif
   LIBAWT_VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/java.desktop/windows/native/libawt/windows/awt.rc
 endif
--- a/make/mapfiles/libj2ucrypto/mapfile-vers	Wed May 18 20:40:17 2016 +0300
+++ b/make/mapfiles/libj2ucrypto/mapfile-vers	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 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,28 +30,35 @@
                 JNI_OnLoad;
                 Java_com_oracle_security_ucrypto_UcryptoProvider_loadLibraries;
                 Java_com_oracle_security_ucrypto_UcryptoProvider_getMechList;
-		Java_com_oracle_security_ucrypto_NativeDigest_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree;
+                Java_com_oracle_security_ucrypto_NativeDigest_nativeInit;
                 Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate;
                 Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest;
-                Java_com_oracle_security_ucrypto_NativeDigest_nativeClone;
                 Java_com_oracle_security_ucrypto_NativeDigest_nativeFree;
-		Java_com_oracle_security_ucrypto_NativeCipher_nativeInit;
-		Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
-		Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
+                Java_com_oracle_security_ucrypto_NativeCipher_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
+                Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
                 Java_com_oracle_security_ucrypto_NativeKey_nativeFree;
                 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit;
                 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
                 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
-		Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
-
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
+                Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest;
-                JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree;
                 JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
@@ -60,10 +67,10 @@
                 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
                 JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
 
 	local:
--- a/make/mapfiles/libjava/mapfile-vers	Wed May 18 20:40:17 2016 +0300
+++ b/make/mapfiles/libjava/mapfile-vers	Wed May 18 12:04:26 2016 -0700
@@ -262,7 +262,7 @@
 		Java_jdk_internal_reflect_Reflection_getCallerClass__;
 		Java_jdk_internal_reflect_Reflection_getCallerClass__I;
 		Java_jdk_internal_reflect_Reflection_getClassAccessFlags;
-		Java_jdk_internal_misc_VM_latestUserDefinedLoader;
+		Java_jdk_internal_misc_VM_latestUserDefinedLoader0;
                 Java_jdk_internal_misc_VM_getuid;
                 Java_jdk_internal_misc_VM_geteuid;
                 Java_jdk_internal_misc_VM_getgid;
--- a/src/java.base/share/classes/java/io/BufferedWriter.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/io/BufferedWriter.java	Wed May 18 12:04:26 2016 -0700
@@ -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
@@ -153,13 +153,18 @@
      * needed.  If the requested length is at least as large as the buffer,
      * however, then this method will flush the buffer and write the characters
      * directly to the underlying stream.  Thus redundant
-     * <code>BufferedWriter</code>s will not copy data unnecessarily.
+     * {@code BufferedWriter}s will not copy data unnecessarily.
      *
      * @param  cbuf  A character array
      * @param  off   Offset from which to start reading characters
      * @param  len   Number of characters to write
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(char cbuf[], int off, int len) throws IOException {
         synchronized (lock) {
@@ -195,17 +200,24 @@
     /**
      * Writes a portion of a String.
      *
-     * <p> If the value of the {@code len} parameter is negative then no
-     * characters are written.  This is contrary to the specification of this
-     * method in the {@linkplain java.io.Writer#write(java.lang.String,int,int)
-     * superclass}, which requires that an {@link IndexOutOfBoundsException} be
-     * thrown.
+     * @implSpec
+     * While the specification of this method in the
+     * {@linkplain java.io.Writer#write(java.lang.String,int,int) superclass}
+     * recommends that an {@link IndexOutOfBoundsException} be thrown
+     * if {@code len} is negative or {@code off + len} is negative,
+     * the implementation in this class does not throw such an exception in
+     * these cases but instead simply writes no characters.
      *
      * @param  s     String to be written
      * @param  off   Offset from which to start reading characters
      * @param  len   Number of characters to be written
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative,
+     *          or {@code off + len} is greater than the length
+     *          of the given string
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(String s, int off, int len) throws IOException {
         synchronized (lock) {
--- a/src/java.base/share/classes/java/io/CharArrayWriter.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/io/CharArrayWriter.java	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, 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
@@ -91,6 +91,11 @@
      * @param c the data to be written
      * @param off       the start offset in the data
      * @param len       the number of chars that are written
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
      */
     public void write(char c[], int off, int len) {
         if ((off < 0) || (off > c.length) || (len < 0) ||
@@ -114,6 +119,11 @@
      * @param  str  String to be written from
      * @param  off  Offset from which to start reading characters
      * @param  len  Number of characters to be written
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given string
      */
     public void write(String str, int off, int len) {
         synchronized (lock) {
--- a/src/java.base/share/classes/java/io/FilterWriter.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/io/FilterWriter.java	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, 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
@@ -72,7 +72,12 @@
      * @param  off   Offset from which to start reading characters
      * @param  len   Number of characters to be written
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(char cbuf[], int off, int len) throws IOException {
         out.write(cbuf, off, len);
@@ -85,7 +90,12 @@
      * @param  off  Offset from which to start reading characters
      * @param  len  Number of characters to be written
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(String str, int off, int len) throws IOException {
         out.write(str, off, len);
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/io/ObjectInputStream.java	Wed May 18 12:04:26 2016 -0700
@@ -603,12 +603,12 @@
      *     Class.forName(desc.getName(), false, loader)
      * </pre>
      * where <code>loader</code> is determined as follows: if there is a
-     * method on the current thread's stack whose declaring class was
-     * defined by a user-defined class loader (and was not a generated to
-     * implement reflective invocations), then <code>loader</code> is class
-     * loader corresponding to the closest such method to the currently
-     * executing frame; otherwise, <code>loader</code> is
-     * <code>null</code>. If this call results in a
+     * method on the current thread's stack whose declaring class is not a
+     * <a href="../lang/ClassLoader.html#builtinLoaders">
+     * <em>platform class</em></a>, then <code>loader</code> is
+     * the class loader of such class; otherwise, <code>loader</code>
+     * is the {@linkplain ClassLoader#getPlatformClassLoader()
+     * platform class loader}.  If this call results in a
      * <code>ClassNotFoundException</code> and the name of the passed
      * <code>ObjectStreamClass</code> instance is the Java language keyword
      * for a primitive type or void, then the <code>Class</code> object
@@ -666,12 +666,15 @@
      * <pre>
      *     Class.forName(i, false, loader)
      * </pre>
-     * where <code>loader</code> is that of the first non-<code>null</code>
-     * class loader up the execution stack, or <code>null</code> if no
-     * non-<code>null</code> class loaders are on the stack (the same class
-     * loader choice used by the <code>resolveClass</code> method).  Unless any
-     * of the resolved interfaces are non-public, this same value of
-     * <code>loader</code> is also the class loader passed to
+     * where <code>loader</code> is determined as follows: if there is a
+     * method on the current thread's stack whose declaring class is not a
+     * <a href="../lang/ClassLoader.html#builtinLoaders">
+     * <em>platform class</em></a>, then <code>loader</code> is
+     * the class loader of such class; otherwise, <code>loader</code>
+     * is the {@linkplain ClassLoader#getPlatformClassLoader()
+     * platform class loader}.
+     * Unless any of the resolved interfaces are non-public, this same value
+     * of <code>loader</code> is also the class loader passed to
      * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
      * their class loader is passed instead (if more than one non-public
      * interface class loader is encountered, an
@@ -2154,10 +2157,11 @@
                                               int ndoubles);
 
     /**
-     * Returns the first non-null class loader (not counting class loaders of
-     * generated reflection implementation classes) up the execution stack, or
-     * null if only code from the null class loader is on the stack.  This
-     * method is also called via reflection by the following RMI-IIOP class:
+     * Returns the first non-null and non-platform class loader
+     * (not counting class loaders of generated reflection implementation classes)
+     * up the execution stack, or null if only code from the bootstrap and
+     * platform class loader is on the stack.
+     * This method is also called via reflection by the following RMI-IIOP class:
      *
      *     com.sun.corba.se.internal.util.JDKClassLoader
      *
--- a/src/java.base/share/classes/java/io/OutputStreamWriter.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/io/OutputStreamWriter.java	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, 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
@@ -202,7 +202,12 @@
      * @param  off   Offset from which to start writing characters
      * @param  len   Number of characters to write
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(char cbuf[], int off, int len) throws IOException {
         se.write(cbuf, off, len);
@@ -215,7 +220,12 @@
      * @param  off  Offset from which to start writing characters
      * @param  len  Number of characters to write
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given string
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(String str, int off, int len) throws IOException {
         se.write(str, off, len);
--- a/src/java.base/share/classes/java/io/PipedWriter.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/io/PipedWriter.java	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, 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
@@ -125,19 +125,25 @@
     }
 
     /**
-     * Writes <code>len</code> characters from the specified character array
-     * starting at offset <code>off</code> to this piped output stream.
+     * Writes {@code len} characters from the specified character array
+     * starting at offset {@code off} to this piped output stream.
      * This method blocks until all the characters are written to the output
      * stream.
      * If a thread was reading data characters from the connected piped input
      * stream, but the thread is no longer alive, then an
-     * <code>IOException</code> is thrown.
+     * {@code IOException} is thrown.
      *
      * @param      cbuf  the data.
      * @param      off   the start offset in the data.
      * @param      len   the number of characters to write.
-     * @exception  IOException  if the pipe is
-     *          <a href=PipedOutputStream.html#BROKEN> <code>broken</code></a>,
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
+     * @throws  IOException  if the pipe is
+     *          <a href=PipedOutputStream.html#BROKEN><code>broken</code></a>,
      *          {@link #connect(java.io.PipedReader) unconnected}, closed
      *          or an I/O error occurs.
      */
--- a/src/java.base/share/classes/java/io/PrintWriter.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/io/PrintWriter.java	Wed May 18 12:04:26 2016 -0700
@@ -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
@@ -410,6 +410,11 @@
      * @param buf Array of characters
      * @param off Offset from which to start writing characters
      * @param len Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
      */
     public void write(char buf[], int off, int len) {
         try {
@@ -440,6 +445,11 @@
      * @param s A String
      * @param off Offset from which to start writing characters
      * @param len Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
      */
     public void write(String s, int off, int len) {
         try {
--- a/src/java.base/share/classes/java/io/StringWriter.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/io/StringWriter.java	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2004, 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
@@ -83,6 +83,11 @@
      * @param  cbuf  Array of characters
      * @param  off   Offset from which to start writing characters
      * @param  len   Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
      */
     public void write(char cbuf[], int off, int len) {
         if ((off < 0) || (off > cbuf.length) || (len < 0) ||
@@ -107,6 +112,11 @@
      * @param  str  String to be written
      * @param  off  Offset from which to start writing characters
      * @param  len  Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given string
      */
     public void write(String str, int off, int len)  {
         buf.append(str, off, off + len);
--- a/src/java.base/share/classes/java/io/Writer.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/io/Writer.java	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, 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
@@ -32,12 +32,11 @@
  * Most subclasses, however, will override some of the methods defined here in
  * order to provide higher efficiency, additional functionality, or both.
  *
- * @see Writer
  * @see   BufferedWriter
  * @see   CharArrayWriter
  * @see   FilterWriter
  * @see   OutputStreamWriter
- * @see     FileWriter
+ * @see   FileWriter
  * @see   PipedWriter
  * @see   PrintWriter
  * @see   StringWriter
@@ -139,6 +138,12 @@
      * @param  len
      *         Number of characters to write
      *
+     * @throws  IndexOutOfBoundsException
+     *          Implementations should throw this exception
+     *          if {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
      * @throws  IOException
      *          If an I/O error occurs
      */
@@ -160,6 +165,11 @@
     /**
      * Writes a portion of a string.
      *
+     * @implSpec
+     * The implementation in this class throws an
+     * {@code IndexOutOfBoundsException} for the indicated conditions;
+     * overriding methods may choose to do otherwise.
+     *
      * @param  str
      *         A String
      *
@@ -170,8 +180,9 @@
      *         Number of characters to write
      *
      * @throws  IndexOutOfBoundsException
-     *          If {@code off} is negative, or {@code len} is negative,
-     *          or {@code off+len} is negative or greater than the length
+     *          Implementations should throw this exception
+     *          if {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
      *          of the given string
      *
      * @throws  IOException
--- a/src/java.base/share/classes/java/lang/Thread.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/lang/Thread.java	Wed May 18 12:04:26 2016 -0700
@@ -341,6 +341,45 @@
     }
 
     /**
+     * Indicates that the caller is momentarily unable to progress, until the
+     * occurrence of one or more actions on the part of other activities. By
+     * invoking this method within each iteration of a spin-wait loop construct,
+     * the calling thread indicates to the runtime that it is busy-waiting.
+     * The runtime may take action to improve the performance of invoking
+     * spin-wait loop constructions.
+     * <p>
+     * @apiNote
+     * As an example consider a method in a class that spins in a loop until
+     * some flag is set outside of that method. A call to the {@code onSpinWait}
+     * method should be placed inside the spin loop.
+     * <pre>{@code
+     *     class EventHandler {
+     *         volatile boolean eventNotificationNotReceived;
+     *         void waitForEventAndHandleIt() {
+     *             while ( eventNotificationNotReceived ) {
+     *                 java.lang.Thread.onSpinWait();
+     *             }
+     *             readAndProcessEvent();
+     *         }
+     *
+     *         void readAndProcessEvent() {
+     *             // Read event from some source and process it
+     *              . . .
+     *         }
+     *     }
+     * }</pre>
+     * <p>
+     * The code above would remain correct even if the {@code onSpinWait}
+     * method was not called at all. However on some architectures the Java
+     * Virtual Machine may issue the processor instructions to address such
+     * code patterns in a more beneficial way.
+     * <p>
+     * @since 9
+     */
+    @HotSpotIntrinsicCandidate
+    public static void onSpinWait() {}
+
+    /**
      * Initializes a Thread with the current AccessControlContext.
      * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean)
      */
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Wed May 18 12:04:26 2016 -0700
@@ -706,6 +706,9 @@
                 case ARRAY_STORE:
                     emitArrayStore(name);
                     continue;
+                case ARRAY_LENGTH:
+                    emitArrayLength(name);
+                    continue;
                 case IDENTITY:
                     assert(name.arguments.length == 1);
                     emitPushArguments(name);
@@ -740,15 +743,16 @@
         return classFile;
     }
 
-    void emitArrayLoad(Name name)  { emitArrayOp(name, Opcodes.AALOAD);  }
-    void emitArrayStore(Name name) { emitArrayOp(name, Opcodes.AASTORE); }
+    void emitArrayLoad(Name name)   { emitArrayOp(name, Opcodes.AALOAD);      }
+    void emitArrayStore(Name name)  { emitArrayOp(name, Opcodes.AASTORE);     }
+    void emitArrayLength(Name name) { emitArrayOp(name, Opcodes.ARRAYLENGTH); }
 
     void emitArrayOp(Name name, int arrayOpcode) {
-        assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE;
+        assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE || arrayOpcode == Opcodes.ARRAYLENGTH;
         Class<?> elementType = name.function.methodType().parameterType(0).getComponentType();
         assert elementType != null;
         emitPushArguments(name);
-        if (elementType.isPrimitive()) {
+        if (arrayOpcode != Opcodes.ARRAYLENGTH && elementType.isPrimitive()) {
             Wrapper w = Wrapper.forPrimitiveType(elementType);
             arrayOpcode = arrayInsnOpcode(arrayTypeCode(w), arrayOpcode);
         }
--- a/src/java.base/share/classes/java/lang/invoke/Invokers.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/Invokers.java	Wed May 18 12:04:26 2016 -0700
@@ -95,12 +95,12 @@
 
     /*non-public*/ MethodHandle varHandleMethodInvoker(VarHandle.AccessMode ak) {
         // TODO cache invoker
-        return makeVarHandleMethodInvoker(ak);
+        return makeVarHandleMethodInvoker(ak, false);
     }
 
     /*non-public*/ MethodHandle varHandleMethodExactInvoker(VarHandle.AccessMode ak) {
         // TODO cache invoker
-        return makeVarHandleMethodExactInvoker(ak);
+        return makeVarHandleMethodInvoker(ak, true);
     }
 
     private MethodHandle cachedInvoker(int idx) {
@@ -127,26 +127,11 @@
         return invoker;
     }
 
-    private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak) {
+    private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak, boolean isExact) {
         MethodType mtype = targetType;
         MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
 
-        LambdaForm lform = varHandleMethodGenericInvokerHandleForm(ak.methodName(), mtype);
-        VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
-        MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
-
-        invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.methodName(), mtype), false);
-        assert(checkVarHandleInvoker(invoker));
-
-        maybeCompileToBytecode(invoker);
-        return invoker;
-    }
-
-    private MethodHandle makeVarHandleMethodExactInvoker(VarHandle.AccessMode ak) {
-        MethodType mtype = targetType;
-        MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
-
-        LambdaForm lform = varHandleMethodExactInvokerHandleForm(ak.methodName(), mtype);
+        LambdaForm lform = varHandleMethodInvokerHandleForm(ak.methodName(), mtype, isExact);
         VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
         MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
 
@@ -400,59 +385,7 @@
         return lform;
     }
 
-    private static LambdaForm varHandleMethodExactInvokerHandleForm(String name, MethodType mtype) {
-        // TODO Cache form?
-
-        final int THIS_MH      = 0;
-        final int CALL_VH      = THIS_MH + 1;
-        final int ARG_BASE     = CALL_VH + 1;
-        final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
-        int nameCursor = ARG_LIMIT;
-        final int VAD_ARG      = nameCursor++;
-        final int CHECK_TYPE   = nameCursor++;
-        final int GET_MEMBER   = nameCursor++;
-        final int LINKER_CALL  = nameCursor++;
-
-        MethodType invokerFormType = mtype.insertParameterTypes(0, VarHandle.class)
-                .basicType()
-                .appendParameterTypes(MemberName.class);
-
-        MemberName linker = new MemberName(MethodHandle.class, "linkToStatic", invokerFormType, REF_invokeStatic);
-        try {
-            linker = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
-        } catch (ReflectiveOperationException ex) {
-            throw newInternalError(ex);
-        }
-
-        Name[] names = new Name[LINKER_CALL + 1];
-        names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
-        names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
-        for (int i = 0; i < mtype.parameterCount(); i++) {
-            names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
-        }
-
-        BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
-        names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
-
-        NamedFunction getter = speciesData.getterFunction(0);
-        names[VAD_ARG] = new Name(getter, names[THIS_MH]);
-
-        Object[] outArgs = Arrays.copyOfRange(names, CALL_VH, ARG_LIMIT + 1, Object[].class);
-
-        names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]);
-
-        names[GET_MEMBER] = new Name(NF_getVarHandleMemberName, names[CALL_VH], names[VAD_ARG]);
-        outArgs[outArgs.length - 1] = names[GET_MEMBER];
-
-        names[LINKER_CALL] = new Name(linker, outArgs);
-        LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)),
-                                          ARG_LIMIT, names);
-
-        lform.compileToBytecode();
-        return lform;
-    }
-
-    private static LambdaForm varHandleMethodGenericInvokerHandleForm(String name, MethodType mtype) {
+    private static LambdaForm varHandleMethodInvokerHandleForm(String name, MethodType mtype, boolean isExact) {
         // TODO Cache form?
 
         final int THIS_MH      = 0;
@@ -477,8 +410,11 @@
         NamedFunction getter = speciesData.getterFunction(0);
         names[VAD_ARG] = new Name(getter, names[THIS_MH]);
 
-        names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]);
-
+        if (isExact) {
+            names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]);
+        } else {
+            names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]);
+        }
         Object[] outArgs = new Object[ARG_LIMIT];
         outArgs[0] = names[CHECK_TYPE];
         for (int i = 1; i < ARG_LIMIT; i++) {
@@ -488,7 +424,8 @@
         MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
                 .basicType();
         names[LINKER_CALL] = new Name(outCallType, outArgs);
-        LambdaForm lform = new LambdaForm(name + ":VarHandle_invoker" + shortenSignature(basicTypeSignature(mtype)),
+        String debugName = isExact ? ":VarHandle_exactInvoker" : ":VarHandle_invoker";
+        LambdaForm lform = new LambdaForm(name + debugName + shortenSignature(basicTypeSignature(mtype)),
                                           ARG_LIMIT, names);
 
         lform.prepare();
@@ -511,21 +448,13 @@
 
     /*non-public*/ static
     @ForceInline
-    void checkVarHandleExactType(VarHandle handle, VarHandle.AccessDescriptor ad) {
-        MethodType erasedTarget = handle.vform.methodType_table[ad.type];
-        MethodType erasedSymbolic = ad.symbolicMethodTypeErased;
-        if (erasedTarget != erasedSymbolic)
-            throw newWrongMethodTypeException(erasedTarget, erasedSymbolic);
-    }
-
-    /*non-public*/ static
-    @ForceInline
-    MemberName getVarHandleMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {
-        MemberName mn = handle.vform.memberName_table[ad.mode];
-        if (mn == null) {
-            throw handle.unsupported();
+    MethodHandle checkVarHandleExactType(VarHandle handle, VarHandle.AccessDescriptor ad) {
+        MethodHandle mh = handle.getMethodHandle(ad.mode);
+        MethodType mt = mh.type();
+        if (mt != ad.symbolicMethodTypeInvoker) {
+            throw newWrongMethodTypeException(mt, ad.symbolicMethodTypeInvoker);
         }
-        return mn;
+        return mh;
     }
 
     /*non-public*/ static
@@ -649,8 +578,7 @@
         NF_getCallSiteTarget,
         NF_checkCustomized,
         NF_checkVarHandleGenericType,
-        NF_checkVarHandleExactType,
-        NF_getVarHandleMemberName;
+        NF_checkVarHandleExactType;
     static {
         try {
             NamedFunction nfs[] = {
@@ -666,8 +594,6 @@
                         .getDeclaredMethod("checkVarHandleGenericType", VarHandle.class, VarHandle.AccessDescriptor.class)),
                 NF_checkVarHandleExactType = new NamedFunction(Invokers.class
                         .getDeclaredMethod("checkVarHandleExactType", VarHandle.class, VarHandle.AccessDescriptor.class)),
-                NF_getVarHandleMemberName = new NamedFunction(Invokers.class
-                        .getDeclaredMethod("getVarHandleMemberName", VarHandle.class, VarHandle.AccessDescriptor.class))
             };
             // Each nf must be statically invocable or we get tied up in our bootstraps.
             assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Wed May 18 12:04:26 2016 -0700
@@ -66,25 +66,28 @@
 
     /// Factory methods to create method handles:
 
-    static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
-        if (arrayClass == Object[].class)
-            return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER);
+    static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, ArrayAccess access) {
+        if (arrayClass == Object[].class) {
+            return ArrayAccess.objectAccessor(access);
+        }
         if (!arrayClass.isArray())
             throw newIllegalArgumentException("not an array: "+arrayClass);
         MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
-        int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX);
+        int cacheIndex = ArrayAccess.cacheIndex(access);
         MethodHandle mh = cache[cacheIndex];
         if (mh != null)  return mh;
-        mh = ArrayAccessor.getAccessor(arrayClass, isSetter);
-        MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter);
+        mh = ArrayAccessor.getAccessor(arrayClass, access);
+        MethodType correctType = ArrayAccessor.correctType(arrayClass, access);
         if (mh.type() != correctType) {
             assert(mh.type().parameterType(0) == Object[].class);
-            assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class);
-            assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType());
+            /* if access == SET */ assert(access != ArrayAccess.SET || mh.type().parameterType(2) == Object.class);
+            /* if access == GET */ assert(access != ArrayAccess.GET ||
+                    (mh.type().returnType() == Object.class &&
+                     correctType.parameterType(0).getComponentType() == correctType.returnType()));
             // safe to view non-strictly, because element type follows from array type
             mh = mh.viewAsType(correctType, false);
         }
-        mh = makeIntrinsic(mh, (isSetter ? Intrinsic.ARRAY_STORE : Intrinsic.ARRAY_LOAD));
+        mh = makeIntrinsic(mh, ArrayAccess.intrinsic(access));
         // Atomically update accessor cache.
         synchronized(cache) {
             if (cache[cacheIndex] == null) {
@@ -97,9 +100,52 @@
         return mh;
     }
 
+    enum ArrayAccess {
+        GET, SET, LENGTH;
+
+        // As ArrayAccess and ArrayAccessor have a circular dependency, the ArrayAccess properties cannot be stored in
+        // final fields.
+
+        static String opName(ArrayAccess a) {
+            switch (a) {
+                case GET: return "getElement";
+                case SET: return "setElement";
+                case LENGTH: return "length";
+            }
+            throw new AssertionError();
+        }
+
+        static MethodHandle objectAccessor(ArrayAccess a) {
+            switch (a) {
+                case GET: return ArrayAccessor.OBJECT_ARRAY_GETTER;
+                case SET: return ArrayAccessor.OBJECT_ARRAY_SETTER;
+                case LENGTH: return ArrayAccessor.OBJECT_ARRAY_LENGTH;
+            }
+            throw new AssertionError();
+        }
+
+        static int cacheIndex(ArrayAccess a) {
+            switch (a) {
+                case GET: return ArrayAccessor.GETTER_INDEX;
+                case SET: return ArrayAccessor.SETTER_INDEX;
+                case LENGTH: return ArrayAccessor.LENGTH_INDEX;
+            }
+            throw new AssertionError();
+        }
+
+        static Intrinsic intrinsic(ArrayAccess a) {
+            switch (a) {
+                case GET: return Intrinsic.ARRAY_LOAD;
+                case SET: return Intrinsic.ARRAY_STORE;
+                case LENGTH: return Intrinsic.ARRAY_LENGTH;
+            }
+            throw new AssertionError();
+        }
+    }
+
     static final class ArrayAccessor {
-        /// Support for array element access
-        static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2;
+        /// Support for array element and length access
+        static final int GETTER_INDEX = 0, SETTER_INDEX = 1, LENGTH_INDEX = 2, INDEX_LIMIT = 3;
         static final ClassValue<MethodHandle[]> TYPED_ACCESSORS
                 = new ClassValue<MethodHandle[]>() {
                     @Override
@@ -107,14 +153,16 @@
                         return new MethodHandle[INDEX_LIMIT];
                     }
                 };
-        static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER;
+        static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER, OBJECT_ARRAY_LENGTH;
         static {
             MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class);
-            cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, false), Intrinsic.ARRAY_LOAD);
-            cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, true),  Intrinsic.ARRAY_STORE);
+            cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.GET),    Intrinsic.ARRAY_LOAD);
+            cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.SET),    Intrinsic.ARRAY_STORE);
+            cache[LENGTH_INDEX] = OBJECT_ARRAY_LENGTH = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.LENGTH), Intrinsic.ARRAY_LENGTH);
 
             assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName()));
             assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName()));
+            assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_LENGTH.internalMemberName()));
         }
 
         static int     getElementI(int[]     a, int i)            { return              a[i]; }
@@ -137,31 +185,47 @@
         static void    setElementC(char[]    a, int i, char    x) {              a[i] = x; }
         static void    setElementL(Object[]  a, int i, Object  x) {              a[i] = x; }
 
-        static String name(Class<?> arrayClass, boolean isSetter) {
+        static int     lengthI(int[]     a)                       { return a.length; }
+        static int     lengthJ(long[]    a)                       { return a.length; }
+        static int     lengthF(float[]   a)                       { return a.length; }
+        static int     lengthD(double[]  a)                       { return a.length; }
+        static int     lengthZ(boolean[] a)                       { return a.length; }
+        static int     lengthB(byte[]    a)                       { return a.length; }
+        static int     lengthS(short[]   a)                       { return a.length; }
+        static int     lengthC(char[]    a)                       { return a.length; }
+        static int     lengthL(Object[]  a)                       { return a.length; }
+
+        static String name(Class<?> arrayClass, ArrayAccess access) {
             Class<?> elemClass = arrayClass.getComponentType();
             if (elemClass == null)  throw newIllegalArgumentException("not an array", arrayClass);
-            return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
+            return ArrayAccess.opName(access) + Wrapper.basicTypeChar(elemClass);
         }
-        static MethodType type(Class<?> arrayClass, boolean isSetter) {
+        static MethodType type(Class<?> arrayClass, ArrayAccess access) {
             Class<?> elemClass = arrayClass.getComponentType();
             Class<?> arrayArgClass = arrayClass;
             if (!elemClass.isPrimitive()) {
                 arrayArgClass = Object[].class;
                 elemClass = Object.class;
             }
-            return !isSetter ?
-                    MethodType.methodType(elemClass,  arrayArgClass, int.class) :
-                    MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
+            switch (access) {
+                case GET:    return MethodType.methodType(elemClass,  arrayArgClass, int.class);
+                case SET:    return MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
+                case LENGTH: return MethodType.methodType(int.class,  arrayArgClass);
+            }
+            throw new IllegalStateException("should not reach here");
         }
-        static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
+        static MethodType correctType(Class<?> arrayClass, ArrayAccess access) {
             Class<?> elemClass = arrayClass.getComponentType();
-            return !isSetter ?
-                    MethodType.methodType(elemClass,  arrayClass, int.class) :
-                    MethodType.methodType(void.class, arrayClass, int.class, elemClass);
+            switch (access) {
+                case GET:    return MethodType.methodType(elemClass,  arrayClass, int.class);
+                case SET:    return MethodType.methodType(void.class, arrayClass, int.class, elemClass);
+                case LENGTH: return MethodType.methodType(int.class,  arrayClass);
+            }
+            throw new IllegalStateException("should not reach here");
         }
-        static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
-            String     name = name(arrayClass, isSetter);
-            MethodType type = type(arrayClass, isSetter);
+        static MethodHandle getAccessor(Class<?> arrayClass, ArrayAccess access) {
+            String     name = name(arrayClass, access);
+            MethodType type = type(arrayClass, access);
             try {
                 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
             } catch (ReflectiveOperationException ex) {
@@ -1282,6 +1346,7 @@
         NEW_ARRAY,
         ARRAY_LOAD,
         ARRAY_STORE,
+        ARRAY_LENGTH,
         IDENTITY,
         ZERO,
         NONE // no intrinsic associated
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Wed May 18 12:04:26 2016 -0700
@@ -2245,6 +2245,20 @@
     }
 
     /**
+     * Produces a method handle returning the length of an array.
+     * The type of the method handle will have {@code int} as return type,
+     * and its sole argument will be the array type.
+     * @param arrayClass an array type
+     * @return a method handle which can retrieve the length of an array of the given array type
+     * @throws NullPointerException if the argument is {@code null}
+     * @throws IllegalArgumentException if arrayClass is not an array type
+     */
+    public static
+    MethodHandle arrayLength(Class<?> arrayClass) throws IllegalArgumentException {
+        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.LENGTH);
+    }
+
+    /**
      * Produces a method handle giving read access to elements of an array.
      * The type of the method handle will have a return type of the array's
      * element type.  Its first argument will be the array type,
@@ -2256,7 +2270,7 @@
      */
     public static
     MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
-        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, false);
+        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.GET);
     }
 
     /**
@@ -2271,7 +2285,7 @@
      */
     public static
     MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
-        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
+        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET);
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Wed May 18 12:04:26 2016 -0700
@@ -26,6 +26,7 @@
 package java.lang.invoke;
 
 import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.util.Preconditions;
 import jdk.internal.vm.annotation.ForceInline;
 import jdk.internal.vm.annotation.Stable;
 
@@ -33,7 +34,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.function.BiFunction;
 import java.util.function.Function;
 
@@ -1475,11 +1475,11 @@
         TypesAndInvokers tis = getTypesAndInvokers();
         MethodHandle mh = tis.methodHandle_table[mode];
         if (mh == null) {
-            mh = tis.methodHandle_table[mode] = getMethodHandleUncached(tis, mode);
+            mh = tis.methodHandle_table[mode] = getMethodHandleUncached(mode);
         }
         return mh;
     }
-    private final MethodHandle getMethodHandleUncached(TypesAndInvokers tis, int mode) {
+    private final MethodHandle getMethodHandleUncached(int mode) {
         MethodType mt = accessModeType(AccessMode.values()[mode]).
                 insertParameterTypes(0, VarHandle.class);
         MemberName mn = vform.getMemberName(mode);
@@ -1501,7 +1501,7 @@
     }
 
     static final BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException>
-            AIOOBE_SUPPLIER = Objects.outOfBoundsExceptionFormatter(
+            AIOOBE_SUPPLIER = Preconditions.outOfBoundsExceptionFormatter(
             new Function<String, ArrayIndexOutOfBoundsException>() {
                 @Override
                 public ArrayIndexOutOfBoundsException apply(String s) {
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Wed May 18 12:04:26 2016 -0700
@@ -24,8 +24,10 @@
  */
 package java.lang.invoke;
 
+import jdk.internal.util.Preconditions;
+import jdk.internal.vm.annotation.ForceInline;
+
 import java.util.Objects;
-import jdk.internal.vm.annotation.ForceInline;
 
 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
 
@@ -163,8 +165,7 @@
 
         @ForceInline
         static boolean weakCompareAndSetVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
-            // TODO defer to strong form until new Unsafe method is added
-            return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+            return UNSAFE.weakCompareAndSwap$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
                                                handle.fieldOffset,
                                                {#if[Object]?handle.fieldType.cast(expected):expected},
                                                {#if[Object]?handle.fieldType.cast(value):value});
@@ -345,8 +346,7 @@
 
         @ForceInline
         static boolean weakCompareAndSetVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
-            // TODO defer to strong form until new Unsafe method is added
-            return UNSAFE.compareAndSwap$Type$(handle.base,
+            return UNSAFE.weakCompareAndSwap$Type$Volatile(handle.base,
                                                handle.fieldOffset,
                                                {#if[Object]?handle.fieldType.cast(expected):expected},
                                                {#if[Object]?handle.fieldType.cast(value):value});
@@ -447,7 +447,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.get$Type$Volatile(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
         }
 
         @ForceInline
@@ -458,7 +458,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             UNSAFE.put$Type$Volatile(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(value):value});
         }
 
@@ -470,7 +470,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.get$Type$Opaque(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
         }
 
         @ForceInline
@@ -481,7 +481,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             UNSAFE.put$Type$Opaque(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(value):value});
         }
 
@@ -493,7 +493,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.get$Type$Acquire(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
         }
 
         @ForceInline
@@ -504,7 +504,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             UNSAFE.put$Type$Release(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(value):value});
         }
 #if[CAS]
@@ -517,7 +517,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.compareAndSwap$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -530,7 +530,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.compareAndExchange$Type$Volatile(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -543,7 +543,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.compareAndExchange$Type$Acquire(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -556,7 +556,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.compareAndExchange$Type$Release(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -569,7 +569,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.weakCompareAndSwap$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -581,9 +581,8 @@
 #else[Object]
             $type$[] array = ($type$[]) oarray;
 #end[Object]
-            // TODO defer to strong form until new Unsafe method is added
-            return UNSAFE.compareAndSwap$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+            return UNSAFE.weakCompareAndSwap$Type$Volatile(array,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -596,7 +595,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.weakCompareAndSwap$Type$Acquire(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -609,7 +608,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.weakCompareAndSwap$Type$Release(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -622,7 +621,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.getAndSet$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(value):value});
         }
 #end[CAS]
@@ -636,7 +635,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.getAndAdd$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     value);
         }
 
@@ -648,7 +647,7 @@
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.getAndAdd$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     value) + value;
         }
 #end[AtomicAdd]
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template	Wed May 18 12:04:26 2016 -0700
@@ -25,6 +25,7 @@
 package java.lang.invoke;
 
 import jdk.internal.misc.Unsafe;
+import jdk.internal.util.Preconditions;
 import jdk.internal.vm.annotation.ForceInline;
 
 import java.nio.ByteBuffer;
@@ -81,7 +82,7 @@
 
         @ForceInline
         static int index(byte[] ba, int index) {
-            return Objects.checkIndex(index, ba.length - ALIGN, null);
+            return Preconditions.checkIndex(index, ba.length - ALIGN, null);
         }
 
         @ForceInline
@@ -233,8 +234,7 @@
         @ForceInline
         static boolean weakCompareAndSetVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
             byte[] ba = (byte[]) oba;
-            // TODO defer to strong form until new Unsafe method is added
-            return UNSAFE.compareAndSwap$RawType$(
+            return UNSAFE.weakCompareAndSwap$RawType$Volatile(
                     ba,
                     address(ba, index(ba, index)),
                     convEndian(handle.be, expected), convEndian(handle.be, value));
@@ -271,22 +271,33 @@
 #if[AtomicAdd]
 
         @ForceInline
-        static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ value) {
+        static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ delta) {
             byte[] ba = (byte[]) oba;
-            return convEndian(handle.be,
-                              UNSAFE.getAndAdd$RawType$(
-                                      ba,
-                                      address(ba, index(ba, index)),
-                                      convEndian(handle.be, value)));
+            if (handle.be == BE) {
+                return UNSAFE.getAndAdd$RawType$(
+                        ba,
+                        address(ba, index(ba, index)),
+                        delta);
+            } else {
+                return getAndAddConvEndianWithCAS(ba, index, delta);
+            }
         }
 
         @ForceInline
-        static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ value) {
-            byte[] ba = (byte[]) oba;
-            return convEndian(handle.be, UNSAFE.getAndAdd$RawType$(
-                    ba,
-                    address(ba, index(ba, index)),
-                    convEndian(handle.be, value))) + value;
+        static $type$ getAndAddConvEndianWithCAS(byte[] ba, int index, $type$ delta) {
+            $type$ nativeExpectedValue, expectedValue;
+            long offset = address(ba, index(ba, index));
+            do {
+                nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset);
+                expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
+            } while (!UNSAFE.weakCompareAndSwap$RawType$Volatile(ba, offset,
+                    nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta)));
+            return expectedValue;
+        }
+
+        @ForceInline
+        static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ delta) {
+            return getAndAdd(handle, oba, index, delta) + delta;
         }
 #end[AtomicAdd]
 
@@ -307,14 +318,14 @@
 
         @ForceInline
         static int index(ByteBuffer bb, int index) {
-            return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
+            return Preconditions.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
         }
 
         @ForceInline
         static int indexRO(ByteBuffer bb, int index) {
             if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY))
                 throw new ReadOnlyBufferException();
-            return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
+            return Preconditions.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
         }
 
         @ForceInline
@@ -466,8 +477,7 @@
         @ForceInline
         static boolean weakCompareAndSetVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
             ByteBuffer bb = (ByteBuffer) obb;
-            // TODO defer to strong form until new Unsafe method is added
-            return UNSAFE.compareAndSwap$RawType$(
+            return UNSAFE.weakCompareAndSwap$RawType$Volatile(
                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
                     address(bb, indexRO(bb, index)),
                     convEndian(handle.be, expected), convEndian(handle.be, value));
@@ -504,23 +514,34 @@
 #if[AtomicAdd]
 
         @ForceInline
-        static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+        static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ delta) {
             ByteBuffer bb = (ByteBuffer) obb;
-            return convEndian(handle.be,
-                              UNSAFE.getAndAdd$RawType$(
-                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
-                                      address(bb, indexRO(bb, index)),
-                                      convEndian(handle.be, value)));
+            if (handle.be == BE) {
+                return UNSAFE.getAndAdd$RawType$(
+                        UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                        address(bb, indexRO(bb, index)),
+                        delta);
+            } else {
+                return getAndAddConvEndianWithCAS(bb, index, delta);
+            }
         }
 
         @ForceInline
-        static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
-            ByteBuffer bb = (ByteBuffer) obb;
-            return convEndian(handle.be,
-                              UNSAFE.getAndAdd$RawType$(
-                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
-                                      address(bb, indexRO(bb, index)),
-                                      convEndian(handle.be, value))) + value;
+        static $type$ getAndAddConvEndianWithCAS(ByteBuffer bb, int index, $type$ delta) {
+            $type$ nativeExpectedValue, expectedValue;
+            Object base = UNSAFE.getObject(bb, BYTE_BUFFER_HB);
+            long offset = address(bb, indexRO(bb, index));
+            do {
+                nativeExpectedValue = UNSAFE.get$RawType$Volatile(base, offset);
+                expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
+            } while (!UNSAFE.weakCompareAndSwap$RawType$Volatile(base, offset,
+                    nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta)));
+            return expectedValue;
+        }
+
+        @ForceInline
+        static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ delta) {
+            return getAndAdd(handle, obb, index, delta) + delta;
         }
 #end[AtomicAdd]
 
--- a/src/java.base/share/classes/java/nio/Buffer.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/nio/Buffer.java	Wed May 18 12:04:26 2016 -0700
@@ -111,7 +111,7 @@
  * to zero.
  *
  *
- * <h2> Clearing, flipping, and rewinding </h2>
+ * <h2> Additional operations </h2>
  *
  * <p> In addition to methods for accessing the position, limit, and capacity
  * values and for marking and resetting, this class also defines the following
@@ -131,6 +131,12 @@
  *   it already contains: It leaves the limit unchanged and sets the position
  *   to zero.  </p></li>
  *
+ *   <li><p> {@link #slice} creates a subsequence of a buffer: It leaves the
+ *   limit and the position unchanged. </p></li>
+ *
+ *   <li><p> {@link #duplicate} creates a shallow copy of a buffer: It leaves
+ *   the limit and the position unchanged. </p></li>
+ *
  * </ul>
  *
  *
@@ -567,6 +573,46 @@
      */
     public abstract boolean isDirect();
 
+    /**
+     * Creates a new buffer whose content is a shared subsequence of
+     * this buffer's content.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position.  Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of elements remaining in this buffer, its mark will be
+     * undefined. The new buffer will be direct if, and only if, this buffer is
+     * direct, and it will be read-only if, and only if, this buffer is
+     * read-only.  </p>
+     *
+     * @return  The new buffer
+     *
+     * @since 9
+     */
+    public abstract Buffer slice();
+
+    /**
+     * Creates a new buffer that shares this buffer's content.
+     *
+     * <p> The content of the new buffer will be that of this buffer.  Changes
+     * to this buffer's content will be visible in the new buffer, and vice
+     * versa; the two buffers' position, limit, and mark values will be
+     * independent.
+     *
+     * <p> The new buffer's capacity, limit, position and mark values will be
+     * identical to those of this buffer. The new buffer will be direct if, and
+     * only if, this buffer is direct, and it will be read-only if, and only if,
+     * this buffer is read-only.  </p>
+     *
+     * @return  The new buffer
+     *
+     * @since 9
+     */
+    public abstract Buffer duplicate();
+
 
     // -- Package-private methods for bounds checking, etc. --
 
--- a/src/java.base/share/classes/java/nio/X-Buffer.java.template	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template	Wed May 18 12:04:26 2016 -0700
@@ -70,8 +70,7 @@
  *
 #end[byte]
  *
- *   <li><p> Methods for {@link #compact compacting}, {@link
- *   #duplicate duplicating}, and {@link #slice slicing}
+ *   <li><p> A method for {@link #compact compacting}
  *   $a$ $type$ buffer.  </p></li>
  *
  * </ul>
@@ -535,6 +534,7 @@
      * @see #alignedSlice(int)
 #end[byte]
      */
+    @Override
     public abstract $Type$Buffer slice();
 
     /**
@@ -557,6 +557,7 @@
      *
      * @return  The new $type$ buffer
      */
+    @Override
     public abstract $Type$Buffer duplicate();
 
     /**
--- a/src/java.base/share/classes/java/text/MessageFormat.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/text/MessageFormat.java	Wed May 18 12:04:26 2016 -0700
@@ -1068,7 +1068,7 @@
      *            index information as described above.
      * @return An <code>Object</code> array parsed from the string. In case of
      *         error, returns null.
-     * @throws NullPointerException if {@code source} or {@code pos} is null.
+     * @throws NullPointerException if {@code pos} is null.
      */
     public Object parseObject(String source, ParsePosition pos) {
         return parse(source, pos);
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java	Wed May 18 12:04:26 2016 -0700
@@ -308,6 +308,7 @@
  *   N       nano-of-day                 number            1234000000
  *
  *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
+ *   v       generic time-zone name      zone-name         Pacific Time; PT
  *   z       time-zone name              zone-name         Pacific Standard Time; PST
  *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00
  *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
@@ -365,9 +366,17 @@
  * letters throws {@code IllegalArgumentException}.
  * <p>
  * <b>Zone names</b>: This outputs the display name of the time-zone ID. If the
- * count of letters is one, two or three, then the short name is output. If the
- * count of letters is four, then the full name is output. Five or more letters
- * throws {@code IllegalArgumentException}.
+ * pattern letter is 'z' the output is the daylight savings aware zone name.
+ * If there is insufficient information to determine whether DST applies,
+ * the name ignoring daylight savings time will be used.
+ * If the count of letters is one, two or three, then the short name is output.
+ * If the count of letters is four, then the full name is output.
+ * Five or more letters throws {@code IllegalArgumentException}.
+ * <p>
+ * If the pattern letter is 'v' the output provides the zone name ignoring
+ * daylight savings time. If the count of letters is one, then the short name is output.
+ * If the count of letters is four, then the full name is output.
+ * Two, three and five or more letters throw {@code IllegalArgumentException}.
  * <p>
  * <b>Offset X and x</b>: This formats the offset based on the number of pattern
  * letters. One letter outputs just the hour, such as '+01', unless the minute
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Wed May 18 12:04:26 2016 -0700
@@ -81,9 +81,11 @@
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.ChronoLocalDateTime;
 import java.time.chrono.Chronology;
 import java.time.chrono.Era;
 import java.time.chrono.IsoChronology;
@@ -1157,10 +1159,11 @@
      * result of {@link ZoneOffset#getId()}.
      * If the zone is not an offset, the textual name will be looked up
      * for the locale set in the {@link DateTimeFormatter}.
-     * If the temporal object being printed represents an instant, then the text
-     * will be the summer or winter time text as appropriate.
+     * If the temporal object being printed represents an instant, or if it is a
+     * local date-time that is not in a daylight saving gap or overlap then
+     * the text will be the summer or winter time text as appropriate.
      * If the lookup for text does not find any suitable result, then the
-     * {@link ZoneId#getId() ID} will be printed instead.
+     * {@link ZoneId#getId() ID} will be printed.
      * If the zone cannot be obtained then an exception is thrown unless the
      * section of the formatter is optional.
      * <p>
@@ -1177,7 +1180,7 @@
      * @return this, for chaining, not null
      */
     public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle) {
-        appendInternal(new ZoneTextPrinterParser(textStyle, null));
+        appendInternal(new ZoneTextPrinterParser(textStyle, null, false));
         return this;
     }
 
@@ -1193,10 +1196,11 @@
      * result of {@link ZoneOffset#getId()}.
      * If the zone is not an offset, the textual name will be looked up
      * for the locale set in the {@link DateTimeFormatter}.
-     * If the temporal object being printed represents an instant, then the text
+     * If the temporal object being printed represents an instant, or if it is a
+     * local date-time that is not in a daylight saving gap or overlap, then the text
      * will be the summer or winter time text as appropriate.
      * If the lookup for text does not find any suitable result, then the
-     * {@link ZoneId#getId() ID} will be printed instead.
+     * {@link ZoneId#getId() ID} will be printed.
      * If the zone cannot be obtained then an exception is thrown unless the
      * section of the formatter is optional.
      * <p>
@@ -1220,7 +1224,70 @@
     public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle,
                                                    Set<ZoneId> preferredZones) {
         Objects.requireNonNull(preferredZones, "preferredZones");
-        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones));
+        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones, false));
+        return this;
+    }
+    //----------------------------------------------------------------------
+    /**
+     * Appends the generic time-zone name, such as 'Pacific Time', to the formatter.
+     * <p>
+     * This appends an instruction to format/parse the generic textual
+     * name of the zone to the builder. The generic name is the same throughout the whole
+     * year, ignoring any daylight saving changes. For example, 'Pacific Time' is the
+     * generic name, whereas 'Pacific Standard Time' and 'Pacific Daylight Time' are the
+     * specific names, see {@link #appendZoneText(TextStyle)}.
+     * <p>
+     * During formatting, the zone is obtained using a mechanism equivalent
+     * to querying the temporal with {@link TemporalQueries#zoneId()}.
+     * If the zone is a {@code ZoneOffset} it will be printed using the
+     * result of {@link ZoneOffset#getId()}.
+     * If the zone is not an offset, the textual name will be looked up
+     * for the locale set in the {@link DateTimeFormatter}.
+     * If the lookup for text does not find any suitable result, then the
+     * {@link ZoneId#getId() ID} will be printed.
+     * If the zone cannot be obtained then an exception is thrown unless the
+     * section of the formatter is optional.
+     * <p>
+     * During parsing, either the textual zone name, the zone ID or the offset
+     * is accepted. Many textual zone names are not unique, such as CST can be
+     * for both "Central Standard Time" and "China Standard Time". In this
+     * situation, the zone id will be determined by the region information from
+     * formatter's  {@link DateTimeFormatter#getLocale() locale} and the standard
+     * zone id for that area, for example, America/New_York for the America Eastern zone.
+     * The {@link #appendGenericZoneText(TextStyle, Set)} may be used
+     * to specify a set of preferred {@link ZoneId} in this situation.
+     *
+     * @param textStyle  the text style to use, not null
+     * @return this, for chaining, not null
+     */
+    public DateTimeFormatterBuilder appendGenericZoneText(TextStyle textStyle) {
+        appendInternal(new ZoneTextPrinterParser(textStyle, null, true));
+        return this;
+    }
+
+    /**
+     * Appends the generic time-zone name, such as 'Pacific Time', to the formatter.
+     * <p>
+     * This appends an instruction to format/parse the generic textual
+     * name of the zone to the builder. The generic name is the same throughout the whole
+     * year, ignoring any daylight saving changes. For example, 'Pacific Time' is the
+     * generic name, whereas 'Pacific Standard Time' and 'Pacific Daylight Time' are the
+     * specific names, see {@link #appendZoneText(TextStyle)}.
+     * <p>
+     * This method also allows a set of preferred {@link ZoneId} to be
+     * specified for parsing. The matched preferred zone id will be used if the
+     * textural zone name being parsed is not unique.
+     * <p>
+     * See {@link #appendGenericZoneText(TextStyle)} for details about
+     * formatting and parsing.
+     *
+     * @param textStyle  the text style to use, not null
+     * @param preferredZones  the set of preferred zone ids, not null
+     * @return this, for chaining, not null
+     */
+    public DateTimeFormatterBuilder appendGenericZoneText(TextStyle textStyle,
+                                                          Set<ZoneId> preferredZones) {
+        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones, true));
         return this;
     }
 
@@ -1416,6 +1483,7 @@
      *   N       nano-of-day                 number            1234000000
      *
      *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
+     *   v       generic time-zone name      zone-name         PT, Pacific Time
      *   z       time-zone name              zone-name         Pacific Standard Time; PST
      *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
      *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
@@ -1537,6 +1605,8 @@
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
      *    VV      2      appendZoneId()
+     *    v       1      appendGenericZoneText(TextStyle.SHORT)
+     *    vvvv    4      appendGenericZoneText(TextStyle.FULL)
      *    z       1      appendZoneText(TextStyle.SHORT)
      *    zz      2      appendZoneText(TextStyle.SHORT)
      *    zzz     3      appendZoneText(TextStyle.SHORT)
@@ -1643,6 +1713,14 @@
                         throw new IllegalArgumentException("Pattern letter count must be 2: " + cur);
                     }
                     appendZoneId();
+                } else if (cur == 'v') {
+                    if (count == 1) {
+                        appendGenericZoneText(TextStyle.SHORT);
+                    } else if (count == 4) {
+                        appendGenericZoneText(TextStyle.FULL);
+                    } else {
+                        throw new IllegalArgumentException("Wrong number of  pattern letters: " + cur);
+                    }
                 } else if (cur == 'Z') {
                     if (count < 4) {
                         appendOffset("+HHMM", "+0000");
@@ -1894,6 +1972,8 @@
         // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4
         // 310 - Z - matches SimpleDateFormat and LDML
         // 310 - V - time-zone id, matches LDML
+        // 310 - v - general timezone names, not matching exactly with LDML because LDML specify to fall back
+        //           to 'VVVV' if general-nonlocation unavailable but here it's not falling back because of lack of data
         // 310 - p - prefix for padding
         // 310 - X - matches LDML, almost matches SDF for 1, exact match 2&3, extended 4&5
         // 310 - x - matches LDML
@@ -1901,7 +1981,6 @@
         // LDML - U - cycle year name, not supported by 310 yet
         // LDML - l - deprecated
         // LDML - j - not relevant
-        // LDML - v,V - extended time-zone names
     }
 
     //-----------------------------------------------------------------------
@@ -3723,9 +3802,12 @@
         /** The preferred zoneid map */
         private Set<String> preferredZones;
 
-        ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones) {
+        /**  Display in generic time-zone format. True in case of pattern letter 'v' */
+        private final boolean isGeneric;
+        ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones, boolean isGeneric) {
             super(TemporalQueries.zone(), "ZoneText(" + textStyle + ")");
             this.textStyle = Objects.requireNonNull(textStyle, "textStyle");
+            this.isGeneric = isGeneric;
             if (preferredZones != null && preferredZones.size() != 0) {
                 this.preferredZones = new HashSet<>();
                 for (ZoneId id : preferredZones) {
@@ -3788,11 +3870,21 @@
             String zname = zone.getId();
             if (!(zone instanceof ZoneOffset)) {
                 TemporalAccessor dt = context.getTemporal();
-                String name = getDisplayName(zname,
-                                             dt.isSupported(ChronoField.INSTANT_SECONDS)
-                                             ? (zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD)
-                                             : GENERIC,
-                                             context.getLocale());
+                int type = GENERIC;
+                if (!isGeneric) {
+                    if (dt.isSupported(ChronoField.INSTANT_SECONDS)) {
+                        type = zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD;
+                    } else if (dt.isSupported(ChronoField.EPOCH_DAY) &&
+                               dt.isSupported(ChronoField.NANO_OF_DAY)) {
+                        LocalDate date = LocalDate.ofEpochDay(dt.getLong(ChronoField.EPOCH_DAY));
+                        LocalTime time = LocalTime.ofNanoOfDay(dt.getLong(ChronoField.NANO_OF_DAY));
+                        LocalDateTime ldt = date.atTime(time);
+                        if (zone.getRules().getTransition(ldt) == null) {
+                            type = zone.getRules().isDaylightSavings(ldt.atZone(zone).toInstant()) ? DST : STD;
+                        }
+                    }
+                }
+                String name = getDisplayName(zname, type, context.getLocale());
                 if (name != null) {
                     zname = name;
                 }
--- a/src/java.base/share/classes/java/time/zone/ZoneRules.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/time/zone/ZoneRules.java	Wed May 18 12:04:26 2016 -0700
@@ -614,7 +614,7 @@
      * One technique, using this method, would be:
      * <pre>
      *  ZoneOffsetTransition trans = rules.getTransition(localDT);
-     *  if (trans == null) {
+     *  if (trans != null) {
      *    // Gap or Overlap: determine what to do from transition
      *  } else {
      *    // Normal case: only one valid offset
--- a/src/java.base/share/classes/java/util/DualPivotQuicksort.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/util/DualPivotQuicksort.java	Wed May 18 12:04:26 2016 -0700
@@ -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
@@ -146,12 +146,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
@@ -598,12 +612,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
@@ -1086,12 +1114,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
@@ -1574,12 +1616,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
@@ -2158,12 +2214,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
@@ -2701,12 +2771,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
--- a/src/java.base/share/classes/java/util/Objects.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/util/Objects.java	Wed May 18 12:04:26 2016 -0700
@@ -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
@@ -25,10 +25,9 @@
 
 package java.util;
 
-import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.util.Preconditions;
+import jdk.internal.vm.annotation.ForceInline;
 
-import java.util.function.BiFunction;
-import java.util.function.Function;
 import java.util.function.Supplier;
 
 /**
@@ -349,172 +348,6 @@
     }
 
     /**
-     * Maps out-of-bounds values to a runtime exception.
-     *
-     * @param checkKind the kind of bounds check, whose name may correspond
-     *        to the name of one of the range check methods, checkIndex,
-     *        checkFromToIndex, checkFromIndexSize
-     * @param args the out-of-bounds arguments that failed the range check.
-     *        If the checkKind corresponds a the name of a range check method
-     *        then the bounds arguments are those that can be passed in order
-     *        to the method.
-     * @param oobef the exception formatter that when applied with a checkKind
-     *        and a list out-of-bounds arguments returns a runtime exception.
-     *        If {@code null} then, it is as if an exception formatter was
-     *        supplied that returns {@link IndexOutOfBoundsException} for any
-     *        given arguments.
-     * @return the runtime exception
-     */
-    private static RuntimeException outOfBounds(
-            BiFunction<String, List<Integer>, ? extends RuntimeException> oobef,
-            String checkKind,
-            Integer... args) {
-        List<Integer> largs = List.of(args);
-        RuntimeException e = oobef == null
-                             ? null : oobef.apply(checkKind, largs);
-        return e == null
-               ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e;
-    }
-
-    // Specific out-of-bounds exception producing methods that avoid
-    // the varargs-based code in the critical methods there by reducing their
-    // the byte code size, and therefore less likely to peturb inlining
-
-    private static RuntimeException outOfBoundsCheckIndex(
-            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
-            int index, int length) {
-        return outOfBounds(oobe, "checkIndex", index, length);
-    }
-
-    private static RuntimeException outOfBoundsCheckFromToIndex(
-            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
-            int fromIndex, int toIndex, int length) {
-        return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length);
-    }
-
-    private static RuntimeException outOfBoundsCheckFromIndexSize(
-            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
-            int fromIndex, int size, int length) {
-        return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length);
-    }
-
-    /**
-     * Returns an out-of-bounds exception formatter from an given exception
-     * factory.  The exception formatter is a function that formats an
-     * out-of-bounds message from its arguments and applies that message to the
-     * given exception factory to produce and relay an exception.
-     *
-     * <p>The exception formatter accepts two arguments: a {@code String}
-     * describing the out-of-bounds range check that failed, referred to as the
-     * <em>check kind</em>; and a {@code List<Integer>} containing the
-     * out-of-bound integer values that failed the check.  The list of
-     * out-of-bound values is not modified.
-     *
-     * <p>Three check kinds are supported {@code checkIndex},
-     * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding
-     * respectively to the specified application of an exception formatter as an
-     * argument to the out-of-bounds range check methods
-     * {@link #checkIndex(int, int, BiFunction) checkIndex},
-     * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and
-     * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}.
-     * Thus a supported check kind corresponds to a method name and the
-     * out-of-bound integer values correspond to method argument values, in
-     * order, preceding the exception formatter argument (similar in many
-     * respects to the form of arguments required for a reflective invocation of
-     * such a range check method).
-     *
-     * <p>Formatter arguments conforming to such supported check kinds will
-     * produce specific exception messages describing failed out-of-bounds
-     * checks.  Otherwise, more generic exception messages will be produced in
-     * any of the following cases: the check kind is supported but fewer
-     * or more out-of-bounds values are supplied, the check kind is not
-     * supported, the check kind is {@code null}, or the list of out-of-bound
-     * values is {@code null}.
-     *
-     * @apiNote
-     * This method produces an out-of-bounds exception formatter that can be
-     * passed as an argument to any of the supported out-of-bounds range check
-     * methods declared by {@code Objects}.  For example, a formatter producing
-     * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a
-     * {@code static final} field as follows:
-     * <pre>{@code
-     * static final
-     * BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException> AIOOBEF =
-     *     outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new);
-     * }</pre>
-     * The formatter instance {@code AIOOBEF} may be passed as an argument to an
-     * out-of-bounds range check method, such as checking if an {@code index}
-     * is within the bounds of a {@code limit}:
-     * <pre>{@code
-     * checkIndex(index, limit, AIOOBEF);
-     * }</pre>
-     * If the bounds check fails then the range check method will throw an
-     * {@code ArrayIndexOutOfBoundsException} with an appropriate exception
-     * message that is a produced from {@code AIOOBEF} as follows:
-     * <pre>{@code
-     * AIOOBEF.apply("checkIndex", List.of(index, limit));
-     * }</pre>
-     *
-     * @param f the exception factory, that produces an exception from a message
-     *        where the message is produced and formatted by the returned
-     *        exception formatter.  If this factory is stateless and side-effect
-     *        free then so is the returned formatter.
-     *        Exceptions thrown by the factory are relayed to the caller
-     *        of the returned formatter.
-     * @param <X> the type of runtime exception to be returned by the given
-     *        exception factory and relayed by the exception formatter
-     * @return the out-of-bounds exception formatter
-     */
-    public static <X extends RuntimeException>
-    BiFunction<String, List<Integer>, X> outOfBoundsExceptionFormatter(Function<String, X> f) {
-        // Use anonymous class to avoid bootstrap issues if this method is
-        // used early in startup
-        return new BiFunction<String, List<Integer>, X>() {
-            @Override
-            public X apply(String checkKind, List<Integer> args) {
-                return f.apply(outOfBoundsMessage(checkKind, args));
-            }
-        };
-    }
-
-    private static String outOfBoundsMessage(String checkKind, List<Integer> args) {
-        if (checkKind == null && args == null) {
-            return String.format("Range check failed");
-        } else if (checkKind == null) {
-            return String.format("Range check failed: %s", args);
-        } else if (args == null) {
-            return String.format("Range check failed: %s", checkKind);
-        }
-
-        int argSize = 0;
-        switch (checkKind) {
-            case "checkIndex":
-                argSize = 2;
-                break;
-            case "checkFromToIndex":
-            case "checkFromIndexSize":
-                argSize = 3;
-                break;
-            default:
-        }
-
-        // Switch to default if fewer or more arguments than required are supplied
-        switch ((args.size() != argSize) ? "" : checkKind) {
-            case "checkIndex":
-                return String.format("Index %d out-of-bounds for length %d",
-                                     args.get(0), args.get(1));
-            case "checkFromToIndex":
-                return String.format("Range [%d, %d) out-of-bounds for length %d",
-                                     args.get(0), args.get(1), args.get(2));
-            case "checkFromIndexSize":
-                return String.format("Range [%d, %<d + %d) out-of-bounds for length %d",
-                                     args.get(0), args.get(1), args.get(2));
-            default:
-                return String.format("Range check failed: %s %s", checkKind, args);
-        }
-    }
-
-    /**
      * Checks if the {@code index} is within the bounds of the range from
      * {@code 0} (inclusive) to {@code length} (exclusive).
      *
@@ -526,72 +359,16 @@
      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
      * </ul>
      *
-     * <p>This method behaves as if {@link #checkIndex(int, int, BiFunction)}
-     * was called with same out-of-bounds arguments and an exception formatter
-     * argument produced from an invocation of
-     * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may
-     * be more efficient).
-     *
      * @param index the index
      * @param length the upper-bound (exclusive) of the range
      * @return {@code index} if it is within bounds of the range
      * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds
      * @since 9
      */
+    @ForceInline
     public static
     int checkIndex(int index, int length) {
-        return checkIndex(index, length, null);
-    }
-
-    /**
-     * Checks if the {@code index} is within the bounds of the range from
-     * {@code 0} (inclusive) to {@code length} (exclusive).
-     *
-     * <p>The {@code index} is defined to be out-of-bounds if any of the
-     * following inequalities is true:
-     * <ul>
-     *  <li>{@code index < 0}</li>
-     *  <li>{@code index >= length}</li>
-     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
-     * </ul>
-     *
-     * <p>If the {@code index} is out-of-bounds, then a runtime exception is
-     * thrown that is the result of applying the following arguments to the
-     * exception formatter: the name of this method, {@code checkIndex};
-     * and an unmodifiable list integers whose values are, in order, the
-     * out-of-bounds arguments {@code index} and {@code length}.
-     *
-     * @param <X> the type of runtime exception to throw if the arguments are
-     *        out-of-bounds
-     * @param index the index
-     * @param length the upper-bound (exclusive) of the range
-     * @param oobef the exception formatter that when applied with this
-     *        method name and out-of-bounds arguments returns a runtime
-     *        exception.  If {@code null} or returns {@code null} then, it is as
-     *        if an exception formatter produced from an invocation of
-     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
-     *        instead (though it may be more efficient).
-     *        Exceptions thrown by the formatter are relayed to the caller.
-     * @return {@code index} if it is within bounds of the range
-     * @throws X if the {@code index} is out-of-bounds and the exception
-     *         formatter is non-{@code null}
-     * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds
-     *         and the exception formatter is {@code null}
-     * @since 9
-     *
-     * @implNote
-     * This method is made intrinsic in optimizing compilers to guide them to
-     * perform unsigned comparisons of the index and length when it is known the
-     * length is a non-negative value (such as that of an array length or from
-     * the upper bound of a loop)
-    */
-    @HotSpotIntrinsicCandidate
-    public static <X extends RuntimeException>
-    int checkIndex(int index, int length,
-                   BiFunction<String, List<Integer>, X> oobef) {
-        if (index < 0 || index >= length)
-            throw outOfBoundsCheckIndex(oobef, index, length);
-        return index;
+        return Preconditions.checkIndex(index, length, null);
     }
 
     /**
@@ -608,12 +385,6 @@
      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
      * </ul>
      *
-     * <p>This method behaves as if {@link #checkFromToIndex(int, int, int, BiFunction)}
-     * was called with same out-of-bounds arguments and an exception formatter
-     * argument produced from an invocation of
-     * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may
-     * be more efficient).
-     *
      * @param fromIndex the lower-bound (inclusive) of the sub-range
      * @param toIndex the upper-bound (exclusive) of the sub-range
      * @param length the upper-bound (exclusive) the range
@@ -623,54 +394,7 @@
      */
     public static
     int checkFromToIndex(int fromIndex, int toIndex, int length) {
-        return checkFromToIndex(fromIndex, toIndex, length, null);
-    }
-
-    /**
-     * Checks if the sub-range from {@code fromIndex} (inclusive) to
-     * {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
-     * (inclusive) to {@code length} (exclusive).
-     *
-     * <p>The sub-range is defined to be out-of-bounds if any of the following
-     * inequalities is true:
-     * <ul>
-     *  <li>{@code fromIndex < 0}</li>
-     *  <li>{@code fromIndex > toIndex}</li>
-     *  <li>{@code toIndex > length}</li>
-     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
-     * </ul>
-     *
-     * <p>If the sub-range  is out-of-bounds, then a runtime exception is
-     * thrown that is the result of applying the following arguments to the
-     * exception formatter: the name of this method, {@code checkFromToIndex};
-     * and an unmodifiable list integers whose values are, in order, the
-     * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}.
-     *
-     * @param <X> the type of runtime exception to throw if the arguments are
-     *        out-of-bounds
-     * @param fromIndex the lower-bound (inclusive) of the sub-range
-     * @param toIndex the upper-bound (exclusive) of the sub-range
-     * @param length the upper-bound (exclusive) the range
-     * @param oobef the exception formatter that when applied with this
-     *        method name and out-of-bounds arguments returns a runtime
-     *        exception.  If {@code null} or returns {@code null} then, it is as
-     *        if an exception formatter produced from an invocation of
-     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
-     *        instead (though it may be more efficient).
-     *        Exceptions thrown by the formatter are relayed to the caller.
-     * @return {@code fromIndex} if the sub-range within bounds of the range
-     * @throws X if the sub-range is out-of-bounds and the exception factory
-     *         function is non-{@code null}
-     * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and
-     *         the exception factory function is {@code null}
-     * @since 9
-     */
-    public static <X extends RuntimeException>
-    int checkFromToIndex(int fromIndex, int toIndex, int length,
-                         BiFunction<String, List<Integer>, X> oobef) {
-        if (fromIndex < 0 || fromIndex > toIndex || toIndex > length)
-            throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length);
-        return fromIndex;
+        return Preconditions.checkFromToIndex(fromIndex, toIndex, length, null);
     }
 
     /**
@@ -687,12 +411,6 @@
      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
      * </ul>
      *
-     * <p>This method behaves as if {@link #checkFromIndexSize(int, int, int, BiFunction)}
-     * was called with same out-of-bounds arguments and an exception formatter
-     * argument produced from an invocation of
-     * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may
-     * be more efficient).
-     *
      * @param fromIndex the lower-bound (inclusive) of the sub-interval
      * @param size the size of the sub-range
      * @param length the upper-bound (exclusive) of the range
@@ -702,54 +420,7 @@
      */
     public static
     int checkFromIndexSize(int fromIndex, int size, int length) {
-        return checkFromIndexSize(fromIndex, size, length, null);
+        return Preconditions.checkFromIndexSize(fromIndex, size, length, null);
     }
 
-    /**
-     * Checks if the sub-range from {@code fromIndex} (inclusive) to
-     * {@code fromIndex + size} (exclusive) is within the bounds of range from
-     * {@code 0} (inclusive) to {@code length} (exclusive).
-     *
-     * <p>The sub-range is defined to be out-of-bounds if any of the following
-     * inequalities is true:
-     * <ul>
-     *  <li>{@code fromIndex < 0}</li>
-     *  <li>{@code size < 0}</li>
-     *  <li>{@code fromIndex + size > length}, taking into account integer overflow</li>
-     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
-     * </ul>
-     *
-     * <p>If the sub-range  is out-of-bounds, then a runtime exception is
-     * thrown that is the result of applying the following arguments to the
-     * exception formatter: the name of this method, {@code checkFromIndexSize};
-     * and an unmodifiable list integers whose values are, in order, the
-     * out-of-bounds arguments {@code fromIndex}, {@code size}, and
-     * {@code length}.
-     *
-     * @param <X> the type of runtime exception to throw if the arguments are
-     *        out-of-bounds
-     * @param fromIndex the lower-bound (inclusive) of the sub-interval
-     * @param size the size of the sub-range
-     * @param length the upper-bound (exclusive) of the range
-     * @param oobef the exception formatter that when applied with this
-     *        method name and out-of-bounds arguments returns a runtime
-     *        exception.  If {@code null} or returns {@code null} then, it is as
-     *        if an exception formatter produced from an invocation of
-     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
-     *        instead (though it may be more efficient).
-     *        Exceptions thrown by the formatter are relayed to the caller.
-     * @return {@code fromIndex} if the sub-range within bounds of the range
-     * @throws X if the sub-range is out-of-bounds and the exception factory
-     *         function is non-{@code null}
-     * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and
-     *         the exception factory function is {@code null}
-     * @since 9
-     */
-    public static <X extends RuntimeException>
-    int checkFromIndexSize(int fromIndex, int size, int length,
-                           BiFunction<String, List<Integer>, X> oobef) {
-        if ((length | fromIndex | size) < 0 || size > length - fromIndex)
-            throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length);
-        return fromIndex;
-    }
 }
--- a/src/java.base/share/classes/java/util/zip/ZipFile.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/java/util/zip/ZipFile.java	Wed May 18 12:04:26 2016 -0700
@@ -462,9 +462,13 @@
 
     private class ZipEntryIterator implements Enumeration<ZipEntry>, Iterator<ZipEntry> {
         private int i = 0;
+        private final int entryCount;
 
         public ZipEntryIterator() {
-            ensureOpen();
+            synchronized (ZipFile.this) {
+                ensureOpen();
+                this.entryCount = zsrc.total;
+            }
         }
 
         public boolean hasMoreElements() {
@@ -472,10 +476,7 @@
         }
 
         public boolean hasNext() {
-            synchronized (ZipFile.this) {
-                ensureOpen();
-                return i < zsrc.total;
-            }
+            return i < entryCount;
         }
 
         public ZipEntry nextElement() {
@@ -485,7 +486,7 @@
         public ZipEntry next() {
             synchronized (ZipFile.this) {
                 ensureOpen();
-                if (i >= zsrc.total) {
+                if (!hasNext()) {
                     throw new NoSuchElementException();
                 }
                 // each "entry" has 3 ints in table entries
@@ -526,34 +527,34 @@
     /* Checks ensureOpen() before invoke this method */
     private ZipEntry getZipEntry(String name, int pos) {
         byte[] cen = zsrc.cen;
-        ZipEntry e = new ZipEntry();
         int nlen = CENNAM(cen, pos);
         int elen = CENEXT(cen, pos);
         int clen = CENCOM(cen, pos);
-        e.flag = CENFLG(cen, pos);  // get the flag first
-        if (name != null) {
-            e.name = name;
-        } else {
-            if (!zc.isUTF8() && (e.flag & EFS) != 0) {
-                e.name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
+        int flag = CENFLG(cen, pos);
+        if (name == null) {
+            if (!zc.isUTF8() && (flag & EFS) != 0) {
+                name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
             } else {
-                e.name = zc.toString(cen, pos + CENHDR, nlen);
+                name = zc.toString(cen, pos + CENHDR, nlen);
             }
         }
+        ZipEntry e = new ZipEntry(name);
+        e.flag = flag;
         e.xdostime = CENTIM(cen, pos);
         e.crc = CENCRC(cen, pos);
         e.size = CENLEN(cen, pos);
         e.csize = CENSIZ(cen, pos);
         e.method = CENHOW(cen, pos);
         if (elen != 0) {
-            e.setExtra0(Arrays.copyOfRange(cen, pos + CENHDR + nlen,
-                                           pos + CENHDR + nlen + elen), true);
+            int start = pos + CENHDR + nlen;
+            e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true);
         }
         if (clen != 0) {
-            if (!zc.isUTF8() && (e.flag & EFS) != 0) {
-                e.comment = zc.toStringUTF8(cen, pos + CENHDR + nlen + elen, clen);
+            int start = pos + CENHDR + nlen + elen;
+            if (!zc.isUTF8() && (flag & EFS) != 0) {
+                e.comment = zc.toStringUTF8(cen, start, clen);
             } else {
-                e.comment = zc.toString(cen, pos + CENHDR + nlen + elen, clen);
+                e.comment = zc.toString(cen, start, clen);
             }
         }
         return e;
@@ -817,7 +818,7 @@
         );
     }
 
-    /*
+    /**
      * Returns an array of strings representing the names of all entries
      * that begin with "META-INF/" (case ignored). This method is used
      * in JarFile, via SharedSecrets, as an optimization when looking up
@@ -827,14 +828,14 @@
     private String[] getMetaInfEntryNames() {
         synchronized (this) {
             ensureOpen();
-            if (zsrc.metanames.size() == 0) {
+            if (zsrc.metanames == null) {
                 return null;
             }
-            String[] names = new String[zsrc.metanames.size()];
+            String[] names = new String[zsrc.metanames.length];
             byte[] cen = zsrc.cen;
             for (int i = 0; i < names.length; i++) {
-                int pos = zsrc.metanames.get(i);
-                names[i] = new String(cen, pos + CENHDR,  CENNAM(cen, pos),
+                int pos = zsrc.metanames[i];
+                names[i] = new String(cen, pos + CENHDR, CENNAM(cen, pos),
                                       StandardCharsets.UTF_8);
             }
             return names;
@@ -850,7 +851,7 @@
         private long locpos;                 // position of first LOC header (usually 0)
         private byte[] comment;              // zip file comment
                                              // list of meta entries in META-INF dir
-        private ArrayList<Integer> metanames = new ArrayList<>();
+        private int[] metanames;
         private final boolean startsWithLoc; // true, if zip file starts with LOCSIG (usually true)
 
         // A Hashmap for all entries.
@@ -1159,7 +1160,7 @@
             int next = -1;
 
             // list for all meta entries
-            metanames = new ArrayList<>();
+            ArrayList<Integer> metanamesList = null;
 
             // Iterate through the entries in the central directory
             int i = 0;
@@ -1194,13 +1195,21 @@
                 idx = addEntry(idx, hash, next, pos);
                 // Adds name to metanames.
                 if (isMetaName(cen, pos + CENHDR, nlen)) {
-                    metanames.add(pos);
+                    if (metanamesList == null)
+                        metanamesList = new ArrayList<>(4);
+                    metanamesList.add(pos);
                 }
                 // skip ext and comment
                 pos += (CENHDR + nlen + elen + clen);
                 i++;
             }
             total = i;
+            if (metanamesList != null) {
+                metanames = new int[metanamesList.size()];
+                for (int j = 0, len = metanames.length; j < len; j++) {
+                    metanames[j] = metanamesList.get(j);
+                }
+            }
             if (pos + ENDHDR != cen.length) {
                 zerror("invalid CEN header (bad header size)");
             }
@@ -1265,30 +1274,23 @@
             }
         }
 
-        private static byte[] metainf = new byte[] {
-            'M', 'E', 'T', 'A', '-', 'I' , 'N', 'F', '/',
-        };
-
-        /*
-         * Returns true if the specified entry's name begins with the string
-         * "META-INF/" irrespective of case.
+        /**
+         * Returns true if the bytes represent a non-directory name
+         * beginning with "META-INF/", disregarding ASCII case.
          */
-        private static boolean isMetaName(byte[] name,  int off, int len) {
-            if (len < 9 || (name[off] != 'M' && name[off] != 'm')) {  //  sizeof("META-INF/") - 1
-                return false;
-            }
-            off++;
-            for (int i = 1; i < metainf.length; i++) {
-                byte c = name[off++];
-                // Avoid toupper; it's locale-dependent
-                if (c >= 'a' && c <= 'z') {
-                    c += 'A' - 'a';
-                }
-                if (metainf[i] != c) {
-                    return false;
-                }
-            }
-            return true;
+        private static boolean isMetaName(byte[] name, int off, int len) {
+            // Use the "oldest ASCII trick in the book"
+            return len > 9                     // "META-INF/".length()
+                && name[off + len - 1] != '/'  // non-directory
+                && (name[off++] | 0x20) == 'm'
+                && (name[off++] | 0x20) == 'e'
+                && (name[off++] | 0x20) == 't'
+                && (name[off++] | 0x20) == 'a'
+                && (name[off++]       ) == '-'
+                && (name[off++] | 0x20) == 'i'
+                && (name[off++] | 0x20) == 'n'
+                && (name[off++] | 0x20) == 'f'
+                && (name[off]         ) == '/';
         }
 
         /*
--- a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java	Wed May 18 12:04:26 2016 -0700
@@ -68,13 +68,14 @@
         if (s != null && s.length() > 0)
             bcp = toURLClassPath(s);
 
-        // we have a class path if -cp is specified or -m is not specified
+        // we have a class path if -cp is specified or -m is not specified.
+        // If neither is specified then default to -cp <working directory>.
         URLClassPath ucp = null;
         String mainMid = System.getProperty("jdk.module.main");
         String cp = System.getProperty("java.class.path");
-        if (mainMid == null && (cp == null || cp.length() == 0))
-            cp = ".";
-        if (cp != null && cp.length() > 0)
+        if (mainMid == null && cp == null)
+            cp = "";
+        if (cp != null)
             ucp = toURLClassPath(cp);
 
 
@@ -197,7 +198,7 @@
          * @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch
          */
         void appendToClassPathForInstrumentation(String path) {
-            appendToUCP(path, ucp);
+            addClassPathToUCP(path, ucp);
         }
 
         /**
@@ -224,7 +225,7 @@
      */
     private static URLClassPath toURLClassPath(String cp) {
         URLClassPath ucp = new URLClassPath(new URL[0]);
-        appendToUCP(cp, ucp);
+        addClassPathToUCP(cp, ucp);
         return ucp;
     }
 
@@ -232,20 +233,28 @@
      * Converts the elements in the given class path to file URLs and adds
      * them to the given URLClassPath.
      */
-    private static void appendToUCP(String cp, URLClassPath ucp) {
-        String[] elements = cp.split(File.pathSeparator);
-        if (elements.length == 0) {
-            // contains path separator(s) only, default to current directory
-            // to be compatible with long standing behavior
-            elements = new String[] { "" };
+    private static void addClassPathToUCP(String cp, URLClassPath ucp) {
+        int off = 0;
+        int next;
+        while ((next = cp.indexOf(File.pathSeparator, off)) != -1) {
+            addURLToUCP(cp.substring(off, next), ucp);
+            off = next + 1;
         }
-        for (String s: elements) {
-            try {
-                URL url = Paths.get(s).toRealPath().toUri().toURL();
-                ucp.addURL(url);
-            } catch (InvalidPathException | IOException ignore) {
-                // malformed path string or class path element does not exist
-            }
+
+        // remaining
+        addURLToUCP(cp.substring(off), ucp);
+    }
+
+    /**
+     * Attempts to convert to the given string to a file URL and adds it
+     * to the given URLClassPath.
+     */
+    private static void addURLToUCP(String s, URLClassPath ucp) {
+        try {
+            URL url = Paths.get(s).toRealPath().toUri().toURL();
+            ucp.addURL(url);
+        } catch (InvalidPathException | IOException ignore) {
+            // malformed path string or class path element does not exist
         }
     }
 
--- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Wed May 18 12:04:26 2016 -0700
@@ -33,6 +33,7 @@
 import jdk.internal.misc.VM;
 
 import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.vm.annotation.ForceInline;
 
 
 /**
@@ -209,46 +210,103 @@
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native boolean getBoolean(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putBoolean(Object o, long offset, boolean x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native byte    getByte(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putByte(Object o, long offset, byte x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native short   getShort(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putShort(Object o, long offset, short x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native char    getChar(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putChar(Object o, long offset, char x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native long    getLong(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putLong(Object o, long offset, long x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native float   getFloat(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putFloat(Object o, long offset, float x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native double  getDouble(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putDouble(Object o, long offset, double x);
 
+    /**
+     * Fetches a native pointer from a given memory address.  If the address is
+     * zero, or does not point into a block obtained from {@link
+     * #allocateMemory}, the results are undefined.
+     *
+     * <p>If the native pointer is less than 64 bits wide, it is extended as
+     * an unsigned number to a Java long.  The pointer may be indexed by any
+     * given byte offset, simply by adding that offset (as a simple integer) to
+     * the long representing the pointer.  The number of bytes actually read
+     * from the target address may be determined by consulting {@link
+     * #addressSize}.
+     *
+     * @see #allocateMemory
+     * @see #getInt(Object, long)
+     */
+    @ForceInline
+    public long getAddress(Object o, long offset) {
+        if (ADDRESS_SIZE == 4) {
+            return Integer.toUnsignedLong(getInt(o, offset));
+        } else {
+            return getLong(o, offset);
+        }
+    }
+
+    /**
+     * Stores a native pointer into a given memory address.  If the address is
+     * zero, or does not point into a block obtained from {@link
+     * #allocateMemory}, the results are undefined.
+     *
+     * <p>The number of bytes actually written at the target address may be
+     * determined by consulting {@link #addressSize}.
+     *
+     * @see #allocateMemory
+     * @see #putInt(Object, long, int)
+     */
+    @ForceInline
+    public void putAddress(Object o, long offset, long x) {
+        if (ADDRESS_SIZE == 4) {
+            putInt(o, offset, (int)x);
+        } else {
+            putLong(o, offset, x);
+        }
+    }
+
     // These read VM internal data.
 
     /**
@@ -287,8 +345,10 @@
      *
      * @see #allocateMemory
      */
-    @HotSpotIntrinsicCandidate
-    public native byte    getByte(long address);
+    @ForceInline
+    public byte getByte(long address) {
+        return getByte(null, address);
+    }
 
     /**
      * Stores a value into a given memory address.  If the address is zero, or
@@ -297,75 +357,94 @@
      *
      * @see #getByte(long)
      */
-    @HotSpotIntrinsicCandidate
-    public native void    putByte(long address, byte x);
+    @ForceInline
+    public void putByte(long address, byte x) {
+        putByte(null, address, x);
+    }
 
     /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native short   getShort(long address);
+    @ForceInline
+    public short getShort(long address) {
+        return getShort(null, address);
+    }
+
     /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putShort(long address, short x);
+    @ForceInline
+    public void putShort(long address, short x) {
+        putShort(null, address, x);
+    }
+
     /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native char    getChar(long address);
+    @ForceInline
+    public char getChar(long address) {
+        return getChar(null, address);
+    }
+
     /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putChar(long address, char x);
+    @ForceInline
+    public void putChar(long address, char x) {
+        putChar(null, address, x);
+    }
+
     /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native int     getInt(long address);
+    @ForceInline
+    public int getInt(long address) {
+        return getInt(null, address);
+    }
+
     /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putInt(long address, int x);
+    @ForceInline
+    public void putInt(long address, int x) {
+        putInt(null, address, x);
+    }
+
     /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native long    getLong(long address);
+    @ForceInline
+    public long getLong(long address) {
+        return getLong(null, address);
+    }
+
     /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putLong(long address, long x);
+    @ForceInline
+    public void putLong(long address, long x) {
+        putLong(null, address, x);
+    }
+
     /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native float   getFloat(long address);
+    @ForceInline
+    public float getFloat(long address) {
+        return getFloat(null, address);
+    }
+
     /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putFloat(long address, float x);
+    @ForceInline
+    public void putFloat(long address, float x) {
+        putFloat(null, address, x);
+    }
+
     /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native double  getDouble(long address);
+    @ForceInline
+    public double getDouble(long address) {
+        return getDouble(null, address);
+    }
+
     /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putDouble(long address, double x);
+    @ForceInline
+    public void putDouble(long address, double x) {
+        putDouble(null, address, x);
+    }
 
-    /**
-     * Fetches a native pointer from a given memory address.  If the address is
-     * zero, or does not point into a block obtained from {@link
-     * #allocateMemory}, the results are undefined.
-     *
-     * <p>If the native pointer is less than 64 bits wide, it is extended as
-     * an unsigned number to a Java long.  The pointer may be indexed by any
-     * given byte offset, simply by adding that offset (as a simple integer) to
-     * the long representing the pointer.  The number of bytes actually read
-     * from the target address may be determined by consulting {@link
-     * #addressSize}.
-     *
-     * @see #allocateMemory
-     */
-    @HotSpotIntrinsicCandidate
-    public native long getAddress(long address);
+    /** @see #getAddress(Object, long) */
+    @ForceInline
+    public long getAddress(long address) {
+        return getAddress(null, address);
+    }
 
-    /**
-     * Stores a native pointer into a given memory address.  If the address is
-     * zero, or does not point into a block obtained from {@link
-     * #allocateMemory}, the results are undefined.
-     *
-     * <p>The number of bytes actually written at the target address may be
-     * determined by consulting {@link #addressSize}.
-     *
-     * @see #getAddress(long)
-     */
-    @HotSpotIntrinsicCandidate
-    public native void putAddress(long address, long x);
+    /** @see #putAddress(Object, long, long) */
+    @ForceInline
+    public void putAddress(long address, long x) {
+        putAddress(null, address, x);
+    }
 
 
 
@@ -1271,6 +1350,13 @@
         return compareAndSwapObject(o, offset, expected, x);
     }
 
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapObjectVolatile(Object o, long offset,
+                                                                Object expected,
+                                                                Object x) {
+        return compareAndSwapObject(o, offset, expected, x);
+    }
+
     /**
      * Atomically updates Java variable to {@code x} if it is currently
      * holding {@code expected}.
@@ -1325,6 +1411,13 @@
         return compareAndSwapInt(o, offset, expected, x);
     }
 
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapIntVolatile(Object o, long offset,
+                                                             int expected,
+                                                             int x) {
+        return compareAndSwapInt(o, offset, expected, x);
+    }
+
     /**
      * Atomically updates Java variable to {@code x} if it is currently
      * holding {@code expected}.
@@ -1379,6 +1472,13 @@
         return compareAndSwapLong(o, offset, expected, x);
     }
 
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapLongVolatile(Object o, long offset,
+                                                              long expected,
+                                                              long x) {
+        return compareAndSwapLong(o, offset, expected, x);
+    }
+
     /**
      * Fetches a reference value from a given Java variable, with volatile
      * load semantics. Otherwise identical to {@link #getObject(Object, long)}
--- a/src/java.base/share/classes/jdk/internal/misc/VM.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/jdk/internal/misc/VM.java	Wed May 18 12:04:26 2016 -0700
@@ -390,10 +390,25 @@
     private static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
 
     /*
-     * Returns the first non-null class loader up the execution stack,
-     * or null if only code from the null class loader is on the stack.
+     * Returns the first user-defined class loader up the execution stack,
+     * or the platform class loader if only code from the platform or
+     * bootstrap class loader is on the stack.
      */
-    public static native ClassLoader latestUserDefinedLoader();
+    public static ClassLoader latestUserDefinedLoader() {
+        ClassLoader loader = latestUserDefinedLoader0();
+        return loader != null ? loader : ClassLoader.getPlatformClassLoader();
+    }
+
+    /*
+     * Returns the first user-defined class loader up the execution stack,
+     * or null if only code from the platform or bootstrap class loader is
+     * on the stack.  VM does not keep a reference of platform loader and so
+     * it returns null.
+     *
+     * This method should be replaced with StackWalker::walk and then we can
+     * remove the logic in the VM.
+     */
+    private static native ClassLoader latestUserDefinedLoader0();
 
     /**
      * Returns {@code true} if we are in a set UID program.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/util/Preconditions.java	Wed May 18 12:04:26 2016 -0700
@@ -0,0 +1,346 @@
+/*
+ * 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.util;
+
+import jdk.internal.HotSpotIntrinsicCandidate;
+
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Utility methods to check if state or arguments are correct.
+ *
+ */
+public class Preconditions {
+
+    /**
+     * Maps out-of-bounds values to a runtime exception.
+     *
+     * @param checkKind the kind of bounds check, whose name may correspond
+     *        to the name of one of the range check methods, checkIndex,
+     *        checkFromToIndex, checkFromIndexSize
+     * @param args the out-of-bounds arguments that failed the range check.
+     *        If the checkKind corresponds a the name of a range check method
+     *        then the bounds arguments are those that can be passed in order
+     *        to the method.
+     * @param oobef the exception formatter that when applied with a checkKind
+     *        and a list out-of-bounds arguments returns a runtime exception.
+     *        If {@code null} then, it is as if an exception formatter was
+     *        supplied that returns {@link IndexOutOfBoundsException} for any
+     *        given arguments.
+     * @return the runtime exception
+     */
+    private static RuntimeException outOfBounds(
+            BiFunction<String, List<Integer>, ? extends RuntimeException> oobef,
+            String checkKind,
+            Integer... args) {
+        List<Integer> largs = List.of(args);
+        RuntimeException e = oobef == null
+                             ? null : oobef.apply(checkKind, largs);
+        return e == null
+               ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e;
+    }
+
+    private static RuntimeException outOfBoundsCheckIndex(
+            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
+            int index, int length) {
+        return outOfBounds(oobe, "checkIndex", index, length);
+    }
+
+    private static RuntimeException outOfBoundsCheckFromToIndex(
+            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
+            int fromIndex, int toIndex, int length) {
+        return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length);
+    }
+
+    private static RuntimeException outOfBoundsCheckFromIndexSize(
+            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
+            int fromIndex, int size, int length) {
+        return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length);
+    }
+
+    /**
+     * Returns an out-of-bounds exception formatter from an given exception
+     * factory.  The exception formatter is a function that formats an
+     * out-of-bounds message from its arguments and applies that message to the
+     * given exception factory to produce and relay an exception.
+     *
+     * <p>The exception formatter accepts two arguments: a {@code String}
+     * describing the out-of-bounds range check that failed, referred to as the
+     * <em>check kind</em>; and a {@code List<Integer>} containing the
+     * out-of-bound integer values that failed the check.  The list of
+     * out-of-bound values is not modified.
+     *
+     * <p>Three check kinds are supported {@code checkIndex},
+     * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding
+     * respectively to the specified application of an exception formatter as an
+     * argument to the out-of-bounds range check methods
+     * {@link #checkIndex(int, int, BiFunction) checkIndex},
+     * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and
+     * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}.
+     * Thus a supported check kind corresponds to a method name and the
+     * out-of-bound integer values correspond to method argument values, in
+     * order, preceding the exception formatter argument (similar in many
+     * respects to the form of arguments required for a reflective invocation of
+     * such a range check method).
+     *
+     * <p>Formatter arguments conforming to such supported check kinds will
+     * produce specific exception messages describing failed out-of-bounds
+     * checks.  Otherwise, more generic exception messages will be produced in
+     * any of the following cases: the check kind is supported but fewer
+     * or more out-of-bounds values are supplied, the check kind is not
+     * supported, the check kind is {@code null}, or the list of out-of-bound
+     * values is {@code null}.
+     *
+     * @apiNote
+     * This method produces an out-of-bounds exception formatter that can be
+     * passed as an argument to any of the supported out-of-bounds range check
+     * methods declared by {@code Objects}.  For example, a formatter producing
+     * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a
+     * {@code static final} field as follows:
+     * <pre>{@code
+     * static final
+     * BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException> AIOOBEF =
+     *     outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new);
+     * }</pre>
+     * The formatter instance {@code AIOOBEF} may be passed as an argument to an
+     * out-of-bounds range check method, such as checking if an {@code index}
+     * is within the bounds of a {@code limit}:
+     * <pre>{@code
+     * checkIndex(index, limit, AIOOBEF);
+     * }</pre>
+     * If the bounds check fails then the range check method will throw an
+     * {@code ArrayIndexOutOfBoundsException} with an appropriate exception
+     * message that is a produced from {@code AIOOBEF} as follows:
+     * <pre>{@code
+     * AIOOBEF.apply("checkIndex", List.of(index, limit));
+     * }</pre>
+     *
+     * @param f the exception factory, that produces an exception from a message
+     *        where the message is produced and formatted by the returned
+     *        exception formatter.  If this factory is stateless and side-effect
+     *        free then so is the returned formatter.
+     *        Exceptions thrown by the factory are relayed to the caller
+     *        of the returned formatter.
+     * @param <X> the type of runtime exception to be returned by the given
+     *        exception factory and relayed by the exception formatter
+     * @return the out-of-bounds exception formatter
+     */
+    public static <X extends RuntimeException>
+    BiFunction<String, List<Integer>, X> outOfBoundsExceptionFormatter(Function<String, X> f) {
+        // Use anonymous class to avoid bootstrap issues if this method is
+        // used early in startup
+        return new BiFunction<String, List<Integer>, X>() {
+            @Override
+            public X apply(String checkKind, List<Integer> args) {
+                return f.apply(outOfBoundsMessage(checkKind, args));
+            }
+        };
+    }
+
+    private static String outOfBoundsMessage(String checkKind, List<Integer> args) {
+        if (checkKind == null && args == null) {
+            return String.format("Range check failed");
+        } else if (checkKind == null) {
+            return String.format("Range check failed: %s", args);
+        } else if (args == null) {
+            return String.format("Range check failed: %s", checkKind);
+        }
+
+        int argSize = 0;
+        switch (checkKind) {
+            case "checkIndex":
+                argSize = 2;
+                break;
+            case "checkFromToIndex":
+            case "checkFromIndexSize":
+                argSize = 3;
+                break;
+            default:
+        }
+
+        // Switch to default if fewer or more arguments than required are supplied
+        switch ((args.size() != argSize) ? "" : checkKind) {
+            case "checkIndex":
+                return String.format("Index %d out-of-bounds for length %d",
+                                     args.get(0), args.get(1));
+            case "checkFromToIndex":
+                return String.format("Range [%d, %d) out-of-bounds for length %d",
+                                     args.get(0), args.get(1), args.get(2));
+            case "checkFromIndexSize":
+                return String.format("Range [%d, %<d + %d) out-of-bounds for length %d",
+                                     args.get(0), args.get(1), args.get(2));
+            default:
+                return String.format("Range check failed: %s %s", checkKind, args);
+        }
+    }
+
+    /**
+     * Checks if the {@code index} is within the bounds of the range from
+     * {@code 0} (inclusive) to {@code length} (exclusive).
+     *
+     * <p>The {@code index} is defined to be out-of-bounds if any of the
+     * following inequalities is true:
+     * <ul>
+     *  <li>{@code index < 0}</li>
+     *  <li>{@code index >= length}</li>
+     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
+     * </ul>
+     *
+     * <p>If the {@code index} is out-of-bounds, then a runtime exception is
+     * thrown that is the result of applying the following arguments to the
+     * exception formatter: the name of this method, {@code checkIndex};
+     * and an unmodifiable list integers whose values are, in order, the
+     * out-of-bounds arguments {@code index} and {@code length}.
+     *
+     * @param <X> the type of runtime exception to throw if the arguments are
+     *        out-of-bounds
+     * @param index the index
+     * @param length the upper-bound (exclusive) of the range
+     * @param oobef the exception formatter that when applied with this
+     *        method name and out-of-bounds arguments returns a runtime
+     *        exception.  If {@code null} or returns {@code null} then, it is as
+     *        if an exception formatter produced from an invocation of
+     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
+     *        instead (though it may be more efficient).
+     *        Exceptions thrown by the formatter are relayed to the caller.
+     * @return {@code index} if it is within bounds of the range
+     * @throws X if the {@code index} is out-of-bounds and the exception
+     *         formatter is non-{@code null}
+     * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds
+     *         and the exception formatter is {@code null}
+     * @since 9
+     *
+     * @implNote
+     * This method is made intrinsic in optimizing compilers to guide them to
+     * perform unsigned comparisons of the index and length when it is known the
+     * length is a non-negative value (such as that of an array length or from
+     * the upper bound of a loop)
+    */
+    @HotSpotIntrinsicCandidate
+    public static <X extends RuntimeException>
+    int checkIndex(int index, int length,
+                   BiFunction<String, List<Integer>, X> oobef) {
+        if (index < 0 || index >= length)
+            throw outOfBoundsCheckIndex(oobef, index, length);
+        return index;
+    }
+
+    /**
+     * Checks if the sub-range from {@code fromIndex} (inclusive) to
+     * {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
+     * (inclusive) to {@code length} (exclusive).
+     *
+     * <p>The sub-range is defined to be out-of-bounds if any of the following
+     * inequalities is true:
+     * <ul>
+     *  <li>{@code fromIndex < 0}</li>
+     *  <li>{@code fromIndex > toIndex}</li>
+     *  <li>{@code toIndex > length}</li>
+     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
+     * </ul>
+     *
+     * <p>If the sub-range  is out-of-bounds, then a runtime exception is
+     * thrown that is the result of applying the following arguments to the
+     * exception formatter: the name of this method, {@code checkFromToIndex};
+     * and an unmodifiable list integers whose values are, in order, the
+     * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}.
+     *
+     * @param <X> the type of runtime exception to throw if the arguments are
+     *        out-of-bounds
+     * @param fromIndex the lower-bound (inclusive) of the sub-range
+     * @param toIndex the upper-bound (exclusive) of the sub-range
+     * @param length the upper-bound (exclusive) the range
+     * @param oobef the exception formatter that when applied with this
+     *        method name and out-of-bounds arguments returns a runtime
+     *        exception.  If {@code null} or returns {@code null} then, it is as
+     *        if an exception formatter produced from an invocation of
+     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
+     *        instead (though it may be more efficient).
+     *        Exceptions thrown by the formatter are relayed to the caller.
+     * @return {@code fromIndex} if the sub-range within bounds of the range
+     * @throws X if the sub-range is out-of-bounds and the exception factory
+     *         function is non-{@code null}
+     * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and
+     *         the exception factory function is {@code null}
+     * @since 9
+     */
+    public static <X extends RuntimeException>
+    int checkFromToIndex(int fromIndex, int toIndex, int length,
+                         BiFunction<String, List<Integer>, X> oobef) {
+        if (fromIndex < 0 || fromIndex > toIndex || toIndex > length)
+            throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length);
+        return fromIndex;
+    }
+
+    /**
+     * Checks if the sub-range from {@code fromIndex} (inclusive) to
+     * {@code fromIndex + size} (exclusive) is within the bounds of range from
+     * {@code 0} (inclusive) to {@code length} (exclusive).
+     *
+     * <p>The sub-range is defined to be out-of-bounds if any of the following
+     * inequalities is true:
+     * <ul>
+     *  <li>{@code fromIndex < 0}</li>
+     *  <li>{@code size < 0}</li>
+     *  <li>{@code fromIndex + size > length}, taking into account integer overflow</li>
+     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
+     * </ul>
+     *
+     * <p>If the sub-range  is out-of-bounds, then a runtime exception is
+     * thrown that is the result of applying the following arguments to the
+     * exception formatter: the name of this method, {@code checkFromIndexSize};
+     * and an unmodifiable list integers whose values are, in order, the
+     * out-of-bounds arguments {@code fromIndex}, {@code size}, and
+     * {@code length}.
+     *
+     * @param <X> the type of runtime exception to throw if the arguments are
+     *        out-of-bounds
+     * @param fromIndex the lower-bound (inclusive) of the sub-interval
+     * @param size the size of the sub-range
+     * @param length the upper-bound (exclusive) of the range
+     * @param oobef the exception formatter that when applied with this
+     *        method name and out-of-bounds arguments returns a runtime
+     *        exception.  If {@code null} or returns {@code null} then, it is as
+     *        if an exception formatter produced from an invocation of
+     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
+     *        instead (though it may be more efficient).
+     *        Exceptions thrown by the formatter are relayed to the caller.
+     * @return {@code fromIndex} if the sub-range within bounds of the range
+     * @throws X if the sub-range is out-of-bounds and the exception factory
+     *         function is non-{@code null}
+     * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and
+     *         the exception factory function is {@code null}
+     * @since 9
+     */
+    public static <X extends RuntimeException>
+    int checkFromIndexSize(int fromIndex, int size, int length,
+                           BiFunction<String, List<Integer>, X> oobef) {
+        if ((length | fromIndex | size) < 0 || size > length - fromIndex)
+            throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length);
+        return fromIndex;
+    }
+}
--- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties	Wed May 18 12:04:26 2016 -0700
@@ -100,7 +100,6 @@
 \    -Xdiag            show additional diagnostic messages\n\
 \    -Xdiag:resolver   show resolver diagnostic messages\n\
 \    -Xnoclassgc       disable class garbage collection\n\
-\    -Xincgc           enable incremental garbage collection\n\
 \    -Xloggc:<file>    log GC status to a file with time stamps\n\
 \    -Xbatch           disable background compilation\n\
 \    -Xms<size>        set initial Java heap size\n\
--- a/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -441,17 +441,89 @@
             (outOfs < 0) || ((out.length - outOfs) < len)) {
             throw new ArrayIndexOutOfBoundsException();
         }
-        len += outOfs;
-        while (outOfs < len) {
-            long i = in[inOfs++];
-            out[outOfs++] = (byte)(i >> 56);
-            out[outOfs++] = (byte)(i >> 48);
-            out[outOfs++] = (byte)(i >> 40);
-            out[outOfs++] = (byte)(i >> 32);
-            out[outOfs++] = (byte)(i >> 24);
-            out[outOfs++] = (byte)(i >> 16);
-            out[outOfs++] = (byte)(i >>  8);
-            out[outOfs++] = (byte)(i      );
+        if (littleEndianUnaligned) {
+            outOfs += byteArrayOfs;
+            len += outOfs;
+            while (outOfs < len) {
+                unsafe.putLong(out, (long)outOfs, reverseBytes(in[inOfs++]));
+                outOfs += 8;
+            }
+        } else {
+            len += outOfs;
+            while (outOfs < len) {
+                long i = in[inOfs++];
+                out[outOfs++] = (byte)(i >> 56);
+                out[outOfs++] = (byte)(i >> 48);
+                out[outOfs++] = (byte)(i >> 40);
+                out[outOfs++] = (byte)(i >> 32);
+                out[outOfs++] = (byte)(i >> 24);
+                out[outOfs++] = (byte)(i >> 16);
+                out[outOfs++] = (byte)(i >>  8);
+                out[outOfs++] = (byte)(i      );
+            }
+        }
+    }
+
+    /**
+     * byte[] to long[] conversion, little endian byte order
+     */
+    static void b2lLittle(byte[] in, int inOfs, long[] out, int outOfs, int len) {
+        if ((inOfs < 0) || ((in.length - inOfs) < len) ||
+            ((outOfs < 0) || (out.length - outOfs) < len/8)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (littleEndianUnaligned) {
+            inOfs += byteArrayOfs;
+            len += inOfs;
+            while (inOfs < len) {
+                out[outOfs++] = unsafe.getLong(in, (long)inOfs);
+                inOfs += 8;
+            }
+       } else {
+            len += inOfs;
+            while (inOfs < len) {
+                out[outOfs++] = ((in[inOfs    ] & 0xffL)
+                   | ((in[inOfs + 1] & 0xffL) <<  8)
+                   | ((in[inOfs + 2] & 0xffL) << 16)
+                   | ((in[inOfs + 3] & 0xffL) << 24)
+                   | ((in[inOfs + 4] & 0xffL) << 32)
+                   | ((in[inOfs + 5] & 0xffL) << 40)
+                   | ((in[inOfs + 6] & 0xffL) << 48)
+                   | ((in[inOfs + 7] & 0xffL) << 56));
+                inOfs += 8;
+            }
+        }
+    }
+
+
+    /**
+     * long[] to byte[] conversion, little endian byte order
+     */
+    static void l2bLittle(long[] in, int inOfs, byte[] out, int outOfs, int len) {
+        if ((inOfs < 0) || ((in.length - inOfs) < len/8) ||
+            (outOfs < 0) || ((out.length - outOfs) < len)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (littleEndianUnaligned) {
+            outOfs += byteArrayOfs;
+            len += outOfs;
+            while (outOfs < len) {
+                unsafe.putLong(out, (long)outOfs, in[inOfs++]);
+                outOfs += 8;
+            }
+        } else {
+            len += outOfs;
+            while (outOfs < len) {
+                long i = in[inOfs++];
+                out[outOfs++] = (byte)(i      );
+                out[outOfs++] = (byte)(i >>  8);
+                out[outOfs++] = (byte)(i >> 16);
+                out[outOfs++] = (byte)(i >> 24);
+                out[outOfs++] = (byte)(i >> 32);
+                out[outOfs++] = (byte)(i >> 40);
+                out[outOfs++] = (byte)(i >> 48);
+                out[outOfs++] = (byte)(i >> 56);
+            }
         }
     }
 }
--- a/src/java.base/share/classes/sun/security/provider/PolicyFile.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/sun/security/provider/PolicyFile.java	Wed May 18 12:04:26 2016 -0700
@@ -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
@@ -259,14 +259,10 @@
 
     private static final Debug debug = Debug.getInstance("policy");
 
-    private static final String NONE = "NONE";
-    private static final String P11KEYSTORE = "PKCS11";
-
     private static final String SELF = "${{self}}";
     private static final String X500PRINCIPAL =
                         "javax.security.auth.x500.X500Principal";
     private static final String POLICY = "java.security.policy";
-    private static final String SECURITY_MANAGER = "java.security.manager";
     private static final String POLICY_URL = "policy.url.";
     private static final String AUTH_POLICY = "java.security.auth.policy";
     private static final String AUTH_POLICY_URL = "auth.policy.url.";
@@ -288,6 +284,17 @@
     private static final Class<?>[] PARAMS2 = { String.class, String.class };
 
     /**
+     * When a policy file has a syntax error, the exception code may generate
+     * another permission check and this can cause the policy file to be parsed
+     * repeatedly, leading to a StackOverflowError or ClassCircularityError.
+     * To avoid this, this set is populated with policy files that have been
+     * previously parsed and have syntax errors, so that they can be
+     * subsequently ignored.
+     */
+    private static AtomicReference<Set<URL>> badPolicyURLs =
+        new AtomicReference<>(new HashSet<>());
+
+    /**
      * Initializes the Policy object and reads the default policy
      * configuration file(s) into the Policy object.
      */
@@ -580,6 +587,16 @@
      * @param policyFile the policy Reader object.
      */
     private boolean init(URL policy, PolicyInfo newInfo) {
+
+        // skip parsing policy file if it has been previously parsed and
+        // has syntax errors
+        if (badPolicyURLs.get().contains(policy)) {
+            if (debug != null) {
+                debug.println("skipping bad policy file: " + policy);
+            }
+            return false;
+        }
+
         boolean success = false;
         PolicyParser pp = new PolicyParser(expandProperties);
         InputStreamReader isr = null;
@@ -622,13 +639,18 @@
                 addGrantEntry(ge, keyStore, newInfo);
             }
         } catch (PolicyParser.ParsingException pe) {
+            // record bad policy file to avoid later reparsing it
+            badPolicyURLs.updateAndGet(k -> {
+                k.add(policy);
+                return k;
+            });
             MessageFormat form = new MessageFormat(ResourcesMgr.getString
                 (POLICY + ".error.parsing.policy.message"));
             Object[] source = {policy, pe.getLocalizedMessage()};
             System.err.println(form.format(source));
-            if (debug != null)
+            if (debug != null) {
                 pe.printStackTrace();
-
+            }
         } catch (Exception e) {
             if (debug != null) {
                 debug.println("error parsing "+policy);
--- a/src/java.base/share/classes/sun/security/provider/PolicyParser.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/sun/security/provider/PolicyParser.java	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, 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
@@ -213,7 +213,9 @@
                             new MessageFormat(ResourcesMgr.getString(
                                 "duplicate.keystore.domain.name"));
                         Object[] source = {domainName};
-                        throw new ParsingException(form.format(source));
+                        String msg = "duplicate keystore domain name: " +
+                                     domainName;
+                        throw new ParsingException(msg, form, source);
                     }
                 }
             } else {
@@ -743,7 +745,8 @@
                     ResourcesMgr.getString
                             ("expected.expect.read.end.of.file."));
             Object[] source = {expect};
-            throw new ParsingException(form.format(source));
+            String msg = "expected [" + expect + "], read [end of file]";
+            throw new ParsingException(msg, form, source);
         case StreamTokenizer.TT_WORD:
             if (expect.equalsIgnoreCase(st.sval)) {
                 lookahead = st.nextToken();
@@ -1244,7 +1247,8 @@
                 MessageFormat form = new MessageFormat(ResourcesMgr.getString(
                     "duplicate.keystore.name"));
                 Object[] source = {keystoreName};
-                throw new ParsingException(form.format(source));
+                String msg = "duplicate keystore name: " + keystoreName;
+                throw new ParsingException(msg, form, source);
             }
         }
 
@@ -1316,6 +1320,8 @@
         private static final long serialVersionUID = -4330692689482574072L;
 
         private String i18nMessage;
+        private MessageFormat form;
+        private Object[] source;
 
         /**
          * Constructs a ParsingException with the specified
@@ -1330,26 +1336,34 @@
             i18nMessage = msg;
         }
 
+        public ParsingException(String msg, MessageFormat form,
+                                Object[] source) {
+            super(msg);
+            this.form = form;
+            this.source = source;
+        }
+
         public ParsingException(int line, String msg) {
             super("line " + line + ": " + msg);
-            MessageFormat form = new MessageFormat
-                (ResourcesMgr.getString("line.number.msg"));
-            Object[] source = {line, msg};
-            i18nMessage = form.format(source);
+            // don't call form.format unless getLocalizedMessage is called
+            // to avoid unnecessary permission checks
+            form = new MessageFormat(ResourcesMgr.getString("line.number.msg"));
+            source = new Object[] {line, msg};
         }
 
         public ParsingException(int line, String expect, String actual) {
             super("line " + line + ": expected [" + expect +
                 "], found [" + actual + "]");
-            MessageFormat form = new MessageFormat(ResourcesMgr.getString
+            // don't call form.format unless getLocalizedMessage is called
+            // to avoid unnecessary permission checks
+            form = new MessageFormat(ResourcesMgr.getString
                 ("line.number.expected.expect.found.actual."));
-            Object[] source = {line, expect, actual};
-            i18nMessage = form.format(source);
+            source = new Object[] {line, expect, actual};
         }
 
         @Override
         public String getLocalizedMessage() {
-            return i18nMessage;
+            return i18nMessage != null ? i18nMessage : form.format(source);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/provider/SHA3.java	Wed May 18 12:04:26 2016 -0700
@@ -0,0 +1,300 @@
+/*
+ * 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 sun.security.provider;
+
+import static sun.security.provider.ByteArrayAccess.*;
+import java.nio.*;
+import java.util.*;
+import java.security.*;
+
+/**
+ * This class implements the Secure Hash Algorithm SHA-3 developed by
+ * the National Institute of Standards and Technology along with the
+ * National Security Agency as defined in FIPS PUB 202.
+ *
+ * <p>It implements java.security.MessageDigestSpi, and can be used
+ * through Java Cryptography Architecture (JCA), as a pluggable
+ * MessageDigest implementation.
+ *
+ * @since       9
+ * @author      Valerie Peng
+ */
+abstract class SHA3 extends DigestBase {
+
+    private static final int WIDTH = 200; // in bytes, e.g. 1600 bits
+    private static final int DM = 5; // dimension of lanes
+
+    private static final int NR = 24; // number of rounds
+
+    // precomputed round constants needed by the step mapping Iota
+    private static final long[] RC_CONSTANTS = {
+        0x01L, 0x8082L, 0x800000000000808aL,
+        0x8000000080008000L, 0x808bL, 0x80000001L,
+        0x8000000080008081L, 0x8000000000008009L, 0x8aL,
+        0x88L, 0x80008009L, 0x8000000aL,
+        0x8000808bL, 0x800000000000008bL, 0x8000000000008089L,
+        0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L,
+        0x800aL, 0x800000008000000aL, 0x8000000080008081L,
+        0x8000000000008080L, 0x80000001L, 0x8000000080008008L,
+    };
+
+    private byte[] state;
+
+    /**
+     * Creates a new SHA-3 object.
+     */
+    SHA3(String name, int digestLength) {
+        super(name, digestLength, (WIDTH - (2 * digestLength)));
+        implReset();
+    }
+
+    /**
+     * Core compression function. Processes blockSize bytes at a time
+     * and updates the state of this object.
+     */
+    void implCompress(byte[] b, int ofs) {
+        for (int i = 0; i < buffer.length; i++) {
+            state[i] ^= b[ofs++];
+        }
+        state = keccak(state);
+    }
+
+    /**
+     * Return the digest. Subclasses do not need to reset() themselves,
+     * DigestBase calls implReset() when necessary.
+     */
+    void implDigest(byte[] out, int ofs) {
+        int numOfPadding =
+            setPaddingBytes(buffer, (int)(bytesProcessed % buffer.length));
+        if (numOfPadding < 1) {
+            throw new ProviderException("Incorrect pad size: " + numOfPadding);
+        }
+        for (int i = 0; i < buffer.length; i++) {
+            state[i] ^= buffer[i];
+        }
+        state = keccak(state);
+        System.arraycopy(state, 0, out, ofs, engineGetDigestLength());
+    }
+
+    /**
+     * Resets the internal state to start a new hash.
+     */
+    void implReset() {
+        state = new byte[WIDTH];
+    }
+
+    /**
+     * Utility function for circular shift the specified long
+     * value to the left for n bits.
+     */
+    private static long circularShiftLeft(long lane, int n) {
+        return ((lane << n) | (lane >>> (64 - n)));
+    }
+
+    /**
+     * Utility function for padding the specified data based on the
+     * pad10*1 algorithm (section 5.1) and the 2-bit suffix "01" required
+     * for SHA-3 hash (section 6.1).
+     */
+    private static int setPaddingBytes(byte[] in, int len) {
+        if (len != in.length) {
+            // erase leftover values
+            Arrays.fill(in, len, in.length, (byte)0);
+            // directly store the padding bytes into the input
+            // as the specified buffer is allocated w/ size = rateR
+            in[len] |= (byte) 0x06;
+            in[in.length - 1] |= (byte) 0x80;
+        }
+        return (in.length - len);
+    }
+
+    /**
+     * Utility function for transforming the specified state from
+     * the byte array format into array of lanes as defined in
+     * section 3.1.2.
+     */
+    private static long[][] bytes2Lanes(byte[] s) {
+        if (s.length != WIDTH) {
+            throw new ProviderException("Error: incorrect input size " +
+                s.length);
+        }
+        // The conversion traverses along x-axis before y-axis. So, y is the
+        // first dimension and x is the second dimension.
+        long[][] s2 = new long[DM][DM];
+        int sOfs = 0;
+        for (int y = 0; y < DM; y++, sOfs += 40) {
+            b2lLittle(s, sOfs, s2[y], 0, 40);
+        }
+        return s2;
+    }
+
+    /**
+     * Utility function for transforming the specified arrays of
+     * lanes into a byte array as defined in section 3.1.3.
+     */
+    private static byte[] lanes2Bytes(long[][] m) {
+        byte[] s = new byte[WIDTH];
+        int sOfs = 0;
+        // The conversion traverses along x-axis before y-axis. So, y is the
+        // first dimension and x is the second dimension.
+        for (int y = 0; y < DM; y++, sOfs += 40) {
+            l2bLittle(m[y], 0, s, sOfs, 40);
+        }
+        return s;
+    }
+
+    /**
+     * Step mapping Theta as defined in section 3.2.1 .
+     */
+    private static long[][] smTheta(long[][] a) {
+        long[] c = new long[DM];
+        for (int i = 0; i < DM; i++) {
+            c[i] = a[0][i]^a[1][i]^a[2][i]^a[3][i]^a[4][i];
+        }
+        long[] d = new long[DM];
+        for (int i = 0; i < DM; i++) {
+            long c1 = c[(i + 4) % DM];
+            // left shift and wrap the leftmost bit into the rightmost bit
+            long c2 = circularShiftLeft(c[(i + 1) % DM], 1);
+            d[i] = c1^c2;
+        }
+        for (int y = 0; y < DM; y++) {
+            for (int x = 0; x < DM; x++) {
+                a[y][x] ^= d[x];
+            }
+        }
+        return a;
+    }
+
+    /**
+     * Step mapping Rho as defined in section 3.2.2.
+     */
+    private static long[][] smRho(long[][] a) {
+        long[][] a2 = new long[DM][DM];
+        a2[0][0] = a[0][0];
+        int xNext, yNext;
+        for (int t = 0, x = 1, y = 0; t <= 23; t++, x = xNext, y = yNext) {
+            int numberOfShift = ((t + 1)*(t + 2)/2) % 64;
+            a2[y][x] = circularShiftLeft(a[y][x], numberOfShift);
+            xNext = y;
+            yNext = (2 * x + 3 * y) % DM;
+        }
+        return a2;
+    }
+
+    /**
+     * Step mapping Pi as defined in section 3.2.3.
+     */
+    private static long[][] smPi(long[][] a) {
+        long[][] a2 = new long[DM][DM];
+        for (int y = 0; y < DM; y++) {
+            for (int x = 0; x < DM; x++) {
+                a2[y][x] = a[x][(x + 3 * y) % DM];
+            }
+        }
+        return a2;
+    }
+
+    /**
+     * Step mapping Chi as defined in section 3.2.4.
+     */
+    private static long[][] smChi(long[][] a) {
+        long[][] a2 = new long[DM][DM];
+        for (int y = 0; y < DM; y++) {
+            for (int x = 0; x < DM; x++) {
+                a2[y][x] = a[y][x] ^
+                    ((a[y][(x + 1) % DM] ^ 0xFFFFFFFFFFFFFFFFL) &
+                     a[y][(x + 2) % DM]);
+            }
+        }
+        return a2;
+    }
+
+    /**
+     * Step mapping Iota as defined in section 3.2.5.
+     *
+     * @return the processed state array
+     * @param state the state array to be processed
+     */
+    private static long[][] smIota(long[][] a, int rndIndex) {
+        a[0][0] ^= RC_CONSTANTS[rndIndex];
+        return a;
+    }
+
+    /**
+     * The function Keccak as defined in section 5.2 with
+     * rate r = 1600 and capacity c = (digest length x 2).
+     */
+    private static byte[] keccak(byte[] state) {
+        long[][] lanes = bytes2Lanes(state);
+        for (int ir = 0; ir < NR; ir++) {
+            lanes = smIota(smChi(smPi(smRho(smTheta(lanes)))), ir);
+        }
+        return lanes2Bytes(lanes);
+    }
+
+    public Object clone() throws CloneNotSupportedException {
+        SHA3 copy = (SHA3) super.clone();
+        copy.state = copy.state.clone();
+        return copy;
+    }
+
+    /**
+     * SHA3-224 implementation class.
+     */
+    public static final class SHA224 extends SHA3 {
+        public SHA224() {
+            super("SHA3-224", 28);
+        }
+    }
+
+    /**
+     * SHA3-256 implementation class.
+     */
+    public static final class SHA256 extends SHA3 {
+        public SHA256() {
+            super("SHA3-256", 32);
+        }
+    }
+
+    /**
+     * SHAs-384 implementation class.
+     */
+    public static final class SHA384 extends SHA3 {
+        public SHA384() {
+            super("SHA3-384", 48);
+        }
+    }
+
+    /**
+     * SHA3-512 implementation class.
+     */
+    public static final class SHA512 extends SHA3 {
+        public SHA512() {
+            super("SHA3-512", 64);
+        }
+    }
+}
--- a/src/java.base/share/classes/sun/security/provider/SunEntries.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java	Wed May 18 12:04:26 2016 -0700
@@ -211,6 +211,25 @@
         map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.6",
                 "SHA-512/256");
 
+        map.put("MessageDigest.SHA3-224", "sun.security.provider.SHA3$SHA224");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.7", "SHA3-224");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.7",
+                "SHA3-224");
+
+        map.put("MessageDigest.SHA3-256", "sun.security.provider.SHA3$SHA256");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.8", "SHA3-256");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.8",
+                "SHA3-256");
+        map.put("MessageDigest.SHA3-384", "sun.security.provider.SHA3$SHA384");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.9", "SHA3-384");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.9",
+                "SHA3-384");
+        map.put("MessageDigest.SHA3-512", "sun.security.provider.SHA3$SHA512");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.10", "SHA3-512");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.10",
+                "SHA3-512");
+
+
         /*
          * Algorithm Parameter Generator engines
          */
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, 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
@@ -108,7 +108,7 @@
      * a hash for the certificate verify message is required.
      */
     HandshakeHash(boolean needCertificateVerify) {
-        clonesNeeded = needCertificateVerify ? 3 : 2;
+        clonesNeeded = needCertificateVerify ? 4 : 3;
     }
 
     void reserve(ByteBuffer input) {
--- a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java	Wed May 18 12:04:26 2016 -0700
@@ -145,11 +145,10 @@
      */
     public static boolean isBlockOrSF(String s) {
         // we currently only support DSA and RSA PKCS7 blocks
-        if (s.endsWith(".SF") || s.endsWith(".DSA") ||
-                s.endsWith(".RSA") || s.endsWith(".EC")) {
-            return true;
-        }
-        return false;
+        return s.endsWith(".SF")
+            || s.endsWith(".DSA")
+            || s.endsWith(".RSA")
+            || s.endsWith(".EC");
     }
 
     /**
--- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java	Wed May 18 12:04:26 2016 -0700
@@ -552,58 +552,61 @@
             return AlgorithmId.sha512WithECDSA_oid;
         }
 
-        // See if any of the installed providers supply a mapping from
-        // the given algorithm name to an OID string
-        String oidString;
-        if (!initOidTable) {
-            Provider[] provs = Security.getProviders();
-            for (int i=0; i<provs.length; i++) {
-                for (Enumeration<Object> enum_ = provs[i].keys();
-                     enum_.hasMoreElements(); ) {
-                    String alias = (String)enum_.nextElement();
-                    String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH);
-                    int index;
-                    if (upperCaseAlias.startsWith("ALG.ALIAS") &&
-                            (index=upperCaseAlias.indexOf("OID.", 0)) != -1) {
-                        index += "OID.".length();
-                        if (index == alias.length()) {
-                            // invalid alias entry
-                            break;
-                        }
-                        if (oidTable == null) {
-                            oidTable = new HashMap<>();
-                        }
-                        oidString = alias.substring(index);
-                        String stdAlgName = provs[i].getProperty(alias);
-                        if (stdAlgName != null) {
-                            stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH);
-                        }
-                        if (stdAlgName != null &&
-                                oidTable.get(stdAlgName) == null) {
-                            oidTable.put(stdAlgName,
-                                         new ObjectIdentifier(oidString));
-                        }
-                    }
-                }
-            }
-
-            if (oidTable == null) {
-                oidTable = Collections.<String,ObjectIdentifier>emptyMap();
-            }
-            initOidTable = true;
-        }
-
-        return oidTable.get(name.toUpperCase(Locale.ENGLISH));
+        return oidTable().get(name.toUpperCase(Locale.ENGLISH));
     }
 
     private static ObjectIdentifier oid(int ... values) {
         return ObjectIdentifier.newInternal(values);
     }
 
-    private static boolean initOidTable = false;
-    private static Map<String,ObjectIdentifier> oidTable;
+    private static volatile Map<String,ObjectIdentifier> oidTable;
     private static final Map<ObjectIdentifier,String> nameTable;
 
+    /** Returns the oidTable, lazily initializing it on first access. */
+    private static Map<String,ObjectIdentifier> oidTable()
+        throws IOException {
+        // Double checked locking; safe because oidTable is volatile
+        Map<String,ObjectIdentifier> tab;
+        if ((tab = oidTable) == null) {
+            synchronized (AlgorithmId.class) {
+                if ((tab = oidTable) == null)
+                    oidTable = tab = computeOidTable();
+            }
+        }
+        return tab;
+    }
+
+    /** Collects the algorithm names from the installed providers. */
+    private static HashMap<String,ObjectIdentifier> computeOidTable()
+        throws IOException {
+        HashMap<String,ObjectIdentifier> tab = new HashMap<>();
+        for (Provider provider : Security.getProviders()) {
+            for (Object key : provider.keySet()) {
+                String alias = (String)key;
+                String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH);
+                int index;
+                if (upperCaseAlias.startsWith("ALG.ALIAS") &&
+                    (index=upperCaseAlias.indexOf("OID.", 0)) != -1) {
+                    index += "OID.".length();
+                    if (index == alias.length()) {
+                        // invalid alias entry
+                        break;
+                    }
+                    String oidString = alias.substring(index);
+                    String stdAlgName = provider.getProperty(alias);
+                    if (stdAlgName != null) {
+                        stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH);
+                    }
+                    if (stdAlgName != null &&
+                        tab.get(stdAlgName) == null) {
+                        tab.put(stdAlgName, new ObjectIdentifier(oidString));
+                    }
+                }
+            }
+        }
+        return tab;
+    }
+
     /*****************************************************************/
 
     /*
--- a/src/java.base/share/conf/security/java.policy	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/conf/security/java.policy	Wed May 18 12:04:26 2016 -0700
@@ -80,6 +80,10 @@
         permission java.security.AllPermission;
 };
 
+grant codeBase "jrt:/java.scripting" {
+        permission java.security.AllPermission;
+};
+
 grant codeBase "jrt:/jdk.scripting.nashorn" {
         permission java.security.AllPermission;
 };
--- a/src/java.base/share/native/include/jvmti.h	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/native/include/jvmti.h	Wed May 18 12:04:26 2016 -0700
@@ -704,7 +704,8 @@
     unsigned int can_generate_resource_exhaustion_heap_events : 1;
     unsigned int can_generate_resource_exhaustion_threads_events : 1;
     unsigned int can_generate_early_vmstart : 1;
-    unsigned int : 6;
+    unsigned int can_generate_early_class_hook_events : 1;
+    unsigned int : 5;
     unsigned int : 16;
     unsigned int : 16;
     unsigned int : 16;
--- a/src/java.base/share/native/libjava/VM.c	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.base/share/native/libjava/VM.c	Wed May 18 12:04:26 2016 -0700
@@ -36,7 +36,7 @@
 };
 
 JNIEXPORT jobject JNICALL
-Java_jdk_internal_misc_VM_latestUserDefinedLoader(JNIEnv *env, jclass cls) {
+Java_jdk_internal_misc_VM_latestUserDefinedLoader0(JNIEnv *env, jclass cls) {
     return JVM_LatestUserDefinedLoader(env);
 }
 
--- a/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java	Wed May 18 12:04:26 2016 -0700
@@ -26,7 +26,6 @@
 import java.io.Closeable;
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.concurrent.ExecutorService;
 import java.util.function.Consumer;
@@ -557,25 +556,37 @@
     }
 
     static void logParams(SSLParameters p) {
-        if (!Log.ssl())
+        if (!Log.ssl()) {
             return;
+        }
+
         Log.logSSL("SSLParameters:");
         if (p == null) {
             Log.logSSL("Null params");
             return;
         }
-        for (String cipher : p.getCipherSuites()) {
-            Log.logSSL("cipher: {0}\n", cipher);
+
+        if (p.getCipherSuites() != null) {
+            for (String cipher : p.getCipherSuites()) {
+                Log.logSSL("cipher: {0}\n", cipher);
+            }
         }
+
+        // SSLParameters.getApplicationProtocols() can't return null
         for (String approto : p.getApplicationProtocols()) {
             Log.logSSL("application protocol: {0}\n", approto);
         }
-        for (String protocol : p.getProtocols()) {
-            Log.logSSL("protocol: {0}\n", protocol);
+
+        if (p.getProtocols() != null) {
+            for (String protocol : p.getProtocols()) {
+                Log.logSSL("protocol: {0}\n", protocol);
+            }
         }
-        if (p.getServerNames() != null)
+
+        if (p.getServerNames() != null) {
             for (SNIServerName sname : p.getServerNames()) {
                 Log.logSSL("server name: {0}\n", sname.toString());
+            }
         }
     }
 
--- a/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java	Wed May 18 12:04:26 2016 -0700
@@ -35,6 +35,7 @@
 import java.nio.channels.SelectableChannel;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -155,6 +156,15 @@
         selmgr.register(exchange);
     }
 
+    /**
+     * Only used from RawChannel to disconnect the channel from
+     * the selector
+     */
+    void cancelRegistration(SocketChannel s) {
+        selmgr.cancel(s);
+    }
+
+
     Http2ClientImpl client2() {
         return client2;
     }
@@ -220,6 +230,13 @@
             selector.wakeup();
         }
 
+        synchronized void cancel(SocketChannel e) {
+            SelectionKey key = e.keyFor(selector);
+            if (key != null)
+                key.cancel();
+            selector.wakeup();
+        }
+
         void wakeupSelector() {
             selector.wakeup();
         }
--- a/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java	Wed May 18 20:40:17 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * 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.  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
- */
-
-package java.net.http;
-
-public interface HttpHeaders1 extends HttpHeaders {
-    public void makeUnmodifiable();
-}
--- a/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java	Wed May 18 12:04:26 2016 -0700
@@ -176,7 +176,7 @@
      *
      * @return
      */
-    RawChannel rawChannel() {
+    RawChannel rawChannel() throws IOException {
         if (rawchan == null) {
             rawchan = new RawChannel(request.client(), connection);
         }
--- a/src/java.httpclient/share/classes/java/net/http/Log.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.httpclient/share/classes/java/net/http/Log.java	Wed May 18 12:04:26 2016 -0700
@@ -88,7 +88,7 @@
                         logging |= TRACE;
                         break;
                     case "all":
-                        logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE;
+                        logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE|SSL;
                         break;
                 }
                 if (val.startsWith("frames")) {
--- a/src/java.httpclient/share/classes/java/net/http/RawChannel.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.httpclient/share/classes/java/net/http/RawChannel.java	Wed May 18 12:04:26 2016 -0700
@@ -29,6 +29,7 @@
 import java.nio.channels.GatheringByteChannel;
 import java.nio.channels.SelectableChannel;
 import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
 
 //
 // Used to implement WebSocket. Each RawChannel corresponds to a TCP connection
@@ -56,9 +57,21 @@
     interface NonBlockingEvent extends RawEvent {
     }
 
-    RawChannel(HttpClientImpl client, HttpConnection connection) {
+    RawChannel(HttpClientImpl client, HttpConnection connection)
+                                                throws IOException {
         this.client = client;
         this.connection = connection;
+        SocketChannel chan = connection.channel();
+        client.cancelRegistration(chan);
+        chan.configureBlocking(false);
+    }
+
+    SocketChannel socketChannel() {
+        return connection.channel();
+    }
+
+    ByteBuffer getRemaining() {
+        return connection.getRemaining();
     }
 
     private class RawAsyncEvent extends AsyncEvent {
--- a/src/java.httpclient/share/classes/java/net/http/Stream.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.httpclient/share/classes/java/net/http/Stream.java	Wed May 18 12:04:26 2016 -0700
@@ -32,6 +32,9 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.function.BiFunction;
 import java.util.function.LongConsumer;
 
@@ -409,13 +412,20 @@
     @Override
     HttpResponseImpl getResponse() throws IOException {
         try {
-            return getResponseAsync(null).join();
-        } catch (Throwable e) {
+            if (request.timeval() > 0) {
+                return getResponseAsync(null).get(
+                        request.timeval(), TimeUnit.MILLISECONDS);
+            } else {
+                return getResponseAsync(null).join();
+            }
+        } catch (TimeoutException e) {
+            throw new HttpTimeoutException("Response timed out");
+        } catch (InterruptedException | ExecutionException e) {
             Throwable t = e.getCause();
             if (t instanceof IOException) {
                 throw (IOException)t;
             }
-            throw e;
+            throw new IOException(e);
         }
     }
 
--- a/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java	Wed May 18 12:04:26 2016 -0700
@@ -24,6 +24,8 @@
  */
 package java.net.http;
 
+import java.io.UncheckedIOException;
+import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
@@ -126,6 +128,8 @@
                         return CompletableFuture.completedFuture(result);
                     } catch (WebSocketHandshakeException e) {
                         return CompletableFuture.failedFuture(e);
+                    } catch (UncheckedIOException ee) {
+                        return CompletableFuture.failedFuture(ee.getCause());
                     }
                 });
     }
@@ -149,7 +153,12 @@
         checkAccept(response, h);
         checkExtensions(response, h);
         String subprotocol = checkAndReturnSubprotocol(response, h);
-        RawChannel channel = ((HttpResponseImpl) response).rawChannel();
+        RawChannel channel = null;
+        try {
+            channel = ((HttpResponseImpl) response).rawChannel();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
         return new Result(subprotocol, channel);
     }
 
--- a/src/java.instrument/share/native/libinstrument/InvocationAdapter.c	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.instrument/share/native/libinstrument/InvocationAdapter.c	Wed May 18 12:04:26 2016 -0700
@@ -518,18 +518,22 @@
 splitPathList(const char* str, int* pathCount, char*** paths) {
     int count = 0;
     char** segments = NULL;
+    char** new_segments;
     char* c = (char*) str;
     while (*c != '\0') {
         while (*c == ' ') c++;          /* skip leading spaces */
         if (*c == '\0') {
             break;
         }
-        if (segments == NULL) {
-            segments = (char**)malloc( sizeof(char**) );
-        } else {
-            segments = (char**)realloc( segments, (count+1)*sizeof(char**) );
+        new_segments = (char**)realloc(segments, (count+1)*sizeof(char*));
+        if (new_segments == NULL) {
+            jplis_assert(0);
+            free(segments);
+            count = 0;
+            segments = NULL;
+            break;
         }
-        jplis_assert(segments != (char**)NULL);
+        segments = new_segments;
         segments[count++] = c;
         c = strchr(c, ' ');
         if (c == NULL) {
--- a/src/java.logging/share/classes/java/util/logging/LogManager.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.logging/share/classes/java/util/logging/LogManager.java	Wed May 18 12:04:26 2016 -0700
@@ -2506,15 +2506,12 @@
         }
     }
 
-    // Management Support
-    private static LoggingMXBean loggingMXBean = null;
     /**
      * String representation of the
      * {@link javax.management.ObjectName} for the management interface
      * for the logging facility.
      *
      * @see java.lang.management.PlatformLoggingMXBean
-     * @see java.util.logging.LoggingMXBean
      *
      * @since 1.5
      */
@@ -2523,24 +2520,21 @@
 
     /**
      * Returns {@code LoggingMXBean} for managing loggers.
-     * An alternative way to manage loggers is through the
-     * {@link java.lang.management.PlatformLoggingMXBean} interface
-     * that can be obtained by calling:
-     * <pre>
-     *     PlatformLoggingMXBean logging = {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
-     *         ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class);
-     * </pre>
      *
      * @return a {@link LoggingMXBean} object.
      *
+     * @deprecated {@code java.util.logging.LoggingMXBean} is deprecated and
+     *      replaced with {@code java.lang.management.PlatformLoggingMXBean}. Use
+     *      {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
+     *      ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class)
+     *      instead.
+     *
      * @see java.lang.management.PlatformLoggingMXBean
      * @since 1.5
      */
+    @Deprecated(since="9")
     public static synchronized LoggingMXBean getLoggingMXBean() {
-        if (loggingMXBean == null) {
-            loggingMXBean =  new Logging();
-        }
-        return loggingMXBean;
+        return Logging.getInstance();
     }
 
     /**
--- a/src/java.logging/share/classes/java/util/logging/Logging.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.logging/share/classes/java/util/logging/Logging.java	Wed May 18 12:04:26 2016 -0700
@@ -44,16 +44,18 @@
  * @see Logger
  * @see LogManager
  */
-class Logging implements LoggingMXBean {
+@SuppressWarnings("deprecation") // implements LoggingMXBean
+final class Logging implements LoggingMXBean {
 
     private static LogManager logManager = LogManager.getLogManager();
 
     /** Constructor of Logging which is the implementation class
      *  of LoggingMXBean.
      */
-    Logging() {
+    private Logging() {
     }
 
+    @Override
     public List<String> getLoggerNames() {
         Enumeration<String> loggers = logManager.getLoggerNames();
         ArrayList<String> array = new ArrayList<>();
@@ -65,6 +67,7 @@
     }
 
     private static String EMPTY_STRING = "";
+    @Override
     public String getLoggerLevel(String loggerName) {
         Logger l = logManager.getLogger(loggerName);
         if (l == null) {
@@ -79,6 +82,7 @@
         }
     }
 
+    @Override
     public void setLoggerLevel(String loggerName, String levelName) {
         if (loggerName == null) {
             throw new NullPointerException("loggerName is null");
@@ -102,6 +106,7 @@
         logger.setLevel(level);
     }
 
+    @Override
     public String getParentLoggerName( String loggerName ) {
         Logger l = logManager.getLogger( loggerName );
         if (l == null) {
@@ -116,4 +121,11 @@
             return p.getName();
         }
     }
+
+    static Logging getInstance() {
+        return INSTANCE;
+    }
+
+    private static final Logging INSTANCE = new Logging();
+
 }
--- a/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java	Wed May 18 12:04:26 2016 -0700
@@ -27,30 +27,23 @@
 
 
 /**
- * The management interface for the logging facility. It is recommended
- * to use the {@link java.lang.management.PlatformLoggingMXBean} management
- * interface that implements all attributes defined in this
- * {@code LoggingMXBean}.  The
- * {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
- * ManagementFactory.getPlatformMXBean} method can be used to obtain
- * the {@code PlatformLoggingMXBean} object representing the management
- * interface for logging.
+ * The management interface for the logging facility.
  *
- * <p>There is a single global instance of the {@code LoggingMXBean}.
- * This instance is an {@link javax.management.MXBean MXBean} that
- * can be obtained by calling the {@link LogManager#getLoggingMXBean}
- * method or from the
- * {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer
+ * {@link java.lang.management.PlatformLoggingMXBean
+ * java.lang.management.PlatformLoggingMXBean} is the management interface
+ * for logging facility registered in the {@link
+ * java.lang.management.ManagementFactory#getPlatformMBeanServer()
  * platform MBeanServer}.
- * <p>
- * The {@link javax.management.ObjectName ObjectName} that uniquely identifies
- * the management interface for logging within the {@code MBeanServer} is:
- * <pre>
- *    {@link LogManager#LOGGING_MXBEAN_NAME java.util.logging:type=Logging}
- * </pre>
- * <p>
- * The instance registered in the platform {@code MBeanServer}
- * is also a {@link java.lang.management.PlatformLoggingMXBean}.
+ * It is recommended to use the {@code PlatformLoggingMXBean} obtained via
+ * the {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
+ * ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class)} method.
+ *
+ * @deprecated {@code LoggingMXBean} is no longer a {@link
+ * java.lang.management.PlatformManagedObject platform MXBean} and is replaced
+ * with {@link java.lang.management.PlatformLoggingMXBean}.
+ * It will not register in the platform {@code MBeanServer}.
+ * Use {@code ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class)}
+ * instead.
  *
  * @author  Ron Mann
  * @author  Mandy Chung
@@ -58,6 +51,7 @@
  *
  * @see java.lang.management.PlatformLoggingMXBean
  */
+@Deprecated(since="9")
 public interface LoggingMXBean {
 
     /**
--- a/src/java.management/share/classes/java/lang/management/ManagementFactory.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.management/share/classes/java/lang/management/ManagementFactory.java	Wed May 18 12:04:26 2016 -0700
@@ -598,9 +598,8 @@
 
         try {
             final ObjectName objName = new ObjectName(mxbeanName);
-            // skip the isInstanceOf check for LoggingMXBean
             String intfName = mxbeanInterface.getName();
-            if (!connection.isInstanceOf(objName, intfName)) {
+            if (!isInstanceOf(connection, objName, intfName)) {
                 throw new IllegalArgumentException(mxbeanName +
                     " is not an instance of " + mxbeanInterface);
             }
@@ -616,6 +615,33 @@
         }
     }
 
+    // This makes it possible to obtain an instance of LoggingMXBean
+    // using newPlatformMXBeanProxy(mbs, on, LoggingMXBean.class)
+    // even though the underlying MXBean no longer implements
+    // java.util.logging.LoggingMXBean.
+    // Altough java.util.logging.LoggingMXBean is deprecated, an application
+    // that uses newPlatformMXBeanProxy(mbs, on, LoggingMXBean.class) will
+    // continue to work.
+    //
+    private static boolean isInstanceOf(MBeanServerConnection connection,
+            ObjectName objName, String intfName)
+            throws InstanceNotFoundException, IOException
+    {
+        // special case for java.util.logging.LoggingMXBean.
+        // java.util.logging.LoggingMXBean is deprecated and
+        // replaced with java.lang.management.PlatformLoggingMXBean,
+        // so we will consider that any MBean implementing
+        // java.lang.management.PlatformLoggingMXBean also implements
+        // java.util.logging.LoggingMXBean.
+        if ("java.util.logging.LoggingMXBean".equals(intfName)) {
+            if (connection.isInstanceOf(objName,
+                    PlatformLoggingMXBean.class.getName())) {
+                return true;
+            }
+        }
+        return connection.isInstanceOf(objName, intfName);
+    }
+
     /**
      * Returns the platform MXBean implementing
      * the given {@code mxbeanInterface} which is specified
--- a/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java	Wed May 18 12:04:26 2016 -0700
@@ -44,10 +44,6 @@
  *      {@link java.util.logging.LogManager#LOGGING_MXBEAN_NAME java.util.logging:type=Logging}
  * </pre>
  *
- * <p>The instance registered in the platform {@code MBeanServer} with
- * this {@code ObjectName} implements all attributes defined by
- * {@link java.util.logging.LoggingMXBean}.
- *
  * @since   1.7
  */
 public interface PlatformLoggingMXBean extends PlatformManagedObject {
--- a/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java	Wed May 18 12:04:26 2016 -0700
@@ -26,6 +26,8 @@
 package sun.management;
 
 import java.lang.management.*;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
 import javax.management.MBeanServer;
@@ -43,9 +45,13 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Module;
+import java.lang.reflect.UndeclaredThrowableException;
 import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
 
 /**
  * ManagementFactoryHelper provides static factory methods to create
@@ -66,6 +72,7 @@
         return jvm;
     }
 
+    static final String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging";
     private static ClassLoadingImpl    classMBean = null;
     private static MemoryImpl          memoryMBean = null;
     private static ThreadImpl          threadMBean = null;
@@ -145,74 +152,138 @@
     }
 
     public static PlatformLoggingMXBean getPlatformLoggingMXBean() {
-        if (LoggingMXBeanSupport.isAvailable()) {
-            return PlatformLoggingImpl.instance;
+        if (LoggingMXBeanAccess.isAvailable()) {
+            return PlatformLoggingImpl.MBEAN;
         } else {
             return null;
         }
     }
 
     public static boolean isPlatformLoggingMXBeanAvailable() {
-        return LoggingMXBeanSupport.isAvailable();
+        return LoggingMXBeanAccess.isAvailable();
     }
 
-    /**
-     * The logging MXBean object is an instance of
-     * PlatformLoggingMXBean and java.util.logging.LoggingMXBean
-     * but it can't directly implement two MXBean interfaces
-     * as a compliant MXBean implements exactly one MXBean interface,
-     * or if it implements one interface that is a subinterface of
-     * all the others; otherwise, it is a non-compliant MXBean
-     * and MBeanServer will throw NotCompliantMBeanException.
-     * See the Definition of an MXBean section in javax.management.MXBean spec.
-     *
-     * To create a compliant logging MXBean, define a LoggingMXBean interface
-     * that extend PlatformLoggingMXBean and j.u.l.LoggingMXBean
-    */
-    public interface LoggingMXBean
-        extends PlatformLoggingMXBean, java.util.logging.LoggingMXBean {
-    }
-
-    // This is a trick: if java.util.logging is not present then
-    // attempting to access something that implements
-    // java.util.logging.LoggingMXBean will trigger a CNFE.
-    // So we cannot directly call any static method or access any static field
-    // on PlatformLoggingImpl, as we would risk raising a CNFE.
-    // Instead we use this intermediate LoggingMXBeanSupport class to determine
+    // The LoggingMXBeanAccess class uses reflection to determine
     // whether java.util.logging is present, and load the actual LoggingMXBean
     // implementation.
     //
-    static final class LoggingMXBeanSupport {
-        final static Object loggingImpl =
-                AccessController.doPrivileged(new PrivilegedAction<Object>() {
-            @Override
-            public Object run() {
-                try {
-                    // create a LoggingProxyImpl instance when
-                    // java.util.logging classes exist
-                    Class<?> c = Class.forName("java.util.logging.Logging", true, null);
-                    Constructor<?> cons = c.getDeclaredConstructor();
-                    cons.setAccessible(true);
-                    return cons.newInstance();
-                } catch (ClassNotFoundException cnf) {
-                    return null;
-                } catch (NoSuchMethodException | InstantiationException
-                        | IllegalAccessException | InvocationTargetException e) {
-                    throw new AssertionError(e);
-                }
-            }});
+    static final class LoggingMXBeanAccess {
+
+        final static String LOG_MANAGER_CLASS_NAME = "java.util.logging.LogManager";
+        final static String LOGGING_MXBEAN_CLASS_NAME = "java.util.logging.LoggingMXBean";
+        final static Class<?> LOG_MANAGER_CLASS = loadLoggingClass(LOG_MANAGER_CLASS_NAME);
 
         static boolean isAvailable() {
-            return loggingImpl != null;
+            return LOG_MANAGER_CLASS != null;
         }
+
+        private static Class<?> loadLoggingClass(String className) {
+            return AccessController.doPrivileged(new PrivilegedAction<>() {
+                @Override
+                public Class<?> run() {
+                    Optional<Module> logging = java.lang.reflect.Layer.boot()
+                        .findModule("java.logging");
+                    if (logging.isPresent()) {
+                        return Class.forName(logging.get(), className);
+                    }
+                    return null;
+                }
+            });
+        }
+
+        private Map<String, Method> initMethodMap(Object impl) {
+            if (impl == null) {
+                return Collections.emptyMap();
+            }
+            Class<?> intfClass = loadLoggingClass(LOGGING_MXBEAN_CLASS_NAME);
+            final Map<String, Method> methodsMap = new HashMap<>();
+            for (Method m : intfClass.getMethods()) {
+                try {
+                    // Sanity checking: all public methods present in
+                    // java.util.logging.LoggingMXBean should
+                    // also be in PlatformLoggingMXBean
+                    Method specMethod = PlatformLoggingMXBean.class
+                             .getMethod(m.getName(), m.getParameterTypes());
+                    if (specMethod.getReturnType().isAssignableFrom(m.getReturnType())) {
+                        if (methodsMap.putIfAbsent(m.getName(), m) != null) {
+                            throw new RuntimeException("unexpected polymorphic method: "
+                                     + m.getName());
+                        }
+                    }
+                } catch (NoSuchMethodException x) {
+                    // All methods in java.util.logging.LoggingMXBean should
+                    // also be in PlatformLoggingMXBean
+                    throw new InternalError(x);
+                }
+            }
+            return Collections.unmodifiableMap(methodsMap);
+        }
+
+        private static Object getMXBeanImplementation() {
+            if (!isAvailable()) {
+                // should not happen
+                throw new NoClassDefFoundError(LOG_MANAGER_CLASS_NAME);
+            }
+            try {
+                final Method m = LOG_MANAGER_CLASS.getMethod("getLoggingMXBean");
+                return m.invoke(null);
+            } catch (NoSuchMethodException
+                    | IllegalAccessException
+                    | InvocationTargetException x) {
+                throw new ExceptionInInitializerError(x);
+            }
+         }
+
+        // The implementation object, which will be invoked through
+        // reflection. The implementation does not need to implement
+        // PlatformLoggingMXBean, but must declare the same methods
+        // with same signatures, and they must be public, with one
+        // exception:
+        // getObjectName will not be called on the implementation object,
+        // so the implementation object does not need to declare such
+        // a method.
+        final Object impl = getMXBeanImplementation();
+        final Map<String, Method> methods = initMethodMap(impl);
+
+        LoggingMXBeanAccess() {
+        }
+
+        <T> T invoke(String methodName, Object... args) {
+            Method m = methods.get(methodName);
+            if (m == null) {
+                throw new UnsupportedOperationException(methodName);
+            }
+            try {
+                @SuppressWarnings("unchecked")
+                T result = (T) m.invoke(impl, args);
+                return result;
+            } catch (IllegalAccessException ex) {
+                throw new UnsupportedOperationException(ex);
+            } catch (InvocationTargetException ex) {
+                throw unwrap(ex);
+            }
+        }
+
+        private static RuntimeException unwrap(InvocationTargetException x) {
+            Throwable t = x.getCause();
+            if (t instanceof RuntimeException) {
+                return (RuntimeException)t;
+            }
+            if (t instanceof Error) {
+                throw (Error)t;
+            }
+            return new UndeclaredThrowableException(t == null ? x : t);
+        }
+
+
     }
 
-    static class PlatformLoggingImpl implements LoggingMXBean
-    {
-        final static java.util.logging.LoggingMXBean impl =
-                (java.util.logging.LoggingMXBean) LoggingMXBeanSupport.loggingImpl;
-        final static PlatformLoggingMXBean instance = new PlatformLoggingImpl();
-        final static String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging";
+    static final class PlatformLoggingImpl implements PlatformLoggingMXBean {
+
+        private final LoggingMXBeanAccess loggingAccess;
+        private PlatformLoggingImpl(LoggingMXBeanAccess loggingAccess) {
+            this.loggingAccess = loggingAccess;
+        }
 
         private volatile ObjectName objname;  // created lazily
         @Override
@@ -232,23 +303,29 @@
 
         @Override
         public java.util.List<String> getLoggerNames() {
-            return impl.getLoggerNames();
+            return loggingAccess.invoke("getLoggerNames");
         }
 
         @Override
         public String getLoggerLevel(String loggerName) {
-            return impl.getLoggerLevel(loggerName);
+            return loggingAccess.invoke("getLoggerLevel", loggerName);
         }
 
         @Override
         public void setLoggerLevel(String loggerName, String levelName) {
-            impl.setLoggerLevel(loggerName, levelName);
+            loggingAccess.invoke("setLoggerLevel", loggerName, levelName);
         }
 
         @Override
         public String getParentLoggerName(String loggerName) {
-            return impl.getParentLoggerName(loggerName);
+            return loggingAccess.invoke("getParentLoggerName", loggerName);
         }
+
+        private static PlatformLoggingImpl getInstance() {
+            return new PlatformLoggingImpl(new LoggingMXBeanAccess());
+         }
+
+        static final PlatformLoggingMXBean MBEAN = getInstance();
     }
 
     private static List<BufferPoolMXBean> bufferPools = null;
--- a/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java	Wed May 18 12:04:26 2016 -0700
@@ -194,7 +194,7 @@
         /*
          * Unless we were told to skip this consideration, choose the
          * "default loader" to simulate the default ObjectInputStream
-         * resolveClass mechanism (that is, choose the first non-null
+         * resolveClass mechanism (that is, choose the first non-platform
          * loader on the execution stack) to maximize the likelihood of
          * type compatibility with calling code.  (This consideration
          * is skipped during server parameter unmarshalling using the 1.2
@@ -268,8 +268,9 @@
     }
 
     /*
-     * Returns the first non-null class loader up the execution stack, or null
-     * if only code from the null class loader is on the stack.
+     * Returns the first non-platform class loader up the execution stack,
+     * or platform class loader if only code from the platform class loader or null
+     * is on the stack.
      */
     private static ClassLoader latestUserDefinedLoader() {
         return jdk.internal.misc.VM.latestUserDefinedLoader();
--- a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java	Wed May 18 12:04:26 2016 -0700
@@ -258,7 +258,7 @@
     /*
      * Convenience method for simple commands
      */
-    private InputStream executeCommand(String cmd, Object ... args) throws IOException {
+    public InputStream executeCommand(String cmd, Object ... args) throws IOException {
         try {
             return execute(cmd, args);
         } catch (AgentLoadException x) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/LibMDMech.java	Wed May 18 12:04:26 2016 -0700
@@ -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.  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 com.oracle.security.ucrypto;
+
+/**
+ * Enum for representing the ucrypto mechanisms.
+ *
+ * @since 9
+ */
+public enum LibMDMech {
+
+    MD5(new ServiceDesc[]
+        { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigestMD$MD5")
+        }),
+    SHA_1(new ServiceDesc[]
+        { sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigestMD$SHA1",
+             "SHA-1", "SHA1")
+        }),
+    SHA_256(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigestMD$SHA256",
+             "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1")
+        }),
+    SHA_384(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigestMD$SHA384",
+             "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2")
+        }),
+    SHA_512(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigestMD$SHA512",
+             "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3")
+        });
+
+    ServiceDesc[] serviceDescs;
+
+    private static ServiceDesc sd(String type, String algo, String cn, String... aliases) {
+        return new ServiceDesc(type, algo, cn, aliases);
+    }
+
+    LibMDMech(ServiceDesc[] serviceDescs) {
+        this.serviceDescs = serviceDescs;
+    }
+
+    public ServiceDesc[] getServiceDescriptions() { return serviceDescs; }
+}
--- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 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
@@ -33,23 +33,67 @@
 import java.security.*;
 
 /**
- * MessageDigest implementation class. This class currently supports
- * MD5, SHA1, SHA256, SHA384, and SHA512
+ * MessageDigest implementation class using native Ucrypto API.
+ * This class currently supports: MD5, SHA-2 (224, 256, 384, 512)
+ * and SHA-3 (224, 256, 384, 512) digests
  *
  * @since 9
  */
-public abstract class NativeDigest extends MessageDigestSpi
-        implements Cloneable {
+abstract class NativeDigest extends MessageDigestSpi {
 
-    private static final int MECH_MD5 = 1;
-    private static final int MECH_SHA1 = 2;
-    private static final int MECH_SHA256 = 3;
-    private static final int MECH_SHA224 = 4;
-    private static final int MECH_SHA384 = 5;
-    private static final int MECH_SHA512 = 6;
+    public static final class MD5 extends NativeDigest {
+        public MD5() {
+            super(UcryptoMech.CRYPTO_MD5, 16);
+        }
+    }
+    public static final class SHA1 extends NativeDigest {
+        public SHA1() {
+            super(UcryptoMech.CRYPTO_SHA1, 20);
+        }
+    }
+    public static final class SHA224 extends NativeDigest {
+        public SHA224() {
+            super(UcryptoMech.CRYPTO_SHA224, 28);
+        }
+    }
+    public static final class SHA256 extends NativeDigest {
+        public SHA256() {
+            super(UcryptoMech.CRYPTO_SHA256, 32);
+        }
+    }
+    public static final class SHA384 extends NativeDigest {
+        public SHA384() {
+            super(UcryptoMech.CRYPTO_SHA384, 48);
+        }
+    }
+    public static final class SHA512 extends NativeDigest {
+        public SHA512() {
+            super(UcryptoMech.CRYPTO_SHA512, 64);
+        }
+    }
+    public static final class SHA3_224 extends NativeDigest {
+        public SHA3_224() {
+            super(UcryptoMech.CRYPTO_SHA3_224, 28);
+        }
+    }
+    public static final class SHA3_256 extends NativeDigest {
+        public SHA3_256() {
+            super(UcryptoMech.CRYPTO_SHA3_256, 32);
+        }
+    }
+    public static final class SHA3_384 extends NativeDigest {
+        public SHA3_384() {
+            super(UcryptoMech.CRYPTO_SHA3_384, 48);
+        }
+    }
+    public static final class SHA3_512 extends NativeDigest {
+        public SHA3_512() {
+            super(UcryptoMech.CRYPTO_SHA3_512, 64);
+        }
+    }
 
     private final int digestLen;
-    private final int mech;
+    private final UcryptoMech mech;
 
     // field for ensuring native memory is freed
     private DigestContextRef pCtxt = null;
@@ -64,10 +108,9 @@
         // referents are GC'ed so we can do post-mortem processing
         private static Set<DigestContextRef> refList =
             new ConcurrentSkipListSet<DigestContextRef>();
-            //            Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>());
 
         private final long id;
-        private final int mech;
+        private final UcryptoMech mech;
 
         private static void drainRefQueueBounded() {
             while (true) {
@@ -77,7 +120,7 @@
             }
         }
 
-        DigestContextRef(NativeDigest nc, long id, int mech) {
+        DigestContextRef(NativeDigest nc, long id, UcryptoMech mech) {
             super(nc, refQueue);
             this.id = id;
             this.mech = mech;
@@ -98,18 +141,22 @@
             refList.remove(this);
             try {
                 if (needFree) {
-                    UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id);
-                    NativeDigest.nativeFree(mech, id);
-                } else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id);
+                    UcryptoProvider.debug("Resource: free Digest Ctxt " +
+                        this.id);
+                    NativeDigest.nativeFree(mech.value(), id);
+                } else {
+                    UcryptoProvider.debug("Resource: discard Digest Ctxt " +
+                        this.id);
+                }
             } finally {
                 this.clear();
             }
         }
     }
 
-    NativeDigest(int mech, int digestLen) {
+    NativeDigest(UcryptoMech mech, int digestLen) {
+        this.mech = mech;
         this.digestLen = digestLen;
-        this.mech = mech;
     }
 
     // see JCA spec
@@ -153,10 +200,10 @@
         }
 
         if (pCtxt == null) {
-            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+            pCtxt = new DigestContextRef(this, nativeInit(mech.value()), mech);
         }
         try {
-            int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen);
+            int status = nativeDigest(mech.value(), pCtxt.id, out, ofs, digestLen);
             if (status != 0) {
                 throw new DigestException("Internal error: " + status);
             }
@@ -183,64 +230,24 @@
                 + len + ". in.length: " + in.length);
         }
         if (pCtxt == null) {
-            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+            pCtxt = new DigestContextRef(this, nativeInit(mech.value()), mech);
         }
-        nativeUpdate(mech, pCtxt.id, in, ofs, len);
+        nativeUpdate(mech.value(), pCtxt.id, in, ofs, len);
     }
 
     /**
      * Clone this digest.
      */
     public synchronized Object clone() throws CloneNotSupportedException {
-        NativeDigest copy = (NativeDigest) super.clone();
-        // re-work the fields that cannot be copied over
-        if (pCtxt != null) {
-            copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech);
-        }
-        return copy;
+        throw new CloneNotSupportedException("Clone is not supported");
     }
 
     // return pointer to the context
-    protected static native long nativeInit(int mech);
+    protected static final native long nativeInit(int mech);
     // return status code; always 0
-    protected static native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
+    protected static final native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
     // return status code; always 0
-    protected static native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
-    // return pointer to the duplicated context
-    protected static native long nativeClone(int mech, long pCtxt);
+    protected static final native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
     // free the specified context
-    private native static void nativeFree(int mech, long id);
-
-
-    public static final class MD5 extends NativeDigest {
-        public MD5() {
-            super(MECH_MD5, 16);
-        }
-    }
-
-    public static final class SHA1 extends NativeDigest {
-        public SHA1() {
-            super(MECH_SHA1, 20);
-        }
-    }
-
-    public static final class SHA256 extends NativeDigest {
-        public SHA256() {
-            super(MECH_SHA256, 32);
-        }
-    }
-
-
-    public static final class SHA384 extends NativeDigest {
-        public SHA384() {
-            super(MECH_SHA384, 48);
-        }
-    }
-
-
-    public static final class SHA512 extends NativeDigest {
-        public SHA512() {
-            super(MECH_SHA512, 64);
-        }
-    }
+    private static final native void nativeFree(int mech, long id);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigestMD.java	Wed May 18 12:04:26 2016 -0700
@@ -0,0 +1,246 @@
+/*
+ * 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 com.oracle.security.ucrypto;
+
+import java.lang.ref.*;
+
+import java.io.ByteArrayOutputStream;
+import java.util.*;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.security.*;
+
+/**
+ * MessageDigest implementation class for libMD API. This class currently supports
+ * MD5, SHA1, SHA256, SHA384, and SHA512
+ *
+ * @since 9
+ */
+public abstract class NativeDigestMD extends MessageDigestSpi
+        implements Cloneable {
+
+    private static final int MECH_MD5 = 1;
+    private static final int MECH_SHA1 = 2;
+    private static final int MECH_SHA256 = 3;
+    private static final int MECH_SHA224 = 4;
+    private static final int MECH_SHA384 = 5;
+    private static final int MECH_SHA512 = 6;
+
+    private final int digestLen;
+    private final int mech;
+
+    // field for ensuring native memory is freed
+    private DigestContextRef pCtxt = null;
+
+    private static class DigestContextRef extends PhantomReference<NativeDigestMD>
+        implements Comparable<DigestContextRef> {
+
+        private static ReferenceQueue<NativeDigestMD> refQueue =
+            new ReferenceQueue<NativeDigestMD>();
+
+        // Needed to keep these references from being GC'ed until when their
+        // referents are GC'ed so we can do post-mortem processing
+        private static Set<DigestContextRef> refList =
+            new ConcurrentSkipListSet<DigestContextRef>();
+            //            Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>());
+
+        private final long id;
+        private final int mech;
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                DigestContextRef next = (DigestContextRef) refQueue.poll();
+                if (next == null) break;
+                next.dispose(true);
+            }
+        }
+
+        DigestContextRef(NativeDigestMD nc, long id, int mech) {
+            super(nc, refQueue);
+            this.id = id;
+            this.mech = mech;
+            refList.add(this);
+            UcryptoProvider.debug("Resource: track Digest Ctxt " + this.id);
+            drainRefQueueBounded();
+        }
+
+        public int compareTo(DigestContextRef other) {
+            if (this.id == other.id) {
+                return 0;
+            } else {
+                return (this.id < other.id) ? -1 : 1;
+            }
+        }
+
+        void dispose(boolean needFree) {
+            refList.remove(this);
+            try {
+                if (needFree) {
+                    UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id);
+                    NativeDigestMD.nativeFree(mech, id);
+                } else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id);
+            } finally {
+                this.clear();
+            }
+        }
+    }
+
+    NativeDigestMD(int mech, int digestLen) {
+        this.digestLen = digestLen;
+        this.mech = mech;
+    }
+
+    // see JCA spec
+    protected int engineGetDigestLength() {
+        return digestLen;
+    }
+
+    // see JCA spec
+    protected synchronized void engineReset() {
+        if (pCtxt != null) {
+            pCtxt.dispose(true);
+            pCtxt = null;
+        }
+    }
+
+    // see JCA spec
+    protected synchronized byte[] engineDigest() {
+        byte[] digest = new byte[digestLen];
+        try {
+            int len = engineDigest(digest, 0, digestLen);
+            if (len != digestLen) {
+                throw new UcryptoException("Digest length mismatch." +
+                    " Len: " + len + ". digestLen: " + digestLen);
+            }
+            return digest;
+        } catch (DigestException de) {
+            throw new UcryptoException("Internal error", de);
+        }
+    }
+
+    // see JCA spec
+    protected synchronized int engineDigest(byte[] out, int ofs, int len)
+            throws DigestException {
+        if (len < digestLen) {
+            throw new DigestException("Output buffer must be at least " +
+                          digestLen + " bytes long. Got: " + len);
+        }
+        if ((ofs < 0) || (len < 0) || (ofs > out.length - len)) {
+            throw new DigestException("Buffer too short to store digest. " +
+                "ofs: " + ofs + ". len: " + len + ". out.length: " + out.length);
+        }
+
+        if (pCtxt == null) {
+            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+        }
+        try {
+            int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen);
+            if (status != 0) {
+                throw new DigestException("Internal error: " + status);
+            }
+        } finally {
+            pCtxt.dispose(false);
+            pCtxt = null;
+        }
+        return digestLen;
+    }
+
+    // see JCA spec
+    protected synchronized void engineUpdate(byte in) {
+        byte[] temp = { in };
+        engineUpdate(temp, 0, 1);
+    }
+
+    // see JCA spec
+    protected synchronized void engineUpdate(byte[] in, int ofs, int len) {
+        if (len == 0) {
+            return;
+        }
+        if ((ofs < 0) || (len < 0) || (ofs > in.length - len)) {
+            throw new ArrayIndexOutOfBoundsException("ofs: " + ofs + ". len: "
+                + len + ". in.length: " + in.length);
+        }
+        if (pCtxt == null) {
+            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+        }
+        nativeUpdate(mech, pCtxt.id, in, ofs, len);
+    }
+
+    /**
+     * Clone this digest.
+     */
+    public synchronized Object clone() throws CloneNotSupportedException {
+        NativeDigestMD copy = (NativeDigestMD) super.clone();
+        // re-work the fields that cannot be copied over
+        if (pCtxt != null) {
+            copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech);
+        }
+        return copy;
+    }
+
+    // return pointer to the context
+    protected static final native long nativeInit(int mech);
+    // return status code; always 0
+    protected static final native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
+    // return status code; always 0
+    protected static final native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
+    // return pointer to the duplicated context
+    protected static final native long nativeClone(int mech, long pCtxt);
+    // free the specified context
+    private static final native void nativeFree(int mech, long id);
+
+
+    public static final class MD5 extends NativeDigestMD {
+        public MD5() {
+            super(MECH_MD5, 16);
+        }
+    }
+
+    public static final class SHA1 extends NativeDigestMD {
+        public SHA1() {
+            super(MECH_SHA1, 20);
+        }
+    }
+
+    public static final class SHA256 extends NativeDigestMD {
+        public SHA256() {
+            super(MECH_SHA256, 32);
+        }
+    }
+
+
+    public static final class SHA384 extends NativeDigestMD {
+        public SHA384() {
+            super(MECH_SHA384, 48);
+        }
+    }
+
+
+    public static final class SHA512 extends NativeDigestMD {
+        public SHA512() {
+            super(MECH_SHA512, 64);
+        }
+    }
+}
--- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java	Wed May 18 12:04:26 2016 -0700
@@ -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
@@ -25,8 +25,6 @@
 
 package com.oracle.security.ucrypto;
 
-import java.util.HashMap;
-
 /**
  * Enum for representing the ucrypto mechanisms.
  *
@@ -35,78 +33,126 @@
 // Check /usr/include/libsoftcrypto.h for updates
 public enum UcryptoMech {
 
-    CRYPTO_AES_ECB(1, new ServiceDesc[]
+    CRYPTO_AES_ECB(new ServiceDesc[]
         { sd("Cipher", "AES/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding"),
           sd("Cipher", "AES/ECB/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesEcbPKCS5",
              "AES"),
-          sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes128EcbNoPadding",
+          sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
              "2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"),
-          sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes192EcbNoPadding",
+          sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
              "2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"),
-          sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes256EcbNoPadding",
+          sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
              "2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41")
         }),
-    CRYPTO_AES_CBC(2, new ServiceDesc[]
+    CRYPTO_AES_CBC(new ServiceDesc[]
         { sd("Cipher", "AES/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding"),
           sd("Cipher", "AES/CBC/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCbcPKCS5"),
-          sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes128CbcNoPadding",
+          sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
              "2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"),
-          sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes192CbcNoPadding",
+          sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
              "2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"),
-          sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes256CbcNoPadding",
+          sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
              "2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42")
         }),
-    CRYPTO_AES_CBC_PAD(3, null), // No support from Solaris yet
-    CRYPTO_AES_CTR(4, new ServiceDesc[]
+//  CRYPTO_AES_CBC_PAD(null), // Support added since S11.1; however we still use CRYPTO_AES_CBC due to known bug
+    CRYPTO_AES_CTR(new ServiceDesc[]
         { sd("Cipher", "AES/CTR/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCtrNoPadding") }),
-    CRYPTO_AES_CCM(5, null), // Cannot support due to lack of Java API which corresponds to CK_AES_CCM_PARAMS
-    CRYPTO_AES_GCM(6, new ServiceDesc[]
+//  CRYPTO_AES_CCM(null), // Need Java API for CK_AES_CCM_PARAMS
+    CRYPTO_AES_GCM(new ServiceDesc[]
         { sd("Cipher", "AES/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding"),
-          sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes128GcmNoPadding",
+          sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
              "2.16.840.1.101.3.4.1.6", "OID.2.16.840.1.101.3.4.1.6"),
-          sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes192GcmNoPadding",
+          sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
              "2.16.840.1.101.3.4.1.26", "OID.2.16.840.1.101.3.4.1.26"),
-          sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes256GcmNoPadding",
+          sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
              "2.16.840.1.101.3.4.1.46", "OID.2.16.840.1.101.3.4.1.46")
         }),
-    CRYPTO_AES_GMAC(7, null), // No support from Solaris yet
-    CRYPTO_AES_CFB128(8, new ServiceDesc[]
+//  CRYPTO_AES_GMAC(null), // No support from Solaris
+    CRYPTO_AES_CFB128(new ServiceDesc[]
         { sd("Cipher", "AES/CFB128/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCfb128NoPadding"),
-          sd("Cipher", "AES/CFB128/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5") }),
-    CRYPTO_RSA_PKCS(31, new ServiceDesc[]
+          sd("Cipher", "AES/CFB128/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5")
+        }),
+
+    CRYPTO_RSA_PKCS(new ServiceDesc[]
         { sd("Cipher", "RSA/ECB/PKCS1Padding", "com.oracle.security.ucrypto.NativeRSACipher$PKCS1Padding",
-             "RSA") }),
-    CRYPTO_RSA_X_509(32, new ServiceDesc[]
+             "RSA")
+        }),
+    CRYPTO_RSA_X_509(new ServiceDesc[]
         { sd("Cipher", "RSA/ECB/NoPadding", "com.oracle.security.ucrypto.NativeRSACipher$NoPadding") }),
-    CRYPTO_MD5_RSA_PKCS(33, new ServiceDesc[]
+    CRYPTO_MD5_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "MD5withRSA", "com.oracle.security.ucrypto.NativeRSASignature$MD5",
-             "1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4") }),
-    CRYPTO_SHA1_RSA_PKCS(34, new ServiceDesc[]
+             "1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4")
+        }),
+    CRYPTO_SHA1_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA1withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA1",
              "1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5",
-             "1.3.14.3.2.29") }),
-    CRYPTO_SHA256_RSA_PKCS(35, new ServiceDesc[]
+             "1.3.14.3.2.29")
+        }),
+    CRYPTO_SHA256_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA256withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA256",
-             "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11") }),
-    CRYPTO_SHA384_RSA_PKCS(36, new ServiceDesc[]
+             "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11")
+        }),
+    CRYPTO_SHA384_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA384withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA384",
-             "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12") }),
-    CRYPTO_SHA512_RSA_PKCS(37, new ServiceDesc[]
+             "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12")
+        }),
+    CRYPTO_SHA512_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA512withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA512",
-             "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13") });
+             "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13")
+        }),
 
-    private final int mech;
+    CRYPTO_MD5(new ServiceDesc[]
+        { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigest$MD5") }),
+    CRYPTO_SHA1(new ServiceDesc[]
+        { sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigest$SHA1", "SHA-1", "SHA1") }),
+    CRYPTO_SHA224(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-224", "com.oracle.security.ucrypto.NativeDigest$SHA224",
+             "2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4")
+    }),
+    CRYPTO_SHA256(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigest$SHA256",
+             "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1")
+    }),
+    CRYPTO_SHA384(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigest$SHA384",
+             "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2")
+    }),
+    CRYPTO_SHA512(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigest$SHA512",
+             "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3")
+    }),
+    CRYPTO_SHA3_224(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-224", "com.oracle.security.ucrypto.NativeDigest$SHA3_224",
+             "2.16.840.1.101.3.4.2.7", "OID.2.16.840.1.101.3.4.2.7")
+    }),
+    CRYPTO_SHA3_256(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-256", "com.oracle.security.ucrypto.NativeDigest$SHA3_256",
+             "2.16.840.1.101.3.4.2.8", "OID.2.16.840.1.101.3.4.2.8")
+    }),
+    CRYPTO_SHA3_384(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-384", "com.oracle.security.ucrypto.NativeDigest$SHA3_384",
+             "2.16.840.1.101.3.4.2.9", "OID.2.16.840.1.101.3.4.2.9")
+    }),
+    CRYPTO_SHA3_512(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-512", "com.oracle.security.ucrypto.NativeDigest$SHA3_512",
+             "2.16.840.1.101.3.4.2.10", "OID.2.16.840.1.101.3.4.2.10")
+    });
+
+    private int mech = 0;
     private final ServiceDesc[] serviceDescs;
 
     private static ServiceDesc sd(String type, String algo, String cn, String... aliases) {
         return new ServiceDesc(type, algo, cn, aliases);
     }
 
-    UcryptoMech(int mech, ServiceDesc[] serviceDescs) {
-        this.mech = mech;
+    UcryptoMech(ServiceDesc[] serviceDescs) {
         this.serviceDescs = serviceDescs;
     }
 
+    public void setValue(int nativeMechValue) {
+        this.mech = nativeMechValue;
+    }
+
     public int value() { return mech; }
     public ServiceDesc[] getServiceDescriptions() { return serviceDescs; }
 }
--- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java	Wed May 18 12:04:26 2016 -0700
@@ -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
@@ -27,6 +27,7 @@
 
 import java.io.IOException;
 import java.io.File;
+import java.lang.reflect.Constructor;
 import java.util.*;
 import java.security.*;
 
@@ -74,48 +75,52 @@
             if (provProp != null) {
                 boolean[] result = loadLibraries();
                 if (result.length == 2) {
-                    if (result[0]) { // successfully loaded libmd
-                        provProp.put("MessageDigest.MD5",
-                            sd("MessageDigest", "MD5",
-                               "com.oracle.security.ucrypto.NativeDigest$MD5"));
-                        provProp.put("MessageDigest.SHA",
-                            sd("MessageDigest", "SHA",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA1",
-                               "SHA-1", "SHA1"));
-                        provProp.put("MessageDigest.SHA-256",
-                            sd("MessageDigest", "SHA-256",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA256",
-                               "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"));
-
-                        provProp.put("MessageDigest.SHA-384",
-                            sd("MessageDigest", "SHA-384",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA384",
-                               "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"));
-
-                        provProp.put("MessageDigest.SHA-512",
-                            sd("MessageDigest", "SHA-512",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA512",
-                               "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"));
-                    };
-                    if (result[1]) { // successfully loaded libsoftcrypto
+                    // true when libsoftcrypto or libucrypto(S12) has been successfully loaded
+                    if (result[1]) {
                         String supportedMechs = getMechList();
                         debug("Prov: supported mechs = " + supportedMechs);
-                        for (UcryptoMech m : UcryptoMech.values()) {
-                            if (supportedMechs.indexOf(m.name() + ",") != -1) {
+                        StringTokenizer st = new StringTokenizer(supportedMechs, ":,;");
+                        // format: numOfSupportedMechs:[mechName,mechValue;]+
+                        // skip the first one which is numberOfSupportedMechs
+                        st.nextToken();
+                        while (st.hasMoreTokens()) {
+                            String mechName = st.nextToken();
+                            int nativeMechVal = Integer.parseInt(st.nextToken());
+                            try {
+                                UcryptoMech m = Enum.valueOf(UcryptoMech.class, mechName);
+                                m.setValue(nativeMechVal);
                                 ServiceDesc[] services = m.getServiceDescriptions();
-                                // skip unsupported UcryptoMech
-                                if (services == null || services.length == 0) continue;
+                                // defined in UcryptoMech as unsupported
+                                if (services == null || services.length == 0) {
+                                    debug("Skip Unsupported Algorithm: " + mechName);
+                                    continue;
+                                }
                                 for (int p = 0; p < services.length; p++) {
                                     ServiceDesc entry = services[p];
                                     provProp.put(entry.getType() + "." + entry.getAlgorithm(),
                                                  entry);
                                 }
+                            } catch (IllegalArgumentException iae) {
+                                // not defined in UcryptoMech
+                                debug("Skip Unrecognized Algorithm: " + mechName);
                             }
                         }
                         // NOTE: GCM support is only available since jdk 7
                         provProp.put("AlgorithmParameters.GCM",
-                                     sd("AlgorithmParameters", "GCM", "com.oracle.security.ucrypto.GCMParameters"));
+                                     sd("AlgorithmParameters", "GCM",
+                                        "com.oracle.security.ucrypto.GCMParameters"));
                     }
+                    // true when libmd is needed and has been successfully loaded
+                    if (result[0]) {
+                        for (LibMDMech m : LibMDMech.values()) {
+                            ServiceDesc[] services = m.getServiceDescriptions();
+                            for (ServiceDesc entry : services) {
+                                String sKey = entry.getType() + "." + entry.getAlgorithm();
+                                //  only register if none has been registered
+                                provProp.putIfAbsent(sKey, entry);
+                            }
+                        }
+                    };
                 } else {
                     debug("Prov: unexpected ucrypto library loading error, got " + result.length);
                 }
@@ -138,6 +143,7 @@
                   sd.getAliases(), null);
         }
 
+        @SuppressWarnings("deprecation")
         @Override
         public Object newInstance(Object ctrParamObj)
             throws NoSuchAlgorithmException {
@@ -152,53 +158,19 @@
                     int keySize = -1;
                     if (algo.charAt(3) == '_') {
                         keySize = Integer.parseInt(algo.substring(4, 7))/8;
-                        algo = algo.substring(0, 3) + algo.substring(7);
                     }
-                    if (algo.equals("AES/ECB/NoPadding")) {
-                        return new NativeCipher.AesEcbNoPadding(keySize);
-                    } else if (algo.equals("AES/ECB/PKCS5Padding")) {
-                        return new NativeCipherWithJavaPadding.AesEcbPKCS5();
-                    } else if (algo.equals("AES/CBC/NoPadding")) {
-                        return new NativeCipher.AesCbcNoPadding(keySize);
-                    } else if (algo.equals("AES/CBC/PKCS5Padding")) {
-                        return new NativeCipherWithJavaPadding.AesCbcPKCS5();
-                    } else if (algo.equals("AES/CTR/NoPadding")) {
-                        return new NativeCipher.AesCtrNoPadding();
-                    } else if (algo.equals("AES/GCM/NoPadding")) {
-                        return new NativeGCMCipher.AesGcmNoPadding(keySize);
-                    } else if (algo.equals("AES/CFB128/NoPadding")) {
-                        return new NativeCipher.AesCfb128NoPadding();
-                    } else if (algo.equals("AES/CFB128/PKCS5Padding")) {
-                        return new NativeCipherWithJavaPadding.AesCfb128PKCS5();
-                    } else if (algo.equals("RSA/ECB/NoPadding")) {
-                        return new NativeRSACipher.NoPadding();
-                    } else if (algo.equals("RSA/ECB/PKCS1Padding")) {
-                        return new NativeRSACipher.PKCS1Padding();
+                    String implClass = getClassName();
+                    Class<?> clz = Class.forName(implClass);
+                    if (keySize != -1) {
+                        Constructor<?> ctr = clz.getConstructor(int.class);
+                        return ctr.newInstance(keySize);
+                    } else {
+                        return clz.newInstance();
                     }
-                } else if (type.equals("Signature")) {
-                    if (algo.equals("SHA1withRSA")) {
-                        return new NativeRSASignature.SHA1();
-                    } else if (algo.equals("SHA256withRSA")) {
-                        return new NativeRSASignature.SHA256();
-                    } else if (algo.equals("SHA384withRSA")) {
-                        return new NativeRSASignature.SHA384();
-                    } else if (algo.equals("SHA512withRSA")) {
-                        return new NativeRSASignature.SHA512();
-                    } else if (algo.equals("MD5withRSA")) {
-                        return new NativeRSASignature.MD5();
-                    }
-                } else if (type.equals("MessageDigest")) {
-                    if (algo.equals("SHA")) {
-                        return new NativeDigest.SHA1();
-                    } else if (algo.equals("SHA-256")) {
-                        return new NativeDigest.SHA256();
-                    } else if (algo.equals("SHA-384")) {
-                        return new NativeDigest.SHA384();
-                    } else if (algo.equals("SHA-512")) {
-                        return new NativeDigest.SHA512();
-                    } else if (algo.equals("MD5")) {
-                        return new NativeDigest.MD5();
-                    }
+                } else if (type.equals("Signature") || type.equals("MessageDigest")) {
+                    String implClass = getClassName();
+                    Class<?> clz = Class.forName(implClass);
+                    return clz.newInstance();
                 } else if (type.equals("AlgorithmParameters")) {
                     if (algo.equals("GCM")) {
                         return new GCMParameters();
--- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/libsoftcrypto.h	Wed May 18 20:40:17 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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.
- */
-
-#ifndef _LIBSOFTCRYPTO_H
-#define _LIBSOFTCRYPTO_H
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <strings.h>
-
-typedef enum ucrypto_mech {
-    CRYPTO_AES_ECB = 1,
-    CRYPTO_AES_CBC,
-    CRYPTO_AES_CBC_PAD,
-    CRYPTO_AES_CTR,
-    CRYPTO_AES_CCM,
-    CRYPTO_AES_GCM,
-    CRYPTO_AES_GMAC,
-    CRYPTO_AES_CFB128,
-    CRYPTO_RSA_PKCS = 31,
-    CRYPTO_RSA_X_509,
-    CRYPTO_MD5_RSA_PKCS,
-    CRYPTO_SHA1_RSA_PKCS,
-    CRYPTO_SHA256_RSA_PKCS,
-    CRYPTO_SHA384_RSA_PKCS,
-    CRYPTO_SHA512_RSA_PKCS
-} ucrypto_mech_t;
-
-typedef struct crypto_ctx {
-    void *cc_provider;
-    uint_t    cc_session;
-    void            *cc_provider_private;    /* owned by provider */
-    void            *cc_framework_private;    /* owned by framework */
-    uint32_t        cc_flags;        /* flags */
-    void            *cc_opstate;        /* state */
-} crypto_ctx_t;
-
-extern int ucrypto_encrypt_init(crypto_ctx_t *context,
-    ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
-    void *iv, size_t iv_len);
-
-extern int ucrypto_encrypt_update(crypto_ctx_t *context, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-extern int ucrypto_encrypt_final(crypto_ctx_t *context, uchar_t *out,
-    size_t *out_len);
-
-/* Encrypt atomic */
-extern int ucrypto_encrypt(ucrypto_mech_t mech_type, uchar_t *key_str,
-    size_t key_len, void *iv, size_t iv_len, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-/* Decrypt multi-part */
-extern int ucrypto_decrypt_init(crypto_ctx_t *context,
-    ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
-    void *iv, size_t iv_len);
-
-extern int ucrypto_decrypt_update(crypto_ctx_t *context, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-extern int ucrypto_decrypt_final(crypto_ctx_t *context, uchar_t *out,
-    size_t *out_len);
-
-/* Decrypt atomic */
-extern int ucrypto_decrypt(ucrypto_mech_t mech_type, uchar_t *key_str,
-    size_t key_len, void *iv, size_t iv_len, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-/* Sign multi-part */
-extern int ucrypto_sign_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len);
-
-extern int ucrypto_sign_update(crypto_ctx_t *context,
-    uchar_t *data_str, size_t data_len);
-
-extern int ucrypto_sign_final(crypto_ctx_t *context,
-    uchar_t *sig_str, size_t *sig_len);
-
-/* Sign atomic */
-extern int ucrypto_sign(ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len,
-    uchar_t *data_str, size_t data_len, uchar_t *sig_str, size_t *sig_len);
-
-/* Verify multi-part */
-extern int ucrypto_verify_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len);
-
-extern int ucrypto_verify_update(crypto_ctx_t *context,
-    uchar_t *data_str, size_t data_len);
-
-extern int ucrypto_verify_final(crypto_ctx_t *context,
-    uchar_t *sig_str, size_t *sig_len);
-
-/* Verify atomic */
-extern int ucrypto_verify(ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len,
-    uchar_t *data_str, size_t data_len, uchar_t *sig, size_t *sig_len);
-
-extern int ucrypto_get_mechlist(char *str);
-
-extern const char *ucrypto_id2mech(ucrypto_mech_t mech_type);
-
-extern ucrypto_mech_t ucrypto_mech2id(const char *str);
-
-extern int ucrypto_version();
-
-typedef struct CK_AES_CTR_PARAMS {
-    ulong_t    ulCounterBits;
-    uint8_t cb[16];
-} CK_AES_CTR_PARAMS;
-
-typedef struct CK_AES_GCM_PARAMS {
-    uchar_t *pIv;
-    ulong_t ulIvLen;
-    ulong_t ulIvBits;
-    uchar_t *pAAD;
-    ulong_t ulAADLen;
-    ulong_t ulTagBits;
-} CK_AES_GCM_PARAMS;
-
-typedef struct crypto_object_attribute {
-    uint64_t    oa_type;    /* attribute type */
-    caddr_t            oa_value;    /* attribute value */
-    ssize_t            oa_value_len;    /* length of attribute value */
-} crypto_object_attribute_t;
-
-/* Attribute types to use for passing a RSA public key or a private key. */
-#define    SUN_CKA_MODULUS            0x00000120
-#define    SUN_CKA_MODULUS_BITS        0x00000121
-#define    SUN_CKA_PUBLIC_EXPONENT        0x00000122
-#define    SUN_CKA_PRIVATE_EXPONENT    0x00000123
-#define    SUN_CKA_PRIME_1            0x00000124
-#define    SUN_CKA_PRIME_2            0x00000125
-#define    SUN_CKA_EXPONENT_1        0x00000126
-#define    SUN_CKA_EXPONENT_2        0x00000127
-#define    SUN_CKA_COEFFICIENT        0x00000128
-#define    SUN_CKA_PRIME            0x00000130
-#define    SUN_CKA_SUBPRIME        0x00000131
-#define    SUN_CKA_BASE            0x00000132
-
-#define    CKK_EC            0x00000003
-#define    CKK_GENERIC_SECRET    0x00000010
-#define    CKK_RC4            0x00000012
-#define    CKK_AES            0x0000001F
-#define    CKK_DES            0x00000013
-#define    CKK_DES2        0x00000014
-#define    CKK_DES3        0x00000015
-
-#define    CKO_PUBLIC_KEY        0x00000002
-#define    CKO_PRIVATE_KEY        0x00000003
-#define    CKA_CLASS        0x00000000
-#define    CKA_VALUE        0x00000011
-#define    CKA_KEY_TYPE        0x00000100
-#define    CKA_VALUE_LEN        0x00000161
-#define    CKA_EC_PARAMS        0x00000180
-#define    CKA_EC_POINT        0x00000181
-
-#endif /* _LIBSOFTCRYPTO_H */
--- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c	Wed May 18 12:04:26 2016 -0700
@@ -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
@@ -35,6 +35,22 @@
 /*
  * Dumps out byte array in hex with and name and length info
  */
+void printError(char* header, int mech, int rv) {
+  if (mech != -1) {
+    printf("%s, mech = %d, rv = 0x%0x\n", header, mech, rv);
+  } else {
+    printf("%s, rv = 0x%0x\n", header, rv);
+  }
+  if (*ftab->ucryptoStrerror != NULL) {
+    char * reason = (*ftab->ucryptoStrerror)(rv);
+    printf("\tcause = %s\n", reason);
+    free(reason);
+  }
+}
+
+/*
+ * Dumps out byte array in hex with and name and length info
+ */
 void printBytes(char* header, unsigned char* bytes, int len) {
   int i;
 
@@ -60,6 +76,16 @@
   (*env)->DeleteLocalRef(env, jExClass);
 }
 
+/*
+ * De-allocates all memory associated with crypto_ctx_t
+ */
+void freeContext(crypto_ctx_t *context) {
+  if (ftab->ucryptoFreeContext != NULL) {
+    (*ftab->ucryptoFreeContext)(context);
+  }
+  free(context);
+}
+
 JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
     return JNI_VERSION_1_4;
 }
@@ -203,10 +229,10 @@
   }
   if (encrypt) {
     rv = (*ftab->ucryptoEncryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
-    if (rv != 0 && DEBUG) printf("ucryptoEncryptInit: ret = 0x%x\n", rv);
+    if (rv != 0 && DEBUG) printError("ucryptoEncryptInit", mech, rv);
   } else {
     rv =(*ftab->ucryptoDecryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
-    if (rv != 0 && DEBUG) printf("ucryptoDecryptInit: ret = 0x%x\n", rv);
+    if (rv != 0 && DEBUG) printError("ucryptoDecryptInit", mech, rv);
   }
 
   if (iv != jIv) {
@@ -234,15 +260,15 @@
   }
   if (encrypt) {
     rv = (*ftab->ucryptoEncryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoEncryptUpdate: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoEncryptUpdate", -1, rv);
     } else {
       *outLen = (int)outLength;
     }
   } else {
     rv = (*ftab->ucryptoDecryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoDecryptUpdate: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoDecryptUpdate", -1, rv);
     } else {
       if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
       *outLen = (int)outLength;
@@ -263,16 +289,16 @@
   if (DEBUG) printf("CipherFinal: OutOfs %i, outLen %i\n", outOfs, *outLen);
   if (encrypt) {
     rv = (*ftab->ucryptoEncryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoDecryptFinal", -1, rv);
     } else {
       if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
       *outLen = (int)outLength;
     }
   } else {
     rv = (*ftab->ucryptoDecryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoDecryptFinal", -1, rv);
     } else {
       if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
       *outLen = (int)outLength;
@@ -285,102 +311,61 @@
 // SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
 ////////////////////////////////////////////////////////
 jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit(jint mech) {
-  void *pContext = NULL;
+  crypto_ctx_t *context = NULL;
+  int rv;
 
-  switch (mech) {
-  case com_oracle_security_ucrypto_NativeDigest_MECH_SHA1:
-    pContext = (SHA1_CTX *) malloc(sizeof(SHA1_CTX));
-    if (pContext != NULL) {
-      (*ftab->sha1Init)((SHA1_CTX *)pContext);
+  context = malloc(sizeof(crypto_ctx_t));
+  if (context != NULL) {
+    rv = (*ftab->ucryptoDigestInit)(context, (ucrypto_mech_t) mech, NULL, 0);
+    if (rv) {
+      freeContext(context);
+      if (DEBUG) printError("ucryptoDigestInit", mech, rv);
+      return 0L;
     }
-    break;
-  case com_oracle_security_ucrypto_NativeDigest_MECH_MD5:
-    pContext = (MD5_CTX *) malloc(sizeof(MD5_CTX));
-    if (pContext != NULL) {
-      (*ftab->md5Init)((MD5_CTX *)pContext);
-    }
-    break;
-  case com_oracle_security_ucrypto_NativeDigest_MECH_SHA256:
-    pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
-    if (pContext != NULL) {
-      (*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext);
-    }
-    break;
-  case com_oracle_security_ucrypto_NativeDigest_MECH_SHA384:
-    pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
-    if (pContext != NULL) {
-      (*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext);
-    }
-    break;
-  case com_oracle_security_ucrypto_NativeDigest_MECH_SHA512:
-    pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
-    if (pContext != NULL) {
-      (*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext);
-    }
-    break;
-  default:
-    if (DEBUG) printf("ERROR: Unsupported mech %i\n", mech);
   }
-  return (jlong) pContext;
+  return (jlong) context;
 }
 
 jint JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
   (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
-  if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
-    (*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len);
-  } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
-    (*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len);
-  } else { // SHA-2 family
-    (*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  crypto_ctx_t *context;
+  jint rv = 0;
+
+  context = (crypto_ctx_t *) pContext;
+  rv = (*ftab->ucryptoDigestUpdate)(context, (const unsigned char*)(in + ofs),
+                                    (size_t) len);
+
+  if (rv) {
+    freeContext(context);
+    if (DEBUG) printError("ucryptoDigestUpdate", mech, rv);
   }
-  return 0;
+
+  return -rv; // use negative value to indicate error
 }
 
-// Do digest and free the context immediately
 jint JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest
   (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
+  crypto_ctx_t *context;
+  jint rv = 0;
+  size_t digest_len = digestLen;
 
-  if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
-    (*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext);
-    free((SHA1_CTX *)pContext);
-  } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
-    (*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext);
-    free((MD5_CTX *)pContext);
-  } else { // SHA-2 family
-    (*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext);
-    free((SHA2_CTX *)pContext);
+  context = (crypto_ctx_t *) pContext;
+  rv = (*ftab->ucryptoDigestFinal)(context, (unsigned char*)(out + ofs),
+                                   &digest_len);
+  if (rv) {
+    freeContext(context);
+    if (DEBUG) printError("ucryptoDigestFinal", mech, rv);
   }
-  return 0;
-}
 
-jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone
-  (jint mech, jlong pContext) {
-  void *copy = NULL;
-  size_t len = 0;
-
-  if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
-    len = sizeof(SHA1_CTX);
-  } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
-    len = sizeof(MD5_CTX);
-  } else { // SHA-2 family
-    len = sizeof(SHA2_CTX);
-  }
-  copy = (void*) malloc(len);
-  if (copy != NULL) {
-    bcopy((void *)pContext, copy, len);
-  }
-  return (jlong) copy;
+  return -rv; // use negative value to indicate error
 }
 
 void JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree
   (jint mech, jlong pContext) {
-  if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
-    free((SHA1_CTX*) pContext);
-  } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
-    free((MD5_CTX*) pContext);
-  } else { // SHA-2 family
-    free((SHA2_CTX*) pContext);
-  }
+  crypto_ctx_t *context;
+
+  context = (crypto_ctx_t *) pContext;
+  freeContext(context);
 }
 
 // AES
@@ -395,7 +380,7 @@
     rv = CipherInit(context, encrypt, (ucrypto_mech_t) mech, bufKey, keyLen,
                     bufIv, ivLen, tagLen, bufAad, aadLen);
     if (rv) {
-      free(context);
+      freeContext(context);
       return 0L;
     }
   }
@@ -417,8 +402,7 @@
   context = (crypto_ctx_t *) pContext;
   rv = CipherUpdate(context, encrypt, (unsigned char*)bufIn, inOfs, inLen, (unsigned char*)bufOut, outOfs, &outLen);
   if (rv) {
-    free(context);
-    context = 0;
+    freeContext(context);
     return -rv; // use negative value to indicate error!
   }
 
@@ -443,7 +427,7 @@
     outLen = 0;
   }
   rv = CipherFinal(context, encrypt, bufOut, outOfs, &outLen);
-  free(context);
+  freeContext(context);
   if (rv) {
      return -rv; // use negative value to indicate error!
   }
@@ -451,8 +435,6 @@
   return outLen;
 }
 
-
-
 /*
  * Class:     com_oracle_security_ucrypto_NativeDigest
  * Method:    nativeInit
@@ -475,13 +457,15 @@
 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
   unsigned char *bufIn;
+  jint rv = 0;
+
 
   bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
   if (!(*env)->ExceptionCheck(env)) {
-    JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
+    rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
     free(bufIn);
   }
-  return 0;
+  return rv;
 }
 
 /*
@@ -492,6 +476,7 @@
 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest
   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
   unsigned char *bufOut;
+  jint rv = 0;
 
   bufOut = (unsigned char *) malloc(digestLen);
   if (bufOut == NULL) {
@@ -499,21 +484,12 @@
     return 0;
   }
 
-  JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
-
-  (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
+  rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
+  if (rv == 0) {
+      (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
+  }
   free(bufOut);
-  return 0;
-}
-
-/*
- * Class:     com_oracle_security_ucrypto_NativeDigest
- * Method:    nativeClone
- * Signature: (IJ)J
- */
-JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeClone
-  (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
-  return JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone(mech, pContext);
+  return rv;
 }
 
 /*
@@ -582,7 +558,7 @@
 
 cleanup:
   if ((result == 0L) && (context != NULL)) {
-    free(context);
+    freeContext(context);
   }
   if (bufKey != NULL) {
     (*env)->ReleaseByteArrayElements(env, jKey, (jbyte *)bufKey, 0);
@@ -626,7 +602,7 @@
 
   rv = CipherUpdate(context, encrypt, bufIn, 0, inLen, bufOut, 0, &outLen);
   if (rv) {
-    free(context);
+    freeContext(context);
     free(bufIn);
     free(bufOut);
     return -rv;
@@ -683,6 +659,7 @@
   return rc;
 }
 
+
 /*
  * Class:     com_oracle_security_ucrypto_NativeKey
  * Method:    nativeFree
@@ -984,9 +961,9 @@
   }
 
   if (DEBUG) {
-    printf("RSAPublicKey Init: keyValue=%ld, keyLen=2\n", pKey);
-    printBytes("RSA PublicKey mod: ", (unsigned char*) mod, modLen);
-    printBytes("RSA PublicKey pubExp: ", (unsigned char*) pub, pubLen);
+    printf("RSAPublicKey.nativeInit: keyValue=%ld, keyLen=2\n", pKey);
+    printBytes("\tmod: ", (unsigned char*) mod, modLen);
+    printBytes("\tpubExp: ", (unsigned char*) pub, pubLen);
   }
 
   pKey[0].oa_type = SUN_CKA_MODULUS;
@@ -1062,7 +1039,7 @@
   if (DEBUG) {
     printf("SignatureInit: context=%ld, mech=%d, sign=%d, keyValue=%ld, keyLength=%d\n",
            context, mech, sign, pKey, keyLength);
-    printf("SignatureInit, ret =>  0x%x\n", rv);
+    printError("SignatureInit", mech, rv);
   }
   return rv;
 }
@@ -1083,7 +1060,7 @@
     pKey = (uchar_t *) jKey;
     rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
     if (rv) {
-      free(context);
+      freeContext(context);
       return 0L;
     }
   }
@@ -1105,7 +1082,7 @@
   pKey = (uchar_t *) jKey;
   rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
   if (rv) {
-    free(context);
+    freeContext(context);
     throwUCExceptionUsingRV(env, rv);
     return 0L;
   }
@@ -1125,7 +1102,7 @@
 
   context = (crypto_ctx_t *) pCtxt;
   if (DEBUG) {
-    printf("Signature update: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n",
+    printf("NativeRSASignature.nativeUpdate: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n",
            context, sign, jIn, jInOfs, jInLen);
   }
   if (sign) {
@@ -1133,9 +1110,9 @@
   } else {
     rv = (*ftab->ucryptoVerifyUpdate)(context, (uchar_t *) (jIn + jInOfs), (size_t) jInLen);
   }
-  if (DEBUG) printf("Signature update, ret =>  0x%x\n", rv);
   if (rv) {
-    free(context);
+    freeContext(context);
+    if (DEBUG) printError("NativeRSASignature.nativeUpdate", -1, rv);
     return -rv; // use negative value to indicate error!
   }
 
@@ -1194,9 +1171,9 @@
 
   context = (crypto_ctx_t *) pCtxt;
   if (DEBUG) {
-      printf("Signature final: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n",
+      printf("NativeRSASignature.nativeFinal: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n",
              context, sign, bufSig, sigOfs, jSigLen);
-      printBytes("Before Final: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
+      printBytes("Before: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
   }
   if (sign) {
     rv = (*ftab->ucryptoSignFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
@@ -1204,18 +1181,17 @@
     rv = (*ftab->ucryptoVerifyFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
   }
 
-  if (DEBUG) {
-    printf("Signature nativeFinal, ret =>  0x%x\n", rv);
-    if (sigLength != jSigLen) {
-      printf("SIG actual output len=%d\n", sigLength);
+  freeContext(context);
+  if (rv) {
+    if (DEBUG) {
+      printError("NativeRSASignature.nativeFinal", -1, rv);
+      if (sigLength != jSigLen) {
+        printf("NativeRSASignature.nativeFinal out sig len=%d\n", sigLength);
+      }
+      if (sign) {
+        printBytes("After: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
+      }
     }
-    if (sign) {
-      printBytes("After nativeFinal: ", (unsigned char*) (bufSig + sigOfs), jSigLen);
-    }
-  }
-
-  free(context);
-  if (rv) {
     return -rv;
   } else return 0;
 }
@@ -1273,10 +1249,10 @@
 
   pKey = (uchar_t *) keyValue;
   if (DEBUG) {
-    printf("Cipher nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n",
+    printf("NativeRSACipher.nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n",
            mech, encrypt, pKey, keyLength);
-    printBytes("Before nativeAtomic: in: ", (unsigned char*) bufIn, jInLen);
-    printBytes("Before nativeAtomic: out: ", (unsigned char*) (bufOut + jOutOfs), jOutLen);
+    printBytes("Before: in  = ", (unsigned char*) bufIn, jInLen);
+    printBytes("Before: out = ", (unsigned char*) (bufOut + jOutOfs), jOutLen);
   }
 
   if (encrypt) {
@@ -1289,11 +1265,11 @@
       (uchar_t *)(bufOut + jOutOfs), &outLength);
   }
   if (DEBUG) {
-    printf("Cipher nativeAtomic, ret =>  0x%x\n", rv);
+    printError("NativeRSACipher.nativeAtomic", mech, rv);
     if (outLength != jOutLen) {
-      printf("CIP actual output len=%d\n", outLength);
+      printf("NativeRSACipher.nativeAtomic out len=%d\n", outLength);
     }
-    printBytes("After nativeAtomic: ", (unsigned char*) (bufOut + jOutOfs), outLength);
+    printBytes("After: ", (unsigned char*) (bufOut + jOutOfs), outLength);
   }
 
   if (rv) {
--- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 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
@@ -29,18 +29,18 @@
 extern "C" {
 #endif
 
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_MD5
-#define com_oracle_security_ucrypto_NativeDigest_MECH_MD5 1L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA1
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA1 2L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA256
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA256 3L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA224
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA224 4L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA384
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA384 5L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA512
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA512 6L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5 1L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1 2L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256 3L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA224
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA224 4L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384 5L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512 6L
 
 #define DEBUG 0
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c	Wed May 18 12:04:26 2016 -0700
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <jni.h>
+#include "jni_util.h"
+#include <libsoftcrypto.h>
+#include "nativeCrypto.h"
+#include "nativeFunc.h"
+
+
+extern void throwOutOfMemoryError(JNIEnv *env, const char *msg);
+extern jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len);
+
+///////////////////////////////////////////////////////
+// SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
+////////////////////////////////////////////////////////
+jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(jint mech) {
+  void *pContext = NULL;
+
+  switch (mech) {
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1:
+    pContext = malloc(sizeof(SHA1_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha1Init)((SHA1_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5:
+    pContext = malloc(sizeof(MD5_CTX));
+    if (pContext != NULL) {
+      (*ftab->md5Init)((MD5_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256:
+    pContext = malloc(sizeof(SHA2_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384:
+    pContext = malloc(sizeof(SHA2_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512:
+    pContext = malloc(sizeof(SHA2_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext);
+    }
+    break;
+  default:
+    if (DEBUG) printf("ERROR: Unsupported mech %i\n", mech);
+  }
+  return (jlong) pContext;
+}
+
+jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
+  (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    (*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    (*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  } else { // SHA-2 family
+    (*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  }
+  return 0;
+}
+
+// Do digest and free the context immediately
+jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
+  (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
+
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    (*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext);
+    free((SHA1_CTX *)pContext);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    (*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext);
+    free((MD5_CTX *)pContext);
+  } else { // SHA-2 family
+    (*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext);
+    free((SHA2_CTX *)pContext);
+  }
+  return 0;
+}
+
+jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
+  (jint mech, jlong pContext) {
+  void *copy = NULL;
+  size_t len = 0;
+
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    len = sizeof(SHA1_CTX);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    len = sizeof(MD5_CTX);
+  } else { // SHA-2 family
+    len = sizeof(SHA2_CTX);
+  }
+  copy = malloc(len);
+  if (copy != NULL) {
+    bcopy((void *)pContext, copy, len);
+  }
+  return (jlong) copy;
+}
+
+void JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
+  (jint mech, jlong pContext) {
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    free((SHA1_CTX*) pContext);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    free((MD5_CTX*) pContext);
+  } else { // SHA-2 family
+    free((SHA2_CTX*) pContext);
+  }
+}
+
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeInit
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit
+  (JNIEnv *env, jclass jcls, jint mech) {
+  jlong result = JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(mech);
+  if (result == NULL) {
+     throwOutOfMemoryError(env, NULL);
+  }
+  return result;
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeUpdate
+ * Signature: (IJ[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
+  unsigned char *bufIn;
+
+  bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
+  if (!(*env)->ExceptionCheck(env)) {
+    JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
+    free(bufIn);
+  }
+  return 0;
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeDigest
+ * Signature: (IJ[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
+  unsigned char *bufOut;
+
+  bufOut = (unsigned char *) malloc(digestLen);
+  if (bufOut == NULL) {
+    throwOutOfMemoryError(env, NULL);
+    return 0;
+  }
+
+  JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
+
+  (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
+  free(bufOut);
+  return 0;
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeClone
+ * Signature: (IJ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
+  return JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone(mech, pContext);
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeFree
+ * Signature: (IJ)V
+ */
+JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
+  JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree(mech, pContext);
+}
+
--- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 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,21 +42,33 @@
 static const char SHA2_FINAL[]                   = "SHA2Final";
 static const char UCRYPTO_VERSION[]              = "ucrypto_version";
 static const char UCRYPTO_GET_MECHLIST[]         = "ucrypto_get_mechlist";
+
 static const char UCRYPTO_ENCRYPT_INIT[]         = "ucrypto_encrypt_init";
 static const char UCRYPTO_ENCRYPT_UPDATE[]       = "ucrypto_encrypt_update";
 static const char UCRYPTO_ENCRYPT_FINAL[]        = "ucrypto_encrypt_final";
 static const char UCRYPTO_ENCRYPT[]              = "ucrypto_encrypt";
+
 static const char UCRYPTO_DECRYPT_INIT[]         = "ucrypto_decrypt_init";
 static const char UCRYPTO_DECRYPT_UPDATE[]       = "ucrypto_decrypt_update";
 static const char UCRYPTO_DECRYPT_FINAL[]        = "ucrypto_decrypt_final";
 static const char UCRYPTO_DECRYPT[]              = "ucrypto_decrypt";
+
 static const char UCRYPTO_SIGN_INIT[]            = "ucrypto_sign_init";
 static const char UCRYPTO_SIGN_UPDATE[]          = "ucrypto_sign_update";
 static const char UCRYPTO_SIGN_FINAL[]           = "ucrypto_sign_final";
+
 static const char UCRYPTO_VERIFY_INIT[]          = "ucrypto_verify_init";
 static const char UCRYPTO_VERIFY_UPDATE[]        = "ucrypto_verify_update";
 static const char UCRYPTO_VERIFY_FINAL[]         = "ucrypto_verify_final";
 
+static const char UCRYPTO_DIGEST_INIT[]          = "ucrypto_digest_init";
+static const char UCRYPTO_DIGEST_UPDATE[]        = "ucrypto_digest_update";
+static const char UCRYPTO_DIGEST_FINAL[]         = "ucrypto_digest_final";
+
+static const char UCRYPTO_FREE_CONTEXT[]         = "ucrypto_free_context";
+
+static const char UCRYPTO_STRERROR[]             = "ucrypto_strerror";
+
 /**
  * Initialize native T4 crypto function pointers
  */
@@ -73,28 +85,6 @@
     return NULL;
   }
 
-  lib = dlopen("libmd.so", RTLD_NOW);
-  if (lib != NULL) {
-    ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT);
-    ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE);
-    ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL);
-    ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT);
-    ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE);
-    ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL);
-    ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT);
-    ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE);
-    ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL);
-    if (ftab->md5Init != NULL && ftab->md5Update != NULL &&
-        ftab->md5Final != NULL && ftab->sha1Init != NULL &&
-        ftab->sha1Update != NULL && ftab->sha1Final != NULL &&
-        ftab->sha2Init != NULL && ftab->sha2Update != NULL &&
-        ftab->sha2Final != NULL) {
-      buf[0] = JNI_TRUE;
-    } else {
-      dlclose(lib);
-    }
-  }
-
   lib = dlopen("libsoftcrypto.so", RTLD_NOW);
   if (lib != NULL) {
     // These APIs aren't available for v0 lib on Solaris 10
@@ -102,7 +92,6 @@
       dlsym(lib, UCRYPTO_VERSION);
     ftab->ucryptoGetMechList = (UCRYPTO_GET_MECHLIST_FN_PTR)
       dlsym(lib, UCRYPTO_GET_MECHLIST);
-    //??
     ftab->ucryptoSignInit = (UCRYPTO_SIGN_INIT_FN_PTR)
       dlsym(lib, UCRYPTO_SIGN_INIT);
     ftab->ucryptoSignUpdate = (UCRYPTO_SIGN_UPDATE_FN_PTR)
@@ -116,6 +105,21 @@
     ftab->ucryptoVerifyFinal = (UCRYPTO_VERIFY_FINAL_FN_PTR)
       dlsym(lib, UCRYPTO_VERIFY_FINAL);
 
+    // These APS are added starting S12
+    ftab->ucryptoDigestInit = (UCRYPTO_DIGEST_INIT_FN_PTR)
+      dlsym(lib, UCRYPTO_DIGEST_INIT);
+    ftab->ucryptoDigestUpdate = (UCRYPTO_DIGEST_UPDATE_FN_PTR)
+      dlsym(lib, UCRYPTO_DIGEST_UPDATE);
+    ftab->ucryptoDigestFinal = (UCRYPTO_DIGEST_FINAL_FN_PTR)
+      dlsym(lib, UCRYPTO_DIGEST_FINAL);
+
+    ftab->ucryptoFreeContext = (UCRYPTO_FREE_CONTEXT_FN_PTR)
+      dlsym(lib, UCRYPTO_FREE_CONTEXT);
+
+    ftab->ucryptoStrerror = (UCRYPTO_STRERROR_FN_PTR)
+      dlsym(lib, UCRYPTO_STRERROR);
+
+
     // These should be avilable for all libsoftcrypto libs
     ftab->ucryptoEncryptInit = (UCRYPTO_ENCRYPT_INIT_FN_PTR)
       dlsym(lib, UCRYPTO_ENCRYPT_INIT);
@@ -147,6 +151,34 @@
     } else {
       dlclose(lib);
     }
+
+    // proceed with libmd when libucrypto does not support digest operations
+    if (ftab->ucryptoDigestInit == NULL ||
+        ftab->ucryptoDigestUpdate == NULL ||
+        ftab->ucryptoDigestFinal == NULL) {
+
+      lib = dlopen("libmd.so", RTLD_NOW);
+      if (lib != NULL) {
+        ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT);
+        ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE);
+        ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL);
+        ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT);
+        ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE);
+        ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL);
+        ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT);
+        ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE);
+        ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL);
+        if (ftab->md5Init != NULL && ftab->md5Update != NULL &&
+            ftab->md5Final != NULL && ftab->sha1Init != NULL &&
+            ftab->sha1Update != NULL && ftab->sha1Final != NULL &&
+            ftab->sha2Init != NULL && ftab->sha2Update != NULL &&
+            ftab->sha2Final != NULL) {
+          buf[0] = JNI_TRUE;
+        } else {
+          dlclose(lib);
+        }
+      }
+    }
   }
 
   return buf;
--- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h	Wed May 18 12:04:26 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 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
@@ -69,15 +69,12 @@
      (crypto_ctx_t *context, ucrypto_mech_t mech_type,
       uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_ENCRYPT_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *in,
       size_t in_len, uchar_t *out, size_t *out_len);
-
 typedef int (*UCRYPTO_ENCRYPT_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *out,
       size_t *out_len);
-
 typedef int (*UCRYPTO_ENCRYPT_FN_PTR)
      (ucrypto_mech_t mech_type, uchar_t *key_str,
       size_t key_len, void *iv, size_t iv_len, uchar_t *in,
@@ -87,15 +84,12 @@
      (crypto_ctx_t *context,
       ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_DECRYPT_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *in,
       size_t in_len, uchar_t *out, size_t *out_len);
-
 typedef int (*UCRYPTO_DECRYPT_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *out,
       size_t *out_len);
-
 typedef int (*UCRYPTO_DECRYPT_FN_PTR)
      (ucrypto_mech_t mech_type, uchar_t *key_str,
       size_t key_len, void *iv, size_t iv_len, uchar_t *in,
@@ -105,10 +99,8 @@
      (crypto_ctx_t *context, ucrypto_mech_t mech_type,
       uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_SIGN_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *data_str, size_t data_len);
-
 typedef int (*UCRYPTO_SIGN_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len);
 
@@ -116,13 +108,24 @@
      (crypto_ctx_t *context, ucrypto_mech_t mech_type,
       uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_VERIFY_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *data_str, size_t data_len);
-
 typedef int (*UCRYPTO_VERIFY_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len);
 
+typedef int (*UCRYPTO_DIGEST_INIT_FN_PTR)
+     (crypto_ctx_t *context, ucrypto_mech_t mech_type,
+      void *param, size_t param_len);
+typedef int (*UCRYPTO_DIGEST_UPDATE_FN_PTR)
+     (crypto_ctx_t *context, const uchar_t *data, size_t data_len);
+typedef int (*UCRYPTO_DIGEST_FINAL_FN_PTR)
+     (crypto_ctx_t *context, uchar_t *digest, size_t *digest_len);
+
+typedef void (*UCRYPTO_FREE_CONTEXT_FN_PTR)
+     (crypto_ctx_t *context);
+
+typedef char* (*UCRYPTO_STRERROR_FN_PTR)(int rv);
+
 
 
 /* dynamically resolved functions from libmd, and libsoftcrypto
@@ -153,6 +156,11 @@
   UCRYPTO_VERIFY_INIT_FN_PTR     ucryptoVerifyInit;
   UCRYPTO_VERIFY_UPDATE_FN_PTR   ucryptoVerifyUpdate;
   UCRYPTO_VERIFY_FINAL_FN_PTR    ucryptoVerifyFinal;
+  UCRYPTO_DIGEST_INIT_FN_PTR     ucryptoDigestInit;
+  UCRYPTO_DIGEST_UPDATE_FN_PTR   ucryptoDigestUpdate;
+  UCRYPTO_DIGEST_FINAL_FN_PTR    ucryptoDigestFinal;
+  UCRYPTO_FREE_CONTEXT_FN_PTR    ucryptoFreeContext;
+  UCRYPTO_STRERROR_FN_PTR        ucryptoStrerror;
 } T4CRYPTO_FUNCTION_TABLE;
 
 typedef T4CRYPTO_FUNCTION_TABLE *T4CRYPTO_FUNCTION_TABLE_PTR;
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java	Wed May 18 12:04:26 2016 -0700
@@ -2498,6 +2498,12 @@
                     //ignore
                 }
 
+                if (o instanceof Runnable) {
+                    ((Runnable) o).run();
+                    sb.setLength(0);
+                    continue;
+                }
+
                 // Search mode.
                 //
                 // Note that we have to do this first, because if there is a command
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java	Wed May 18 12:04:26 2016 -0700
@@ -0,0 +1,418 @@
+/*
+ * 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.  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.jline.extra;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.function.Supplier;
+
+import jdk.internal.jline.console.ConsoleReader;
+import jdk.internal.jline.console.KeyMap;
+import jdk.internal.jline.console.history.History;
+import jdk.internal.jline.console.history.History.Entry;
+import jdk.internal.jline.console.history.MemoryHistory;
+
+/*Public for tests (HistoryTest).
+ */
+public abstract class EditingHistory implements History {
+
+    private final History fullHistory;
+    private History currentDelegate;
+
+    protected EditingHistory(ConsoleReader in, Iterable<? extends String> originalHistory) {
+        this.fullHistory = new MemoryHistory();
+        this.currentDelegate = fullHistory;
+        bind(in, CTRL_UP,
+             (Runnable) () -> moveHistoryToSnippet(in, ((EditingHistory) in.getHistory())::previousSnippet));
+        bind(in, CTRL_DOWN,
+             (Runnable) () -> moveHistoryToSnippet(in, ((EditingHistory) in.getHistory())::nextSnippet));
+        load(originalHistory);
+    }
+
+    private void moveHistoryToSnippet(ConsoleReader in, Supplier<Boolean> action) {
+        if (!action.get()) {
+            try {
+                in.beep();
+            } catch (IOException ex) {
+                throw new IllegalStateException(ex);
+            }
+        } else {
+            try {
+                //could use:
+                //in.resetPromptLine(in.getPrompt(), in.getHistory().current().toString(), -1);
+                //but that would mean more re-writing on the screen, (and prints an additional
+                //empty line), so using setBuffer directly:
+                Method setBuffer = in.getClass().getDeclaredMethod("setBuffer", String.class);
+
+                setBuffer.setAccessible(true);
+                setBuffer.invoke(in, in.getHistory().current().toString());
+                in.flush();
+            } catch (ReflectiveOperationException | IOException ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+    }
+
+    private void bind(ConsoleReader in, String shortcut, Object action) {
+        KeyMap km = in.getKeys();
+        for (int i = 0; i < shortcut.length(); i++) {
+            Object value = km.getBound(Character.toString(shortcut.charAt(i)));
+            if (value instanceof KeyMap) {
+                km = (KeyMap) value;
+            } else {
+                km.bind(shortcut.substring(i), action);
+            }
+        }
+    }
+
+    private static final String CTRL_UP = "\033\133\061\073\065\101"; //Ctrl-UP
+    private static final String CTRL_DOWN = "\033\133\061\073\065\102"; //Ctrl-DOWN
+
+    @Override
+    public int size() {
+        return currentDelegate.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return currentDelegate.isEmpty();
+    }
+
+    @Override
+    public int index() {
+        return currentDelegate.index();
+    }
+
+    @Override
+    public void clear() {
+        if (currentDelegate != fullHistory)
+            throw new IllegalStateException("narrowed");
+        currentDelegate.clear();
+    }
+
+    @Override
+    public CharSequence get(int index) {
+        return currentDelegate.get(index);
+    }
+
+    @Override
+    public void add(CharSequence line) {
+        NarrowingHistoryLine currentLine = null;
+        int origIndex = fullHistory.index();
+        int fullSize;
+        try {
+            fullHistory.moveToEnd();
+            fullSize = fullHistory.index();
+            if (currentDelegate == fullHistory) {
+                if (origIndex < fullHistory.index()) {
+                    for (Entry entry : fullHistory) {
+                        if (!(entry.value() instanceof NarrowingHistoryLine))
+                            continue;
+                        int[] cluster = ((NarrowingHistoryLine) entry.value()).span;
+                        if (cluster[0] == origIndex && cluster[1] > cluster[0]) {
+                            currentDelegate = new MemoryHistory();
+                            for (int i = cluster[0]; i <= cluster[1]; i++) {
+                                currentDelegate.add(fullHistory.get(i));
+                            }
+                        }
+                    }
+                }
+            }
+            fullHistory.moveToEnd();
+            while (fullHistory.previous()) {
+                CharSequence c = fullHistory.current();
+                if (c instanceof NarrowingHistoryLine) {
+                    currentLine = (NarrowingHistoryLine) c;
+                    break;
+                }
+            }
+        } finally {
+            fullHistory.moveTo(origIndex);
+        }
+        if (currentLine == null || currentLine.span[1] != (-1)) {
+            line = currentLine = new NarrowingHistoryLine(line, fullSize);
+        }
+        StringBuilder complete = new StringBuilder();
+        for (int i = currentLine.span[0]; i < fullSize; i++) {
+            complete.append(fullHistory.get(i));
+        }
+        complete.append(line);
+        if (isComplete(complete)) {
+            currentLine.span[1] = fullSize; //TODO: +1?
+            currentDelegate = fullHistory;
+        }
+        fullHistory.add(line);
+    }
+
+    protected abstract boolean isComplete(CharSequence input);
+
+    @Override
+    public void set(int index, CharSequence item) {
+        if (currentDelegate != fullHistory)
+            throw new IllegalStateException("narrowed");
+        currentDelegate.set(index, item);
+    }
+
+    @Override
+    public CharSequence remove(int i) {
+        if (currentDelegate != fullHistory)
+            throw new IllegalStateException("narrowed");
+        return currentDelegate.remove(i);
+    }
+
+    @Override
+    public CharSequence removeFirst() {
+        if (currentDelegate != fullHistory)
+            throw new IllegalStateException("narrowed");
+        return currentDelegate.removeFirst();
+    }
+
+    @Override
+    public CharSequence removeLast() {
+        if (currentDelegate != fullHistory)
+            throw new IllegalStateException("narrowed");
+        return currentDelegate.removeLast();
+    }
+
+    @Override
+    public void replace(CharSequence item) {
+        if (currentDelegate != fullHistory)
+            throw new IllegalStateException("narrowed");
+        currentDelegate.replace(item);
+    }
+
+    @Override
+    public ListIterator<Entry> entries(int index) {
+        return currentDelegate.entries(index);
+    }
+
+    @Override
+    public ListIterator<Entry> entries() {
+        return currentDelegate.entries();
+    }
+
+    @Override
+    public Iterator<Entry> iterator() {
+        return currentDelegate.iterator();
+    }
+
+    @Override
+    public CharSequence current() {
+        return currentDelegate.current();
+    }
+
+    @Override
+    public boolean previous() {
+        return currentDelegate.previous();
+    }
+
+    @Override
+    public boolean next() {
+        return currentDelegate.next();
+    }
+
+    @Override
+    public boolean moveToFirst() {
+        return currentDelegate.moveToFirst();
+    }
+
+    @Override
+    public boolean moveToLast() {
+        return currentDelegate.moveToLast();
+    }
+
+    @Override
+    public boolean moveTo(int index) {
+        return currentDelegate.moveTo(index);
+    }
+
+    @Override
+    public void moveToEnd() {
+        currentDelegate.moveToEnd();
+    }
+
+    public boolean previousSnippet() {
+        for (int i = index() - 1; i >= 0; i--) {
+            if (get(i) instanceof NarrowingHistoryLine) {
+                moveTo(i);
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public boolean nextSnippet() {
+        for (int i = index() + 1; i < size(); i++) {
+            if (get(i) instanceof NarrowingHistoryLine) {
+                moveTo(i);
+                return true;
+            }
+        }
+
+        if (index() < size()) {
+            moveToEnd();
+            return true;
+        }
+
+        return false;
+    }
+
+    public final void load(Iterable<? extends String> originalHistory) {
+        NarrowingHistoryLine currentHistoryLine = null;
+        boolean start = true;
+        int currentLine = 0;
+        for (String historyItem : originalHistory) {
+            StringBuilder line = new StringBuilder(historyItem);
+            int trailingBackSlashes = countTrailintBackslashes(line);
+            boolean continuation = trailingBackSlashes % 2 != 0;
+            line.delete(line.length() - trailingBackSlashes / 2 - (continuation ? 1 : 0), line.length());
+            if (start) {
+                class PersistentNarrowingHistoryLine extends NarrowingHistoryLine implements PersistentEntryMarker {
+                    public PersistentNarrowingHistoryLine(CharSequence delegate, int start) {
+                        super(delegate, start);
+                    }
+                }
+                fullHistory.add(currentHistoryLine = new PersistentNarrowingHistoryLine(line, currentLine));
+            } else {
+                class PersistentLine implements CharSequence, PersistentEntryMarker {
+                    private final CharSequence delegate;
+                    public PersistentLine(CharSequence delegate) {
+                        this.delegate = delegate;
+                    }
+                    @Override public int length() {
+                        return delegate.length();
+                    }
+                    @Override public char charAt(int index) {
+                        return delegate.charAt(index);
+                    }
+                    @Override public CharSequence subSequence(int start, int end) {
+                        return delegate.subSequence(start, end);
+                    }
+                    @Override public String toString() {
+                        return delegate.toString();
+                    }
+                }
+                fullHistory.add(new PersistentLine(line));
+            }
+            start = !continuation;
+            currentHistoryLine.span[1] = currentLine;
+            currentLine++;
+        }
+    }
+
+    public Collection<? extends String> save() {
+        Collection<String> result = new ArrayList<>();
+        Iterator<Entry> entries = fullHistory.iterator();
+
+        if (entries.hasNext()) {
+            Entry entry = entries.next();
+            while (entry != null) {
+                StringBuilder historyLine = new StringBuilder(entry.value());
+                int trailingBackSlashes = countTrailintBackslashes(historyLine);
+                for (int i = 0; i < trailingBackSlashes; i++) {
+                    historyLine.append("\\");
+                }
+                entry = entries.hasNext() ? entries.next() : null;
+                if (entry != null && !(entry.value() instanceof NarrowingHistoryLine)) {
+                    historyLine.append("\\");
+                }
+                result.add(historyLine.toString());
+            }
+        }
+
+        return result;
+    }
+
+    private int countTrailintBackslashes(CharSequence text) {
+        int count = 0;
+
+        for (int i = text.length() - 1; i >= 0; i--) {
+            if (text.charAt(i) == '\\') {
+                count++;
+            } else {
+                break;
+            }
+        }
+
+        return count;
+    }
+
+    public List<String> currentSessionEntries() {
+        List<String> result = new ArrayList<>();
+
+        for (Entry e : fullHistory) {
+            if (!(e.value() instanceof PersistentEntryMarker)) {
+                result.add(e.value().toString());
+            }
+        }
+
+        return result;
+    }
+
+    public void fullHistoryReplace(String source) {
+        fullHistory.replace(source);
+    }
+
+    private class NarrowingHistoryLine implements CharSequence {
+        private final CharSequence delegate;
+        private final int[] span;
+
+        public NarrowingHistoryLine(CharSequence delegate, int start) {
+            this.delegate = delegate;
+            this.span = new int[] {start, -1};
+        }
+
+        @Override
+        public int length() {
+            return delegate.length();
+        }
+
+        @Override
+        public char charAt(int index) {
+            return delegate.charAt(index);
+        }
+
+        @Override
+        public CharSequence subSequence(int start, int end) {
+            return delegate.subSequence(start, end);
+        }
+
+        @Override
+        public String toString() {
+            return delegate.toString();
+        }
+
+    }
+
+    private interface PersistentEntryMarker {}
+}
+
--- a/src/jdk.internal.le/share/classes/module-info.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.internal.le/share/classes/module-info.java	Wed May 18 12:04:26 2016 -0700
@@ -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
@@ -36,6 +36,9 @@
     exports jdk.internal.jline.console.history to
         jdk.scripting.nashorn.shell,
         jdk.jshell;
+    exports jdk.internal.jline.extra to
+        jdk.scripting.nashorn.shell,
+        jdk.jshell;
     exports jdk.internal.jline.internal to
         jdk.scripting.nashorn.shell,
         jdk.jshell;
--- a/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java	Wed May 18 20:40:17 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +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.vm.agent.spi;
-
-/**
- * Service interface for jdk.hotspot.agent to provide the tools that
- * jstack, jmap, jinfo will invoke, if present.
- */
-public interface ToolProvider {
-    /**
-     * Returns the name of the tool provider
-     */
-    String getName();
-
-    /**
-     * Invoke the tool provider with the given arguments
-     */
-    void run(String... arguments);
-}
--- a/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java	Wed May 18 20:40:17 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +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.vm.agent.spi;
-
-import java.lang.reflect.Layer;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.ServiceLoader;
-
-public final class ToolProviderFinder {
-    private static final Map<String, ToolProvider> providers = init();
-
-    public static ToolProvider find(String name) {
-        return providers.get(name);
-    }
-
-    private static Map<String, ToolProvider> init() {
-        Map<String, ToolProvider> providers = new HashMap<>();
-        ServiceLoader.load(Layer.boot(), ToolProvider.class)
-                     .forEach(p -> providers.putIfAbsent(p.getName(), p));
-        return providers;
-    }
-}
--- a/src/jdk.jcmd/share/classes/module-info.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.jcmd/share/classes/module-info.java	Wed May 18 12:04:26 2016 -0700
@@ -26,9 +26,4 @@
 module jdk.jcmd {
     requires jdk.attach;
     requires jdk.jvmstat;
-
-    exports jdk.internal.vm.agent.spi to jdk.hotspot.agent;
-
-    uses jdk.internal.vm.agent.spi.ToolProvider;
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java	Wed May 18 12:04:26 2016 -0700
@@ -0,0 +1,128 @@
+/*
+ * 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 sun.tools.common;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.VirtualMachineDescriptor;
+
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredHost;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.MonitoredVmUtil;
+import sun.jvmstat.monitor.VmIdentifier;
+
+/**
+ * Class for finding process matching a process argument,
+ * excluding tool it self and returning a list containing
+ * the process identifiers.
+ */
+public class ProcessArgumentMatcher {
+    private String excludeCls;
+    private String matchClass = null;
+    private String singlePid = null;
+    private boolean matchAll = false;
+
+    public ProcessArgumentMatcher(String pidArg, Class<?> excludeClass) {
+        excludeCls = excludeClass.getName();
+        if (pidArg == null || pidArg.isEmpty()) {
+            throw new IllegalArgumentException("Pid string is invalid");
+        }
+        if (pidArg.charAt(0) == '-') {
+            throw new IllegalArgumentException("Unrecognized " + pidArg);
+        }
+        try {
+            long pid = Long.parseLong(pidArg);
+            if (pid == 0) {
+                matchAll = true;
+            } else {
+                singlePid = String.valueOf(pid);
+            }
+        } catch (NumberFormatException nfe) {
+            matchClass = pidArg;
+        }
+    }
+
+    private boolean check(VirtualMachineDescriptor vmd) {
+        String mainClass = null;
+        try {
+            VmIdentifier vmId = new VmIdentifier(vmd.id());
+            MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId);
+            MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1);
+            mainClass = MonitoredVmUtil.mainClass(monitoredVm, true);
+            monitoredHost.detach(monitoredVm);
+        } catch (NullPointerException npe) {
+            // There is a potential race, where a running java app is being
+            // queried, unfortunately the java app has shutdown after this
+            // method is started but before getMonitoredVM is called.
+            // If this is the case, then the /tmp/hsperfdata_xxx/pid file
+            // will have disappeared and we will get a NullPointerException.
+            // Handle this gracefully....
+            return false;
+        } catch (MonitorException | URISyntaxException e) {
+            if (e.getMessage() != null) {
+                System.err.println(e.getMessage());
+            } else {
+                Throwable cause = e.getCause();
+                if ((cause != null) && (cause.getMessage() != null)) {
+                    System.err.println(cause.getMessage());
+                } else {
+                    e.printStackTrace();
+                }
+            }
+            return false;
+        }
+
+        if (mainClass.equals(excludeCls)) {
+            return false;
+        }
+
+        if (matchAll || mainClass.indexOf(matchClass) != -1) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public Collection<String> getPids() {
+        Collection<String> pids = new ArrayList<>();
+        if (singlePid != null) {
+            pids.add(singlePid);
+            return pids;
+        }
+        List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
+        for (VirtualMachineDescriptor vmd : vmds) {
+            if (check(vmd)) {
+                pids.add(vmd.id());
+            }
+        }
+        return pids;
+    }
+}
--- a/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java	Wed May 18 12:04:26 2016 -0700
@@ -33,16 +33,14 @@
     private boolean listProcesses = false;
     private boolean listCounters  = false;
     private boolean showUsage     = false;
-    private int     pid           = -1;
     private String  command       = null;
-    private String  processSubstring;
+    private String  processString = null;
 
     public boolean isListProcesses() { return listProcesses; }
     public boolean isListCounters() { return listCounters; }
     public boolean isShowUsage() { return showUsage; }
-    public int getPid() { return pid; }
     public String getCommand() { return command; }
-    public String getProcessSubstring() { return processSubstring; }
+    public String getProcessString() { return processString; }
 
     public Arguments(String[] args) {
         if (args.length == 0 || args[0].equals("-l")) {
@@ -55,15 +53,7 @@
             return;
         }
 
-        try {
-            pid = Integer.parseInt(args[0]);
-        } catch (NumberFormatException ex) {
-            // use as a partial class-name instead
-            if (args[0].charAt(0) != '-') {
-                // unless it starts with a '-'
-                processSubstring = args[0];
-            }
-        }
+        processString = args[0];
 
         StringBuilder sb = new StringBuilder();
         for (int i = 1; i < args.length; i++) {
--- a/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java	Wed May 18 12:04:26 2016 -0700
@@ -29,22 +29,22 @@
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.List;
-import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.net.URISyntaxException;
 
 import com.sun.tools.attach.AttachOperationFailedException;
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.VirtualMachineDescriptor;
-import com.sun.tools.attach.AgentLoadException;
 import com.sun.tools.attach.AttachNotSupportedException;
 
 import sun.tools.attach.HotSpotVirtualMachine;
+import sun.tools.common.ProcessArgumentMatcher;
 import sun.tools.jstat.JStatLogger;
 import sun.jvmstat.monitor.Monitor;
 import sun.jvmstat.monitor.MonitoredHost;
 import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.MonitoredVmUtil;
 import sun.jvmstat.monitor.MonitorException;
 import sun.jvmstat.monitor.VmIdentifier;
 
@@ -73,52 +73,18 @@
             System.exit(0);
         }
 
-        List<String> pids = new ArrayList<String>();
-        if (arg.getPid() == 0) {
-            // find all VMs
-            List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
-            for (VirtualMachineDescriptor vmd : vmds) {
-                if (!isJCmdProcess(vmd)) {
-                    pids.add(vmd.id());
-                }
-            }
-        } else if (arg.getProcessSubstring() != null) {
-            // use the partial class-name match
-            List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
-            for (VirtualMachineDescriptor vmd : vmds) {
-                if (isJCmdProcess(vmd)) {
-                    continue;
-                }
-                try {
-                    String mainClass = getMainClass(vmd);
-                    if (mainClass != null
-                        && mainClass.indexOf(arg.getProcessSubstring()) != -1) {
-                            pids.add(vmd.id());
-                    }
-                } catch (MonitorException|URISyntaxException e) {
-                    if (e.getMessage() != null) {
-                        System.err.println(e.getMessage());
-                    } else {
-                        Throwable cause = e.getCause();
-                        if ((cause != null) && (cause.getMessage() != null)) {
-                            System.err.println(cause.getMessage());
-                        } else {
-                            e.printStackTrace();
-                        }
-                    }
-                }
-            }
-            if (pids.isEmpty()) {
-                System.err.println("Could not find any processes matching : '"
-                                   + arg.getProcessSubstring() + "'");
-                System.exit(1);
-            }
-        } else if (arg.getPid() == -1) {
+        Collection<String> pids = Collections.emptyList();
+        try {
+            ProcessArgumentMatcher ap = new ProcessArgumentMatcher(arg.getProcessString(), JCmd.class);
+            pids = ap.getPids();
+        } catch (IllegalArgumentException iae) {
             System.err.println("Invalid pid specified");
             System.exit(1);
-        } else {
-            // Use the found pid
-            pids.add(arg.getPid() + "");
+        }
+        if (pids.isEmpty()) {
+            System.err.println("Could not find any processes matching : '"
+                               + arg.getProcessString() + "'");
+            System.exit(1);
         }
 
         boolean success = true;
@@ -199,36 +165,6 @@
         }
     }
 
-    private static boolean isJCmdProcess(VirtualMachineDescriptor vmd) {
-        try {
-            String mainClass = getMainClass(vmd);
-            return mainClass != null && mainClass.equals(JCmd.class.getName());
-        } catch (URISyntaxException|MonitorException ex) {
-            return false;
-        }
-    }
-
-    private static String getMainClass(VirtualMachineDescriptor vmd)
-            throws URISyntaxException, MonitorException {
-        try {
-            String mainClass = null;
-            VmIdentifier vmId = new VmIdentifier(vmd.id());
-            MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId);
-            MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1);
-            mainClass = MonitoredVmUtil.mainClass(monitoredVm, true);
-            monitoredHost.detach(monitoredVm);
-            return mainClass;
-        } catch(NullPointerException e) {
-            // There is a potential race, where a running java app is being
-            // queried, unfortunately the java app has shutdown after this
-            // method is started but before getMonitoredVM is called.
-            // If this is the case, then the /tmp/hsperfdata_xxx/pid file
-            // will have disappeared and we will get a NullPointerException.
-            // Handle this gracefully....
-            return null;
-        }
-    }
-
     /**
      * Class to compare two Monitor objects by name in ascending order.
      * (from jstat)
--- a/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java	Wed May 18 12:04:26 2016 -0700
@@ -25,15 +25,14 @@
 
 package sun.tools.jinfo;
 
-import java.util.Arrays;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Collection;
 
 import com.sun.tools.attach.VirtualMachine;
 
 import sun.tools.attach.HotSpotVirtualMachine;
-import jdk.internal.vm.agent.spi.ToolProvider;
-import jdk.internal.vm.agent.spi.ToolProviderFinder;
+import sun.tools.common.ProcessArgumentMatcher;
 
 /*
  * This class is the main class for the JInfo utility. It parses its arguments
@@ -41,157 +40,96 @@
  * or an SA tool.
  */
 final public class JInfo {
-    private static final String SA_JINFO_TOOL_NAME = "jinfo";
-    private boolean useSA = false;
-    private String[] args = null;
 
-    private JInfo(String[] args) throws IllegalArgumentException {
+    public static void main(String[] args) throws Exception {
         if (args.length == 0) {
-            throw new IllegalArgumentException();
+            usage(1); // no arguments
+        }
+        checkForUnsupportedOptions(args);
+
+        boolean doFlag = false;
+        boolean doFlags = false;
+        boolean doSysprops = false;
+
+        // Parse the options (arguments starting with "-" )
+        int optionCount = 0;
+        while (optionCount < args.length) {
+            String arg = args[optionCount];
+            if (!arg.startsWith("-")) {
+                break;
+            }
+
+            optionCount++;
+
+            if (arg.equals("-help") || arg.equals("-h")) {
+                usage(0);
+            }
+
+            if (arg.equals("-flag")) {
+                doFlag = true;
+                continue;
+            }
+
+            if (arg.equals("-flags")) {
+                doFlags = true;
+                continue;
+            }
+
+            if (arg.equals("-sysprops")) {
+                doSysprops = true;
+                continue;
+            }
         }
 
-        int argCopyIndex = 0;
-        // First determine if we should launch SA or not
-        if (args[0].equals("-F")) {
-            // delete the -F
-            argCopyIndex = 1;
-            useSA = true;
-        } else if (args[0].equals("-flags")
-                   || args[0].equals("-sysprops"))
-        {
-            if (args.length == 2) {
-                if (!isPid(args[1])) {
-                    // If args[1] doesn't parse to a number then
-                    // it must be the SA debug server
-                    // (otherwise it is the pid)
-                    useSA = true;
-                }
-            } else if (args.length == 3) {
-                // arguments include an executable and a core file
-                useSA = true;
-            } else {
-                throw new IllegalArgumentException();
-            }
-        } else if (!args[0].startsWith("-")) {
-            if (args.length == 2) {
-                // the only arguments are an executable and a core file
-                useSA = true;
-            } else if (args.length == 1) {
-                if (!isPid(args[0])) {
-                    // The only argument is not a PID; it must be SA debug
-                    // server
-                    useSA = true;
-                }
-            } else {
-                throw new IllegalArgumentException();
-            }
-        } else if (args[0].equals("-h") || args[0].equals("-help")) {
-            if (args.length > 1) {
-                throw new IllegalArgumentException();
-            }
-        } else if (args[0].equals("-flag")) {
-            if (args.length == 3) {
-                if (!isPid(args[2])) {
-                    throw new IllegalArgumentException();
-                }
-            } else {
-                throw new IllegalArgumentException();
-            }
-        } else {
-            throw new IllegalArgumentException();
+        // Next we check the parameter count. -flag allows extra parameters
+        int paramCount = args.length - optionCount;
+        if ((doFlag && paramCount != 2) || ((!doFlag && paramCount != 1))) {
+            usage(1);
         }
 
-        this.args = Arrays.copyOfRange(args, argCopyIndex, args.length);
-    }
-
-    @SuppressWarnings("fallthrough")
-    private void execute() throws Exception {
-        if (args[0].equals("-h")
-            || args[0].equals("-help")) {
-            usage(0);
+        if (!doFlag && !doFlags && !doSysprops) {
+            // Print flags and sysporps if no options given
+            ProcessArgumentMatcher ap = new ProcessArgumentMatcher(args[optionCount], JInfo.class);
+            Collection<String> pids = ap.getPids();
+            for (String pid : pids) {
+                if (pids.size() > 1) {
+                    System.out.println("Pid:" + pid);
+                }
+                sysprops(pid);
+                System.out.println();
+                flags(pid);
+                System.out.println();
+                commandLine(pid);
+            }
         }
 
-        if (useSA) {
-            // SA only supports -flags or -sysprops
-            if (args[0].startsWith("-")) {
-                if (!(args[0].equals("-flags") || args[0].equals("-sysprops"))) {
-                    usage(1);
+        if (doFlag) {
+            ProcessArgumentMatcher ap = new ProcessArgumentMatcher(args[optionCount+1], JInfo.class);
+            Collection<String> pids = ap.getPids();
+            for (String pid : pids) {
+                if (pids.size() > 1) {
+                    System.out.println("Pid:" + pid);
+                }
+                flag(pid, args[optionCount]);
+            }
+        }
+        else if (doFlags || doSysprops) {
+            ProcessArgumentMatcher ap = new ProcessArgumentMatcher(args[optionCount], JInfo.class);
+            Collection<String> pids = ap.getPids();
+            for (String pid : pids) {
+                if (pids.size() > 1) {
+                    System.out.println("Pid:" + pid);
+                }
+                if (doFlags) {
+                    flags(pid);
+                }
+                else if (doSysprops) {
+                    sysprops(pid);
                 }
             }
-
-            // invoke SA which does it's own argument parsing
-            runTool();
-
-        } else {
-            // Now we can parse arguments for the non-SA case
-            String pid = null;
-
-            switch(args[0]) {
-                case "-flag":
-                    if (args.length != 3) {
-                        usage(1);
-                    }
-                    String option = args[1];
-                    pid = args[2];
-                    flag(pid, option);
-                    break;
-                case "-flags":
-                    if (args.length != 2) {
-                        usage(1);
-                    }
-                    pid = args[1];
-                    flags(pid);
-                    break;
-                case "-sysprops":
-                    if (args.length != 2) {
-                        usage(1);
-                    }
-                    pid = args[1];
-                    sysprops(pid);
-                    break;
-                case "-help":
-                case "-h":
-                    usage(0);
-                    // Fall through
-                default:
-                    if (args.length == 1) {
-                        // no flags specified, we do -sysprops and -flags
-                        pid = args[0];
-                        sysprops(pid);
-                        System.out.println();
-                        flags(pid);
-                        System.out.println();
-                        commandLine(pid);
-                    } else {
-                        usage(1);
-                    }
-            }
         }
     }
 
-    public static void main(String[] args) throws Exception {
-        JInfo jinfo = null;
-        try {
-            jinfo = new JInfo(args);
-            jinfo.execute();
-        } catch (IllegalArgumentException e) {
-            usage(1);
-        }
-    }
-
-    private static boolean isPid(String arg) {
-        return arg.matches("[0-9]+");
-    }
-
-    // Invoke SA tool with the given arguments
-    private void runTool() throws Exception {
-        ToolProvider tool = ToolProviderFinder.find(SA_JINFO_TOOL_NAME);
-        if (tool == null) {
-            usage(1);
-        }
-        tool.run(args);
-    }
-
     private static void flag(String pid, String option) throws IOException {
         HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid);
         String flag;
@@ -274,46 +212,49 @@
         vm.detach();
     }
 
+    private static void checkForUnsupportedOptions(String[] args) {
+        // Check arguments for -F, and non-numeric value
+        // and warn the user that SA is not supported anymore
+        int maxCount = 1;
+        int paramCount = 0;
 
-    // print usage message
-    private static void usage(int exit) {
-        boolean usageSA = ToolProviderFinder.find(SA_JINFO_TOOL_NAME) != null;
-
-        System.err.println("Usage:");
-        if (usageSA) {
-            System.err.println("    jinfo [option] <pid>");
-            System.err.println("        (to connect to a running process)");
-            System.err.println("    jinfo -F [option] <pid>");
-            System.err.println("        (to connect to a hung process)");
-            System.err.println("    jinfo [option] <executable> <core>");
-            System.err.println("        (to connect to a core file)");
-            System.err.println("    jinfo [option] [server_id@]<remote server IP or hostname>");
-            System.err.println("        (to connect to remote debug server)");
-            System.err.println("");
-            System.err.println("where <option> is one of:");
-            System.err.println("  for running processes:");
-            System.err.println("    -flag <name>         to print the value of the named VM flag");
-            System.err.println("    -flag [+|-]<name>    to enable or disable the named VM flag");
-            System.err.println("    -flag <name>=<value> to set the named VM flag to the given value");
-            System.err.println("  for running or hung processes and core files:");
-            System.err.println("    -flags               to print VM flags");
-            System.err.println("    -sysprops            to print Java system properties");
-            System.err.println("    <no option>          to print both VM flags and system properties");
-            System.err.println("    -h | -help           to print this help message");
-        } else {
-            System.err.println("    jinfo <option> <pid>");
-            System.err.println("       (to connect to a running process)");
-            System.err.println("");
-            System.err.println("where <option> is one of:");
-            System.err.println("    -flag <name>         to print the value of the named VM flag");
-            System.err.println("    -flag [+|-]<name>    to enable or disable the named VM flag");
-            System.err.println("    -flag <name>=<value> to set the named VM flag to the given value");
-            System.err.println("    -flags               to print VM flags");
-            System.err.println("    -sysprops            to print Java system properties");
-            System.err.println("    <no option>          to print both VM flags and system properties");
-            System.err.println("    -h | -help           to print this help message");
+        for (String s : args) {
+            if (s.equals("-F")) {
+                SAOptionError("-F option used");
+            }
+            if (s.equals("-flag")) {
+                maxCount = 2;
+            }
+            if (! s.startsWith("-")) {
+                paramCount += 1;
+            }
         }
 
+        if (paramCount > maxCount) {
+            SAOptionError("More than " + maxCount + " non-option argument");
+        }
+    }
+
+    private static void SAOptionError(String msg) {
+        System.err.println("Error: " + msg);
+        System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jinfo instead");
+        System.exit(1);
+    }
+
+     // print usage message
+    private static void usage(int exit) {
+        System.err.println("Usage:");
+        System.err.println("    jinfo <option> <pid>");
+        System.err.println("       (to connect to a running process)");
+        System.err.println("");
+        System.err.println("where <option> is one of:");
+        System.err.println("    -flag <name>         to print the value of the named VM flag");
+        System.err.println("    -flag [+|-]<name>    to enable or disable the named VM flag");
+        System.err.println("    -flag <name>=<value> to set the named VM flag to the given value");
+        System.err.println("    -flags               to print VM flags");
+        System.err.println("    -sysprops            to print Java system properties");
+        System.err.println("    <no option>          to print both VM flags and system properties");
+        System.err.println("    -h | -help           to print this help message");
         System.exit(exit);
     }
 }
--- a/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java	Wed May 18 12:04:26 2016 -0700
@@ -28,12 +28,13 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Collection;
 
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.AttachNotSupportedException;
 import sun.tools.attach.HotSpotVirtualMachine;
-import jdk.internal.vm.agent.spi.ToolProvider;
-import jdk.internal.vm.agent.spi.ToolProviderFinder;
+import sun.tools.common.ProcessArgumentMatcher;
 
 /*
  * This class is the main class for the JMap utility. It parses its arguments
@@ -44,34 +45,18 @@
  */
 public class JMap {
 
-    // Options handled by the attach mechanism
-    private static String HISTO_OPTION = "-histo";
-    private static String LIVE_HISTO_OPTION = "-histo:live";
-    private static String DUMP_OPTION_PREFIX = "-dump:";
-
-    // These options imply the use of a SA tool
-    private static String SA_TOOL_OPTIONS =
-      "-heap|-heap:format=b|-clstats|-finalizerinfo";
-
-    // The -F (force) option is currently not passed through to SA
-    private static String FORCE_SA_OPTION = "-F";
-
-    // Default option (if nothing provided)
-    private static String DEFAULT_OPTION = "-pmap";
-
     public static void main(String[] args) throws Exception {
         if (args.length == 0) {
             usage(1); // no arguments
         }
 
-        // used to indicate if we should use SA
-        boolean useSA = false;
+        checkForUnsupportedOptions(args);
 
-        // the chosen option (-heap, -dump:*, ... )
+        // the chosen option
         String option = null;
 
         // First iterate over the options (arguments starting with -).  There should be
-        // one (but maybe two if -F is also used).
+        // one.
         int optionCount = 0;
         while (optionCount < args.length) {
             String arg = args[optionCount];
@@ -80,8 +65,6 @@
             }
             if (arg.equals("-help") || arg.equals("-h")) {
                 usage(0);
-            } else if (arg.equals(FORCE_SA_OPTION)) {
-                useSA = true;
             } else {
                 if (option != null) {
                     usage(1);  // option already specified
@@ -93,123 +76,102 @@
 
         // if no option provided then use default.
         if (option == null) {
-            option = DEFAULT_OPTION;
-        }
-        if (option.matches(SA_TOOL_OPTIONS)) {
-            useSA = true;
+            usage(0);
         }
 
-        // Next we check the parameter count. For the SA tools there are
-        // one or two parameters. For the built-in -dump option there is
-        // only one parameter (the process-id)
+        // Next we check the parameter count.
         int paramCount = args.length - optionCount;
-        if (paramCount == 0 || paramCount > 2) {
+        if (paramCount != 1) {
             usage(1);
         }
 
-        if (optionCount == 0 || paramCount != 1) {
-            useSA = true;
-        } else {
-            // the parameter for the -dump option is a process-id.
-            // If it doesn't parse to a number then it must be SA
-            // debug server
-            if (!args[optionCount].matches("[0-9]+")) {
-                useSA = true;
+        String pidArg = args[1];
+        // Here we handle the built-in options
+        // As more options are added we should create an abstract tool class and
+        // have a table to map the options
+        ProcessArgumentMatcher ap = new ProcessArgumentMatcher(pidArg, JMap.class);
+        Collection<String> pids = ap.getPids();
+        for (String pid : pids) {
+            if (pids.size() > 1) {
+                System.out.println("Pid:" + pid);
             }
-        }
-
-
-        // at this point we know if we are executing an SA tool or a built-in
-        // option.
-
-        if (useSA) {
-            // parameters (<pid> or <exe> <core>)
-            String params[] = new String[paramCount];
-            for (int i=optionCount; i<args.length; i++ ){
-                params[i-optionCount] = args[i];
-            }
-            runTool(option, params);
-
-        } else {
-            String pid = args[1];
-            // Here we handle the built-in options
-            // As more options are added we should create an abstract tool class and
-            // have a table to map the options
-            if (option.equals(HISTO_OPTION)) {
-                histo(pid, false);
-            } else if (option.equals(LIVE_HISTO_OPTION)) {
-                histo(pid, true);
-            } else if (option.startsWith(DUMP_OPTION_PREFIX)) {
-                dump(pid, option);
+            if (option.equals("-histo")) {
+                histo(pid, "");
+            } else if (option.startsWith("-histo:")) {
+                histo(pid, option.substring("-histo:".length()));
+            } else if (option.startsWith("-dump:")) {
+                dump(pid, option.substring("-dump:".length()));
+            } else if (option.equals("-finalizerinfo")) {
+                executeCommandForPid(pid, "jcmd", "GC.finalizer_info");
+            } else if (option.equals("-clstats")) {
+                executeCommandForPid(pid, "jcmd", "GC.class_stats");
             } else {
-                usage(1);
+              usage(1);
             }
         }
     }
 
-    // Invoke SA tool  with the given arguments
-    private static void runTool(String option, String args[]) throws Exception {
-        String[][] tools = {
-            { "-pmap",          "pmap"             },
-            { "-heap",          "heapSummary"      },
-            { "-heap:format=b", "heapDumper"       },
-            { "-histo",         "objectHistogram"  },
-            { "-clstats",       "classLoaderStats" },
-            { "-finalizerinfo", "finalizerInfo"    },
-        };
+    private static void executeCommandForPid(String pid, String command, Object ... args)
+        throws AttachNotSupportedException, IOException,
+               UnsupportedEncodingException {
+        VirtualMachine vm = VirtualMachine.attach(pid);
 
-        String name = null;
+        // Cast to HotSpotVirtualMachine as this is an
+        // implementation specific method.
+        HotSpotVirtualMachine hvm = (HotSpotVirtualMachine) vm;
+        try (InputStream in = hvm.executeCommand(command, args)) {
+          // read to EOF and just print output
+          byte b[] = new byte[256];
+          int n;
+          do {
+              n = in.read(b);
+              if (n > 0) {
+                  String s = new String(b, 0, n, "UTF-8");
+                  System.out.print(s);
+              }
+          } while (n > 0);
+        }
+        vm.detach();
+    }
 
-        // -dump option needs to be handled in a special way
-        if (option.startsWith(DUMP_OPTION_PREFIX)) {
-            // first check that the option can be parsed
-            String fn = parseDumpOptions(option);
-            if (fn == null) {
-                usage(1);
-            }
-
-            // tool for heap dumping
-            name = "heapDumper";
-
-            // HeapDumper -f <file>
-            args = prepend(fn, args);
-            args = prepend("-f", args);
-        } else {
-            int i=0;
-            while (i < tools.length) {
-                if (option.equals(tools[i][0])) {
-                    name = tools[i][1];
-                    break;
-                }
-                i++;
-            }
+    private static void histo(String pid, String options)
+        throws AttachNotSupportedException, IOException,
+               UnsupportedEncodingException {
+        String liveopt = "-all";
+        if (options.equals("") || options.equals("all")) {
+            //  pass
         }
-        if (name == null) {
-            usage(1);   // no mapping to tool
+        else if (options.equals("live")) {
+            liveopt = "-live";
         }
-
-        // Tool not available on this platform.
-        ToolProvider tool = ToolProviderFinder.find(name);
-        if (tool == null) {
+        else {
             usage(1);
         }
 
-        // invoke the main method with the arguments
-        tool.run(args);
+        // inspectHeap is not the same as jcmd GC.class_histogram
+        executeCommandForPid(pid, "inspectheap", liveopt);
     }
 
-    private static final String LIVE_OBJECTS_OPTION = "-live";
-    private static final String ALL_OBJECTS_OPTION = "-all";
-    private static void histo(String pid, boolean live) throws IOException {
-        VirtualMachine vm = attach(pid);
-        InputStream in = ((HotSpotVirtualMachine)vm).
-            heapHisto(live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION);
-        drain(vm, in);
-    }
+    private static void dump(String pid, String options)
+        throws AttachNotSupportedException, IOException,
+               UnsupportedEncodingException {
 
-    private static void dump(String pid, String options) throws IOException {
-        // parse the options to get the dump filename
-        String filename = parseDumpOptions(options);
+        String subopts[] = options.split(",");
+        String filename = null;
+        String liveopt = "-all";
+
+        for (int i = 0; i < subopts.length; i++) {
+            String subopt = subopts[i];
+            if (subopt.equals("live")) {
+                liveopt = "-live";
+            } else if (subopt.startsWith("file=")) {
+                // file=<file> - check that <file> is specified
+                if (subopt.length() > 5) {
+                    filename = subopt.substring(5);
+                }
+            }
+        }
+
         if (filename == null) {
             usage(1);  // invalid options or no filename
         }
@@ -219,156 +181,73 @@
         // working directory rather than the directory where jmap
         // is executed.
         filename = new File(filename).getCanonicalPath();
-
-        // dump live objects only or not
-        boolean live = isDumpLiveObjects(options);
-
-        VirtualMachine vm = attach(pid);
-        System.out.println("Dumping heap to " + filename + " ...");
-        InputStream in = ((HotSpotVirtualMachine)vm).
-            dumpHeap((Object)filename,
-                     (live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION));
-        drain(vm, in);
+        // dumpHeap is not the same as jcmd GC.heap_dump
+        executeCommandForPid(pid, "dumpheap", filename, liveopt);
     }
 
-    // Parse the options to the -dump option. Valid options are format=b and
-    // file=<file>. Returns <file> if provided. Returns null if <file> not
-    // provided, or invalid option.
-    private static String parseDumpOptions(String arg) {
-        assert arg.startsWith(DUMP_OPTION_PREFIX);
+    private static void checkForUnsupportedOptions(String[] args) {
+        // Check arguments for -F, -m, and non-numeric value
+        // and warn the user that SA is not supported anymore
 
-        String filename = null;
+        int paramCount = 0;
 
-        // options are separated by comma (,)
-        String options[] = arg.substring(DUMP_OPTION_PREFIX.length()).split(",");
+        for (String s : args) {
+            if (s.equals("-F")) {
+                SAOptionError("-F option used");
+            }
 
-        for (int i=0; i<options.length; i++) {
-            String option = options[i];
+            if (s.equals("-heap")) {
+                SAOptionError("-heap option used");
+            }
 
-            if (option.equals("format=b")) {
-                // ignore format (not needed at this time)
-            } else if (option.equals("live")) {
-                // a valid suboption
-            } else {
+            /* Reimplemented using jcmd, output format is different
+               from original one
 
-                // file=<file> - check that <file> is specified
-                if (option.startsWith("file=")) {
-                    filename = option.substring(5);
-                    if (filename.length() == 0) {
-                        return null;
-                    }
-                } else {
-                    return null;  // option not recognized
-                }
+            if (s.equals("-clstats")) {
+                warnSA("-clstats option used");
+            }
+
+            if (s.equals("-finalizerinfo")) {
+                warnSA("-finalizerinfo option used");
+            }
+            */
+
+            if (! s.startsWith("-")) {
+                paramCount += 1;
             }
         }
-        return filename;
-    }
 
-    private static boolean isDumpLiveObjects(String arg) {
-        // options are separated by comma (,)
-        String options[] = arg.substring(DUMP_OPTION_PREFIX.length()).split(",");
-        for (String suboption : options) {
-            if (suboption.equals("live")) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    // Attach to <pid>, existing if we fail to attach
-    private static VirtualMachine attach(String pid) {
-        try {
-            return VirtualMachine.attach(pid);
-        } catch (Exception x) {
-            String msg = x.getMessage();
-            if (msg != null) {
-                System.err.println(pid + ": " + msg);
-            } else {
-                x.printStackTrace();
-            }
-            if ((x instanceof AttachNotSupportedException) && haveSA()) {
-                System.err.println("The -F option can be used when the " +
-                  "target process is not responding");
-            }
-            System.exit(1);
-            return null; // keep compiler happy
+        if (paramCount > 1) {
+            SAOptionError("More than one non-option argument");
         }
     }
 
-    // Read the stream from the target VM until EOF, then detach
-    private static void drain(VirtualMachine vm, InputStream in) throws IOException {
-        // read to EOF and just print output
-        byte b[] = new byte[256];
-        int n;
-        do {
-            n = in.read(b);
-            if (n > 0) {
-                String s = new String(b, 0, n, "UTF-8");
-                System.out.print(s);
-            }
-        } while (n > 0);
-        in.close();
-        vm.detach();
-    }
-
-    // return a new string array with arg as the first element
-    private static String[] prepend(String arg, String args[]) {
-        String[] newargs = new String[args.length+1];
-        newargs[0] = arg;
-        System.arraycopy(args, 0, newargs, 1, args.length);
-        return newargs;
-    }
-
-    // returns true if SA is available
-    private static boolean haveSA() {
-        return ToolProviderFinder.find("heapSummary") != null;
+    private static void SAOptionError(String msg) {
+        System.err.println("Error: " + msg);
+        System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jmap instead");
+        System.exit(1);
     }
 
     // print usage message
     private static void usage(int exit) {
         System.err.println("Usage:");
-        if (haveSA()) {
-            System.err.println("    jmap [option] <pid>");
-            System.err.println("        (to connect to running process)");
-            System.err.println("    jmap [option] <executable <core>");
-            System.err.println("        (to connect to a core file)");
-            System.err.println("    jmap [option] [server_id@]<remote server IP or hostname>");
-            System.err.println("        (to connect to remote debug server)");
-            System.err.println("");
-            System.err.println("where <option> is one of:");
-            System.err.println("    <none>               to print same info as Solaris pmap");
-            System.err.println("    -heap                to print java heap summary");
-            System.err.println("    -histo[:live]        to print histogram of java object heap; if the \"live\"");
-            System.err.println("                         suboption is specified, only count live objects");
-            System.err.println("    -clstats             to print class loader statistics");
-            System.err.println("    -finalizerinfo       to print information on objects awaiting finalization");
-            System.err.println("    -dump:<dump-options> to dump java heap in hprof binary format");
-            System.err.println("                         dump-options:");
-            System.err.println("                           live         dump only live objects; if not specified,");
-            System.err.println("                                        all objects in the heap are dumped.");
-            System.err.println("                           format=b     binary format");
-            System.err.println("                           file=<file>  dump heap to <file>");
-            System.err.println("                         Example: jmap -dump:live,format=b,file=heap.bin <pid>");
-            System.err.println("    -F                   force. Use with -dump:<dump-options> <pid> or -histo");
-            System.err.println("                         to force a heap dump or histogram when <pid> does not");
-            System.err.println("                         respond. The \"live\" suboption is not supported");
-            System.err.println("                         in this mode.");
-            System.err.println("    -h | -help           to print this help message");
-            System.err.println("    -J<flag>             to pass <flag> directly to the runtime system");
-        } else {
-            System.err.println("    jmap -histo <pid>");
-            System.err.println("      (to connect to running process and print histogram of java object heap");
-            System.err.println("    jmap -dump:<dump-options> <pid>");
-            System.err.println("      (to connect to running process and dump java heap)");
-            System.err.println("");
-            System.err.println("    dump-options:");
-            System.err.println("      format=b     binary default");
-            System.err.println("      file=<file>  dump heap to <file>");
-            System.err.println("");
-            System.err.println("    Example:       jmap -dump:format=b,file=heap.bin <pid>");
-        }
-
+        System.err.println("    jmap -clstats <pid>");
+        System.err.println("        to connect to running process and print class loader statistics");
+        System.err.println("    jmap -finalizerinfo <pid>");
+        System.err.println("        to connect to running process and print information on objects awaiting finalization");
+        System.err.println("    jmap -histo[:live] <pid>");
+        System.err.println("        to connect to running process and print histogram of java object heap");
+        System.err.println("        if the \"live\" suboption is specified, only count live objects");
+        System.err.println("    jmap -dump:<dump-options> <pid>");
+        System.err.println("        to connect to running process and dump java heap");
+        System.err.println("");
+        System.err.println("    dump-options:");
+        System.err.println("      live         dump only live objects; if not specified,");
+        System.err.println("                   all objects in the heap are dumped.");
+        System.err.println("      format=b     binary format");
+        System.err.println("      file=<file>  dump heap to <file>");
+        System.err.println("");
+        System.err.println("    Example: jmap -dump:live,format=b,file=heap.bin <pid>");
         System.exit(exit);
     }
 }
--- a/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java	Wed May 18 20:40:17 2016 +0300
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java	Wed May 18 12:04:26 2016 -0700
@@ -26,12 +26,11 @@
 package sun.tools.jstack;
 
 import java.io.InputStream;
+import java.util.Collection;
 
 import com.sun.tools.attach.VirtualMachine;
-import com.sun.tools.attach.AttachNotSupportedException;
 import sun.tools.attach.HotSpotVirtualMachine;
-import jdk.internal.vm.agent.spi.ToolProvider;
-import jdk.internal.vm.agent.spi.ToolProviderFinder;
+import sun.tools.common.ProcessArgumentMatcher;
 
 /*
  * This class is the main class for the JStack utility. It parses its arguments
@@ -39,15 +38,14 @@
  * obtained the thread dump from a target process using the VM attach mechanism
  */
 public class JStack {
-    private static final String SA_JSTACK_TOOL_NAME = "jstack";
 
     public static void main(String[] args) throws Exception {
         if (args.length == 0) {
             usage(1); // no arguments
         }
 
-        boolean useSA = false;
-        boolean mixed = false;
+        checkForUnsupportedOptions(args);
+
         boolean locks = false;
 
         // Parse the options (arguments starting with "-" )
@@ -60,87 +58,40 @@
             if (arg.equals("-help") || arg.equals("-h")) {
                 usage(0);
             }
-            else if (arg.equals("-F")) {
-                useSA = true;
-            }
             else {
-                if (arg.equals("-m")) {
-                    mixed = true;
+                if (arg.equals("-l")) {
+                    locks = true;
                 } else {
-                    if (arg.equals("-l")) {
-                       locks = true;
-                    } else {
-                        usage(1);
-                    }
+                    usage(1);
                 }
             }
             optionCount++;
         }
 
-        // mixed stack implies SA tool
-        if (mixed) {
-            useSA = true;
+        // Next we check the parameter count.
+        int paramCount = args.length - optionCount;
+        if (paramCount != 1) {
+            usage(1);
         }
 
-        // Next we check the parameter count. If there are two parameters
-        // we assume core file and executable so we use SA.
-        int paramCount = args.length - optionCount;
-        if (paramCount == 0 || paramCount > 2) {
-            usage(1);
+        // pass -l to thread dump operation to get extra lock info
+        String pidArg = args[optionCount];
+        String params[];
+        if (locks) {
+            params = new String[] { "-l" };
+        } else {
+            params = new String[0];
         }
-        if (paramCount == 2) {
-            useSA = true;
-        } else {
-            // If we can't parse it as a pid then it must be debug server
-            if (!args[optionCount].matches("[0-9]+")) {
-                useSA = true;
-            }
-        }
-
-        // now execute using the SA JStack tool or the built-in thread dumper
-        if (useSA) {
-            // parameters (<pid> or <exe> <core>
-            String params[] = new String[paramCount];
-            for (int i=optionCount; i<args.length; i++ ){
-                params[i-optionCount] = args[i];
-            }
-            runJStackTool(mixed, locks, params);
-        } else {
-            // pass -l to thread dump operation to get extra lock info
-            String pid = args[optionCount];
-            String params[];
-            if (locks) {
-                params = new String[] { "-l" };
-            } else {
-                params = new String[0];
+        ProcessArgumentMatcher ap = new ProcessArgumentMatcher(pidArg, JStack.class);
+        Collection<String> pids = ap.getPids();
+        for (String pid : pids) {
+            if (pids.size() > 1) {
+                System.out.println("Pid:" + pid);
             }
             runThreadDump(pid, params);
         }
     }
 
-    // SA JStack tool
-    private static boolean isAgentToolPresent() {
-        return ToolProviderFinder.find(SA_JSTACK_TOOL_NAME) != null;
-    }
-
-    private static void runJStackTool(boolean mixed, boolean locks, String args[]) throws Exception {
-        ToolProvider tool = ToolProviderFinder.find(SA_JSTACK_TOOL_NAME);
-        if (tool == null) {
-            usage(1);            // SA not available
-        }
-
-        // JStack tool also takes -m and -l arguments
-        if (mixed) {
-            args = prepend("-m", args);
-        }
-        if (locks) {
-            args = prepend("-l", args);
-        }
-
-        tool.run(args);
-    }
-
-
     // Attach to pid and perform a thread dump
     private static void runThreadDump(String pid, String args[]) throws Exception {
         VirtualMachine vm = null;
@@ -153,10 +104,6 @@
             } else {
                 x.printStackTrace();
             }
-            if ((x instanceof AttachNotSupportedException) && isAgentToolPresent()) {
-                System.err.println("The -F option can be used when the target " +
-                    "process is not responding");
-            }
             System.exit(1);
         }
 
@@ -178,12 +125,35 @@
         vm.detach();
     }
 
-    // return a new string array with arg as the first element
-    private static String[] prepend(String arg, String args[]) {
-        String[] newargs = new String[args.length+1];
-        newargs[0] = arg;
-        System.arraycopy(args, 0, newargs, 1, args.length);
-        return newargs;
+    private static void checkForUnsupportedOptions(String[] args) {
+        // Check arguments for -F, -m, and non-numeric value
+        // and warn the user that SA is not supported anymore
+
+        int paramCount = 0;
+
+        for (String s : args) {
+            if (s.equals("-F")) {
+                SAOptionError("-F option used");
+            }
+
+            if (s.equals("-m")) {
+                SAOptionError("-m option used");
+            }
+
+            if (! s.startsWith("-")) {
+                paramCount += 1;
+            }
+        }
+
+        if (paramCount > 1) {
+            SAOptionError("More than one non-option argument");
+        }
+    }
+
+    private static void SAOptionError(String msg) {
+        System.err.println("Error: " + msg);
+        System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jstack instead");
+        System.exit(1);
     }
 
     // print usage message
@@ -191,25 +161,8 @@
         System.err.println("Usage:");
         System.err.println("    jstack [-l] <pid>");
         System.err.println("        (to connect to running process)");
-
-        if (isAgentToolPresent()) {
-            System.err.println("    jstack -F [-m] [-l] <pid>");
-            System.err.println("        (to connect to a hung process)");
-            System.err.println("    jstack [-m] [-l] <executable> <core>");
-            System.err.println("        (to connect to a core file)");
-            System.err.println("    jstack [-m] [-l] [server_id@]<remote server IP or hostname>");
-            System.err.println("        (to connect to a remote debug server)");
-        }
-
         System.err.println("");
         System.err.println("Options:");
-
-        if (isAgentToolPresent()) {
-            System.err.println("    -F  to force a thread dump. Use when jstack <pid> does not respond" +