Merge
authoramurillo
Thu, 30 Jun 2016 22:38:17 +0000
changeset 39331 a688c540c4ca
parent 39300 eb132b5b40fd (current diff)
parent 39330 6f808f6d8684 (diff)
child 39332 98615d275088
Merge
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ExecutableImage.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PostProcessorPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/TransformerPlugin.java
--- a/jdk/make/gensrc/GensrcMisc.gmk	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/make/gensrc/GensrcMisc.gmk	Thu Jun 30 22:38:17 2016 +0000
@@ -34,7 +34,11 @@
         @@LAUNCHER_NAME@@ => $(LAUNCHER_NAME) ; \
         @@RUNTIME_NAME@@ => $(RUNTIME_NAME) ; \
         @@VERSION_SHORT@@ => $(VERSION_SHORT) ; \
-        @@VERSION_STRING@@ => $(VERSION_STRING), \
+        @@VERSION_STRING@@ => $(VERSION_STRING) ; \
+        @@VERSION_NUMBER@@ => $(VERSION_NUMBER) ; \
+        @@VERSION_PRE@@ => $(VERSION_PRE) ; \
+        @@VERSION_BUILD@@ => $(VERSION_BUILD) ; \
+        @@VERSION_OPT@@ => $(VERSION_OPT), \
 ))
 
 GENSRC_JAVA_BASE += $(BUILD_VERSION_JAVA)
--- a/jdk/make/mapfiles/libjava/mapfile-vers	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Thu Jun 30 22:38:17 2016 +0000
@@ -56,6 +56,7 @@
 		JNU_ThrowArrayIndexOutOfBoundsException;
 		JNU_ThrowByName;
 		JNU_ThrowByNameWithLastError;
+		JNU_ThrowByNameWithMessageAndLastError;
 		JNU_ThrowClassNotFoundException;
 		JNU_ThrowIllegalAccessError;
 		JNU_ThrowIllegalAccessException;
--- a/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c	Thu Jun 30 22:38:17 2016 +0000
@@ -182,7 +182,17 @@
         // Copy out the char*
         osVersionCStr = strdup([nsVerStr UTF8String]);
     }
-
+    // Fallback if running on pre-10.9 Mac OS
+    if (osVersionCStr == NULL) {
+        NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile :
+                                 @"/System/Library/CoreServices/SystemVersion.plist"];
+        if (version != NULL) {
+            NSString *nsVerStr = [version objectForKey : @"ProductVersion"];
+            if (nsVerStr != NULL) {
+                osVersionCStr = strdup([nsVerStr UTF8String]);
+            }
+        }
+    }
     if (osVersionCStr == NULL) {
         osVersionCStr = strdup("Unknown");
     }
@@ -190,7 +200,9 @@
 }
 
 
-static Boolean getProxyInfoForProtocol(CFDictionaryRef inDict, CFStringRef inEnabledKey, CFStringRef inHostKey, CFStringRef inPortKey, CFStringRef *outProxyHost, int *ioProxyPort) {
+static Boolean getProxyInfoForProtocol(CFDictionaryRef inDict, CFStringRef inEnabledKey,
+                                       CFStringRef inHostKey, CFStringRef inPortKey,
+                                       CFStringRef *outProxyHost, int *ioProxyPort) {
     /* See if the proxy is enabled. */
     CFNumberRef cf_enabled = CFDictionaryGetValue(inDict, inEnabledKey);
     if (cf_enabled == NULL) {
--- a/jdk/src/java.base/share/classes/java/lang/Runtime.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java	Thu Jun 30 22:38:17 2016 +0000
@@ -27,8 +27,6 @@
 
 import java.io.*;
 import java.math.BigInteger;
-import java.util.AbstractList;
-import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -36,11 +34,9 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
-import java.util.RandomAccess;
 import java.util.StringTokenizer;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
-import sun.security.action.GetPropertyAction;
 
 /**
  * Every Java application has a single instance of class
@@ -941,8 +937,9 @@
      */
     public static Version version() {
         if (version == null) {
-            version = Version.parse(
-                GetPropertyAction.privilegedGetProperty("java.runtime.version"));
+            version = new Version(VersionProps.versionNumbers(),
+                    VersionProps.pre(), VersionProps.build(),
+                    VersionProps.optional());
         }
         return version;
     }
@@ -1084,86 +1081,12 @@
         private final Optional<Integer> build;
         private final Optional<String>  optional;
 
-
-        // $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)?
-        // RE limits the format of version strings
-        // ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))?
-
-        private static final String VNUM
-            = "(?<VNUM>[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)";
-        private static final String VNUM_GROUP  = "VNUM";
-
-        private static final String PRE      = "(?:-(?<PRE>[a-zA-Z0-9]+))?";
-        private static final String PRE_GROUP   = "PRE";
-
-        private static final String BUILD
-            = "(?:(?<PLUS>\\+)(?<BUILD>0|[1-9][0-9]*)?)?";
-        private static final String PLUS_GROUP  = "PLUS";
-        private static final String BUILD_GROUP = "BUILD";
-
-        private static final String OPT      = "(?:-(?<OPT>[-a-zA-Z0-9.]+))?";
-        private static final String OPT_GROUP   = "OPT";
-
-        private static final String VSTR_FORMAT
-            = "^" + VNUM + PRE + BUILD + OPT + "$";
-        private static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);
-
-        /**
-         * Constructs a valid <a href="verStr">version string</a> containing
-         * a <a href="#verNum">version number</a> followed by pre-release and
-         * build information.
-         *
-         * @param  s
-         *         A string to be interpreted as a version
-         *
-         * @throws  IllegalArgumentException
-         *          If the given string cannot be interpreted as a valid
-         *          version
-         *
-         * @throws  NullPointerException
-         *          If {@code s} is {@code null}
-         *
-         * @throws  NumberFormatException
-         *          If an element of the version number or the build number
-         *          cannot be represented as an {@link Integer}
-         */
-        private Version(String s) {
-            if (s == null)
-                throw new NullPointerException();
-
-            Matcher m = VSTR_PATTERN.matcher(s);
-            if (!m.matches())
-                throw new IllegalArgumentException("Invalid version string: '"
-                                                   + s + "'");
-
-            // $VNUM is a dot-separated list of integers of arbitrary length
-            List<Integer> list = new ArrayList<>();
-            for (String i : m.group(VNUM_GROUP).split("\\."))
-                list.add(Integer.parseInt(i));
-            version = Collections.unmodifiableList(list);
-
-            pre = Optional.ofNullable(m.group(PRE_GROUP));
-
-            String b = m.group(BUILD_GROUP);
-            // $BUILD is an integer
-            build = (b == null)
-                ? Optional.<Integer>empty()
-                : Optional.ofNullable(Integer.parseInt(b));
-
-            optional = Optional.ofNullable(m.group(OPT_GROUP));
-
-            // empty '+'
-            if ((m.group(PLUS_GROUP) != null) && !build.isPresent()) {
-                if (optional.isPresent()) {
-                    if (pre.isPresent())
-                        throw new IllegalArgumentException("'+' found with"
-                            + " pre-release and optional components:'" + s
-                            + "'");
-                } else {
-                    throw new IllegalArgumentException("'+' found with neither"
-                        + " build or optional components: '" + s + "'");
-                }
-            }
+        Version(List<Integer> version, Optional<String> pre,
+                Optional<Integer> build, Optional<String> optional) {
+            this.version = Collections.unmodifiableList(version);
+            this.pre = pre;
+            this.build = build;
+            this.optional = optional;
         }
 
         /**
@@ -1189,7 +1112,7 @@
          * @return  The Version of the given string
          */
         public static Version parse(String s) {
-            return new Version(s);
+            return VersionBuilder.parse(s);
         }
 
         /**
@@ -1518,4 +1441,86 @@
         }
     }
 
+    private static class VersionBuilder {
+        // $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)?
+        // RE limits the format of version strings
+        // ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))?
+
+        private static final String VNUM
+            = "(?<VNUM>[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)";
+        private static final String VNUM_GROUP  = "VNUM";
+
+        private static final String PRE      = "(?:-(?<PRE>[a-zA-Z0-9]+))?";
+        private static final String PRE_GROUP   = "PRE";
+
+        private static final String BUILD
+            = "(?:(?<PLUS>\\+)(?<BUILD>0|[1-9][0-9]*)?)?";
+        private static final String PLUS_GROUP  = "PLUS";
+        private static final String BUILD_GROUP = "BUILD";
+
+        private static final String OPT      = "(?:-(?<OPT>[-a-zA-Z0-9.]+))?";
+        private static final String OPT_GROUP   = "OPT";
+
+        private static final String VSTR_FORMAT
+            = "^" + VNUM + PRE + BUILD + OPT + "$";
+        private static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);
+
+        /**
+         * Constructs a valid <a href="verStr">version string</a> containing
+         * a <a href="#verNum">version number</a> followed by pre-release and
+         * build information.
+         *
+         * @param  s
+         *         A string to be interpreted as a version
+         *
+         * @throws  IllegalArgumentException
+         *          If the given string cannot be interpreted as a valid
+         *          version
+         *
+         * @throws  NullPointerException
+         *          If {@code s} is {@code null}
+         *
+         * @throws  NumberFormatException
+         *          If an element of the version number or the build number
+         *          cannot be represented as an {@link Integer}
+         */
+        static Version parse(String s) {
+            if (s == null)
+                throw new NullPointerException();
+
+            Matcher m = VSTR_PATTERN.matcher(s);
+            if (!m.matches())
+                throw new IllegalArgumentException("Invalid version string: '"
+                                                   + s + "'");
+
+            // $VNUM is a dot-separated list of integers of arbitrary length
+            List<Integer> version = new ArrayList<>();
+            for (String i : m.group(VNUM_GROUP).split("\\."))
+                version.add(Integer.parseInt(i));
+
+            Optional<String> pre = Optional.ofNullable(m.group(PRE_GROUP));
+
+            String b = m.group(BUILD_GROUP);
+            // $BUILD is an integer
+            Optional<Integer> build = (b == null)
+                ? Optional.empty()
+                : Optional.of(Integer.parseInt(b));
+
+            Optional<String> optional = Optional.ofNullable(m.group(OPT_GROUP));
+
+            // empty '+'
+            if ((m.group(PLUS_GROUP) != null) && !build.isPresent()) {
+                if (optional.isPresent()) {
+                    if (pre.isPresent())
+                        throw new IllegalArgumentException("'+' found with"
+                            + " pre-release and optional components:'" + s
+                            + "'");
+                } else {
+                    throw new IllegalArgumentException("'+' found with neither"
+                        + " build or optional components: '" + s + "'");
+                }
+            }
+            return new Version(version, pre, build, optional);
+        }
+    }
 }
--- a/jdk/src/java.base/share/classes/java/lang/StringLatin1.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/StringLatin1.java	Thu Jun 30 22:38:17 2016 +0000
@@ -137,8 +137,8 @@
                 char c1 = (char) CharacterDataLatin1.instance.toUpperCase(getChar(value, k));
                 char c2 = (char) CharacterDataLatin1.instance.toUpperCase(getChar(other, k));
                 if (c1 != c2) {
-                    c1 = (char) CharacterDataLatin1.instance.toLowerCase(c1);
-                    c2 = (char) CharacterDataLatin1.instance.toLowerCase(c2);
+                    c1 = Character.toLowerCase(c1);
+                    c2 = Character.toLowerCase(c2);
                     if (c1 != c2) {
                         return c1 - c2;
                     }
--- a/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template	Thu Jun 30 22:38:17 2016 +0000
@@ -26,6 +26,9 @@
 package java.lang;
 
 import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
 
 class VersionProps {
 
@@ -42,6 +45,18 @@
     private static final String java_runtime_version =
         "@@VERSION_STRING@@";
 
+    private static final String VERSION_NUMBER =
+        "@@VERSION_NUMBER@@";
+
+    private static final String VERSION_BUILD =
+        "@@VERSION_BUILD@@";
+
+    private static final String VERSION_PRE =
+        "@@VERSION_PRE@@";
+
+    private static final String VERSION_OPT =
+        "@@VERSION_OPT@@";
+
     static {
         init();
     }
@@ -52,6 +67,44 @@
         System.setProperty("java.runtime.name", java_runtime_name);
     }
 
+    static List<Integer> versionNumbers() {
+        List<Integer> versionNumbers = new ArrayList<>(4);
+        int prevIndex = 0;
+        int index = VERSION_NUMBER.indexOf('.');
+        while (index > 0) {
+            versionNumbers.add(
+                    Integer.parseInt(VERSION_NUMBER, prevIndex, index, 10));
+            prevIndex = index + 1; // Skip the period
+            index = VERSION_NUMBER.indexOf('.', prevIndex);
+        }
+        versionNumbers.add(Integer.parseInt(VERSION_NUMBER,
+                prevIndex, VERSION_NUMBER.length(), 10));
+        return versionNumbers;
+    }
+
+    static Optional<String> pre() {
+        return optionalOf(VERSION_PRE);
+    }
+
+    static Optional<Integer> build() {
+        return VERSION_BUILD.isEmpty() ?
+                Optional.empty() :
+                Optional.of(Integer.parseInt(VERSION_BUILD));
+    }
+
+    static Optional<String> optional() {
+        return optionalOf(VERSION_OPT);
+    }
+
+    // Treat empty strings as value not being present
+    private static Optional<String> optionalOf(String value) {
+        if (!value.isEmpty()) {
+            return Optional.of(value);
+        } else {
+            return Optional.empty();
+        }
+    }
+
     /**
      * In case you were wondering this method is called by java -version.
      * Sad that it prints to stderr; would be nicer if default printed on
@@ -111,4 +164,4 @@
                    java_vm_info + ")");
     }
 
-}
\ No newline at end of file
+}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Thu Jun 30 22:38:17 2016 +0000
@@ -1275,8 +1275,6 @@
             this.methodName = methodName;
             this.at = at;
 
-            // Assert method name is correctly derived from value name
-            assert methodName.equals(toMethodName(name()));
             // Assert that return type is correct
             // Otherwise, when disabled avoid using reflection
             assert at.returnType == getReturnType(methodName);
@@ -1311,16 +1309,6 @@
             throw new IllegalArgumentException("No AccessMode value for method name " + methodName);
         }
 
-        private static String toMethodName(String name) {
-            StringBuilder s = new StringBuilder(name.toLowerCase());
-            int i;
-            while ((i = s.indexOf("_")) !=  -1) {
-                s.deleteCharAt(i);
-                s.setCharAt(i, Character.toUpperCase(s.charAt(i)));
-            }
-            return s.toString();
-        }
-
         private static Class<?> getReturnType(String name) {
             try {
                 Method m = VarHandle.class.getMethod(name, Object[].class);
--- a/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java	Thu Jun 30 22:38:17 2016 +0000
@@ -221,7 +221,7 @@
      * </ul>
      * The zone ID is <em>not</em> localized; it's one of the valid IDs of
      * the {@link java.util.TimeZone TimeZone} class that are not
-     * <a href="../java/util/TimeZone.html#CustomID">custom IDs</a>.
+     * <a href="../util/TimeZone.html#CustomID">custom IDs</a>.
      * All other entries are localized names.
      * @see java.util.TimeZone
      * @serial
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java	Thu Jun 30 22:38:17 2016 +0000
@@ -295,13 +295,13 @@
      * @throws IllegalStateException if the zip file has been closed
      */
     public ZipEntry getEntry(String name) {
-
         Objects.requireNonNull(name, "name");
         synchronized (this) {
             ensureOpen();
-            int pos = zsrc.getEntryPos(zc.getBytes(name), true);
+            byte[] bname = zc.getBytes(name);
+            int pos = zsrc.getEntryPos(bname, true);
             if (pos != -1) {
-                return getZipEntry(name, pos);
+                return getZipEntry(name, bname, pos);
             }
         }
         return null;
@@ -492,7 +492,7 @@
                     throw new NoSuchElementException();
                 }
                 // each "entry" has 3 ints in table entries
-                return getZipEntry(null, zsrc.getEntryPos(i++ * 3));
+                return getZipEntry(null, null, zsrc.getEntryPos(i++ * 3));
             }
         }
 
@@ -527,13 +527,17 @@
     }
 
     /* Checks ensureOpen() before invoke this method */
-    private ZipEntry getZipEntry(String name, int pos) {
+    private ZipEntry getZipEntry(String name, byte[] bname, int pos) {
         byte[] cen = zsrc.cen;
         int nlen = CENNAM(cen, pos);
         int elen = CENEXT(cen, pos);
         int clen = CENCOM(cen, pos);
         int flag = CENFLG(cen, pos);
-        if (name == null) {
+        if (name == null || bname.length != nlen) {
+            // to use the entry name stored in cen, if the passed in name is
+            // (1) null, invoked from iterator, or
+            // (2) not equal to the name stored, a slash is appended during
+            // getEntryPos() search.
             if (!zc.isUTF8() && (flag & EFS) != 0) {
                 name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
             } else {
--- a/jdk/src/java.base/share/classes/javax/crypto/Cipher.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/javax/crypto/Cipher.java	Thu Jun 30 22:38:17 2016 +0000
@@ -93,7 +93,7 @@
  * provide authenticity assurances for both confidential data and
  * Additional Associated Data (AAD) that is not encrypted.  (Please see
  * <a href="http://www.ietf.org/rfc/rfc5116.txt"> RFC 5116 </a> for more
- * information on AEAD and AEAD algorithms such as GCM/CCM.) Both
+ * information on AEAD and AAD algorithms such as GCM/CCM.) Both
  * confidential and AAD data can be used when calculating the
  * authentication tag (similar to a {@link Mac}).  This tag is appended
  * to the ciphertext during encryption, and is verified on decryption.
@@ -1186,7 +1186,7 @@
      * determined from the given key, or if the given key has a keysize that
      * exceeds the maximum allowable keysize (as determined from the
      * configured jurisdiction policy files).
-     * @throws UnsupportedOperationException if (@code opmode} is
+     * @throws UnsupportedOperationException if {@code opmode} is
      * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
      * by the underlying {@code CipherSpi}.
      */
@@ -1239,7 +1239,7 @@
      * determined from the given key, or if the given key has a keysize that
      * exceeds the maximum allowable keysize (as determined from the
      * configured jurisdiction policy files).
-     * @throws UnsupportedOperationException if (@code opmode} is
+     * @throws UnsupportedOperationException if {@code opmode} is
      * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
      * by the underlying {@code CipherSpi}.
      */
@@ -1325,7 +1325,7 @@
      * algorithm parameters imply a cryptographic strength that would exceed
      * the legal limits (as determined from the configured jurisdiction
      * policy files).
-     * @throws UnsupportedOperationException if (@code opmode} is
+     * @throws UnsupportedOperationException if {@code opmode} is
      * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
      * by the underlying {@code CipherSpi}.
      */
@@ -1386,7 +1386,7 @@
      * algorithm parameters imply a cryptographic strength that would exceed
      * the legal limits (as determined from the configured jurisdiction
      * policy files).
-     * @throws UnsupportedOperationException if (@code opmode} is
+     * @throws UnsupportedOperationException if {@code opmode} is
      * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
      * by the underlying {@code CipherSpi}.
      */
@@ -1468,7 +1468,7 @@
      * algorithm parameters imply a cryptographic strength that would exceed
      * the legal limits (as determined from the configured jurisdiction
      * policy files).
-     * @throws UnsupportedOperationException if (@code opmode} is
+     * @throws UnsupportedOperationException if {@code opmode} is
      * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
      * by the underlying {@code CipherSpi}.
      */
@@ -1529,7 +1529,7 @@
      * algorithm parameters imply a cryptographic strength that would exceed
      * the legal limits (as determined from the configured jurisdiction
      * policy files).
-     * @throws UnsupportedOperationException if (@code opmode} is
+     * @throws UnsupportedOperationException if {@code opmode} is
      * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
      * by the underlying {@code CipherSpi}.
      */
@@ -1616,7 +1616,7 @@
      * in the given certificate has a keysize that exceeds the maximum
      * allowable keysize (as determined by the configured jurisdiction policy
      * files).
-     * @throws UnsupportedOperationException if (@code opmode} is
+     * @throws UnsupportedOperationException if {@code opmode} is
      * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
      * by the underlying {@code CipherSpi}.
      */
@@ -1686,7 +1686,7 @@
      * in the given certificate has a keysize that exceeds the maximum
      * allowable keysize (as determined by the configured jurisdiction policy
      * files).
-     * @throws UnsupportedOperationException if (@code opmode} is
+     * @throws UnsupportedOperationException if {@code opmode} is
      * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
      * by the underlying {@code CipherSpi}.
      */
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Thu Jun 30 22:38:17 2016 +0000
@@ -318,24 +318,6 @@
      */
     public native Object getUncompressedObject(long address);
 
-    /**
-     * Fetches the {@link java.lang.Class} Java mirror for the given native
-     * metaspace {@code Klass} pointer.
-     *
-     * @param metaspaceKlass a native metaspace {@code Klass} pointer
-     * @return the {@link java.lang.Class} Java mirror
-     */
-    public native Class<?> getJavaMirror(long metaspaceKlass);
-
-    /**
-     * Fetches a native metaspace {@code Klass} pointer for the given Java
-     * object.
-     *
-     * @param o Java heap object for which to fetch the class pointer
-     * @return a native metaspace {@code Klass} pointer
-     */
-    public native long getKlassPointer(Object o);
-
     // These work on values in the C heap.
 
     /**
--- a/jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java	Thu Jun 30 22:38:17 2016 +0000
@@ -222,7 +222,8 @@
                 // Any files in META-INF/ will be indexed explicitly
                 if (fileName.equals("META-INF/") ||
                     fileName.equals(INDEX_NAME) ||
-                    fileName.equals(JarFile.MANIFEST_NAME))
+                    fileName.equals(JarFile.MANIFEST_NAME) ||
+                    fileName.startsWith("META-INF/versions/"))
                     continue;
 
                 if (!metaInfFilenames || !fileName.startsWith("META-INF/")) {
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties	Thu Jun 30 22:38:17 2016 +0000
@@ -60,6 +60,9 @@
 \                  limit the universe of observable modules\n\
 \    -listmods[:<modulename>[,<modulename>...]]\n\
 \                  list the observable modules and exit\n\
+\    --dry-run     create VM but do not execute main method.\n\
+\                  This --dry-run option may be useful for validating the\n\
+\                  command-line options such as the module system configuration.\n\
 \    -D<name>=<value>\n\
 \                  set a system property\n\
 \    -verbose:[class|gc|jni]\n\
--- a/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java	Thu Jun 30 22:38:17 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -97,10 +97,11 @@
                 t.setDaemon(true);
                 return t;
             }
-        });
+        }, new ThreadPoolExecutor.DiscardPolicy());
         threadMgr.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
         threadMgr.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
         threadMgr.setKeepAliveTime(5000, TimeUnit.MILLISECONDS);
+        threadMgr.allowCoreThreadTimeOut(true);
         responseCache = Cache.newSoftMemoryCache(cacheCapacity, cacheLifetime);
     }
 
--- a/jdk/src/java.base/share/native/libjava/jni_util.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/native/libjava/jni_util.c	Thu Jun 30 22:38:17 2016 +0000
@@ -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
@@ -147,9 +147,9 @@
     JNU_ThrowByName(env, "java/lang/InstantiationException", msg);
 }
 
-
-/* Throw an exception by name, using the string returned by
- * JVM_LastErrorString for the detail string.  If the last-error
+/*
+ * Throw an exception by name, using the string returned by
+ * getLastErrorString for the detail string. If the last-error
  * string is NULL, use the given default detail string.
  */
 JNIEXPORT void JNICALL
@@ -174,9 +174,64 @@
     }
 }
 
-/* Throw an IOException, using the last-error string for the detail
- * string.  If the last-error string is NULL, use the given default
- * detail string.
+/*
+ * Throw an exception by name, using a given message and the string
+ * returned by getLastErrorString to construct the detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowByNameWithMessageAndLastError
+  (JNIEnv *env, const char *name, const char *message)
+{
+    char buf[256];
+    size_t n = getLastErrorString(buf, sizeof(buf));
+    size_t messagelen = message == NULL ? 0 : strlen(message);
+
+    if (n > 0) {
+        jstring s = JNU_NewStringPlatform(env, buf);
+        if (s != NULL) {
+            jobject x = NULL;
+            if (messagelen) {
+                jstring s2 = NULL;
+                size_t messageextlen = messagelen + 4;
+                char *str1 = (char *)malloc((messageextlen) * sizeof(char));
+                if (str1 == 0) {
+                    JNU_ThrowOutOfMemoryError(env, 0);
+                    return;
+                }
+                jio_snprintf(str1, messageextlen, " (%s)", message);
+                s2 = (*env)->NewStringUTF(env, str1);
+                free(str1);
+                if (s2 != NULL) {
+                    jstring s3 = JNU_CallMethodByName(
+                                     env, NULL, s, "concat",
+                                     "(Ljava/lang/String;)Ljava/lang/String;",
+                                     s2).l;
+                    (*env)->DeleteLocalRef(env, s2);
+                    if (s3 != NULL) {
+                        (*env)->DeleteLocalRef(env, s);
+                        s = s3;
+                    }
+                }
+            }
+            x = JNU_NewObjectByName(env, name, "(Ljava/lang/String;)V", s);
+            if (x != NULL) {
+                (*env)->Throw(env, x);
+            }
+        }
+    }
+
+    if (!(*env)->ExceptionOccurred(env)) {
+        if (messagelen) {
+            JNU_ThrowByName(env, name, message);
+        } else {
+            JNU_ThrowByName(env, name, "no further information");
+        }
+    }
+}
+
+/*
+ * Convenience method.
+ * Call JNU_ThrowByNameWithLastError for java.io.IOException.
  */
 JNIEXPORT void JNICALL
 JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail)
--- a/jdk/src/java.base/share/native/libjava/jni_util.h	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/native/libjava/jni_util.h	Thu Jun 30 22:38:17 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,15 +98,22 @@
 JNU_ThrowInstantiationException(JNIEnv *env, const char *msg);
 
 /* Throw an exception by name, using the string returned by
- * JVM_LastErrorString for the detail string.  If the last-error
+ * getLastErrorString for the detail string. If the last-error
  * string is NULL, use the given default detail string.
  */
 JNIEXPORT void JNICALL
 JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name,
-                             const char *defaultMessage);
+                             const char *defaultDetail);
+
+/* Throw an exception by name, using a given message and the string
+ * returned by getLastErrorString to construct the detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowByNameWithMessageAndLastError
+  (JNIEnv *env, const char *name, const char *message);
 
 /* Throw an IOException, using the last-error string for the detail
- * string.  If the last-error string is NULL, use the given default
+ * string. If the last-error string is NULL, use the given default
  * detail string.
  */
 JNIEXPORT void JNICALL
--- a/jdk/src/java.base/share/native/libjli/java.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/share/native/libjli/java.c	Thu Jun 30 22:38:17 2016 +0000
@@ -68,6 +68,7 @@
 static jboolean showVersion = JNI_FALSE;  /* print but continue */
 static jboolean printUsage = JNI_FALSE;   /* print and exit*/
 static jboolean printXUsage = JNI_FALSE;  /* print and exit*/
+static jboolean dryRun = JNI_FALSE;       /* initialize VM and exit */
 static char     *showSettings = NULL;      /* print but continue */
 static char     *listModules = NULL;
 
@@ -489,14 +490,18 @@
     mainArgs = CreateApplicationArgs(env, argv, argc);
     CHECK_EXCEPTION_NULL_LEAVE(mainArgs);
 
-    /* Invoke main method. */
-    (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
+    if (dryRun) {
+        ret = 0;
+    } else {
+        /* Invoke main method. */
+        (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
 
-    /*
-     * The launcher's exit code (in the absence of calls to
-     * System.exit) will be non-zero if main threw an exception.
-     */
-    ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
+        /*
+         * The launcher's exit code (in the absence of calls to
+         * System.exit) will be non-zero if main threw an exception.
+         */
+        ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
+    }
     LEAVE();
 }
 
@@ -1203,6 +1208,8 @@
             return JNI_TRUE;
         } else if (JLI_StrCmp(arg, "-showversion") == 0) {
             showVersion = JNI_TRUE;
+        } else if (JLI_StrCmp(arg, "--dry-run") == 0) {
+            dryRun = JNI_TRUE;
         } else if (JLI_StrCmp(arg, "-X") == 0) {
             printXUsage = JNI_TRUE;
             return JNI_TRUE;
--- a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Thu Jun 30 22:38:17 2016 +0000
@@ -621,8 +621,8 @@
     (*env)->ReleaseStringUTFChars(env, name, name_utf);
 
     if (ret < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGLIFFLAGS failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "getFlags() failed");
         return -1;
     }
 
@@ -1061,8 +1061,8 @@
         // If EPROTONOSUPPORT is returned it means we don't have
         // support for this proto so don't throw an exception.
         if (errno != EPROTONOSUPPORT) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "Socket creation failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Socket creation failed");
         }
         return -1;
     }
@@ -1087,13 +1087,13 @@
     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         if (errno == EPROTONOSUPPORT) {
             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
-                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                             "IPV6 Socket creation failed");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
             }
         } else { // errno is not NOSUPPORT
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "IPV4 Socket creation failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
             return -1;
         }
     }
@@ -1122,15 +1122,15 @@
     // SIOCGIFCOUNT doesn't work
     ifc.ifc_buf = NULL;
     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGIFCONF failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFCONF) failed");
         return ifs;
     }
 #elif defined(_AIX)
     ifc.ifc_buf = NULL;
     if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGSIZIFCONF failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGSIZIFCONF) failed");
         return ifs;
     }
 #endif /* __linux__ */
@@ -1142,8 +1142,8 @@
     siocgifconfRequest = CSIOCGIFCONF;
 #endif
     if (ioctl(sock, siocgifconfRequest, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGIFCONF failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFCONF) failed");
         free(buf);
         return ifs;
     }
@@ -1268,8 +1268,8 @@
 
     ifc.ifc_buf = NULL;
     if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                    "ioctl SIOCGSIZIFCONF failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGSIZIFCONF) failed");
         return ifs;
     }
     bufsize = ifc.ifc_len;
@@ -1282,8 +1282,8 @@
     ifc.ifc_len = bufsize;
     ifc.ifc_buf = buf;
     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl CSIOCGIFCONF failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFCONF) failed");
         free(buf);
         return ifs;
     }
@@ -1368,16 +1368,16 @@
 
     // Let's make sure the interface does have a broadcast address.
     if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2)  < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGIFFLAGS failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFFLAGS) failed");
         return ret;
     }
 
     if (if2.ifr_flags & IFF_BROADCAST) {
         // It does, let's retrieve it
         if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "ioctl SIOCGIFBRDADDR failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFBRDADDR) failed");
             return ret;
         }
 
@@ -1400,8 +1400,8 @@
     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
 
     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGIFNETMASK failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFNETMASK) failed");
         return -1;
     }
 
@@ -1463,8 +1463,8 @@
     memset((char *)&ifr, 0, sizeof(ifr));
     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
     if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGIFHWADDR failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFHWADDR) failed");
         return -1;
     }
 
@@ -1493,8 +1493,8 @@
     }
 
     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGIFMTU failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
         return -1;
     }
 
@@ -1535,15 +1535,15 @@
     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         if (errno == EPROTONOSUPPORT) {
             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
-                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                             "IPV6 Socket creation failed");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
             }
 
             alreadyV6=1;
         } else { // errno is not NOSUPPORT
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "IPV4 Socket creation failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
             return -1;
         }
     }
@@ -1562,8 +1562,8 @@
         if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
             close(sock);
             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
-                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                             "IPV6 Socket creation failed");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
             }
         }
@@ -1607,8 +1607,8 @@
     numifs.lifn_family = family;
     numifs.lifn_flags = 0;
     if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGLIFNUM failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed");
         return ifs;
     }
 
@@ -1621,8 +1621,8 @@
     ifc.lifc_len = bufsize;
     ifc.lifc_buf = buf;
     if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGLIFCONF failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed");
         free(buf);
         return ifs;
     }
@@ -1689,16 +1689,16 @@
 
     // Let's make sure the interface does have a broadcast address
     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2)  < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGLIFFLAGS failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFFLAGS) failed");
         return ret;
     }
 
     if (if2.lifr_flags & IFF_BROADCAST) {
         // It does, let's retrieve it
         if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "ioctl SIOCGLIFBRDADDR failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFBRDADDR) failed");
             return ret;
         }
 
@@ -1721,8 +1721,8 @@
     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
 
     if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGLIFNETMASK failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNETMASK) failed");
         return -1;
     }
 
@@ -1764,8 +1764,8 @@
     msg.len = DL_PHYS_ADDR_REQ_SIZE;
 
     if (putmsg(fd, &msg, NULL, 0) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "putmsg failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "putmsg() failed");
         return -1;
     }
 
@@ -1775,8 +1775,8 @@
     msg.len = 0;
     msg.maxlen = sizeof (buf);
     if (getmsg(fd, &msg, NULL, &flags) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "getmsg failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "getmsg() failed");
         return -1;
     }
 
@@ -1860,8 +1860,8 @@
     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
 
     if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                    "ioctl SIOCGLIFMTU failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFMTU) failed");
         return -1;
     }
 
@@ -1900,13 +1900,13 @@
      if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
          if (errno == EPROTONOSUPPORT) {
               if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
-                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                              "IPV6 Socket creation failed");
+                 JNU_ThrowByNameWithMessageAndLastError
+                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                  return -1;
               }
          } else { // errno is not NOSUPPORT
-             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                          "IPV4 Socket creation failed");
+             JNU_ThrowByNameWithMessageAndLastError
+                 (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
              return -1;
          }
    }
@@ -1927,8 +1927,8 @@
     struct ifaddrs *ifa, *origifa;
 
     if (getifaddrs(&origifa) != 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "getifaddrs() function failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "getifaddrs() failed");
         return ifs;
     }
 
@@ -1997,8 +1997,8 @@
     struct in6_ifreq ifr6;
 
     if (getifaddrs(&origifa) != 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "getifaddrs() function failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "getifaddrs() failed");
         return ifs;
     }
 
@@ -2014,8 +2014,8 @@
                MIN(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len));
 
         if (ioctl(sock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "ioctl SIOCGIFNETMASK_IN6 failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFNETMASK_IN6) failed");
             freeifaddrs(origifa);
             freeif(ifs);
             return NULL;
@@ -2075,16 +2075,16 @@
 
     // Make sure the interface does have a broadcast address
     if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGIFFLAGS failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFFLAGS) failed");
         return ret;
     }
 
     if (if2.ifr_flags & IFF_BROADCAST) {
         // It does, let's retrieve it
         if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "ioctl SIOCGIFBRDADDR failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFBRDADDR) failed");
             return ret;
         }
 
@@ -2107,8 +2107,8 @@
     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
 
     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGIFNETMASK failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFNETMASK) failed");
         return -1;
     }
 
@@ -2156,8 +2156,8 @@
     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
 
     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "ioctl SIOCGIFMTU failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
         return -1;
     }
 
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Thu Jun 30 22:38:17 2016 +0000
@@ -221,8 +221,8 @@
             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
                             "Bind failed");
         } else {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                            "Bind failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Bind failed");
         }
         return;
     }
@@ -233,8 +233,8 @@
          * that the system chose for us and store it in the Socket object.
          */
         if (getsockname(fd, (struct sockaddr *)&him, &slen) == -1) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                            "Error getting socket name");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
             return;
         }
 
@@ -469,7 +469,7 @@
             JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
                             "ICMP Port Unreachable");
         } else {
-            NET_ThrowByNameWithLastError(env, "java/io/IOException", "sendto failed");
+            JNU_ThrowIOExceptionWithLastError(env, "sendto failed");
         }
     }
 
@@ -520,7 +520,8 @@
             } else if (errno == ENOMEM) {
                  JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
             } else {
-                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Peek failed");
+                 JNU_ThrowByNameWithMessageAndLastError
+                     (env, JNU_JAVANETPKG "SocketException", "Peek failed");
             }
             return ret;
         }
@@ -544,7 +545,8 @@
             if (errno == EBADF) {
                  JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
             } else {
-                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Peek failed");
+                 JNU_ThrowByNameWithMessageAndLastError
+                     (env, JNU_JAVANETPKG "SocketException", "Peek failed");
             }
         }
         return 0;
@@ -616,7 +618,8 @@
             } else if (errno == EBADF) {
                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
             } else {
-                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, JNU_JAVANETPKG "SocketException", "Receive failed");
 #else
             } else {
                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
@@ -681,7 +684,8 @@
             if (errno == EBADF) {
                  JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
             } else {
-                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
+                 JNU_ThrowByNameWithMessageAndLastError
+                     (env, JNU_JAVANETPKG "SocketException", "Receive failed");
             }
         }
     } else {
@@ -827,7 +831,8 @@
                     } else if (errno == EBADF) {
                          JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
                     } else {
-                        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
+                        JNU_ThrowByNameWithMessageAndLastError
+                            (env, JNU_JAVANETPKG "SocketException", "Receive failed");
 #else
                     } else {
                         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
@@ -859,7 +864,8 @@
                 if (errno == EBADF) {
                      JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
                  } else {
-                     NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
+                     JNU_ThrowByNameWithMessageAndLastError
+                         (env, JNU_JAVANETPKG "SocketException", "Receive failed");
                  }
             }
         } else {
@@ -932,8 +938,8 @@
     }
 
     if ((fd = socket(domain, SOCK_DGRAM, 0)) == -1) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                       "Error creating socket");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error creating socket");
         return;
     }
 
@@ -1080,8 +1086,8 @@
 
     if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                    (const char*)&in, sizeof(in)) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                       "Error setting socket option");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
     }
 }
 
@@ -1109,8 +1115,8 @@
                 "IPV6_MULTICAST_IF failed (interface has IPv4 "
                 "address only?)");
         } else {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                           "Error setting socket option");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
         }
         return;
     }
@@ -1129,8 +1135,8 @@
 
     if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                    (const char*)&in, sizeof(in)) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                         "Error setting socket option");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
     }
 }
 
@@ -1256,8 +1262,10 @@
     on = (*env)->GetBooleanField(env, value, fid);
     loopback = (!on ? 1 : 0);
 
-    if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&loopback, sizeof(char)) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
+    if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
+                       (const void *)&loopback, sizeof(char)) < 0) {
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
         return;
     }
 }
@@ -1280,8 +1288,10 @@
     on = (*env)->GetBooleanField(env, value, fid);
     loopback = (!on ? 1 : 0);
 
-    if (NET_SetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&loopback, sizeof(int)) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
+    if (NET_SetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
+                       (const void *)&loopback, sizeof(int)) < 0) {
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
         return;
     }
 
@@ -1420,7 +1430,8 @@
     }
 
     if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
         return;
     }
 }
@@ -1483,8 +1494,8 @@
 
         if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                        (char *)inP, &len) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                             "Error getting socket option");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
             return NULL;
         }
 
@@ -1581,8 +1592,8 @@
 
         if (getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
                        (char*)&index, &len) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                           "Error getting socket option");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
             return NULL;
         }
 
@@ -1726,8 +1737,8 @@
         len = SOCKADDR_LEN;
 
         if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                           "Error getting socket name");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
             return NULL;
         }
         iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
@@ -1752,8 +1763,8 @@
     }
 
     if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                         "Error getting socket option");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
         return NULL;
     }
 
@@ -1805,8 +1816,8 @@
     char ittl = (char)ttl;
     if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ittl,
                    sizeof(ittl)) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                       "Error setting socket option");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
     }
 }
 
@@ -1818,8 +1829,8 @@
     int ittl = (int)ttl;
     if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
                    (char*)&ittl, sizeof(ittl)) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                       "Error setting socket option");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
     }
 }
 #endif
@@ -1901,8 +1912,8 @@
 
         if (getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
                        (char*)&ttl, &len) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "Error getting socket option");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
             return -1;
         }
         return (jint)ttl;
@@ -1913,8 +1924,8 @@
             socklen_t len = sizeof(ttl);
             if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL,
                            (char*)&ttl, &len) < 0) {
-                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                               "Error getting socket option");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
                 return -1;
             }
             return (jint)ttl;
--- a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c	Thu Jun 30 22:38:17 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, 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
@@ -476,7 +476,8 @@
             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                             "Socket closed");
         } else {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "connect failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "connect failed");
         }
         return;
     }
@@ -498,8 +499,8 @@
          */
         socklen_t slen = SOCKADDR_LEN;
         if (getsockname(fd, (struct sockaddr *)&him, &slen) == -1) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                           "Error getting socket name");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
         } else {
             localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
             (*env)->SetIntField(env, this, psi_localportID, localport);
@@ -536,8 +537,9 @@
     }
 
     /* bind */
-    if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) {
-      return;
+    if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him,
+                                  &len, JNI_TRUE) != 0) {
+        return;
     }
     setDefaultScopeID(env, (struct sockaddr *)&him);
 
@@ -547,8 +549,8 @@
             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
                            "Bind failed");
         } else {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                           "Bind failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Bind failed");
         }
         return;
     }
@@ -563,8 +565,8 @@
          * that the system chose for us and store it in the Socket object.
          */
         if (getsockname(fd, (struct sockaddr *)&him, &slen) == -1) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                           "Error getting socket name");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
             return;
         }
         localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
@@ -580,8 +582,8 @@
  * Signature: (I)V
  */
 JNIEXPORT void JNICALL
-Java_java_net_PlainSocketImpl_socketListen (JNIEnv *env, jobject this,
-                                            jint count)
+Java_java_net_PlainSocketImpl_socketListen(JNIEnv *env, jobject this,
+                                           jint count)
 {
     /* this FileDescriptor fd field */
     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
@@ -604,8 +606,8 @@
         count -= 1;
 
     if (listen(fd, count) == -1) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                       "Listen failed");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Listen failed");
     }
 }
 
@@ -684,7 +686,8 @@
             } else if (errno == ENOMEM) {
                JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
             } else {
-               NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Accept failed");
+               JNU_ThrowByNameWithMessageAndLastError
+                   (env, JNU_JAVANETPKG "SocketException", "Accept failed");
             }
             return;
         }
@@ -727,7 +730,8 @@
             if (errno == EBADF) {
                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
             } else {
-                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Accept failed");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, JNU_JAVANETPKG "SocketException", "Accept failed");
             }
         }
         return;
@@ -781,8 +785,8 @@
         if (errno == ECONNRESET) {
             JNU_ThrowByName(env, "sun/net/ConnectionResetException", "");
         } else {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "ioctl FIONREAD failed");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "ioctl FIONREAD failed");
         }
     }
     return ret;
@@ -936,8 +940,8 @@
             return;
         }
 #endif /* __solaris__ */
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                      "Error setting socket option");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
     }
 }
 
@@ -981,8 +985,8 @@
         len = SOCKADDR_LEN;
 
         if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                             "Error getting socket name");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
             return -1;
         }
         iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
@@ -1014,8 +1018,8 @@
     }
 
     if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                      "Error getting socket option");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
         return -1;
     }
 
@@ -1063,6 +1067,6 @@
     }
     n = NET_Send(fd, (char *)&d, 1, MSG_OOB);
     if (n == -1) {
-        NET_ThrowByNameWithLastError(env, "java/io/IOException", "Write failed");
+        JNU_ThrowIOExceptionWithLastError(env, "Write failed");
     }
 }
--- a/jdk/src/java.base/unix/native/libnet/SocketInputStream.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/SocketInputStream.c	Thu Jun 30 22:38:17 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, 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
@@ -111,8 +111,8 @@
                 } else if (errno == ENOMEM) {
                     JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
                 } else {
-                    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                                  "select/poll failed");
+                    JNU_ThrowByNameWithMessageAndLastError
+                        (env, JNU_JAVANETPKG "SocketException", "select/poll failed");
                 }
             }
             if (bufP != BUF) {
@@ -145,8 +145,8 @@
                      break;
 
                 default:
-                    NET_ThrowByNameWithLastError(env,
-                        JNU_JAVANETPKG "SocketException", "Read failed");
+                    JNU_ThrowByNameWithMessageAndLastError
+                        (env, JNU_JAVANETPKG "SocketException", "Read failed");
             }
         }
     } else {
--- a/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c	Thu Jun 30 22:38:17 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, 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
@@ -114,8 +114,8 @@
                 JNU_ThrowByName(env, "sun/net/ConnectionResetException",
                     "Connection reset");
             } else {
-                NET_ThrowByNameWithLastError(env, "java/net/SocketException",
-                    "Write failed");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, "java/net/SocketException", "Write failed");
             }
             if (bufP != BUF) {
                 free(bufP);
--- a/jdk/src/java.base/windows/native/libjli/cmdtoargs.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/windows/native/libjli/cmdtoargs.c	Thu Jun 30 22:38:17 2016 +0000
@@ -155,6 +155,7 @@
                 }
             }
             dest += copyCh(ch, dest);
+            slashes = 0;
             break;
 
         default:
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Thu Jun 30 22:38:17 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1713,8 +1713,8 @@
             in.s_addr = htonl(getInetAddress_addr(env, value));
             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                                (const char*)&in, sizeof(in)) < 0) {
-                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Error setting socket option");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
             }
             return;
         }
@@ -1741,7 +1741,7 @@
             }
             index = (*env)->GetIntField(env, value, ni_indexID);
 
-            if ( isAdapterIpv6Enabled(env, index) != 0 ) {
+            if (isAdapterIpv6Enabled(env, index) != 0) {
                 if (setsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF,
                                (const char*)&index, sizeof(index)) < 0) {
                     if (errno == EINVAL && index > 0) {
@@ -1749,8 +1749,8 @@
                             "IPV6_MULTICAST_IF failed (interface has IPv4 "
                             "address only?)");
                     } else {
-                        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                   "Error setting socket option");
+                        JNU_ThrowByNameWithMessageAndLastError
+                            (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
                     }
                     return;
                 }
@@ -1758,13 +1758,13 @@
             /* If there are any IPv4 addresses on this interface then
              * repeat the operation on the IPv4 fd */
 
-            if (getInet4AddrFromIf (env, value, &in) < 0) {
+            if (getInet4AddrFromIf(env, value, &in) < 0) {
                 return;
             }
             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                                (const char*)&in, sizeof(in)) < 0) {
-                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Error setting socket option");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
             }
             return;
         } else {
@@ -1781,8 +1781,8 @@
 
             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                                (const char*)&in, sizeof(in)) < 0) {
-                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                               "Error setting socket option");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
             }
             return;
         }
@@ -1932,8 +1932,8 @@
         int len = sizeof(struct in_addr);
         if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                            (char *)inP, &len) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                             "Error getting socket option");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
             return NULL;
         }
 
@@ -2056,8 +2056,8 @@
         {
             if (getsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF,
                                (char*)&index, &len) < 0) {
-                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                               "Error getting socket option");
+                JNU_ThrowByNameWithMessageAndLastError
+                    (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
                 return NULL;
             }
         }
@@ -2288,8 +2288,8 @@
     }
 
     if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                       "Error getting socket name");
+        JNU_ThrowByNameWithMessageAndLastError
+            (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
         return NULL;
     }
     iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Thu Jun 30 22:38:17 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, 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
@@ -1054,8 +1054,8 @@
         }
 
         if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                             "Error getting socket name");
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
             return -1;
         }
         iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java	Thu Jun 30 22:38:17 2016 +0000
@@ -298,7 +298,7 @@
 
         ByteBuffer[] buffers = frame.getHeaderBlock();
         for (int i = 0; i < buffers.length; i++) {
-            hpackIn.decode(buffers[i], endOfHeaders, decoder);
+            hpackIn.decode(buffers[i], endOfHeaders && (i == buffers.length - 1), decoder);
         }
     }
 
--- a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringReader.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringReader.java	Thu Jun 30 22:38:17 2016 +0000
@@ -78,6 +78,7 @@
             if (isLast) {
                 input.limit(input.position() + remainingLength);
             }
+            remainingLength -= Math.min(input.remaining(), remainingLength);
             if (huffman) {
                 huffmanReader.read(input, output, isLast);
             } else {
@@ -85,6 +86,7 @@
             }
             if (isLast) {
                 input.limit(oldLimit);
+                state = DONE;
             }
             return isLast;
         }
--- a/jdk/src/java.logging/share/classes/java/util/logging/FileHandler.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.logging/share/classes/java/util/logging/FileHandler.java	Thu Jun 30 22:38:17 2016 +0000
@@ -94,6 +94,9 @@
  * <li>   &lt;handler-name&gt;.append
  *        specifies whether the FileHandler should append onto
  *        any existing files (defaults to false). </li>
+ * <li>   &lt;handler-name&gt;.maxLocks
+ *        specifies the maximum number of concurrent locks held by
+ *        FileHandler (defaults to 100). </li>
  * </ul>
  * <p>
  * For example, the properties for {@code FileHandler} would be:
@@ -157,6 +160,7 @@
     private FileChannel lockFileChannel;
     private File files[];
     private static final int MAX_LOCKS = 100;
+    private int maxLocks = MAX_LOCKS;
     private static final Set<String> locks = new HashSet<>();
 
     /**
@@ -235,6 +239,12 @@
         setLevel(manager.getLevelProperty(cname + ".level", Level.ALL));
         setFilter(manager.getFilterProperty(cname + ".filter", null));
         setFormatter(manager.getFormatterProperty(cname + ".formatter", new XMLFormatter()));
+        // Initialize maxLocks from the logging.properties file.
+        // If invalid/no property is provided 100 will be used as a default value.
+        maxLocks = manager.getIntProperty(cname + ".maxLocks", MAX_LOCKS);
+        if(maxLocks <= 0) {
+            maxLocks = MAX_LOCKS;
+        }
         try {
             setEncoding(manager.getStringProperty(cname +".encoding", null));
         } catch (Exception ex) {
@@ -476,7 +486,7 @@
         int unique = -1;
         for (;;) {
             unique++;
-            if (unique > MAX_LOCKS) {
+            if (unique > maxLocks) {
                 throw new IOException("Couldn't get lock for " + pattern);
             }
             // Generate a lock file name from the "unique" int.
--- a/jdk/src/java.logging/share/conf/logging.properties	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/java.logging/share/conf/logging.properties	Thu Jun 30 22:38:17 2016 +0000
@@ -37,6 +37,10 @@
 java.util.logging.FileHandler.pattern = %h/java%u.log
 java.util.logging.FileHandler.limit = 50000
 java.util.logging.FileHandler.count = 1
+# Default number of locks FileHandler can obtain synchronously.
+# This specifies maximum number of attempts to obtain lock file by FileHandler
+# implemented by incrementing the unique field %u as per FileHandler API documentation.
+java.util.logging.FileHandler.maxLocks = 100
 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
 
 # Limit the message that are printed on the console to INFO and above.
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	Thu Jun 30 22:38:17 2016 +0000
@@ -48,6 +48,7 @@
 import java.util.function.Supplier;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import java.util.zip.*;
 import java.util.jar.*;
 import java.util.jar.Pack200.*;
@@ -77,24 +78,82 @@
     PrintStream out, err;
     String fname, mname, ename;
     String zname = "";
-    String[] files;
     String rootjar = null;
 
-    // An entryName(path)->File map generated during "expand", it helps to
+    private static final int BASE_VERSION = 0;
+
+    class Entry {
+        final String basename;
+        final String entryname;
+        final File file;
+        final boolean isDir;
+
+        Entry(int version, File file) {
+            this.file = file;
+            String path = file.getPath();
+            if (file.isDirectory()) {
+                isDir = true;
+                path = path.endsWith(File.separator) ? path :
+                            path + File.separator;
+            } else {
+                isDir = false;
+            }
+            EntryName en = new EntryName(path, version);
+            basename = en.baseName;
+            entryname = en.entryName;
+        }
+    }
+
+    class EntryName {
+        final String baseName;
+        final String entryName;
+
+        EntryName(String name, int version) {
+            name = name.replace(File.separatorChar, '/');
+            String matchPath = "";
+            for (String path : pathsMap.get(version)) {
+                if (name.startsWith(path)
+                        && (path.length() > matchPath.length())) {
+                    matchPath = path;
+                }
+            }
+            name = safeName(name.substring(matchPath.length()));
+            // the old implementaton doesn't remove
+            // "./" if it was led by "/" (?)
+            if (name.startsWith("./")) {
+                name = name.substring(2);
+            }
+            this.baseName = name;
+            this.entryName = (version > BASE_VERSION)
+                    ? VERSIONS_DIR + version + "/" + this.baseName
+                    : this.baseName;
+        }
+    }
+
+    // An entryName(path)->Entry map generated during "expand", it helps to
     // decide whether or not an existing entry in a jar file needs to be
     // replaced, during the "update" operation.
-    Map<String, File> entryMap = new HashMap<String, File>();
+    Map<String, Entry> entryMap = new HashMap<>();
 
-    // All files need to be added/updated.
-    Set<File> entries = new LinkedHashSet<File>();
+    // All entries need to be added/updated.
+    Map<String, Entry> entries = new LinkedHashMap<>();
+
     // All packages.
     Set<String> packages = new HashSet<>();
     // All actual entries added, or existing, in the jar file ( excl manifest
     // and module-info.class ). Populated during create or update.
     Set<String> jarEntries = new HashSet<>();
 
-    // Directories specified by "-C" operation.
-    Set<String> paths = new HashSet<String>();
+    // A paths Set for each version, where each Set contains directories
+    // specified by the "-C" operation.
+    Map<Integer,Set<String>> pathsMap = new HashMap<>();
+
+    // There's also a files array per version
+    Map<Integer,String[]> filesMap = new HashMap<>();
+
+    // Do we think this is a multi-release jar?  Set to true
+    // if --release option found followed by at least file
+    boolean isMultiRelease;
 
     /*
      * cflag: create
@@ -241,10 +300,15 @@
                     if (ename != null) {
                         addMainClass(manifest, ename);
                     }
+                    if (isMultiRelease) {
+                        addMultiRelease(manifest);
+                    }
                 }
                 Map<String,Path> moduleInfoPaths = new HashMap<>();
-                expand(null, files, false, moduleInfoPaths);
-
+                for (int version : filesMap.keySet()) {
+                    String[] files = filesMap.get(version);
+                    expand(null, files, false, moduleInfoPaths, version);
+                }
                 Map<String,byte[]> moduleInfos = new LinkedHashMap<>();
                 if (!moduleInfoPaths.isEmpty()) {
                     if (!checkModuleInfos(moduleInfoPaths))
@@ -348,7 +412,10 @@
                     (new FileInputStream(mname)) : null;
 
                 Map<String,Path> moduleInfoPaths = new HashMap<>();
-                expand(null, files, true, moduleInfoPaths);
+                for (int version : filesMap.keySet()) {
+                    String[] files = filesMap.get(version);
+                    expand(null, files, true, moduleInfoPaths, version);
+                }
 
                 Map<String,byte[]> moduleInfos = new HashMap<>();
                 for (Map.Entry<String,Path> e : moduleInfoPaths.entrySet())
@@ -381,10 +448,11 @@
                     tmpFile.delete();
                 }
             } else if (tflag) {
-                replaceFSC(files);
+                replaceFSC(filesMap);
                 // For the "list table contents" action, access using the
                 // ZipFile class is always most efficient since only a
                 // "one-finger" scan through the central directory is required.
+                String[] files = filesMapToFiles(filesMap);
                 if (fname != null) {
                     list(fname, files);
                 } else {
@@ -396,7 +464,7 @@
                     }
                 }
             } else if (xflag) {
-                replaceFSC(files);
+                replaceFSC(filesMap);
                 // For the extract action, when extracting all the entries,
                 // access using the ZipInputStream class is most efficient,
                 // since only a single sequential scan through the zip file is
@@ -406,6 +474,8 @@
                 // "leading garbage", we fall back from the ZipInputStream
                 // implementation to the ZipFile implementation, since only the
                 // latter can handle it.
+
+                String[] files = filesMapToFiles(filesMap);
                 if (fname != null && files != null) {
                     extract(fname, files);
                 } else {
@@ -421,6 +491,7 @@
                     }
                 }
             } else if (iflag) {
+                String[] files = filesMap.get(BASE_VERSION);  // base entries only, can be null
                 genIndex(rootjar, files);
             } else if (printModuleDescriptor) {
                 boolean found;
@@ -449,6 +520,20 @@
         return ok;
     }
 
+    private String[] filesMapToFiles(Map<Integer,String[]> filesMap) {
+        if (filesMap.isEmpty()) return null;
+        return filesMap.entrySet()
+                .stream()
+                .flatMap(this::filesToEntryNames)
+                .toArray(String[]::new);
+    }
+
+    Stream<String> filesToEntryNames(Map.Entry<Integer,String[]> fileEntries) {
+        int version = fileEntries.getKey();
+        return Stream.of(fileEntries.getValue())
+                .map(f -> (new EntryName(f, version)).entryName);
+    }
+
     /**
      * Parses command line arguments.
      */
@@ -579,8 +664,10 @@
         /* parse file arguments */
         int n = args.length - count;
         if (n > 0) {
+            int version = BASE_VERSION;
             int k = 0;
             String[] nameBuf = new String[n];
+            pathsMap.put(version, new HashSet<>());
             try {
                 for (int i = count; i < args.length; i++) {
                     if (args[i].equals("-C")) {
@@ -592,8 +679,33 @@
                         while (dir.indexOf("//") > -1) {
                             dir = dir.replace("//", "/");
                         }
-                        paths.add(dir.replace(File.separatorChar, '/'));
+                        pathsMap.get(version).add(dir.replace(File.separatorChar, '/'));
                         nameBuf[k++] = dir + args[++i];
+                    } else if (args[i].startsWith("--release")) {
+                        int v = BASE_VERSION;
+                        try {
+                            v = Integer.valueOf(args[++i]);
+                        } catch (NumberFormatException x) {
+                            error(formatMsg("error.release.value.notnumber", args[i]));
+                            // this will fall into the next error, thus returning false
+                        }
+                        if (v < 9) {
+                            error(formatMsg("error.release.value.toosmall", String.valueOf(v)));
+                            usageError();
+                            return false;
+                        }
+                        // associate the files, if any, with the previous version number
+                        if (k > 0) {
+                            String[] files = new String[k];
+                            System.arraycopy(nameBuf, 0, files, 0, k);
+                            filesMap.put(version, files);
+                            isMultiRelease = version > BASE_VERSION;
+                        }
+                        // reset the counters and start with the new version number
+                        k = 0;
+                        nameBuf = new String[n];
+                        version = v;
+                        pathsMap.put(version, new HashSet<>());
                     } else {
                         nameBuf[k++] = args[i];
                     }
@@ -602,8 +714,13 @@
                 usageError();
                 return false;
             }
-            files = new String[k];
-            System.arraycopy(nameBuf, 0, files, 0, k);
+            // associate remaining files, if any, with a version
+            if (k > 0) {
+                String[] files = new String[k];
+                System.arraycopy(nameBuf, 0, files, 0, k);
+                filesMap.put(version, files);
+                isMultiRelease = version > BASE_VERSION;
+            }
         } else if (cflag && (mname == null)) {
             error(getMsg("error.bad.cflag"));
             usageError();
@@ -651,7 +768,8 @@
     void expand(File dir,
                 String[] files,
                 boolean isUpdate,
-                Map<String,Path> moduleInfoPaths)
+                Map<String,Path> moduleInfoPaths,
+                int version)
         throws IOException
     {
         if (files == null)
@@ -664,29 +782,29 @@
             else
                 f = new File(dir, files[i]);
 
+            Entry entry = new Entry(version, f);
+            String entryName = entry.entryname;
+
             if (f.isFile()) {
-                String path = f.getPath();
-                String entryName = entryName(path);
                 if (entryName.endsWith(MODULE_INFO)) {
                     moduleInfoPaths.put(entryName, f.toPath());
                     if (isUpdate)
-                        entryMap.put(entryName, f);
-                } else if (entries.add(f)) {
+                        entryMap.put(entryName, entry);
+                } else if (!entries.containsKey(entryName)) {
+                    entries.put(entryName, entry);
                     jarEntries.add(entryName);
-                    if (path.endsWith(".class") && !entryName.startsWith(VERSIONS_DIR))
-                        packages.add(toPackageName(entryName));
+                    if (entry.basename.endsWith(".class") && !entryName.startsWith(VERSIONS_DIR))
+                        packages.add(toPackageName(entry.basename));
                     if (isUpdate)
-                        entryMap.put(entryName, f);
+                        entryMap.put(entryName, entry);
                 }
             } else if (f.isDirectory()) {
-                if (entries.add(f)) {
+                if (!entries.containsKey(entryName)) {
+                    entries.put(entryName, entry);
                     if (isUpdate) {
-                        String dirPath = f.getPath();
-                        dirPath = (dirPath.endsWith(File.separator)) ? dirPath :
-                            (dirPath + File.separator);
-                        entryMap.put(entryName(dirPath), f);
+                        entryMap.put(entryName, entry);
                     }
-                    expand(f, f.list(), isUpdate, moduleInfoPaths);
+                    expand(f, f.list(), isUpdate, moduleInfoPaths, version);
                 }
             } else {
                 error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
@@ -740,8 +858,9 @@
             in.transferTo(zos);
             zos.closeEntry();
         }
-        for (File file: entries) {
-            addFile(zos, file);
+        for (String entryname : entries.keySet()) {
+            Entry entry = entries.get(entryname);
+            addFile(zos, entry);
         }
         zos.close();
     }
@@ -823,7 +942,7 @@
                 || (Mflag && isManifestEntry)) {
                 continue;
             } else if (isManifestEntry && ((newManifest != null) ||
-                        (ename != null))) {
+                        (ename != null) || isMultiRelease)) {
                 foundManifest = true;
                 if (newManifest != null) {
                     // Don't read from the newManifest InputStream, as we
@@ -862,21 +981,21 @@
                     zos.putNextEntry(e2);
                     copy(zis, zos);
                 } else { // replace with the new files
-                    File f = entryMap.get(name);
-                    addFile(zos, f);
+                    Entry ent = entryMap.get(name);
+                    addFile(zos, ent);
                     entryMap.remove(name);
-                    entries.remove(f);
+                    entries.remove(name);
                 }
 
                 jarEntries.add(name);
-                if (name.endsWith(".class"))
+                if (name.endsWith(".class") && !(name.startsWith(VERSIONS_DIR)))
                     packages.add(toPackageName(name));
             }
         }
 
         // add the remaining new files
-        for (File f: entries) {
-            addFile(zos, f);
+        for (String entryname : entries.keySet()) {
+            addFile(zos, entries.get(entryname));
         }
         if (!foundManifest) {
             if (newManifest != null) {
@@ -961,6 +1080,9 @@
         if (ename != null) {
             addMainClass(m, ename);
         }
+        if (isMultiRelease) {
+            addMultiRelease(m);
+        }
         ZipEntry e = new ZipEntry(MANIFEST_NAME);
         e.setTime(System.currentTimeMillis());
         if (flag0) {
@@ -1016,24 +1138,6 @@
         return name;
     }
 
-    private String entryName(String name) {
-        name = name.replace(File.separatorChar, '/');
-        String matchPath = "";
-        for (String path : paths) {
-            if (name.startsWith(path)
-                && (path.length() > matchPath.length())) {
-                matchPath = path;
-            }
-        }
-        name = safeName(name.substring(matchPath.length()));
-        // the old implementaton doesn't remove
-        // "./" if it was led by "/" (?)
-        if (name.startsWith("./")) {
-            name = name.substring(2);
-        }
-        return name;
-    }
-
     private void addVersion(Manifest m) {
         Attributes global = m.getMainAttributes();
         if (global.getValue(Attributes.Name.MANIFEST_VERSION) == null) {
@@ -1058,6 +1162,11 @@
         global.put(Attributes.Name.MAIN_CLASS, mainApp);
     }
 
+    private void addMultiRelease(Manifest m) {
+        Attributes global = m.getMainAttributes();
+        global.put(Attributes.Name.MULTI_RELEASE, "true");
+    }
+
     private boolean isAmbiguousMainClass(Manifest m) {
         if (ename != null) {
             Attributes global = m.getMainAttributes();
@@ -1073,14 +1182,10 @@
     /**
      * Adds a new file entry to the ZIP output stream.
      */
-    void addFile(ZipOutputStream zos, File file) throws IOException {
-        String name = file.getPath();
-        boolean isDir = file.isDirectory();
-        if (isDir) {
-            name = name.endsWith(File.separator) ? name :
-                (name + File.separator);
-        }
-        name = entryName(name);
+    void addFile(ZipOutputStream zos, Entry entry) throws IOException {
+        File file = entry.file;
+        String name = entry.entryname;
+        boolean isDir = entry.isDir;
 
         if (name.equals("") || name.equals(".") || name.equals(zname)) {
             return;
@@ -1221,12 +1326,15 @@
         os.updateEntry(e);
     }
 
-    void replaceFSC(String files[]) {
-        if (files != null) {
-            for (int i = 0; i < files.length; i++) {
-                files[i] = files[i].replace(File.separatorChar, '/');
+    void replaceFSC(Map<Integer, String []> filesMap) {
+        filesMap.keySet().forEach(version -> {
+            String[] files = filesMap.get(version);
+            if (files != null) {
+                for (int i = 0; i < files.length; i++) {
+                    files[i] = files[i].replace(File.separatorChar, '/');
+                }
             }
-        }
+        });
     }
 
     @SuppressWarnings("serial")
@@ -1566,7 +1674,7 @@
     /**
      * Print an error message; like something is broken
      */
-    protected void error(String s) {
+    void error(String s) {
         err.println(s);
     }
 
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties	Thu Jun 30 22:38:17 2016 +0000
@@ -63,24 +63,28 @@
 error.module.descriptor.not.found=\
         Module descriptor not found
 error.versioned.info.without.root=\
-        module-info.class found in versioned section without module-info.class \
+        module-info.class found in a versioned directory without module-info.class \
         in the root
 error.versioned.info.name.notequal=\
-        module-info.class in versioned section contains incorrect name
+        module-info.class in a versioned directory contains incorrect name
 error.versioned.info.requires.public=\
-        module-info.class in versioned section contains additional requires public
+        module-info.class in a versioned directory contains additional requires public
 error.versioned.info.requires.added=\
-        module-info.class in versioned section contains additional requires
+        module-info.class in a versioned directory contains additional requires
 error.versioned.info.requires.dropped=\
-        module-info.class in versioned section contains missing requires
+        module-info.class in a versioned directory contains missing requires
 error.versioned.info.exports.notequal=\
-        module-info.class in versioned section contains different exports
+        module-info.class in a versioned directory contains different exports
 error.versioned.info.provides.notequal=\
-        module-info.class in versioned section contains different provides
+        module-info.class in a versioned directory contains different provides
 error.invalid.versioned.module.attribute=\
         Invalid module descriptor attribute {0}
 error.missing.provider=\
         Service provider not found: {0}
+error.release.value.notnumber=\
+        release {0} not valid
+error.release.value.toosmall=\
+        release {0} not valid, must be >= 9
 out.added.manifest=\
         added manifest
 out.added.module-info=\
@@ -109,7 +113,7 @@
 usage.compat=\
 \Compatibility Interface:\
 \n\
-Usage: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\
+Usage: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files] ...\n\
 Options:\n\
 \ \   -c  create new archive\n\
 \ \   -t  list table of contents for archive\n\
@@ -141,7 +145,7 @@
 Try `jar --help' for more information.
 
 main.help.preopt=\
-Usage: jar [OPTION...] [-C dir] files ...\n\
+Usage: jar [OPTION...] [ [--release VERSION] [-C dir] files] ...\n\
 jar creates an archive for classes and resources, and can manipulate or\n\
 restore individual classes or resources from an archive.\n\
 \n\
@@ -156,7 +160,9 @@
 \     -C foo/ classes resources\n\
 \ # Update an existing non-modular jar to a modular jar:\n\
 \ jar --update --file foo.jar --main-class com.foo.Main --module-version 1.0\n\
-\     -C foo/ module-info.class
+\     -C foo/ module-info.class\n\
+\ # Create a multi-release jar, placing some files in the META-INF/versions/9 directory:\n\
+\ jar --create --file mr.jar -C foo classes --release 9 -C foo9 classes
 main.help.opt.main=\
 \ Main operation mode:\n
 main.help.opt.main.create=\
@@ -178,7 +184,9 @@
 \  -C DIR                     Change to the specified directory and include the\n\
 \                             following file
 main.help.opt.any.file=\
-\  -f, --file=FILE            The archive file name
+\  -f, --file=FILE            The archive file name\n\
+\      --release VERSION      Places all following files in a versioned directory\n\
+\                             of the jar (i.e. META-INF/versions/VERSION/)
 main.help.opt.any.verbose=\
 \  -v, --verbose              Generate verbose output on standard output
 main.help.opt.create.update=\
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java	Thu Jun 30 22:38:17 2016 +0000
@@ -32,10 +32,10 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import jdk.tools.jlink.internal.ExecutableImage;
 import jdk.tools.jlink.internal.JlinkTask;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.builder.ImageBuilder;
 import jdk.tools.jlink.internal.PluginRepository;
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java	Thu Jun 30 22:38:17 2016 +0000
@@ -57,7 +57,7 @@
 import jdk.tools.jlink.internal.BasicImageWriter;
 import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
 import jdk.tools.jlink.internal.plugins.FileCopierPlugin.SymImageFile;
-import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.internal.ExecutableImage;
 import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.PluginException;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java	Thu Jun 30 22:38:17 2016 +0000
@@ -27,7 +27,7 @@
 import java.io.DataOutputStream;
 import java.util.Properties;
 
-import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.internal.ExecutableImage;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ModulePool;
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractModuleEntry.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractModuleEntry.java	Thu Jun 30 22:38:17 2016 +0000
@@ -25,7 +25,6 @@
 
 package jdk.tools.jlink.internal;
 
-import java.io.InputStream;
 import java.util.Objects;
 import jdk.tools.jlink.plugin.ModuleEntry;
 
@@ -77,9 +76,7 @@
 
     @Override
     public int hashCode() {
-        int hash = 7;
-        hash = 89 * hash + Objects.hashCode(this.path);
-        return hash;
+        return Objects.hashCode(this.path);
     }
 
     @Override
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Archive.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Archive.java	Thu Jun 30 22:38:17 2016 +0000
@@ -42,7 +42,6 @@
     public abstract class Entry {
 
         public static enum EntryType {
-
             MODULE_NAME,
             CLASS_OR_RESOURCE,
             NATIVE_LIB,
@@ -57,14 +56,10 @@
         private final String path;
 
         public Entry(Archive archive, String path, String name, EntryType type) {
-            Objects.requireNonNull(archive);
-            Objects.requireNonNull(path);
-            Objects.requireNonNull(name);
-            Objects.requireNonNull(type);
-            this.archive = archive;
-            this.path = path;
-            this.name = name;
-            this.type = type;
+            this.archive = Objects.requireNonNull(archive);
+            this.path = Objects.requireNonNull(path);
+            this.name = Objects.requireNonNull(name);
+            this.type = Objects.requireNonNull(type);
         }
 
         public Archive archive() {
@@ -79,7 +74,7 @@
             return type;
         }
 
-        /**
+        /*
          * Returns the name of this entry.
          */
         public String name() {
@@ -91,7 +86,7 @@
             return "type " + type.name() + " path " + path;
         }
 
-        /**
+        /*
          * Returns the number of uncompressed bytes for this entry.
          */
         public abstract long size();
@@ -99,17 +94,17 @@
         public abstract InputStream stream() throws IOException;
     }
 
-    /**
+    /*
      * The module name.
      */
     String moduleName();
 
-    /**
+    /*
      * Returns the path to this module's content
      */
     Path getPath();
 
-    /**
+    /*
      * Stream of Entry.
      * The stream of entries needs to be closed after use
      * since it might cover lazy I/O based resources.
@@ -117,12 +112,12 @@
      */
     Stream<Entry> entries();
 
-    /**
+    /*
      * Open the archive
      */
     void open() throws IOException;
 
-    /**
+    /*
      * Close the archive
      */
     void close() throws IOException;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryModuleEntry.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryModuleEntry.java	Thu Jun 30 22:38:17 2016 +0000
@@ -25,7 +25,6 @@
 
 package jdk.tools.jlink.internal;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UncheckedIOException;
@@ -46,7 +45,7 @@
      * @param entry The archive Entry.
      */
     ArchiveEntryModuleEntry(String module, String path, Archive.Entry entry) {
-        super(module, path, getImageFileType(entry));
+        super(module, path, getImageFileType(Objects.requireNonNull(entry)));
         this.entry = entry;
     }
 
@@ -65,7 +64,6 @@
     }
 
     private static ModuleEntry.Type getImageFileType(Archive.Entry entry) {
-        Objects.requireNonNull(entry);
         switch(entry.type()) {
             case CLASS_OR_RESOURCE:
                 return ModuleEntry.Type.CLASS_OR_RESOURCE;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/BasicImageWriter.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/BasicImageWriter.java	Thu Jun 30 22:38:17 2016 +0000
@@ -28,6 +28,7 @@
 import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import jdk.internal.jimage.ImageHeader;
 import jdk.internal.jimage.ImageStream;
 import jdk.internal.jimage.ImageStringsReader;
@@ -54,7 +55,7 @@
     }
 
     public BasicImageWriter(ByteOrder byteOrder) {
-        this.byteOrder = byteOrder;
+        this.byteOrder = Objects.requireNonNull(byteOrder);
         this.input = new ArrayList<>();
         this.strings = new ImageStringsWriter();
         this.headerStream = new ImageStream(byteOrder);
@@ -96,8 +97,8 @@
     private void generatePerfectHash() {
         PerfectHashBuilder<ImageLocationWriter> builder =
             new PerfectHashBuilder<>(
-                        PerfectHashBuilder.Entry.class, // PerfectHashBuilder.Entry<ImageLocationWriter>().getClass()
-                        PerfectHashBuilder.Bucket.class); // PerfectHashBuilder.Bucket<ImageLocationWriter>().getClass()
+                        PerfectHashBuilder.Entry.class,
+                        PerfectHashBuilder.Bucket.class);
 
         input.forEach((location) -> {
             builder.put(location.getFullName(), location);
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayModuleEntry.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayModuleEntry.java	Thu Jun 30 22:38:17 2016 +0000
@@ -31,7 +31,6 @@
 import java.io.OutputStream;
 import java.io.UncheckedIOException;
 import java.util.Objects;
-import jdk.tools.jlink.plugin.ModuleEntry;
 
 /**
  * A ModuleEntry backed by a given byte[].
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/DirArchive.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/DirArchive.java	Thu Jun 30 22:38:17 2016 +0000
@@ -112,13 +112,11 @@
 
     @Override
     public Stream<Entry> entries() {
-        Stream<Entry> ret = null;
         try {
-            ret = Files.walk(dirPath).map(this::toEntry).filter(n -> n != null);
+            return Files.walk(dirPath).map(this::toEntry).filter(n -> n != null);
         } catch (IOException ex) {
             throw new RuntimeException(ex);
         }
-        return ret;
     }
 
     private Archive.Entry toEntry(Path p) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ExecutableImage.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.tools.jlink.internal;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * An executable runtime image. Contains the information about the executable
+ * image created.
+ */
+public interface ExecutableImage {
+
+    /**
+     * Image home directory,
+     *
+     * @return The home directory.
+     */
+    public Path getHome();
+
+    /**
+     * The names of the modules located in the image.
+     *
+     * @return The set of modules.
+     */
+    public Set<String> getModules();
+
+    /**
+     * The list of arguments required to execute the image.
+     *
+     * @return The list of arguments.
+     */
+    public List<String> getExecutionArgs();
+
+    /**
+     * Store new arguments required to execute the image.
+     *
+     * @param args Additional arguments
+     */
+    public void storeLaunchArgs(List<String> args);
+}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java	Thu Jun 30 22:38:17 2016 +0000
@@ -25,10 +25,8 @@
 package jdk.tools.jlink.internal;
 
 import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteOrder;
 import java.nio.file.Files;
@@ -45,9 +43,7 @@
 import jdk.tools.jlink.internal.Archive.Entry;
 import jdk.tools.jlink.internal.Archive.Entry.EntryType;
 import jdk.tools.jlink.internal.ModulePoolImpl.CompressedModuleData;
-import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.ModuleEntry;
 
 /**
@@ -73,7 +69,7 @@
     private final Map<String, List<Entry>> entriesForModule = new HashMap<>();
     private final ImagePluginStack plugins;
     private ImageFileCreator(ImagePluginStack plugins) {
-        this.plugins = plugins;
+        this.plugins = Objects.requireNonNull(plugins);
     }
 
     public static ExecutableImage create(Set<Archive> archives,
@@ -232,9 +228,9 @@
         out.write(bytes, 0, bytes.length);
 
         // write module content
-        for (ModuleEntry res : content) {
+        content.stream().forEach((res) -> {
             res.write(out);
-        }
+        });
 
         tree.addContent(out);
 
@@ -283,21 +279,6 @@
         return resources;
     }
 
-    private static final int BUF_SIZE = 8192;
-
-    private static byte[] readAllBytes(InputStream is) throws IOException {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        byte[] buf = new byte[BUF_SIZE];
-        while (true) {
-            int n = is.read(buf);
-            if (n < 0) {
-                break;
-            }
-            baos.write(buf, 0, n);
-        }
-        return baos.toByteArray();
-    }
-
     /**
      * Helper method that splits a Resource path onto 3 items: module, parent
      * and resource name.
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java	Thu Jun 30 22:38:17 2016 +0000
@@ -32,33 +32,30 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.builder.ImageBuilder;
 import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.Plugin.Category;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.PostProcessorPlugin;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 
 /**
  * Plugins configuration.
  */
 public final class ImagePluginConfiguration {
 
-    private static final List<Plugin.Category> CATEGORIES_ORDER = new ArrayList<>();
+    private static final List<Category> CATEGORIES_ORDER = new ArrayList<>();
 
     static {
-        CATEGORIES_ORDER.add(Plugin.Category.FILTER);
-        CATEGORIES_ORDER.add(Plugin.Category.TRANSFORMER);
-        CATEGORIES_ORDER.add(Plugin.Category.MODULEINFO_TRANSFORMER);
-        CATEGORIES_ORDER.add(Plugin.Category.SORTER);
-        CATEGORIES_ORDER.add(Plugin.Category.COMPRESSOR);
-        CATEGORIES_ORDER.add(Plugin.Category.METAINFO_ADDER);
-        CATEGORIES_ORDER.add(Plugin.Category.VERIFIER);
-        CATEGORIES_ORDER.add(Plugin.Category.PROCESSOR);
-        CATEGORIES_ORDER.add(Plugin.Category.PACKAGER);
+        CATEGORIES_ORDER.add(Category.FILTER);
+        CATEGORIES_ORDER.add(Category.TRANSFORMER);
+        CATEGORIES_ORDER.add(Category.MODULEINFO_TRANSFORMER);
+        CATEGORIES_ORDER.add(Category.SORTER);
+        CATEGORIES_ORDER.add(Category.COMPRESSOR);
+        CATEGORIES_ORDER.add(Category.METAINFO_ADDER);
+        CATEGORIES_ORDER.add(Category.VERIFIER);
+        CATEGORIES_ORDER.add(Category.PROCESSOR);
+        CATEGORIES_ORDER.add(Category.PACKAGER);
     }
 
     private ImagePluginConfiguration() {
@@ -72,8 +69,8 @@
         if (pluginsConfiguration == null) {
             return new ImagePluginStack();
         }
-        Map<Plugin.Category, List<Plugin>> plugins = new LinkedHashMap<>();
-        for (Plugin.Category cat : CATEGORIES_ORDER) {
+        Map<Category, List<Plugin>> plugins = new LinkedHashMap<>();
+        for (Category cat : CATEGORIES_ORDER) {
             plugins.put(cat, new ArrayList<>());
         }
 
@@ -85,7 +82,7 @@
                         + " added more than once to stack ");
             }
             seen.add(plug.getName());
-            Category category = Utils.getCategory(plug);
+            Category category = plug.getType();
             if (category == null) {
                 throw new PluginException("Invalid category for "
                         + plug.getName());
@@ -94,26 +91,13 @@
             lst.add(plug);
         }
 
-        List<TransformerPlugin> transformerPlugins = new ArrayList<>();
-        List<PostProcessorPlugin> postProcessingPlugins = new ArrayList<>();
-        for (Entry<Plugin.Category, List<Plugin>> entry : plugins.entrySet()) {
+        List<Plugin> orderedPlugins = new ArrayList<>();
+        plugins.entrySet().stream().forEach((entry) -> {
             // Sort according to plugin constraints
-            List<Plugin> orderedPlugins = PluginOrderingGraph.sort(entry.getValue());
-            Category category = entry.getKey();
-            for (Plugin p : orderedPlugins) {
-                if (category.isPostProcessor()) {
-                    @SuppressWarnings("unchecked")
-                    PostProcessorPlugin pp = (PostProcessorPlugin) p;
-                    postProcessingPlugins.add(pp);
-                } else {
-                    @SuppressWarnings("unchecked")
-                    TransformerPlugin trans = (TransformerPlugin) p;
-                    transformerPlugins.add(trans);
-                }
-            }
-        }
+            orderedPlugins.addAll(PluginOrderingGraph.sort(entry.getValue()));
+        });
         Plugin lastSorter = null;
-        for (Plugin plugin : transformerPlugins) {
+        for (Plugin plugin : orderedPlugins) {
             if (plugin.getName().equals(pluginsConfiguration.getLastSorterPluginName())) {
                 lastSorter = plugin;
                 break;
@@ -145,7 +129,6 @@
             };
         }
 
-        return new ImagePluginStack(builder, transformerPlugins,
-                lastSorter, postProcessingPlugins);
+        return new ImagePluginStack(builder, orderedPlugins, lastSorter);
     }
 }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,7 +24,6 @@
  */
 package jdk.tools.jlink.internal;
 
-import java.io.ByteArrayInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.lang.module.ModuleDescriptor;
@@ -45,14 +44,11 @@
 
 import jdk.internal.jimage.decompressor.Decompressor;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.builder.ImageBuilder;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.LinkModule;
 import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.PostProcessorPlugin;
 
 /**
  * Plugins Stack. Plugins entry point to apply transformations onto resources
@@ -96,7 +92,7 @@
 
         public CheckOrderResourcePool(ByteOrder order, List<ModuleEntry> orderedList, StringTable table) {
             super(order, table);
-            this.orderedList = orderedList;
+            this.orderedList = Objects.requireNonNull(orderedList);
         }
 
         /**
@@ -119,7 +115,6 @@
 
         private int currentid = 0;
         private final Map<String, Integer> stringsUsage = new HashMap<>();
-
         private final Map<String, Integer> stringsMap = new HashMap<>();
         private final Map<Integer, String> reverseMap = new HashMap<>();
 
@@ -161,47 +156,40 @@
         }
     }
 
+    private final ImageBuilder imageBuilder;
     private final Plugin lastSorter;
-    private final List<TransformerPlugin> contentPlugins = new ArrayList<>();
-    private final List<PostProcessorPlugin> postProcessingPlugins = new ArrayList<>();
+    private final List<Plugin> plugins = new ArrayList<>();
     private final List<ResourcePrevisitor> resourcePrevisitors = new ArrayList<>();
 
-    private final ImageBuilder imageBuilder;
 
     public ImagePluginStack() {
-        this(null, Collections.emptyList(), null,
-                Collections.emptyList());
+        this(null, Collections.emptyList(), null);
     }
 
     public ImagePluginStack(ImageBuilder imageBuilder,
-            List<TransformerPlugin> contentPlugins,
-            Plugin lastSorter,
-            List<PostProcessorPlugin> postprocessingPlugins) {
-        Objects.requireNonNull(contentPlugins);
+            List<Plugin> plugins,
+            Plugin lastSorter) {
+        this.imageBuilder = Objects.requireNonNull(imageBuilder);
         this.lastSorter = lastSorter;
-        for (TransformerPlugin p : contentPlugins) {
+        this.plugins.addAll(Objects.requireNonNull(plugins));
+        plugins.stream().forEach((p) -> {
             Objects.requireNonNull(p);
             if (p instanceof ResourcePrevisitor) {
                 resourcePrevisitors.add((ResourcePrevisitor) p);
             }
-            this.contentPlugins.add(p);
-        }
-        for (PostProcessorPlugin p : postprocessingPlugins) {
-            Objects.requireNonNull(p);
-            this.postProcessingPlugins.add(p);
-        }
-        this.imageBuilder = imageBuilder;
+        });
     }
 
     public void operate(ImageProvider provider) throws Exception {
         ExecutableImage img = provider.retrieve(this);
         List<String> arguments = new ArrayList<>();
-        for (PostProcessorPlugin plugin : postProcessingPlugins) {
-            List<String> lst = plugin.process(img);
-            if (lst != null) {
-                arguments.addAll(lst);
-            }
-        }
+        plugins.stream()
+                .filter(PostProcessor.class::isInstance)
+                .map((plugin) -> ((PostProcessor)plugin).process(img))
+                .filter((lst) -> (lst != null))
+                .forEach((lst) -> {
+                     arguments.addAll(lst);
+                });
         img.storeLaunchArgs(arguments);
     }
 
@@ -230,19 +218,19 @@
                     resources.getStringTable());
         }
         PreVisitStrings previsit = new PreVisitStrings();
-        for (ResourcePrevisitor p : resourcePrevisitors) {
+        resourcePrevisitors.stream().forEach((p) -> {
             p.previsit(resources, previsit);
-        }
+        });
 
         // Store the strings resulting from the previsit.
         List<String> sorted = previsit.getSortedStrings();
-        for (String s : sorted) {
+        sorted.stream().forEach((s) -> {
             resources.getStringTable().addString(s);
-        }
+        });
 
         ModulePoolImpl current = resources;
         List<ModuleEntry> frozenOrder = null;
-        for (TransformerPlugin p : contentPlugins) {
+        for (Plugin p : plugins) {
             current.setReadOnly();
             ModulePoolImpl output = null;
             if (p == lastSorter) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java	Thu Jun 30 22:38:17 2016 +0000
@@ -113,8 +113,7 @@
             private final boolean isEmpty;
 
             PackageReference(String name, boolean isEmpty) {
-                Objects.requireNonNull(name);
-                this.name = name;
+                this.name = Objects.requireNonNull(name);
                 this.isEmpty = isEmpty;
             }
 
@@ -132,12 +131,8 @@
 
         private void addReference(String name, boolean isEmpty) {
             PackageReference ref = references.get(name);
-            if (ref == null) {
+            if (ref == null || ref.isEmpty) {
                 references.put(name, new PackageReference(name, isEmpty));
-            } else {
-                if (ref.isEmpty) { // replace with new one incase non empty.
-                    references.put(name, new PackageReference(name, isEmpty));
-                }
             }
         }
 
@@ -267,8 +262,7 @@
             }
             // Validate that the packages are well formed.
             for (Node n : packages.children.values()) {
-                PackageNode pkg = (PackageNode) n;
-                pkg.validate();
+                ((PackageNode)n).validate();
             }
 
         }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageStringsWriter.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageStringsWriter.java	Thu Jun 30 22:38:17 2016 +0000
@@ -44,9 +44,15 @@
 
         // Reserve 0 offset for empty string.
         int offset = addString("");
-        assert offset == 0 : "Empty string not zero offset";
+        if (offset != 0) {
+            throw new InternalError("Empty string not offset zero");
+        }
+
         // Reserve 1 offset for frequently used ".class".
-        addString("class");
+        offset = addString("class");
+        if (offset != 1) {
+            throw new InternalError("'class' string not offset one");
+        }
     }
 
     private int addString(final String string) {
@@ -76,7 +82,9 @@
     public String get(int offset) {
         ByteBuffer buffer = stream.getBuffer();
         int capacity = buffer.capacity();
-        assert 0 <= offset && offset < capacity : "String buffer offset out of range";
+        if (offset < 0 || offset >= capacity) {
+            throw new InternalError("String buffer offset out of range");
+        }
         int zero = NOT_FOUND;
         for (int i = offset; i < capacity; i++) {
             if (buffer.get(i) == '\0') {
@@ -84,7 +92,9 @@
                 break;
             }
         }
-        assert zero != NOT_FOUND;
+        if (zero == NOT_FOUND) {
+            throw new InternalError("String zero terminator not found");
+        }
         int length = zero - offset;
         byte[] bytes = new byte[length];
         int mark = buffer.position();
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JarArchive.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JarArchive.java	Thu Jun 30 22:38:17 2016 +0000
@@ -30,8 +30,6 @@
 import java.io.UncheckedIOException;
 import java.nio.file.Path;
 import java.util.Objects;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
@@ -53,8 +51,8 @@
 
         JarEntry(String path, String name, EntryType type, ZipFile file, ZipEntry entry) {
             super(JarArchive.this, path, name, type);
-            this.entry = entry;
-            this.file = file;
+            this.entry = Objects.requireNonNull(entry);
+            this.file = Objects.requireNonNull(file);
             size = entry.getSize();
         }
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java	Thu Jun 30 22:38:17 2016 +0000
@@ -49,7 +49,6 @@
 import jdk.tools.jlink.internal.TaskHelper.Option;
 import jdk.tools.jlink.internal.TaskHelper.OptionsHelper;
 import jdk.tools.jlink.internal.ImagePluginStack.ImageProvider;
-import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.Jlink.JlinkConfiguration;
 import jdk.tools.jlink.Jlink.PluginsConfiguration;
 import jdk.tools.jlink.plugin.PluginException;
@@ -82,7 +81,7 @@
     private static final TaskHelper taskHelper
             = new TaskHelper(JLINK_BUNDLE);
 
-    static Option<?>[] recognizedOptions = {
+    private static final Option<?>[] recognizedOptions = {
         new Option<JlinkTask>(false, (task, opt, arg) -> {
             task.options.help = true;
         }, "--help"),
@@ -184,8 +183,8 @@
                 optionsHelper.showHelp(PROGNAME);
                 return EXIT_OK;
             }
-            if (optionsHelper.listPlugins()) {
-                optionsHelper.listPlugins(true);
+            if (optionsHelper.shouldListPlugins()) {
+                optionsHelper.listPlugins();
                 return EXIT_OK;
             }
             if (options.version || options.fullVersion) {
@@ -325,7 +324,6 @@
                                                Set<String> limitMods,
                                                Set<String> addMods)
     {
-
         ModuleFinder finder = ModuleFinder.of(paths.toArray(new Path[0]));
 
         // jmods are located at link-time
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JmodArchive.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JmodArchive.java	Thu Jun 30 22:38:17 2016 +0000
@@ -25,7 +25,6 @@
 
 package jdk.tools.jlink.internal;
 
-import jdk.tools.jlink.internal.JarArchive;
 import java.nio.file.Path;
 import java.util.Objects;
 import jdk.tools.jlink.internal.Archive.Entry.EntryType;
@@ -35,7 +34,7 @@
  */
 public class JmodArchive extends JarArchive {
 
-    private static final String JMOD_EXT = ".jmod";
+    private static final String JMOD_EXT    = ".jmod";
     private static final String MODULE_NAME = "module";
     private static final String MODULE_INFO = "module-info.class";
     private static final String CLASSES     = "classes";
@@ -46,8 +45,9 @@
     public JmodArchive(String mn, Path jmod) {
         super(mn, jmod);
         String filename = Objects.requireNonNull(jmod.getFileName()).toString();
-        if (!filename.endsWith(JMOD_EXT))
+        if (!filename.endsWith(JMOD_EXT)) {
             throw new UnsupportedOperationException("Unsupported format: " + filename);
+        }
     }
 
     @Override
@@ -65,7 +65,6 @@
             case MODULE_NAME:
                 return EntryType.MODULE_NAME;
             default:
-                //throw new InternalError("unexpected entry: " + name + " " + zipfile.toString()); //TODO
                 throw new InternalError("unexpected entry: " + section);
         }
     }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModularJarArchive.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModularJarArchive.java	Thu Jun 30 22:38:17 2016 +0000
@@ -39,8 +39,9 @@
     public ModularJarArchive(String mn, Path jmod) {
         super(mn, jmod);
         String filename = Objects.requireNonNull(jmod.getFileName()).toString();
-        if (!filename.endsWith(JAR_EXT))
+        if (!filename.endsWith(JAR_EXT)) {
             throw new UnsupportedOperationException("Unsupported format: " + filename);
+        }
     }
 
     @Override
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryFactory.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryFactory.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,7 +24,6 @@
  */
 package jdk.tools.jlink.internal;
 
-import java.io.InputStream;
 import java.nio.file.Path;
 import java.util.Objects;
 import jdk.tools.jlink.plugin.ModuleEntry;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,8 +24,6 @@
  */
 package jdk.tools.jlink.internal;
 
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
 import java.lang.module.ModuleDescriptor;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -168,8 +166,8 @@
     }
 
     public ModulePoolImpl(ByteOrder order, StringTable table) {
-        this.order = order;
-        this.table = table;
+        this.order = Objects.requireNonNull(order);
+        this.table = Objects.requireNonNull(table);
     }
 
     /**
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathModuleEntry.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathModuleEntry.java	Thu Jun 30 22:38:17 2016 +0000
@@ -31,7 +31,6 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Objects;
-import jdk.tools.jlink.plugin.ModuleEntry;
 
 /**
  * A ModuleEntry backed by a given nio Path.
@@ -43,9 +42,9 @@
      * Create a new PathModuleEntry.
      *
      * @param module The module name.
-     * @param file The data file identifier.
+     * @param path The path for the resource content.
      * @param type The data type.
-     * @param file The Path for the resource content.
+     * @param file The data file identifier.
      */
     public PathModuleEntry(String module, String path, Type type, Path file) {
         super(module, path, type);
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginRepository.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginRepository.java	Thu Jun 30 22:38:17 2016 +0000
@@ -34,8 +34,6 @@
 import java.util.ServiceLoader;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.PostProcessorPlugin;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 
 /**
  *
@@ -59,17 +57,7 @@
      */
     public static Plugin getPlugin(String name,
             Layer pluginsLayer) {
-        Plugin tp = getPlugin(TransformerPlugin.class, name, pluginsLayer);
-        Plugin ppp = getPlugin(PostProcessorPlugin.class, name, pluginsLayer);
-
-        // We should not have a transformer plugin and a post processor plugin
-        // of the same name. That kind of duplicate is detected here.
-        if (tp != null && ppp != null) {
-            throw new PluginException("Multiple plugin "
-                        + "for the name " + name);
-        }
-
-        return tp != null? tp : ppp;
+        return getPlugin(Plugin.class, name, pluginsLayer);
     }
 
     /**
@@ -112,10 +100,7 @@
     }
 
     public static List<Plugin> getPlugins(Layer pluginsLayer) {
-        List<Plugin> plugins = new ArrayList<>();
-        plugins.addAll(getPlugins(TransformerPlugin.class, pluginsLayer));
-        plugins.addAll(getPlugins(PostProcessorPlugin.class, pluginsLayer));
-        return plugins;
+        return getPlugins(Plugin.class, pluginsLayer);
     }
 
     private static <T extends Plugin> T getPlugin(Class<T> clazz, String name,
@@ -138,10 +123,10 @@
     }
 
     /**
-     * The post processors accessible in the current context.
+     * The plugins accessible in the current context.
      *
      * @param pluginsLayer
-     * @return The list of post processors.
+     * @return The list of plugins.
      */
     private static <T extends Plugin> List<T> getPlugins(Class<T> clazz, Layer pluginsLayer) {
         Objects.requireNonNull(pluginsLayer);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PostProcessor.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.tools.jlink.internal;
+
+import java.util.List;
+
+/**
+ * Plugin wishing to post-proces must implement this interface. PostProcessors
+ * are called once the image has been generated and is executable.
+ **/
+public interface PostProcessor {
+
+    /**
+     * Post process an image.
+     *
+     * @param image The executable image.
+     * @return The list of arguments to add to launchers (if any).
+     */
+    public List<String> process(ExecutableImage image);
+}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java	Thu Jun 30 22:38:17 2016 +0000
@@ -42,7 +42,6 @@
      * @param resources Read only resources.
      * @param strings StringTable instance. Add string to the StringTable to track string
      * usage.
-     * @throws PluginException
      */
     public void previsit(ModulePool resources, StringTable strings);
 }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java	Thu Jun 30 22:38:17 2016 +0000
@@ -428,7 +428,7 @@
             return opt.hasArg;
         }
 
-        public boolean listPlugins() {
+        public boolean shouldListPlugins() {
             return pluginOptions.listPlugins;
         }
 
@@ -570,26 +570,19 @@
             log.println(bundleHelper.getMessage("main.command.files"));
         }
 
-        public void listPlugins(boolean showsImageBuilder) {
+        public void listPlugins() {
             log.println("\n" + bundleHelper.getMessage("main.extended.help"));
             List<Plugin> pluginList = PluginRepository.
                     getPlugins(pluginOptions.pluginsLayer);
-            for (Plugin plugin : Utils.
-                    getSortedPreProcessors(pluginList)) {
-                showPlugin(plugin, log, showsImageBuilder);
-            }
-
-            if (showsImageBuilder) {
-                for (Plugin plugin : Utils.getSortedPostProcessors(pluginList)) {
-                    showPlugin(plugin, log, showsImageBuilder);
-                }
+            for (Plugin plugin : Utils.getSortedPlugins(pluginList)) {
+                showPlugin(plugin, log);
             }
 
             log.println("\n" + bundleHelper.getMessage("main.extended.help.footer"));
         }
 
-        private void showPlugin(Plugin plugin, PrintWriter log, boolean showsImageBuilder) {
-            if (showsPlugin(plugin, showsImageBuilder)) {
+        private void showPlugin(Plugin plugin, PrintWriter log) {
+            if (showsPlugin(plugin)) {
                 log.println("\n" + bundleHelper.getMessage("main.plugin.name")
                         + ": " + plugin.getName());
 
@@ -599,7 +592,7 @@
                          + ": " + plugin.getClass().getName());
                     log.println(bundleHelper.getMessage("main.plugin.module")
                          + ": " + plugin.getClass().getModule().getName());
-                    Category category = Utils.getCategory(plugin);
+                    Category category = plugin.getType();
                     log.println(bundleHelper.getMessage("main.plugin.category")
                          + ": " + category.getName());
                     log.println(bundleHelper.getMessage("main.plugin.state")
@@ -722,14 +715,8 @@
         }
     }
 
-    // Display all plugins or pre processors only.
-    private static boolean showsPlugin(Plugin plugin, boolean showsImageBuilder) {
-        if (!Utils.isDisabled(plugin) && plugin.getOption() != null) {
-            if (Utils.isPostProcessor(plugin) && !showsImageBuilder) {
-                return false;
-            }
-            return true;
-        }
-        return false;
+    // Display all plugins
+    private static boolean showsPlugin(Plugin plugin) {
+        return (!Utils.isDisabled(plugin) && plugin.getOption() != null);
     }
 }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java	Thu Jun 30 22:38:17 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,6 @@
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
-import java.util.Objects;
 import java.util.stream.Collectors;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.Plugin.Category;
@@ -56,51 +55,10 @@
                      .collect(Collectors.toList());
     }
 
-    public static boolean isPostProcessor(Plugin provider) {
-        return provider.getType().isPostProcessor();
-    }
 
-    public static boolean isPreProcessor(Plugin provider) {
-        return !isPostProcessor(provider);
-    }
-
-    public static Category getCategory(Plugin provider) {
-        return provider.getType();
-    }
-
-    public static List<Plugin> getPreProcessors(List<Plugin> plugins) {
+    public static List<Plugin> getSortedPlugins(List<Plugin> plugins) {
         List<Plugin> res = new ArrayList<>();
-        for (Plugin p : plugins) {
-            if (isPreProcessor(p)) {
-                res.add(p);
-            }
-        }
-        return res;
-    }
-
-    public static List<Plugin> getPostProcessors(List<Plugin> plugins) {
-        List<Plugin> res = new ArrayList<>();
-        for (Plugin p : plugins) {
-            if (isPostProcessor(p)) {
-                res.add(p);
-            }
-        }
-        return res;
-    }
-
-    public static List<Plugin> getSortedPostProcessors(List<Plugin> plugins) {
-        List<Plugin> res = getPostProcessors(plugins);
-        res.sort(new Comparator<Plugin>() {
-            @Override
-            public int compare(Plugin o1, Plugin o2) {
-                return o1.getName().compareTo(o2.getName());
-            }
-        });
-        return res;
-    }
-
-    public static List<Plugin> getSortedPreProcessors(List<Plugin> plugins) {
-        List<Plugin> res = getPreProcessors(plugins);
+        res.addAll(plugins);
         res.sort(new Comparator<Plugin>() {
             @Override
             public int compare(Plugin o1, Plugin o2) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java	Thu Jun 30 22:38:17 2016 +0000
@@ -127,7 +127,7 @@
         jlink.build(jlinkConfig, pluginConfig);
     }
 
-    /**
+    /*
      * Returns a ModuleFinder that limits observability to the given root
      * modules, their transitive dependences, plus a set of other modules.
      */
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,12 +24,11 @@
  */
 package jdk.tools.jlink.internal.plugins;
 
-import java.util.Collections;
 import java.util.Map;
 
 import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.internal.ImagePluginStack;
 import jdk.tools.jlink.internal.ResourcePrevisitor;
 import jdk.tools.jlink.internal.StringTable;
@@ -38,7 +37,7 @@
  *
  * ZIP and String Sharing compression plugin
  */
-public final class DefaultCompressPlugin implements TransformerPlugin, ResourcePrevisitor {
+public final class DefaultCompressPlugin implements Plugin, ResourcePrevisitor {
     public static final String NAME = "compress";
     public static final String FILTER = "filter";
     public static final String LEVEL_0 = "0";
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,20 +24,17 @@
  */
 package jdk.tools.jlink.internal.plugins;
 
-import java.io.UncheckedIOException;
-import java.util.Collections;
 import java.util.Map;
 import java.util.function.Predicate;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.internal.Utils;
 
 /**
  *
  * Exclude files plugin
  */
-public final class ExcludeFilesPlugin implements TransformerPlugin {
+public final class ExcludeFilesPlugin implements Plugin {
 
     public static final String NAME = "exclude-files";
     private Predicate<String> predicate;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,10 +24,9 @@
  */
 package jdk.tools.jlink.internal.plugins;
 
-import java.util.Collections;
 import java.util.Map;
 import java.util.function.Predicate;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
 
@@ -35,7 +34,7 @@
  *
  * Exclude resources plugin
  */
-public final class ExcludePlugin implements TransformerPlugin {
+public final class ExcludePlugin implements Plugin {
 
     public static final String NAME = "exclude-resources";
     private Predicate<String> predicate;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -25,19 +25,17 @@
 package jdk.tools.jlink.internal.plugins;
 
 import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.UncheckedIOException;
 import java.nio.charset.StandardCharsets;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeSet;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.PluginException;
@@ -46,7 +44,7 @@
  *
  * Exclude VM plugin
  */
-public final class ExcludeVMPlugin implements TransformerPlugin {
+public final class ExcludeVMPlugin implements Plugin {
 
     private static final class JvmComparator implements Comparator<Jvm> {
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -26,7 +26,6 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.UncheckedIOException;
 import java.nio.file.FileVisitResult;
 import java.nio.file.FileVisitor;
@@ -35,7 +34,6 @@
 import java.nio.file.Paths;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -43,14 +41,14 @@
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.internal.Utils;
 
 /**
  *
  * Copy files to image from various locations.
  */
-public class FileCopierPlugin implements TransformerPlugin {
+public class FileCopierPlugin implements Plugin {
 
     public static final String NAME = "copy-files";
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,10 +24,8 @@
  */
 package jdk.tools.jlink.internal.plugins;
 
-import java.io.ByteArrayInputStream;
 import java.lang.reflect.Method;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
@@ -36,12 +34,12 @@
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 
 /**
  * Plugin to generate java.lang.invoke classes.
  */
-public final class GenerateJLIClassesPlugin implements TransformerPlugin {
+public final class GenerateJLIClassesPlugin implements Plugin {
 
     private static final String NAME = "generate-jli-classes";
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,10 +24,8 @@
  */
 package jdk.tools.jlink.internal.plugins;
 
-import java.io.ByteArrayInputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.IllformedLocaleException;
 import java.util.Locale;
 import java.util.List;
@@ -46,7 +44,7 @@
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 
 /**
  * Plugin to explicitly specify the locale data included in jdk.localedata
@@ -70,7 +68,7 @@
  *     start with at least one white space character, e.g., " ar ar-EG ..."
  *                                                           ^
  */
-public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePrevisitor {
+public final class IncludeLocalesPlugin implements Plugin, ResourcePrevisitor {
 
     public static final String NAME = "include-locales";
     private static final String MODULENAME = "jdk.localedata";
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -30,7 +30,6 @@
 import java.io.UncheckedIOException;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -30,23 +30,21 @@
 import java.nio.file.Files;
 import java.nio.file.PathMatcher;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.function.ToIntFunction;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.internal.Utils;
 
 /**
  *
  * Order Resources plugin
  */
-public final class OrderResourcesPlugin implements TransformerPlugin {
+public final class OrderResourcesPlugin implements Plugin {
     public static final String NAME = "order-resources";
     private static final FileSystem JRT_FILE_SYSTEM = Utils.jrtFileSystem();
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -26,7 +26,6 @@
 
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Map;
@@ -37,12 +36,12 @@
 import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.Plugin.Category;
 import jdk.tools.jlink.plugin.Plugin.State;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 
 /**
  * This plugin adds/deletes information for 'release' file.
  */
-public final class ReleaseInfoPlugin implements TransformerPlugin {
+public final class ReleaseInfoPlugin implements Plugin {
     // option name
     public static final String NAME = "release-info";
     public static final String KEYS = "keys";
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -46,7 +46,6 @@
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -57,7 +56,7 @@
 import jdk.internal.jimage.decompressor.SignatureParser;
 import jdk.internal.jimage.decompressor.StringSharingDecompressor;
 import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
@@ -69,7 +68,7 @@
  * A Plugin that stores the image classes constant pool UTF_8 entries into the
  * Image StringsTable.
  */
-public class StringSharingPlugin implements TransformerPlugin, ResourcePrevisitor {
+public class StringSharingPlugin implements Plugin, ResourcePrevisitor {
 
     public static final String NAME = "compact-cp";
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,21 +24,18 @@
  */
 package jdk.tools.jlink.internal.plugins;
 
-import java.io.ByteArrayInputStream;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.function.Predicate;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 
 /**
  *
  * Strip debug attributes plugin
  */
-public final class StripDebugPlugin implements TransformerPlugin {
+public final class StripDebugPlugin implements Plugin {
     public static final String NAME = "strip-debug";
     private final Predicate<String> predicate;
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,16 +24,15 @@
  */
 package jdk.tools.jlink.internal.plugins;
 
-import java.util.Collections;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 
 /**
  *
  * Strip Native Commands plugin
  */
-public final class StripNativeCommandsPlugin implements TransformerPlugin {
+public final class StripNativeCommandsPlugin implements Plugin {
 
     public static final String NAME = "strip-native-commands";
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -52,7 +52,7 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin.Builder.*;
 import jdk.tools.jlink.plugin.ModuleEntry;
 
@@ -67,7 +67,7 @@
  * @see java.lang.module.SystemModuleFinder
  * @see SystemModules
  */
-public final class SystemModuleDescriptorPlugin implements TransformerPlugin {
+public final class SystemModuleDescriptorPlugin implements Plugin {
     private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
 
     // TODO: packager has the dependency on the plugin name
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -28,20 +28,19 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Map;
 import java.util.function.Predicate;
 import java.util.zip.Deflater;
 import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 
 /**
  *
  * ZIP Compression plugin
  */
-public final class ZipPlugin implements TransformerPlugin {
+public final class ZipPlugin implements Plugin {
 
     public static final String NAME = "zip";
     private Predicate<String> predicate;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -25,7 +25,7 @@
 package jdk.tools.jlink.internal.plugins.asm;
 
 import java.util.Objects;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.internal.ModulePoolImpl;
@@ -35,7 +35,7 @@
  * resources.
  *
  */
-public abstract class AsmPlugin implements TransformerPlugin {
+public abstract class AsmPlugin implements Plugin {
 
     public AsmPlugin() {
     }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ControlFlow.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ControlFlow.java	Thu Jun 30 22:38:17 2016 +0000
@@ -76,9 +76,7 @@
 
         @Override
         public int hashCode() {
-            int hash = 3;
-            hash = 79 * hash + Objects.hashCode(this.firstInstruction);
-            return hash;
+            return Objects.hashCode(this.firstInstruction);
         }
 
         @Override
@@ -214,9 +212,7 @@
 
         @Override
         public int hashCode() {
-            int hash = 3;
-            hash = 89 * hash + this.getIndex();
-            return hash;
+            return this.getIndex();
         }
 
         @Override
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ExecutableImage.java	Thu Jun 30 22:10:10 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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.tools.jlink.plugin;
-
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Set;
-
-/**
- * An executable runtime image. Contains the information about the executable
- * image created.
- */
-public interface ExecutableImage {
-
-    /**
-     * Image home directory,
-     *
-     * @return The home directory.
-     */
-    public Path getHome();
-
-    /**
-     * The names of the modules located in the image.
-     *
-     * @return The set of modules.
-     */
-    public Set<String> getModules();
-
-    /**
-     * The list of arguments required to execute the image.
-     *
-     * @return The list of arguments.
-     */
-    public List<String> getExecutionArgs();
-
-    /**
-     * Store new arguments required to execute the image.
-     *
-     * @param args Additional arguments
-     */
-    public void storeLaunchArgs(List<String> args);
-}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -57,29 +57,19 @@
         SORTER("SORTER"),
         COMPRESSOR("COMPRESSOR"),
         METAINFO_ADDER("METAINFO_ADDER"),
-        VERIFIER("VERIFIER", true),
-        PROCESSOR("PROCESSOR", true),
-        PACKAGER("PACKAGER", true);
+        VERIFIER("VERIFIER"),
+        PROCESSOR("PROCESSOR"),
+        PACKAGER("PACKAGER");
 
         private final String name;
-        private final boolean postProcessor;
-
-        Category(String name, boolean postProcessor) {
-            this.name = name;
-            this.postProcessor = postProcessor;
-        }
 
         Category(String name) {
-            this(name, false);
+            this.name = name;
         }
 
         public String getName() {
             return name;
         }
-
-        public boolean isPostProcessor() {
-            return postProcessor;
-        }
     }
 
     /**
@@ -209,4 +199,15 @@
      */
     public default void configure(Map<String, String> config) {
     }
+
+    /**
+     * Visit the content of the modules that are composing the image.
+     *
+     * @param in Read only content.
+     * @param out The pool to fill with content. This pool must contain
+     * the result of the visit.
+     *
+     * @throws PluginException
+     */
+    public void visit(ModulePool in, ModulePool out);
 }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PostProcessorPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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.tools.jlink.plugin;
-
-import java.util.List;
-
-/**
- * Implement this interface to develop a PostProcessor plugin.
- * PostProcessor plugins are called once the image has been generated and is executable.
- **/
-public interface PostProcessorPlugin extends Plugin {
-
-    /**
-     * Post process an image.
-     *
-     * @param image The executable image.
-     * @return The list of arguments to add to launchers (if any).
-     */
-    public List<String> process(ExecutableImage image);
-}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/TransformerPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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.tools.jlink.plugin;
-
-
-/**
- * Implement this interface to develop a Transformer plugin.
- * TransformerPlugin are called during image creation. This kind of plugin aims to
- * modify the content of the runtime image.
- */
-public interface TransformerPlugin extends Plugin {
-    /**
-     * Visit the content of the modules that are composing the image.
-     *
-     * @param in Read only content.
-     * @param out The pool to fill with content. This pool must contain
-     * the result of the visit.
-     *
-     * @throws PluginException
-     */
-    public void visit(ModulePool in, ModulePool out);
-}
--- a/jdk/src/jdk.jlink/share/classes/module-info.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/module-info.java	Thu Jun 30 22:38:17 2016 +0000
@@ -29,20 +29,19 @@
     requires jdk.internal.opt;
     requires jdk.jdeps;
 
-    uses jdk.tools.jlink.plugin.TransformerPlugin;
-    uses jdk.tools.jlink.plugin.PostProcessorPlugin;
+    uses jdk.tools.jlink.plugin.Plugin;
 
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.FileCopierPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.StripDebugPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ExcludePlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.StripNativeCommandsPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.OrderResourcesPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.OptimizationPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.IncludeLocalesPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.FileCopierPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.StripDebugPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludePlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.StripNativeCommandsPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.OrderResourcesPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.OptimizationPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.IncludeLocalesPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin;
 }
--- a/jdk/src/jdk.management/share/classes/com/sun/management/internal/DiagnosticCommandImpl.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/DiagnosticCommandImpl.java	Thu Jun 30 22:38:17 2016 +0000
@@ -259,9 +259,20 @@
                     && signature[0] != null
                     && signature[0].compareTo(strArrayClassName) == 0)) {
                 return w.execute((String[]) params[0]);
+            } else {
+                throw new ReflectionException(
+                    new NoSuchMethodException(actionName
+                    + ": mismatched signature "
+                    + (signature != null ? Arrays.toString(signature) : "[]")
+                    + " or parameters"));
             }
+        } else {
+            throw new ReflectionException(
+                new NoSuchMethodException("Method " + actionName
+                + " with signature "
+                + (signature != null ? Arrays.toString(signature) : "[]")
+                + " not found"));
         }
-        throw new ReflectionException(new NoSuchMethodException(actionName));
     }
 
     private static String transform(String name) {
--- a/jdk/test/ProblemList.txt	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/ProblemList.txt	Thu Jun 30 22:38:17 2016 +0000
@@ -164,6 +164,10 @@
 
 java/net/DatagramSocket/SendDatagramToBadAddress.java           7143960 macosx-all
 
+java/net/httpclient/http2/BasicTest.java                        8157408 linux-all
+java/net/httpclient/http2/ErrorTest.java                        8158127 solaris-all,windows-all
+java/net/httpclient/http2/TLSConnection.java                    8157482 macosx-all
+
 ############################################################################
 
 # jdk_nio
--- a/jdk/test/TEST.groups	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/TEST.groups	Thu Jun 30 22:38:17 2016 +0000
@@ -27,7 +27,6 @@
 
 tier1 = \
     :jdk_lang \
-    -java/lang/ProcessHandle/TreeTest.java \
     :jdk_util \
     -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
     -java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
@@ -38,7 +37,6 @@
     tools/pack200
 
 tier2 = \
-    java/lang/ProcessHandle/TreeTest.java \
     java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
     java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
     :jdk_io \
--- a/jdk/test/com/sun/jdi/BacktraceFieldTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/com/sun/jdi/BacktraceFieldTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,8 @@
 /**
  *  @test
  *  @bug 4446677
- *  @summary debuggee crashes when debugging under jbuilder
+ *  @bug 8158237
+ *  @summary debuggee used to crash when debugging under jbuilder
  *
  *  @author jjh
  *
@@ -101,6 +102,16 @@
         new BacktraceFieldTest(args).startTests();
     }
 
+    private void printval(ArrayReference backTraceVal, int index) throws Exception {
+        ArrayReference val = (ArrayReference)backTraceVal.getValue(index);
+        println("BT: val at " + index + " = " + val);
+
+        // The segv used to happen here for index = 0
+        // Now all objects in the backtrace are objects.
+        Object xVal = (Object)val.getValue(0);
+        println("BT: xVal = " + xVal);
+    }
+
     /********** test core **********/
 
     protected void runTests() throws Exception {
@@ -128,42 +139,45 @@
          * Search through the fields of ee to verify that
          * java.lang.Throwable.backtrace isn't there.
          */
+        boolean backtrace_found = false;
         Iterator iter = allFields.iterator();
         while(iter.hasNext()) {
             Field ff = (Field)iter.next();
             if (ff.toString().equals("java.lang.Throwable.backtrace")) {
-                failure("ERROR: java.lang.Throwable.backtrace field not filtered out.");
+                backtrace_found = true;
+                println("java.lang.Throwable.backtrace field not filtered out.");
 
                 /*
                  * If you want to experience the segv this bug causes, change
                  * this test to 1 == 1 and run it with jdk 1.4, build 74 or earlier
                  */
-                if (1 == 0) {
+                if (1 == 1) {
                     // The following code will show the segv that this can cause.
                     ObjectReference myVal = (ObjectReference)myFrame.getValue(lv);
                     println("BT: myVal = " + myVal);
 
-                    ArrayReference backTraceVal = null;
-                    backTraceVal = (ArrayReference)myVal.getValue(ff);
+                    ArrayReference backTraceVal = (ArrayReference)myVal.getValue(ff);
                     println("BT: backTraceVal = " + backTraceVal);
 
-                    ArrayReference secondVal = (ArrayReference)backTraceVal.getValue(1);
-                    println("BT: secondVal = " + secondVal);
-
-                    Object x2Val = (Object)secondVal.getValue(0);
-                    println("BT: x2Val = " + x2Val);
+                    printval(backTraceVal, 0);
+                    printval(backTraceVal, 1);
+                    printval(backTraceVal, 2);
+                    printval(backTraceVal, 3);  // backtrace has 4 elements
 
-                    ArrayReference firstVal = (ArrayReference)backTraceVal.getValue(0);
-                    println("BT: firstVal = " + firstVal);
-
-                    // The segv happens here.
-                    Object xVal = (Object)firstVal.getValue(0);
-                    println("BT: xVal = " + xVal);
+                    try {
+                        printval(backTraceVal, 4);
+                    } catch (Exception e) {
+                        println("Exception " + e);
+                    }
                 }
                 break;
             }
         }
 
+        if (!backtrace_found) {
+            failure("ERROR: java.lang.Throwable.backtrace field filtered out.");
+        }
+
         // Next, verify that we don't accidently discard a field that we shouldn't
 
         if (!testFailed) {
--- a/jdk/test/java/lang/ProcessHandle/TreeTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -50,7 +50,6 @@
  * @build jdk.test.lib.Utils
  * @run testng/othervm TreeTest
  * @summary Test counting and JavaChild.spawning and counting of Processes.
- * @key intermittent
  * @author Roger Riggs
  */
 public class TreeTest extends ProcessUtil {
--- a/jdk/test/java/lang/String/CompareIC.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/java/lang/String/CompareIC.java	Thu Jun 30 22:38:17 2016 +0000
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4124769
+ * @bug 4124769 8160312
  * @summary Test ignore-case comparison
  *
  */
@@ -45,6 +45,10 @@
         comparer.testTriplet(test1, test2, test3);
         test2 = test2.toLowerCase();
         comparer.testTriplet(test1, test2, test3);
+
+        // toLowerCase -> non-latin1
+        if ("\u00b5".compareToIgnoreCase("X") < 0)
+            throw new RuntimeException("Comparison failure1");
     }
 
     private void testTriplet(String one, String two, String three)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessModeMethodNames.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng VarHandleTestAccessModeMethodNames
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.VarHandle;
+import java.util.stream.Stream;
+
+import static org.testng.Assert.assertEquals;
+
+public class VarHandleTestAccessModeMethodNames {
+
+    @DataProvider
+    public static Object[][] accessModesProvider() {
+        return Stream.of(VarHandle.AccessMode.values()).
+                map(am -> new Object[]{am}).
+                toArray(Object[][]::new);
+    }
+
+
+    @Test(dataProvider = "accessModesProvider")
+    public void testMethodName(VarHandle.AccessMode am) {
+        assertEquals(am.methodName(), toMethodName(am.name()));
+    }
+
+    private static String toMethodName(String name) {
+        StringBuilder s = new StringBuilder(name.toLowerCase());
+        int i;
+        while ((i = s.indexOf("_")) !=  -1) {
+            s.deleteCharAt(i);
+            s.setCharAt(i, Character.toUpperCase(s.charAt(i)));
+        }
+        return s.toString();
+    }
+}
--- a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/DecoderTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/DecoderTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -27,14 +27,20 @@
 import java.io.UncheckedIOException;
 import java.net.ProtocolException;
 import java.nio.ByteBuffer;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static sun.net.httpclient.hpack.TestHelper.*;
 
+//
+// Tests whose names start with "testX" are the ones captured from real HPACK
+// use cases
+//
 public final class DecoderTest {
 
     //
@@ -138,6 +144,23 @@
         // @formatter:on
     }
 
+    @Test
+    public void example5AllSplits() {
+        // @formatter:off
+        testAllSplits(
+                "8286 8441 0f77 7777 2e65 7861 6d70 6c65\n" +
+                "2e63 6f6d",
+
+                "[  1] (s =  57) :authority: www.example.com\n" +
+                "      Table size:  57",
+
+                ":method: GET\n" +
+                ":scheme: http\n" +
+                ":path: /\n" +
+                ":authority: www.example.com");
+        // @formatter:on
+    }
+
     //
     // http://tools.ietf.org/html/rfc7541#appendix-C.4
     //
@@ -334,6 +357,45 @@
         // @formatter:on
     }
 
+    @Test
+    public void testX1() {
+        // Supplier of a decoder with a particular state
+        Supplier<Decoder> s = () -> {
+            Decoder d = new Decoder(4096);
+            // @formatter:off
+            test(d, "88 76 92 ca 54 a7 d7 f4 fa ec af ed 6d da 61 d7 bb 1e ad ff" +
+                    "df 61 97 c3 61 be 94 13 4a 65 b6 a5 04 00 b8 a0 5a b8 db 77" +
+                    "1b 71 4c 5a 37 ff 0f 0d 84 08 00 00 03",
+
+                    "[  1] (s =  65) date: Fri, 24 Jun 2016 14:55:56 GMT\n" +
+                    "[  2] (s =  59) server: Jetty(9.3.z-SNAPSHOT)\n" +
+                    "      Table size: 124",
+
+                    ":status: 200\n" +
+                    "server: Jetty(9.3.z-SNAPSHOT)\n" +
+                    "date: Fri, 24 Jun 2016 14:55:56 GMT\n" +
+                    "content-length: 100000"
+            );
+            // @formatter:on
+            return d;
+        };
+        // For all splits of the following data fed to the supplied decoder we
+        // must get what's expected
+        // @formatter:off
+        testAllSplits(s,
+                "88 bf be 0f 0d 84 08 00 00 03",
+
+                "[  1] (s =  65) date: Fri, 24 Jun 2016 14:55:56 GMT\n" +
+                "[  2] (s =  59) server: Jetty(9.3.z-SNAPSHOT)\n" +
+                "      Table size: 124",
+
+                ":status: 200\n" +
+                "server: Jetty(9.3.z-SNAPSHOT)\n" +
+                "date: Fri, 24 Jun 2016 14:55:56 GMT\n" +
+                "content-length: 100000");
+        // @formatter:on
+    }
+
     //
     // This test is missing in the spec
     //
@@ -567,6 +629,38 @@
         test(new Decoder(4096), hexdump, headerTable, headerList);
     }
 
+    private static void testAllSplits(String hexdump,
+                                      String expectedHeaderTable,
+                                      String expectedHeaderList) {
+        testAllSplits(() -> new Decoder(256), hexdump, expectedHeaderTable, expectedHeaderList);
+    }
+
+    private static void testAllSplits(Supplier<Decoder> supplier, String hexdump,
+                                      String expectedHeaderTable, String expectedHeaderList) {
+        ByteBuffer source = SpecHelper.toBytes(hexdump);
+
+        BuffersTestingKit.forEachSplit(source, iterable -> {
+            List<String> actual = new LinkedList<>();
+            Iterator<? extends ByteBuffer> i = iterable.iterator();
+            if (!i.hasNext()) {
+                return;
+            }
+            Decoder d = supplier.get();
+            do {
+                ByteBuffer n = i.next();
+                d.decode(n, !i.hasNext(), (name, value) -> {
+                    if (value == null) {
+                        actual.add(name.toString());
+                    } else {
+                        actual.add(name + ": " + value);
+                    }
+                });
+            } while (i.hasNext());
+            assertEquals(d.getTable().getStateString(), expectedHeaderTable);
+            assertEquals(actual.stream().collect(Collectors.joining("\n")), expectedHeaderList);
+        });
+    }
+
     //
     // Sometimes we need to keep the same decoder along several runs,
     // as it models the same connection
--- a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/EncoderTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/EncoderTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,17 +24,23 @@
 
 import org.testng.annotations.Test;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.function.Consumer;
 import java.util.function.Function;
 
+import static sun.net.httpclient.hpack.BuffersTestingKit.concat;
+import static sun.net.httpclient.hpack.BuffersTestingKit.forEachSplit;
+import static sun.net.httpclient.hpack.SpecHelper.toHexdump;
+import static sun.net.httpclient.hpack.TestHelper.assertVoidThrows;
 import static java.util.Arrays.asList;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
-import static sun.net.httpclient.hpack.SpecHelper.toHexdump;
-import static sun.net.httpclient.hpack.TestHelper.assertVoidThrows;
 
 // TODO: map textual representation of commands from the spec to actual
 // calls to encoder (actually, this is a good idea for decoder as well)
@@ -198,6 +204,61 @@
         // @formatter:on
     }
 
+    @Test
+    public void example5AllSplits() {
+
+        List<Consumer<Encoder>> actions = new LinkedList<>();
+        actions.add(e -> e.indexed(2));
+        actions.add(e -> e.indexed(6));
+        actions.add(e -> e.indexed(4));
+        actions.add(e -> e.literalWithIndexing(1, "www.example.com", false));
+
+        encodeAllSplits(
+                actions,
+
+                "8286 8441 0f77 7777 2e65 7861 6d70 6c65\n" +
+                "2e63 6f6d",
+
+                "[  1] (s =  57) :authority: www.example.com\n" +
+                "      Table size:  57");
+    }
+
+    private static void encodeAllSplits(Iterable<Consumer<Encoder>> consumers,
+                                        String expectedHexdump,
+                                        String expectedTableState) {
+        ByteBuffer buffer = SpecHelper.toBytes(expectedHexdump);
+        erase(buffer); // Zeroed buffer of size needed to hold the encoding
+        forEachSplit(buffer, iterable -> {
+            List<ByteBuffer> copy = new LinkedList<>();
+            iterable.forEach(b -> copy.add(ByteBuffer.allocate(b.remaining())));
+            Iterator<ByteBuffer> output = copy.iterator();
+            if (!output.hasNext()) {
+                throw new IllegalStateException("No buffers to encode to");
+            }
+            Encoder e = newCustomEncoder(256); // FIXME: pull up (as a parameter)
+            drainInitialUpdate(e);
+            boolean encoded;
+            ByteBuffer b = output.next();
+            for (Consumer<Encoder> c : consumers) {
+                c.accept(e);
+                do {
+                    encoded = e.encode(b);
+                    if (!encoded) {
+                        if (output.hasNext()) {
+                            b = output.next();
+                        } else {
+                            throw new IllegalStateException("No room for encoding");
+                        }
+                    }
+                }
+                while (!encoded);
+            }
+            copy.forEach(Buffer::flip);
+            ByteBuffer data = concat(copy);
+            test(e, data, expectedHexdump, expectedTableState);
+        });
+    }
+
     //
     // http://tools.ietf.org/html/rfc7541#appendix-C.4
     //
@@ -620,4 +681,12 @@
             b.flip();
         } while (!done);
     }
+
+    private static void erase(ByteBuffer buffer) {
+        buffer.clear();
+        while (buffer.hasRemaining()) {
+            buffer.put((byte) 0);
+        }
+        buffer.clear();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/FileHandlerMaxLocksTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8153955
+ * @summary test the FileHandler's new property
+ *  "java.util.logging.FileHandler.maxLocks" which will be present in
+ *  "logging.properties" file with default value of 100. This property can be
+ *  overriden by specifying this property in the custom config file.
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils
+ * @author rpatil
+ * @run main/othervm FileHandlerMaxLocksTest
+ */
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.FileHandler;
+import jdk.testlibrary.FileUtils;
+
+public class FileHandlerMaxLocksTest {
+
+    private static final String LOGGER_DIR = "logger-dir";
+    private static final String MAX_LOCK_PROPERTY = "java.util.logging.FileHandler.maxLocks = 200";
+    private static final String CONFIG_FILE_NAME = "logging.properties";
+
+    public static void main(String[] args) throws Exception {
+        File loggerDir = createLoggerDir();
+        String configFilePath = loggerDir.getPath() + File.separator + CONFIG_FILE_NAME;
+        File configFile = new File(configFilePath);
+        createFile(configFile, false);
+        System.setProperty("java.util.logging.config.file", configFilePath);
+        List<FileHandler> fileHandlers = new ArrayList<>();
+        try (FileWriter writer = new FileWriter(configFile)) {
+            writer.write(MAX_LOCK_PROPERTY);
+            writer.flush();
+            // 200 raises the default limit of 100, we try 102 times
+            for (int i = 0; i < 102; i++) {
+                fileHandlers.add(new FileHandler(loggerDir.getPath() + File.separator + "test_%u.log"));
+            }
+        } catch (IOException ie) {
+            throw new RuntimeException("Test Failed: " + ie.getMessage());
+        } finally {
+            for (FileHandler fh : fileHandlers) {
+                fh.close();
+            }
+            FileUtils.deleteFileTreeWithRetry(Paths.get(loggerDir.getPath()));
+        }
+    }
+
+    /**
+     * Create a writable directory in user directory for the test
+     *
+     * @return writable directory created that needs to be deleted when done
+     * @throws RuntimeException
+     */
+    private static File createLoggerDir() throws RuntimeException {
+        String userDir = System.getProperty("user.dir", ".");
+        File loggerDir = new File(userDir, LOGGER_DIR);
+        if (!createFile(loggerDir, true)) {
+            throw new RuntimeException("Test failed: unable to create"
+                    + " writable working directory "
+                    + loggerDir.getAbsolutePath());
+        }
+        // System.out.println("Created Logger Directory: " + loggerDir.getPath());
+        return loggerDir;
+    }
+
+    /**
+     * @param newFile  File to be created
+     * @param makeDirectory  is File to be created is directory
+     * @return true if file already exists or creation succeeded
+     */
+    private static boolean createFile(File newFile, boolean makeDirectory) {
+        if (newFile.exists()) {
+            return true;
+        }
+        if (makeDirectory) {
+            return newFile.mkdir();
+        } else {
+            try {
+                return newFile.createNewFile();
+            } catch (IOException ie) {
+                System.err.println("Not able to create file: " + newFile
+                        + ", IOException: " + ie.getMessage());
+                return false;
+            }
+        }
+    }
+}
--- a/jdk/test/java/util/zip/ZipFile/ReadZip.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/java/util/zip/ZipFile/ReadZip.java	Thu Jun 30 22:38:17 2016 +0000
@@ -22,7 +22,7 @@
  */
 
 /* @test
-   @bug 4241361 4842702 4985614 6646605 5032358 6923692
+   @bug 4241361 4842702 4985614 6646605 5032358 6923692 6233323 8144977
    @summary Make sure we can read a zip file.
    @key randomness
  */
@@ -105,6 +105,40 @@
             newZip.delete();
         }
 
+        // Read directory entry
+        try {
+            try (FileOutputStream fos = new FileOutputStream(newZip);
+                 ZipOutputStream zos = new ZipOutputStream(fos))
+            {
+                ZipEntry ze = new ZipEntry("directory/");
+                zos.putNextEntry(ze);
+                zos.closeEntry();
+            }
+            try (ZipFile zf = new ZipFile(newZip)) {
+                ZipEntry ze = zf.getEntry("directory/");
+                if (ze == null || !ze.isDirectory())
+                    throw new RuntimeException("read entry \"directory/\" failed");
+                try (InputStream is = zf.getInputStream(ze)) {
+                    is.available();
+                } catch (Exception x) {
+                    x.printStackTrace();
+                }
+
+                ze = zf.getEntry("directory");
+                if (ze == null || !ze.isDirectory())
+                    throw new RuntimeException("read entry \"directory\" failed");
+                try (InputStream is = zf.getInputStream(ze)) {
+                    is.available();
+                } catch (Exception x) {
+                    x.printStackTrace();
+                }
+            }
+        } finally {
+            newZip.delete();
+        }
+
+
+
         // Throw a FNF exception when read a non-existing zip file
         try { unreached (new ZipFile(
                              new File(System.getProperty("test.src", "."),
--- a/jdk/test/javax/net/ssl/Stapling/SSLSocketWithStapling.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/javax/net/ssl/Stapling/SSLSocketWithStapling.java	Thu Jun 30 22:38:17 2016 +0000
@@ -510,25 +510,27 @@
         sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
 
         SSLServerSocketFactory sslssf = sslc.getServerSocketFactory();
-        SSLServerSocket sslServerSocket =
-            (SSLServerSocket) sslssf.createServerSocket(serverPort);
 
-        serverPort = sslServerSocket.getLocalPort();
+        try (SSLServerSocket sslServerSocket =
+                (SSLServerSocket) sslssf.createServerSocket(serverPort)) {
 
-        /*
-         * Signal Client, we're ready for his connect.
-         */
-        serverReady = true;
+            serverPort = sslServerSocket.getLocalPort();
+
+            /*
+             * Signal Client, we're ready for his connect.
+             */
+            serverReady = true;
 
-        try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
-                InputStream sslIS = sslSocket.getInputStream();
-                OutputStream sslOS = sslSocket.getOutputStream()) {
-            int numberIn = sslIS.read();
-            int numberSent = 85;
-            log("Server received number: " + numberIn);
-            sslOS.write(numberSent);
-            sslOS.flush();
-            log("Server sent number: " + numberSent);
+            try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+                    InputStream sslIS = sslSocket.getInputStream();
+                    OutputStream sslOS = sslSocket.getOutputStream()) {
+                int numberIn = sslIS.read();
+                int numberSent = 85;
+                log("Server received number: " + numberIn);
+                sslOS.write(numberSent);
+                sslOS.flush();
+                log("Server sent number: " + numberSent);
+            }
         }
     }
 
--- a/jdk/test/sun/security/tools/keytool/standard.sh	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/sun/security/tools/keytool/standard.sh	Thu Jun 30 22:38:17 2016 +0000
@@ -25,6 +25,7 @@
 # @summary (almost) all keytool behaviors
 # @author Weijun Wang
 # @run shell/timeout=600 standard.sh
+# @key intermittent
 #
 # This test is always excecuted.
 #
--- a/jdk/test/sun/tools/jps/JpsBase.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/sun/tools/jps/JpsBase.java	Thu Jun 30 22:38:17 2016 +0000
@@ -35,27 +35,28 @@
  */
 public final class JpsBase {
 
-    private static final String shortProcessName;
-    private static final String fullProcessName;
-
     /**
      * The jps output should contain processes' names
      * (except when jps is started in quite mode).
      * The expected name of the test process is prepared here.
      */
-    static {
+
+    private static String getShortProcessName() {
         URL url = JpsBase.class.getResource("JpsBase.class");
         boolean isJar = url.getProtocol().equals("jar");
+        return (isJar) ? JpsBase.class.getSimpleName() + ".jar" : JpsBase.class.getSimpleName();
+    }
 
+    private static String getFullProcessName() {
+        URL url = JpsBase.class.getResource("JpsBase.class");
+        boolean isJar = url.getProtocol().equals("jar");
         if (isJar) {
-            shortProcessName = JpsBase.class.getSimpleName() + ".jar";
             String urlPath = url.getPath();
             File jar = new File(urlPath.substring(urlPath.indexOf("file:") + 5, urlPath.indexOf("jar!") + 3));
-            fullProcessName = jar.getAbsolutePath();
-        } else {
-            shortProcessName = JpsBase.class.getSimpleName();
-            fullProcessName = JpsBase.class.getName();
+            return jar.getAbsolutePath();
         }
+
+        return JpsBase.class.getName();
     }
 
     public static void main(String[] args) throws Exception {
@@ -83,6 +84,7 @@
                     // or the full path name to the application's JAR file:
                     // 30673 /tmp/jtreg/jtreg-workdir/scratch/JpsBase.jar ...
                     isFull = true;
+                    String fullProcessName = getFullProcessName();
                     pattern = "^" + pid + "\\s+" + replaceSpecialChars(fullProcessName) + ".*";
                     output.shouldMatch(pattern);
                     break;
@@ -120,6 +122,7 @@
                 // Output should only contain lines with pids after the first line with pid.
                 JpsHelper.verifyJpsOutput(output, "^\\d+\\s+.*");
                 if (!isFull) {
+                    String shortProcessName = getShortProcessName();
                     pattern = "^" + pid + "\\s+" + replaceSpecialChars(shortProcessName);
                     if (combination.isEmpty()) {
                         // If no arguments are specified output should only contain
--- a/jdk/test/sun/util/locale/provider/Bug8038436.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/sun/util/locale/provider/Bug8038436.java	Thu Jun 30 22:38:17 2016 +0000
@@ -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
@@ -23,24 +23,25 @@
 
 /*
  * @test
- * @bug 8038436
+ * @bug 8038436 8158504
  * @summary Test for changes in 8038436
  * @modules java.base/sun.util.locale.provider
  *          java.base/sun.util.spi
  * @compile -XDignore.symbol.file Bug8038436.java
- * @run main/othervm Bug8038436 -Djava.ext.dirs=foo security
- * @run main/othervm Bug8038436 -Djava.locale.providers=JRE availlocs
+ * @run main/othervm  -limitmods java.base           Bug8038436  security
+ * @run main/othervm  -Djava.locale.providers=COMPAT Bug8038436  availlocs
  */
 
 import java.security.*;
-import java.text.*;
 import java.util.*;
 import java.util.stream.*;
 import sun.util.locale.provider.*;
 
 public class Bug8038436 {
     public static void main(String[] args) {
-        switch (args[1]) {
+
+        switch (args[0]) {
+
         case "security":
             securityTests();
             break;
@@ -50,6 +51,7 @@
         default:
             throw new RuntimeException("no test was specified.");
         }
+
     }
 
     private static void securityTests() {
@@ -67,12 +69,14 @@
 
         /*
          * Check only English/ROOT locales are returned if the jdk.localedata
-         * module is not installed (implied by "java.ext.dirs" set to "foo").
+         * module is not loaded (implied by "-limitmods java.base").
          */
-        if (Arrays.asList(Locale.getAvailableLocales())
-                .stream()
-                .anyMatch(l -> l != Locale.ROOT && l.getLanguage() != "en")) {
-            throw new RuntimeException("non English locale(s) included in available locales");
+        List<Locale> nonEnglishLocales= (Arrays.stream(Locale.getAvailableLocales())
+                .filter(l -> (l != Locale.ROOT && !(l.getLanguage() == "en" && (l.getCountry() == "US" || l.getCountry() == "" ))))
+                .collect(Collectors.toList()));
+
+        if (!nonEnglishLocales.isEmpty()) {
+            throw new RuntimeException("non English locale(s)" + nonEnglishLocales + " included in available locales");
         }
     }
 
--- a/jdk/test/tools/jar/compat/CLICompatibility.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jar/compat/CLICompatibility.java	Thu Jun 30 22:38:17 2016 +0000
@@ -415,14 +415,14 @@
         jar("-h")
             .assertSuccess()
             .resultChecker(r ->
-                assertTrue(r.output.startsWith("Usage: jar [OPTION...] [-C dir] files"),
+                assertTrue(r.output.startsWith("Usage: jar [OPTION...] [ [--release VERSION] [-C dir] files]"),
                            "Failed, got [" + r.output + "]")
             );
 
         jar("--help")
             .assertSuccess()
             .resultChecker(r ->
-                assertTrue(r.output.startsWith("Usage: jar [OPTION...] [-C dir] files"),
+                assertTrue(r.output.startsWith("Usage: jar [OPTION...] [ [--release VERSION] [-C dir] files]"),
                            "Failed, got [" + r.output + "]")
             );
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/Basic.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib/share/classes
+ * @modules java.base/jdk.internal.misc
+ * @build jdk.test.lib.JDKToolFinder jdk.test.lib.Platform
+ * @run testng Basic
+ */
+
+import static org.testng.Assert.*;
+
+import org.testng.annotations.*;
+
+import java.io.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.jar.*;
+import java.util.stream.Stream;
+import java.util.zip.*;
+
+import jdk.test.lib.JDKToolFinder;
+
+import static java.lang.String.format;
+import static java.lang.System.out;
+
+public class Basic {
+    private final String src = System.getProperty("test.src", ".");
+    private final String usr = System.getProperty("user.dir", ".");
+
+    @Test
+    // create a regular, non-multi-release jar
+    public void test00() throws IOException {
+        String jarfile = "test.jar";
+
+        compile("test01");  //use same data as test01
+
+        Path classes = Paths.get("classes");
+        jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".")
+                .assertSuccess();
+
+        checkMultiRelease(jarfile, false);
+
+        Map<String,String[]> names = Map.of(
+                "version/Main.class",
+                new String[] {"base", "version", "Main.class"},
+
+                "version/Version.class",
+                new String[] {"base", "version", "Version.class"}
+        );
+
+        compare(jarfile, names);
+
+        delete(jarfile);
+        deleteDir(Paths.get(usr, "classes"));
+    }
+
+    @Test
+    // create a multi-release jar
+    public void test01() throws IOException {
+        String jarfile = "test.jar";
+
+        compile("test01");
+
+        Path classes = Paths.get("classes");
+        jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+                "--release", "9", "-C", classes.resolve("v9").toString(), ".",
+                "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+                .assertSuccess();
+
+        checkMultiRelease(jarfile, true);
+
+        Map<String,String[]> names = Map.of(
+                "version/Main.class",
+                new String[] {"base", "version", "Main.class"},
+
+                "version/Version.class",
+                new String[] {"base", "version", "Version.class"},
+
+                "META-INF/versions/9/version/Version.class",
+                new String[] {"v9", "version", "Version.class"},
+
+                "META-INF/versions/10/version/Version.class",
+                new String[] {"v10", "version", "Version.class"}
+        );
+
+        compare(jarfile, names);
+
+        delete(jarfile);
+        deleteDir(Paths.get(usr, "classes"));
+    }
+
+    @Test
+    // update a regular jar to a multi-release jar
+    public void test02() throws IOException {
+        String jarfile = "test.jar";
+
+        compile("test01");  //use same data as test01
+
+        Path classes = Paths.get("classes");
+        jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".")
+                .assertSuccess();
+
+        checkMultiRelease(jarfile, false);
+
+        jar("uf", jarfile, "--release", "9", "-C", classes.resolve("v9").toString(), ".")
+                .assertSuccess();
+
+        checkMultiRelease(jarfile, true);
+
+        Map<String,String[]> names = Map.of(
+                "version/Main.class",
+                new String[] {"base", "version", "Main.class"},
+
+                "version/Version.class",
+                new String[] {"base", "version", "Version.class"},
+
+                "META-INF/versions/9/version/Version.class",
+                new String[] {"v9", "version", "Version.class"}
+        );
+
+        compare(jarfile, names);
+
+        delete(jarfile);
+        deleteDir(Paths.get(usr, "classes"));
+    }
+
+    @Test
+    // replace a base entry and a versioned entry
+    public void test03() throws IOException {
+        String jarfile = "test.jar";
+
+        compile("test01");  //use same data as test01
+
+        Path classes = Paths.get("classes");
+        jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+                "--release", "9", "-C", classes.resolve("v9").toString(), ".")
+                .assertSuccess();
+
+        checkMultiRelease(jarfile, true);
+
+        Map<String,String[]> names = Map.of(
+                "version/Main.class",
+                new String[] {"base", "version", "Main.class"},
+
+                "version/Version.class",
+                new String[] {"base", "version", "Version.class"},
+
+                "META-INF/versions/9/version/Version.class",
+                new String[] {"v9", "version", "Version.class"}
+        );
+
+        compare(jarfile, names);
+
+        // write the v9 version/Version.class entry in base and the v10
+        // version/Version.class entry in versions/9 section
+        jar("uf", jarfile, "-C", classes.resolve("v9").toString(), "version",
+                "--release", "9", "-C", classes.resolve("v10").toString(), ".")
+                .assertSuccess();
+
+        checkMultiRelease(jarfile, true);
+
+        names = Map.of(
+                "version/Main.class",
+                new String[] {"base", "version", "Main.class"},
+
+                "version/Version.class",
+                new String[] {"v9", "version", "Version.class"},
+
+                "META-INF/versions/9/version/Version.class",
+                new String[] {"v10", "version", "Version.class"}
+        );
+
+        delete(jarfile);
+        deleteDir(Paths.get(usr, "classes"));
+    }
+
+    /*
+     *  Test Infrastructure
+     */
+    private void compile(String test) throws IOException {
+        Path classes = Paths.get(usr, "classes", "base");
+        Files.createDirectories(classes);
+        Path source = Paths.get(src, "data", test, "base", "version");
+        javac(classes, source.resolve("Main.java"), source.resolve("Version.java"));
+
+        classes = Paths.get(usr, "classes", "v9");
+        Files.createDirectories(classes);
+        source = Paths.get(src, "data", test, "v9", "version");
+        javac(classes, source.resolve("Version.java"));
+
+        classes = Paths.get(usr, "classes", "v10");
+        Files.createDirectories(classes);
+        source = Paths.get(src, "data", test, "v10", "version");
+        javac(classes, source.resolve("Version.java"));
+    }
+
+    private void checkMultiRelease(String jarFile, boolean expected) throws IOException {
+        try (JarFile jf = new JarFile(new File(jarFile), true, ZipFile.OPEN_READ,
+                JarFile.Release.RUNTIME)) {
+            assertEquals(jf.isMultiRelease(), expected);
+        }
+    }
+
+    // compares the bytes found in the jar entries with the bytes found in the
+    // corresponding data files used to create the entries
+    private void compare(String jarfile, Map<String,String[]> names) throws IOException {
+        try (JarFile jf = new JarFile(jarfile)) {
+            for (String name : names.keySet()) {
+                Path path = Paths.get("classes", names.get(name));
+                byte[] b1 = Files.readAllBytes(path);
+                byte[] b2;
+                JarEntry je = jf.getJarEntry(name);
+                try (InputStream is = jf.getInputStream(je)) {
+                    b2 = is.readAllBytes();
+                }
+                assertEquals(b1,b2);
+            }
+        }
+    }
+
+    private void delete(String name) throws IOException {
+        Files.delete(Paths.get(usr, name));
+    }
+
+    private void deleteDir(Path dir) throws IOException {
+        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                Files.delete(file);
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+                Files.delete(dir);
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    /*
+     * The following methods were taken from modular jar and other jar tests
+     */
+
+    void javac(Path dest, Path... sourceFiles) throws IOException {
+        String javac = JDKToolFinder.getJDKTool("javac");
+
+        List<String> commands = new ArrayList<>();
+        commands.add(javac);
+        commands.add("-d");
+        commands.add(dest.toString());
+        Stream.of(sourceFiles).map(Object::toString).forEach(x -> commands.add(x));
+
+        quickFail(run(new ProcessBuilder(commands)));
+    }
+
+    Result jarWithStdin(File stdinSource, String... args) {
+        String jar = JDKToolFinder.getJDKTool("jar");
+        List<String> commands = new ArrayList<>();
+        commands.add(jar);
+        Stream.of(args).forEach(x -> commands.add(x));
+        ProcessBuilder p = new ProcessBuilder(commands);
+        if (stdinSource != null)
+            p.redirectInput(stdinSource);
+        return run(p);
+    }
+
+    Result jar(String... args) {
+        return jarWithStdin(null, args);
+    }
+
+    void quickFail(Result r) {
+        if (r.ec != 0)
+            throw new RuntimeException(r.output);
+    }
+
+    Result run(ProcessBuilder pb) {
+        Process p;
+        out.printf("Running: %s%n", pb.command());
+        try {
+            p = pb.start();
+        } catch (IOException e) {
+            throw new RuntimeException(
+                    format("Couldn't start process '%s'", pb.command()), e);
+        }
+
+        String output;
+        try {
+            output = toString(p.getInputStream(), p.getErrorStream());
+        } catch (IOException e) {
+            throw new RuntimeException(
+                    format("Couldn't read process output '%s'", pb.command()), e);
+        }
+
+        try {
+            p.waitFor();
+        } catch (InterruptedException e) {
+            throw new RuntimeException(
+                    format("Process hasn't finished '%s'", pb.command()), e);
+        }
+        return new Result(p.exitValue(), output);
+    }
+
+    String toString(InputStream in1, InputStream in2) throws IOException {
+        try (ByteArrayOutputStream dst = new ByteArrayOutputStream();
+             InputStream concatenated = new SequenceInputStream(in1, in2)) {
+            concatenated.transferTo(dst);
+            return new String(dst.toByteArray(), "UTF-8");
+        }
+    }
+
+    static class Result {
+        final int ec;
+        final String output;
+
+        private Result(int ec, String output) {
+            this.ec = ec;
+            this.output = output;
+        }
+        Result assertSuccess() {
+            assertTrue(ec == 0, format("ec: %d, output: %s", ec, output));
+            return this;
+        }
+        Result assertFailure() {
+            assertTrue(ec != 0, format("ec: %d, output: %s", ec, output));
+            return this;
+        }
+        Result resultChecker(Consumer<Result> r) { r.accept(this); return this; }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/test01/base/version/Main.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,8 @@
+package version;
+
+public class Main {
+    public static void main(String[] args) {
+        Version v = new Version();
+        System.out.println("I am running on version " + v.getVersion());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/test01/base/version/Version.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,13 @@
+package version;
+
+public class Version {
+    public int getVersion() {
+        return 8;
+    }
+
+    protected void doNothing() {
+    }
+
+    private void reallyDoNothing() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/test01/v10/version/Version.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,13 @@
+package version;
+
+public class Version {
+    public int getVersion() {
+        return 10;
+    }
+
+    protected void doNothing() {
+    }
+
+    private void someName() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/test01/v9/version/Version.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,13 @@
+package version;
+
+public class Version {
+    public int getVersion() {
+        return 9;
+    }
+
+    protected void doNothing() {
+    }
+
+    private void anyName() {
+    }
+}
--- a/jdk/test/tools/jlink/DefaultProviderTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/DefaultProviderTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -33,7 +33,6 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 import tests.Helper;
 
 /*
@@ -60,7 +59,7 @@
         expectedOptions.put("option2", "value2");
     }
 
-    private static class Custom implements TransformerPlugin {
+    private static class Custom implements Plugin {
         private boolean enabled = true;
 
         @Override
--- a/jdk/test/tools/jlink/ImageFileCreatorTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -37,7 +37,7 @@
 import jdk.tools.jlink.internal.Archive;
 import jdk.tools.jlink.internal.ImageFileCreator;
 import jdk.tools.jlink.internal.ImagePluginStack;
-import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.internal.ExecutableImage;
 import jdk.tools.jlink.builder.ImageBuilder;
 import jdk.tools.jlink.plugin.ModulePool;
 
@@ -220,7 +220,7 @@
         };
 
         ImagePluginStack stack = new ImagePluginStack(noopBuilder, Collections.emptyList(),
-                null, Collections.emptyList());
+                null);
 
         ImageFileCreator.create(archives, ByteOrder.nativeOrder(), stack);
     }
--- a/jdk/test/tools/jlink/IntegrationTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/IntegrationTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -34,17 +34,17 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.Jlink.JlinkConfiguration;
 import jdk.tools.jlink.Jlink.PluginsConfiguration;
 import jdk.tools.jlink.builder.DefaultImageBuilder;
-import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.PostProcessorPlugin;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.internal.ExecutableImage;
+import jdk.tools.jlink.internal.PostProcessor;
 import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
 import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
-import jdk.tools.jlink.plugin.Plugin;
 
 import tests.Helper;
 import tests.JImageGenerator;
@@ -70,7 +70,7 @@
 
     private static final List<Integer> ordered = new ArrayList<>();
 
-    public static class MyPostProcessor implements PostProcessorPlugin {
+    public static class MyPostProcessor implements PostProcessor, Plugin {
 
         public static final String NAME = "mypostprocessor";
 
@@ -98,9 +98,14 @@
         public void configure(Map<String, String> config) {
             throw new UnsupportedOperationException("Shouldn't be called");
         }
+
+        @Override
+        public void visit(ModulePool in, ModulePool out) {
+            in.transformAndCopy(Function.identity(), out);
+        }
     }
 
-    public static class MyPlugin1 implements TransformerPlugin {
+    public static class MyPlugin1 implements Plugin {
 
         Integer index;
         Set<String> after;
--- a/jdk/test/tools/jlink/JLinkOptionsTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/JLinkOptionsTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -26,7 +26,7 @@
 import java.util.Set;
 import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.internal.PluginRepository;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 
 import tests.Helper;
 
@@ -46,7 +46,7 @@
  */
 public class JLinkOptionsTest {
 
-    private static class TestPlugin implements TransformerPlugin {
+    private static class TestPlugin implements Plugin {
         private final String name;
         private final String option;
 
--- a/jdk/test/tools/jlink/JLinkPostProcessingTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/JLinkPostProcessingTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -28,10 +28,13 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.internal.PluginRepository;
-import jdk.tools.jlink.plugin.ExecutableImage;
-import jdk.tools.jlink.plugin.PostProcessorPlugin;
+import jdk.tools.jlink.internal.PostProcessor;
+import jdk.tools.jlink.internal.ExecutableImage;
 import tests.Helper;
 
 /*
@@ -50,7 +53,7 @@
  */
 public class JLinkPostProcessingTest {
 
-    private static class PPPlugin implements PostProcessorPlugin {
+    private static class PPPlugin implements PostProcessor, Plugin {
 
         private static ExecutableImage called;
         private static final String NAME = "pp";
@@ -68,6 +71,11 @@
         }
 
         @Override
+        public void visit(ModulePool in, ModulePool out) {
+            in.transformAndCopy(Function.identity(), out);
+        }
+
+        @Override
         public String getName() {
             return NAME;
         }
--- a/jdk/test/tools/jlink/JLinkTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/JLinkTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -35,7 +35,6 @@
 import java.util.stream.Stream;
 
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 import jdk.tools.jlink.internal.PluginRepository;
 import tests.Helper;
 import tests.JImageGenerator;
@@ -53,17 +52,21 @@
  *          jdk.jlink/jdk.tools.jimage
  *          jdk.compiler
  * @build tests.*
- * @run main/othervm -verbose:gc -Xmx1g JLinkTest
+ * @run main/othervm -Xmx1g JLinkTest
  */
 public class JLinkTest {
     // number of built-in plugins from jdk.jlink module
     private static int getNumJlinkPlugins() {
         ModuleDescriptor desc = Plugin.class.getModule().getDescriptor();
         return desc.provides().
-                    get(TransformerPlugin.class.getName()).
+                    get(Plugin.class.getName()).
                     providers().size();
     }
 
+    private static boolean isOfJLinkModule(Plugin p) {
+        return p.getClass().getModule() == Plugin.class.getModule();
+    }
+
     public static void main(String[] args) throws Exception {
 
         Helper helper = Helper.newHelper();
@@ -72,20 +75,27 @@
             return;
         }
         helper.generateDefaultModules();
-        int numPlugins = getNumJlinkPlugins();
+        // expected num. of plugins from jdk.jlink module
+        int expectedJLinkPlugins = getNumJlinkPlugins();
+        int totalPlugins = 0;
         {
             // number of built-in plugins
             List<Plugin> builtInPlugins = new ArrayList<>();
             builtInPlugins.addAll(PluginRepository.getPlugins(Layer.boot()));
+            totalPlugins = builtInPlugins.size();
+            // actual num. of plugins loaded from jdk.jlink module
+            int actualJLinkPlugins = 0;
             for (Plugin p : builtInPlugins) {
                 p.getState();
                 p.getType();
+                if (isOfJLinkModule(p)) {
+                    actualJLinkPlugins++;
+                }
             }
-            // Note: other boot layer modules may provide jlink plugins.
-            // We should at least see the builtin plugins from jdk.jlink.
-            if (builtInPlugins.size() < numPlugins) {
-                throw new AssertionError("Found plugins doesn't match expected number : " +
-                        numPlugins + "\n" + builtInPlugins);
+            if (expectedJLinkPlugins != actualJLinkPlugins) {
+                throw new AssertionError("Actual plugins loaded from jdk.jlink: " +
+                        actualJLinkPlugins + " which doesn't match expected number : " +
+                        expectedJLinkPlugins);
             }
         }
 
@@ -150,9 +160,9 @@
             long number = Stream.of(output.split("\\R"))
                     .filter((s) -> s.matches("Plugin Name:.*"))
                     .count();
-            if (number != numPlugins) {
+            if (number != totalPlugins) {
                 System.err.println(output);
-                throw new AssertionError("Found: " + number + " expected " + numPlugins);
+                throw new AssertionError("Found: " + number + " expected " + totalPlugins);
             }
         }
 
--- a/jdk/test/tools/jlink/customplugin/module-info.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/customplugin/module-info.java	Thu Jun 30 22:38:17 2016 +0000
@@ -23,6 +23,6 @@
 
 module customplugin {
     requires jdk.jlink;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with plugin.HelloPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with plugin.CustomPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with plugin.HelloPlugin;
+    provides jdk.tools.jlink.plugin.Plugin with plugin.CustomPlugin;
 }
--- a/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -27,9 +27,9 @@
 import java.util.function.Function;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 
-public class CustomPlugin implements TransformerPlugin {
+public class CustomPlugin implements Plugin {
 
     private final static String NAME = "custom-plugin";
 
--- a/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java	Thu Jun 30 22:38:17 2016 +0000
@@ -29,12 +29,12 @@
 import java.util.Map;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 
 /**
  * Custom plugin
  */
-public final class HelloPlugin implements TransformerPlugin {
+public final class HelloPlugin implements Plugin {
 
     private static final String OUTPUT_FILE = "customplugin.txt";
     public static final String NAME = "hello";
--- a/jdk/test/tools/jlink/plugins/CompressorPluginTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/CompressorPluginTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -61,7 +61,6 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class CompressorPluginTest {
 
@@ -279,9 +278,8 @@
             ModulePoolImpl inputResources,
             ModuleEntry res,
             List<Pattern> includesPatterns) {
-        TransformerPlugin compressor = (TransformerPlugin) plugin;
         ModulePool compressedModulePool = new ModulePoolImpl(ByteOrder.nativeOrder(), inputResources.getStringTable());
-        compressor.visit(inputResources, compressedModulePool);
+        plugin.visit(inputResources, compressedModulePool);
         String path = res.getPath();
         ModuleEntry compressed = compressedModulePool.findEntry(path).get();
         CompressedResourceHeader header
--- a/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -40,7 +40,6 @@
 import jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class ExcludeFilesPluginTest {
     public static void main(String[] args) throws Exception {
--- a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -38,7 +38,6 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class ExcludeVMPluginTest {
 
@@ -173,7 +172,7 @@
         }
         ModulePool out = new ModulePoolImpl();
 
-        TransformerPlugin p = new ExcludeVMPlugin();
+        Plugin p = new ExcludeVMPlugin();
         Map<String, String> config = new HashMap<>();
         if (vm != null) {
             config.put(ExcludeVMPlugin.NAME, vm);
--- a/jdk/test/tools/jlink/plugins/LastSorterTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/LastSorterTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -45,7 +45,6 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class LastSorterTest {
 
@@ -167,7 +166,7 @@
         }
     }
 
-    public static class SorterPlugin implements TransformerPlugin {
+    public static class SorterPlugin implements Plugin {
 
         private final String name;
         private String starts;
--- a/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -42,7 +42,7 @@
 import jdk.tools.jlink.internal.plugins.OrderResourcesPlugin;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 
 public class OrderResourcesPluginTest {
 
@@ -93,7 +93,7 @@
             ModulePool out = new ModulePoolImpl();
             Map<String, String> config = new HashMap<>();
             config.put(OrderResourcesPlugin.NAME, "/zazou/**,**/module-info.class");
-            TransformerPlugin p = new OrderResourcesPlugin();
+            Plugin p = new OrderResourcesPlugin();
             p.configure(config);
             p.visit(resources, out);
             check(out.entries().collect(Collectors.toList()), sorted);
@@ -116,7 +116,7 @@
             ModulePool out = new ModulePoolImpl();
             Map<String, String> config = new HashMap<>();
             config.put(OrderResourcesPlugin.NAME, "@" + order.getAbsolutePath());
-            TransformerPlugin p = new OrderResourcesPlugin();
+            Plugin p = new OrderResourcesPlugin();
             p.configure(config);
             p.visit(resources, out);
             check(out.entries().collect(Collectors.toList()), sorted2);
--- a/jdk/test/tools/jlink/plugins/PluginOrderTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/PluginOrderTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -46,7 +46,6 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.Plugin.Category;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class PluginOrderTest {
 
@@ -225,7 +224,7 @@
         PluginOrderingGraph.sort(plugins);
     }
 
-    private static class Plug implements TransformerPlugin {
+    private static class Plug implements Plugin {
 
         private final Set<String> isBefore;
         private final Set<String> isAfter;
--- a/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -44,7 +44,6 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class PluginsNegativeTest {
 
@@ -117,7 +116,7 @@
         }
     }
 
-    public static class CustomPlugin implements TransformerPlugin {
+    public static class CustomPlugin implements Plugin {
 
         private final String name;
 
--- a/jdk/test/tools/jlink/plugins/PrevisitorTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/PrevisitorTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -49,7 +49,6 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class PrevisitorTest {
 
@@ -107,7 +106,7 @@
         }
     }
 
-    private static class CustomPlugin implements TransformerPlugin, ResourcePrevisitor {
+    private static class CustomPlugin implements Plugin, ResourcePrevisitor {
 
         private static String NAME = "plugin";
 
--- a/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -57,7 +57,7 @@
 import jdk.tools.jlink.internal.plugins.StringSharingPlugin;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import tests.Helper;
 import tests.JImageValidator;
 
@@ -119,7 +119,7 @@
         try (java.util.stream.Stream<Path> stream = Files.walk(compiledClasses)) {
             stream.forEach(c);
         }
-        TransformerPlugin plugin = new StringSharingPlugin();
+        Plugin plugin = new StringSharingPlugin();
         ModulePoolImpl result = new ModulePoolImpl(resources.getByteOrder(), resources.getStringTable());
         plugin.visit(resources, result);
 
--- a/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -58,7 +58,7 @@
 import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Plugin;
 import tests.Helper;
 
 public class StripDebugPluginTest {
@@ -124,7 +124,7 @@
         checkDebugAttributes(result1.getBytes());
     }
 
-    private ModuleEntry stripDebug(TransformerPlugin debug, ModuleEntry classResource,
+    private ModuleEntry stripDebug(Plugin debug, ModuleEntry classResource,
             String path, String infoPath, byte[] moduleInfo) throws Exception {
         ModulePool resources = new ModulePoolImpl();
         resources.add(classResource);
--- a/jdk/test/tools/launcher/Arrrghs.java	Thu Jun 30 22:10:10 2016 +0000
+++ b/jdk/test/tools/launcher/Arrrghs.java	Thu Jun 30 22:38:17 2016 +0000
@@ -24,7 +24,7 @@
 /**
  * @test
  * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938
- *      6894719 6968053 7151434 7146424 8007333 8077822
+ *      6894719 6968053 7151434 7146424 8007333 8077822 8143640
  * @summary Argument parsing validation.
  * @compile -XDignore.symbol.file Arrrghs.java
  * @run main/othervm Arrrghs
@@ -197,6 +197,8 @@
         // more treatment of  mixed slashes
         checkArgumentParsing("f1/ f3\\ f4/", "f1/", "f3\\", "f4/");
         checkArgumentParsing("f1/ f2\' ' f3/ f4/", "f1/", "f2\'", "'", "f3/", "f4/");
+
+        checkArgumentParsing("a\\*\\b", "a\\*\\b");
     }
 
     private void initEmptyDir(File emptyDir) throws IOException {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/dryrun/DryRunTest.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8159596
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ *          jdk.jartool/sun.tools.jar
+ * @build DryRunTest CompilerUtils jdk.testlibrary.ProcessTools
+ * @run testng DryRunTest
+ * @summary Test java --dry-run
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.testlibrary.ProcessTools;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+
+@Test
+public class DryRunTest {
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+    private static final Path LIBS_DIR = Paths.get("libs");
+
+    // the module name of the test module
+    private static final String TEST_MODULE = "test";
+    private static final String M_MODULE = "m";
+
+    // the module main class
+    private static final String MAIN_CLASS = "jdk.test.Main";
+
+
+    @BeforeTest
+    public void compileTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+        assertTrue(CompilerUtils.compile(SRC_DIR.resolve(M_MODULE),
+                                         MODS_DIR,
+                                         "-modulesourcepath", SRC_DIR.toString()));
+
+        assertTrue(CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
+                                         MODS_DIR,
+                                         "-modulesourcepath", SRC_DIR.toString()));
+
+        Files.createDirectories(LIBS_DIR);
+
+        // create JAR files with no module-info.class
+        assertTrue(jar(M_MODULE, "p/Lib.class"));
+        assertTrue(jar(TEST_MODULE, "jdk/test/Main.class"));
+    }
+
+    /**
+     * Execute "java" with the given arguments, returning the exit code.
+     */
+    private int exec(String... args) throws Exception {
+       return ProcessTools.executeTestJava(args)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+    }
+
+
+    /**
+     * Launch module main
+     */
+    public void testModule() throws Exception {
+        String dir = MODS_DIR.toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        // java -modulepath mods -module $TESTMODULE/$MAINCLASS
+        // no resolution failure
+        int exitValue = exec("--dry-run", "-modulepath", dir, "-m", mid);
+        assertTrue(exitValue == 0);
+    }
+
+    /**
+     * Test non-existence module in -addmods
+     */
+    public void testNonExistAddModules() throws Exception {
+        String dir = MODS_DIR.toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        int exitValue = exec("--dry-run", "-modulepath", dir,
+                             "-addmods", "non.existence",
+                             "-m", mid);
+        assertTrue(exitValue != 0);
+    }
+
+    /**
+     * Launch main class from class path
+     */
+    public void testClassPath() throws Exception {
+        Path testJar = LIBS_DIR.resolve(TEST_MODULE + ".jar");
+        String libs = testJar.toString() + File.pathSeparator +
+                        LIBS_DIR.resolve(M_MODULE + ".jar").toString();
+
+        // test pass with m.jar:test.jar
+        int exitValue = exec("-classpath", libs, MAIN_CLASS);
+        assertTrue(exitValue == 0);
+
+        // m.jar is not on classpath and fails with p.Lib not found
+        exitValue = exec("-classpath", testJar.toString(), MAIN_CLASS);
+        assertTrue(exitValue != 0);
+
+        // dry pass passes since main is not executed
+        exitValue = exec("--dry-run", "-classpath", testJar.toString(), MAIN_CLASS);
+        assertTrue(exitValue == 0);
+    }
+
+    /**
+     * Test automatic modules
+     */
+    public void testAutomaticModule() throws Exception {
+        String libs = LIBS_DIR.resolve(M_MODULE + ".jar").toString() +
+                        File.pathSeparator +
+                        LIBS_DIR.resolve(TEST_MODULE + ".jar").toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        // test main method with and without -addmods mm
+        int exitValue = exec("-modulepath", LIBS_DIR.toString(),
+                             "-m", mid);
+        assertTrue(exitValue != 0);
+
+        exitValue = exec("-modulepath", LIBS_DIR.toString(),
+                         "-addmods", M_MODULE,
+                         "-m", mid);
+        assertTrue(exitValue == 0);
+
+        // test dry run with and without -addmods m
+        // no resolution failure
+        exitValue = exec("--dry-run", "-modulepath", LIBS_DIR.toString(),
+                         "-m", mid);
+        assertTrue(exitValue == 0);
+
+        exitValue = exec("--dry-run", "-modulepath", LIBS_DIR.toString(),
+                         "-addmods", M_MODULE,
+                         "-m", mid);
+        assertTrue(exitValue == 0);
+    }
+
+    /**
+     * module m not found
+     */
+    public void testMissingModule() throws Exception {
+        String subdir = MODS_DIR.resolve(TEST_MODULE).toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        // resolution failure
+        int exitValue = exec("--dry-run", "-modulepath", subdir, "-m", mid);
+        assertTrue(exitValue != 0);
+    }
+
+    private static boolean jar(String name, String entries) throws IOException {
+        Path jar = LIBS_DIR.resolve(name + ".jar");
+
+        // jar --create ...
+        String classes = MODS_DIR.resolve(name).toString();
+        String[] args = {
+            "--create",
+            "--file=" + jar,
+            "-C", classes, entries
+        };
+        boolean success
+            = new sun.tools.jar.Main(System.out, System.out, "jar").run(args);
+        return success;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/dryrun/src/m/module-info.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m {
+    exports p;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/dryrun/src/m/p/Lib.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+
+public class Lib {
+    public static void sayHi() {
+        System.out.println("Hello world");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/dryrun/src/test/jdk/test/Main.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test;
+
+public class Main {
+    public static void main(String[] args) {
+        p.Lib.sayHi();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/dryrun/src/test/module-info.java	Thu Jun 30 22:38:17 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module test {
+    requires m;
+}