changeset 13736:b9a92b2a8b37

Merge
author ddehaven
date Tue, 02 Feb 2016 12:12:52 -0800
parents 55a81cfbe8be 00821d616077
children d74d0c07410f
files src/java.base/share/classes/sun/misc/Cleaner.java test/java/net/SocketPermission/policy test/sun/misc/Cleaner/ExitOnThrow.java test/sun/misc/Cleaner/exitOnThrow.sh
diffstat 346 files changed, 89410 insertions(+), 1778 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Feb 02 16:33:03 2016 +0300
+++ b/.hgtags	Tue Feb 02 12:12:52 2016 -0800
@@ -345,3 +345,4 @@
 3d452840f48299a36842760d17c0c8402f0e1266 jdk-9+100
 5e8370fb3ed925335164afe340d1e54beab2d4d5 jdk-9+101
 6eb3c8132e489dab81adde4ce29844904ce15482 jdk-9+102
+eee1ced1d8e78293f2a004af818ca474387dbebf jdk-9+103
--- a/make/launcher/Launcher-jdk.javadoc.gmk	Tue Feb 02 16:33:03 2016 +0300
+++ b/make/launcher/Launcher-jdk.javadoc.gmk	Tue Feb 02 12:12:52 2016 -0800
@@ -26,7 +26,7 @@
 include LauncherCommon.gmk
 
 $(eval $(call SetupBuildLauncher, javadoc, \
-    MAIN_CLASS := com.sun.tools.javadoc.Main, \
+    MAIN_CLASS := jdk.javadoc.internal.tool.Main, \
     CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
         -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
 ))
--- a/make/mapfiles/libjava/mapfile-vers	Tue Feb 02 16:33:03 2016 +0300
+++ b/make/mapfiles/libjava/mapfile-vers	Tue Feb 02 12:12:52 2016 -0800
@@ -250,6 +250,7 @@
 		Java_sun_misc_Signal_raise0;
               Java_sun_reflect_ConstantPool_getClassAt0;
               Java_sun_reflect_ConstantPool_getClassAtIfLoaded0;
+              Java_sun_reflect_ConstantPool_getClassRefIndexAt0;
               Java_sun_reflect_ConstantPool_getDoubleAt0;
               Java_sun_reflect_ConstantPool_getFieldAt0;
               Java_sun_reflect_ConstantPool_getFieldAtIfLoaded0;
@@ -259,8 +260,11 @@
               Java_sun_reflect_ConstantPool_getMemberRefInfoAt0;
               Java_sun_reflect_ConstantPool_getMethodAt0;
               Java_sun_reflect_ConstantPool_getMethodAtIfLoaded0;
+              Java_sun_reflect_ConstantPool_getNameAndTypeRefIndexAt0;
+              Java_sun_reflect_ConstantPool_getNameAndTypeRefInfoAt0;
               Java_sun_reflect_ConstantPool_getSize0;
               Java_sun_reflect_ConstantPool_getStringAt0;
+              Java_sun_reflect_ConstantPool_getTagAt0;
               Java_sun_reflect_ConstantPool_getUTF8At0;
 		Java_java_io_Console_istty;
 		Java_java_io_Console_encoding;
--- a/src/java.base/share/classes/com/sun/crypto/provider/AESCrypt.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/com/sun/crypto/provider/AESCrypt.java	Tue Feb 02 12:12:52 2016 -0800
@@ -351,8 +351,8 @@
      */
     void encryptBlock(byte[] in, int inOffset,
                       byte[] out, int outOffset) {
-        cryptBlockCheck(in, inOffset);
-        cryptBlockCheck(out, outOffset);
+        Objects.checkFromIndexSize(inOffset, AES_BLOCK_SIZE, in.length);
+        Objects.checkFromIndexSize(outOffset, AES_BLOCK_SIZE, out.length);
         implEncryptBlock(in, inOffset, out, outOffset);
     }
 
@@ -430,8 +430,8 @@
      */
     void decryptBlock(byte[] in, int inOffset,
                       byte[] out, int outOffset) {
-        cryptBlockCheck(in, inOffset);
-        cryptBlockCheck(out, outOffset);
+        Objects.checkFromIndexSize(inOffset, AES_BLOCK_SIZE, in.length);
+        Objects.checkFromIndexSize(outOffset, AES_BLOCK_SIZE, out.length);
         implDecryptBlock(in, inOffset, out, outOffset);
     }
 
@@ -593,26 +593,6 @@
         out[outOffset  ] = (byte)(Si[(a0       ) & 0xFF] ^ (t1       ));
     }
 
-    // Used to perform all checks required by the Java semantics
-    // (i.e., null checks and bounds checks) on the input parameters
-    // to encryptBlock and to decryptBlock.
-    // Normally, the Java Runtime performs these checks, however, as
-    // encryptBlock and decryptBlock are possibly replaced with
-    // compiler intrinsics, the JDK performs the required checks instead.
-    // Does not check accesses to class-internal (private) arrays.
-    private static void cryptBlockCheck(byte[] array, int offset) {
-        Objects.requireNonNull(array);
-
-        if (offset < 0 || offset >= array.length) {
-            throw new ArrayIndexOutOfBoundsException(offset);
-        }
-
-        int largestIndex = offset + AES_BLOCK_SIZE - 1;
-        if (largestIndex < 0 || largestIndex >= array.length) {
-            throw new ArrayIndexOutOfBoundsException(largestIndex);
-        }
-    }
-
     /**
      * Expand a user-supplied key material into a session key.
      *
--- a/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java	Tue Feb 02 12:12:52 2016 -0800
@@ -173,9 +173,9 @@
      */
     private int crypt(byte[] in, int inOff, int len, byte[] out, int outOff) {
 
-        cryptBlockCheck(in, inOff, len);
-        cryptBlockCheck(out, outOff, len);
-        return implCrypt(in, inOff, len, out, outOff);
+      Objects.checkFromIndexSize(inOff, len, in.length);
+      Objects.checkFromIndexSize(outOff, len, out.length);
+      return implCrypt(in, inOff, len, out, outOff);
     }
 
     // Implementation of crpyt() method. Possibly replaced with a compiler intrinsic.
@@ -193,22 +193,4 @@
         return result;
     }
 
-    // Used to perform all checks required by the Java semantics
-    // (i.e., null checks and bounds checks) on the input parameters to crypt().
-    // Normally, the Java Runtime performs these checks, however, as crypt() is
-    // possibly replaced with compiler intrinsic, the JDK performs the
-    // required checks instead.
-    // Does not check accesses to class-internal (private) arrays.
-    private static void cryptBlockCheck(byte[] array, int offset, int len) {
-        Objects.requireNonNull(array);
-
-        if (offset < 0 || len < 0 || offset >= array.length) {
-            throw new ArrayIndexOutOfBoundsException(offset);
-        }
-
-        int largestIndex = offset + len - 1;
-        if (largestIndex < 0 || largestIndex >= array.length) {
-            throw new ArrayIndexOutOfBoundsException(largestIndex);
-        }
-    }
 }
--- a/src/java.base/share/classes/java/lang/Integer.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/lang/Integer.java	Tue Feb 02 12:12:52 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -339,7 +339,6 @@
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
         int chars = Math.max(((mag + (shift - 1)) / shift), 1);
-
         if (COMPACT_STRINGS) {
             byte[] buf = new byte[chars];
             formatUnsignedInt(val, shift, buf, 0, chars);
@@ -477,8 +476,13 @@
      * values, to cover the Integer.MIN_VALUE case. Converting otherwise
      * (negative to positive) will expose -Integer.MIN_VALUE that overflows
      * integer.
+     *
+     * @param i     value to convert
+     * @param index next index, after the least significant digit
+     * @param buf   target buffer, Latin1-encoded
+     * @return index of the most significant digit or minus sign, if present
      */
-    static void getChars(int i, int index, byte[] buf) {
+    static int getChars(int i, int index, byte[] buf) {
         int q, r;
         int charPos = index;
 
@@ -509,9 +513,19 @@
         if (negative) {
             buf[--charPos] = (byte)'-';
         }
+        return charPos;
     }
 
-    static void getCharsUTF16(int i, int index, byte[] buf) {
+    /**
+     * This is a variant of {@link #getChars(int, int, byte[])}, but for
+     * UTF-16 coder.
+     *
+     * @param i     value to convert
+     * @param index next index, after the least significant digit
+     * @param buf   target buffer, UTF16-coded.
+     * @return index of the most significant digit or minus sign, if present
+     */
+    static int getCharsUTF16(int i, int index, byte[] buf) {
         int q, r;
         int charPos = index;
 
@@ -542,6 +556,7 @@
         if (negative) {
             StringUTF16.putChar(buf, --charPos, '-');
         }
+        return charPos;
     }
 
     // Left here for compatibility reasons, see JDK-8143900.
--- a/src/java.base/share/classes/java/lang/Long.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/lang/Long.java	Tue Feb 02 12:12:52 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -379,7 +379,6 @@
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         int mag = Long.SIZE - Long.numberOfLeadingZeros(val);
         int chars = Math.max(((mag + (shift - 1)) / shift), 1);
-
         if (COMPACT_STRINGS) {
             byte[] buf = new byte[chars];
             formatUnsignedLong0(val, shift, buf, 0, chars);
@@ -489,8 +488,13 @@
      * values, to cover the Long.MIN_VALUE case. Converting otherwise
      * (negative to positive) will expose -Long.MIN_VALUE that overflows
      * long.
+     *
+     * @param i     value to convert
+     * @param index next index, after the least significant digit
+     * @param buf   target buffer, Latin1-encoded
+     * @return index of the most significant digit or minus sign, if present
      */
-    static void getChars(long i, int index, byte[] buf) {
+    static int getChars(long i, int index, byte[] buf) {
         long q;
         int r;
         int charPos = index;
@@ -533,9 +537,19 @@
         if (negative) {
             buf[--charPos] = (byte)'-';
         }
+        return charPos;
     }
 
-    static void getCharsUTF16(long i, int index, byte[] buf) {
+    /**
+     * This is a variant of {@link #getChars(long, int, byte[])}, but for
+     * UTF-16 coder.
+     *
+     * @param i     value to convert
+     * @param index next index, after the least significant digit
+     * @param buf   target buffer, UTF16-coded.
+     * @return index of the most significant digit or minus sign, if present
+     */
+    static int getCharsUTF16(long i, int index, byte[] buf) {
         long q;
         int r;
         int charPos = index;
@@ -578,6 +592,7 @@
         if (negative) {
             StringUTF16.putChar(buf, --charPos, '-');
         }
+        return charPos;
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/StringConcatHelper.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * Helper for string concatenation. These methods are mostly looked up with private lookups
+ * from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle}
+ * combinators there.
+ */
+final class StringConcatHelper {
+
+    private StringConcatHelper() {
+        // no instantiation
+    }
+
+    /**
+     * Check for overflow, throw the exception on overflow.
+     * @param len String length
+     * @return length
+     */
+    private static int checkOverflow(int len) {
+        if (len < 0) {
+            throw new OutOfMemoryError("Overflow: String length out of range");
+        }
+        return len;
+    }
+
+    /**
+     * Mix value length into current length
+     * @param current current length
+     * @param value   value to mix in
+     * @return new length
+     */
+    static int mixLen(int current, boolean value) {
+        return checkOverflow(current + (value ? 4 : 5));
+    }
+
+    /**
+     * Mix value length into current length
+     * @param current current length
+     * @param value   value to mix in
+     * @return new length
+     */
+    static int mixLen(int current, byte value) {
+        return mixLen(current, (int)value);
+    }
+
+    /**
+     * Mix value length into current length
+     * @param current current length
+     * @param value   value to mix in
+     * @return new length
+     */
+    static int mixLen(int current, char value) {
+        return checkOverflow(current + 1);
+    }
+
+    /**
+     * Mix value length into current length
+     * @param current current length
+     * @param value   value to mix in
+     * @return new length
+     */
+    static int mixLen(int current, short value) {
+        return mixLen(current, (int)value);
+    }
+
+    /**
+     * Mix value length into current length
+     * @param current current length
+     * @param value   value to mix in
+     * @return new length
+     */
+    static int mixLen(int current, int value) {
+        return checkOverflow(current + Integer.stringSize(value));
+    }
+
+    /**
+     * Mix value length into current length
+     * @param current current length
+     * @param value   value to mix in
+     * @return new length
+     */
+    static int mixLen(int current, long value) {
+        return checkOverflow(current + Long.stringSize(value));
+    }
+
+    /**
+     * Mix value length into current length
+     * @param current current length
+     * @param value   value to mix in
+     * @return new length
+     */
+    static int mixLen(int current, String value) {
+        return checkOverflow(current + value.length());
+    }
+
+    /**
+     * Mix coder into current coder
+     * @param current current coder
+     * @param value   value to mix in
+     * @return new coder
+     */
+    static byte mixCoder(byte current, char value) {
+        return (byte)(current | (StringLatin1.canEncode(value) ? 0 : 1));
+    }
+
+    /**
+     * Mix coder into current coder
+     * @param current current coder
+     * @param value   value to mix in
+     * @return new coder
+     */
+    static byte mixCoder(byte current, String value) {
+        return (byte)(current | value.coder());
+    }
+
+    /**
+     * Mix coder into current coder
+     * @param current current coder
+     * @param value   value to mix in
+     * @return new coder
+     */
+    static byte mixCoder(byte current, boolean value) {
+        // Booleans are represented with Latin1
+        return current;
+    }
+
+    /**
+     * Mix coder into current coder
+     * @param current current coder
+     * @param value   value to mix in
+     * @return new coder
+     */
+    static byte mixCoder(byte current, byte value) {
+        // Bytes are represented with Latin1
+        return current;
+    }
+
+    /**
+     * Mix coder into current coder
+     * @param current current coder
+     * @param value   value to mix in
+     * @return new coder
+     */
+    static byte mixCoder(byte current, short value) {
+        // Shorts are represented with Latin1
+        return current;
+    }
+
+    /**
+     * Mix coder into current coder
+     * @param current current coder
+     * @param value   value to mix in
+     * @return new coder
+     */
+    static byte mixCoder(byte current, int value) {
+        // Ints are represented with Latin1
+        return current;
+    }
+
+    /**
+     * Mix coder into current coder
+     * @param current current coder
+     * @param value   value to mix in
+     * @return new coder
+     */
+    static byte mixCoder(byte current, long value) {
+        // Longs are represented with Latin1
+        return current;
+    }
+
+    /**
+     * Prepends the stringly representation of boolean value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param index final char index in the buffer
+     * @param buf   buffer to append to
+     * @param coder coder to add with
+     * @param value boolean value to encode
+     * @return new index
+     */
+    static int prepend(int index, byte[] buf, byte coder, boolean value) {
+        if (coder == String.LATIN1) {
+            if (value) {
+                buf[--index] = 'e';
+                buf[--index] = 'u';
+                buf[--index] = 'r';
+                buf[--index] = 't';
+            } else {
+                buf[--index] = 'e';
+                buf[--index] = 's';
+                buf[--index] = 'l';
+                buf[--index] = 'a';
+                buf[--index] = 'f';
+            }
+        } else {
+            if (value) {
+                StringUTF16.putChar(buf, --index, 'e');
+                StringUTF16.putChar(buf, --index, 'u');
+                StringUTF16.putChar(buf, --index, 'r');
+                StringUTF16.putChar(buf, --index, 't');
+            } else {
+                StringUTF16.putChar(buf, --index, 'e');
+                StringUTF16.putChar(buf, --index, 's');
+                StringUTF16.putChar(buf, --index, 'l');
+                StringUTF16.putChar(buf, --index, 'a');
+                StringUTF16.putChar(buf, --index, 'f');
+            }
+        }
+        return index;
+    }
+
+    /**
+     * Prepends the stringly representation of byte value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param index final char index in the buffer
+     * @param buf   buffer to append to
+     * @param coder coder to add with
+     * @param value byte value to encode
+     * @return new index
+     */
+    static int prepend(int index, byte[] buf, byte coder, byte value) {
+        return prepend(index, buf, coder, (int)value);
+    }
+
+    /**
+     * Prepends the stringly representation of char value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param index final char index in the buffer
+     * @param buf   buffer to append to
+     * @param coder coder to add with
+     * @param value char value to encode
+     * @return new index
+     */
+    static int prepend(int index, byte[] buf, byte coder, char value) {
+        if (coder == String.LATIN1) {
+            buf[--index] = (byte) (value & 0xFF);
+        } else {
+            StringUTF16.putChar(buf, --index, value);
+        }
+        return index;
+    }
+
+    /**
+     * Prepends the stringly representation of short value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param index final char index in the buffer
+     * @param buf   buffer to append to
+     * @param coder coder to add with
+     * @param value short value to encode
+     * @return new index
+     */
+    static int prepend(int index, byte[] buf, byte coder, short value) {
+        return prepend(index, buf, coder, (int)value);
+    }
+
+    /**
+     * Prepends the stringly representation of integer value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param index final char index in the buffer
+     * @param buf   buffer to append to
+     * @param coder coder to add with
+     * @param value integer value to encode
+     * @return new index
+     */
+    static int prepend(int index, byte[] buf, byte coder, int value) {
+        if (coder == String.LATIN1) {
+            return Integer.getChars(value, index, buf);
+        } else {
+            return Integer.getCharsUTF16(value, index, buf);
+        }
+    }
+
+    /**
+     * Prepends the stringly representation of long value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param index final char index in the buffer
+     * @param buf   buffer to append to
+     * @param coder coder to add with
+     * @param value long value to encode
+     * @return new index
+     */
+    static int prepend(int index, byte[] buf, byte coder, long value) {
+        if (coder == String.LATIN1) {
+            return Long.getChars(value, index, buf);
+        } else {
+            return Long.getCharsUTF16(value, index, buf);
+        }
+    }
+
+    /**
+     * Prepends the stringly representation of String value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param index final char index in the buffer
+     * @param buf   buffer to append to
+     * @param coder coder to add with
+     * @param value String value to encode
+     * @return new index
+     */
+    static int prepend(int index, byte[] buf, byte coder, String value) {
+        index -= value.length();
+        value.getBytes(buf, index, coder);
+        return index;
+    }
+
+    /**
+     * Instantiates the String with given buffer and coder
+     * @param buf     buffer to use
+     * @param coder   coder to use
+     * @return String resulting string
+     */
+    static String newString(byte[] buf, byte coder) {
+        // Use the private, non-copying constructor (unsafe!)
+        return new String(buf, coder);
+    }
+
+}
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Tue Feb 02 12:12:52 2016 -0800
@@ -30,7 +30,7 @@
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
 import static java.lang.invoke.MethodHandleStatics.*;
 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
-import sun.misc.Cleaner;
+import jdk.internal.ref.Cleaner;
 
 /**
  * The JVM interface for the method handles package is all here.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatException.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * StringConcatException is thrown by {@link StringConcatFactory} when linkage
+ * invariants are violated.
+ *
+ * @since 9
+ */
+public class StringConcatException extends Exception {
+    private static final long serialVersionUID = 292L + 9L;
+
+    /**
+     * Constructs an exception with a message
+     * @param msg exception message
+     */
+    public StringConcatException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs an exception with a message and a linked throwable
+     * @param msg   exception message
+     * @param cause throwable cause
+     */
+    public StringConcatException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,1804 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.vm.annotation.ForceInline;
+import sun.misc.Unsafe;
+
+import java.lang.invoke.MethodHandles.Lookup;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+/**
+ * <p>Methods to facilitate the creation of String concatenation methods, that
+ * can be used to efficiently concatenate a known number of arguments of known
+ * types, possibly after type adaptation and partial evaluation of arguments.
+ * These methods are typically used as <em>bootstrap methods</em> for {@code
+ * invokedynamic} call sites, to support the <em>string concatenation</em>
+ * feature of the Java Programming Language.
+ *
+ * <p>Indirect access to the behavior specified by the provided {@code
+ * MethodHandle} proceeds in order through two phases:
+ *
+ * <ol>
+ *     <li><em>Linkage</em> occurs when the methods in this class are invoked.
+ * They take as arguments a method type describing the concatenated arguments
+ * count and types, and optionally the String <em>recipe</em>, plus the
+ * constants that participate in the String concatenation. The details on
+ * accepted recipe shapes are described further below. Linkage may involve
+ * dynamically loading a new class that implements the expected concatenation
+ * behavior. The {@code CallSite} holds the {@code MethodHandle} pointing to the
+ * exact concatenation method. The concatenation methods may be shared among
+ * different {@code CallSite}s, e.g. if linkage methods produce them as pure
+ * functions.</li>
+ *
+ * <li><em>Invocation</em> occurs when a generated concatenation method is
+ * invoked with the exact dynamic arguments. This may occur many times for a
+ * single concatenation method. The method referenced by the behavior {@code
+ * MethodHandle} is invoked with the static arguments and any additional dynamic
+ * arguments provided on invocation, as if by {@link MethodHandle#invoke(Object...)}.</li>
+ * </ol>
+ *
+ * <p> This class provides two forms of linkage methods: a simple version
+ * ({@link #makeConcat(java.lang.invoke.MethodHandles.Lookup, String,
+ * MethodType)}) using only the dynamic arguments, and an advanced version
+ * ({@link #makeConcatWithConstants(java.lang.invoke.MethodHandles.Lookup,
+ * String, MethodType, String, Object...)} using the advanced forms of capturing
+ * the constant arguments. The advanced strategy can produce marginally better
+ * invocation bytecode, at the expense of exploding the number of shapes of
+ * string concatenation methods present at runtime, because those shapes would
+ * include constant static arguments as well.
+ *
+ * @author Aleksey Shipilev
+ * @author Remi Forax
+ * @author Peter Levart
+ *
+ * @apiNote
+ * <p>There is a JVM limit (classfile structural constraint): no method
+ * can call with more than 255 slots. This limits the number of static and
+ * dynamic arguments one can pass to bootstrap method. Since there are potential
+ * concatenation strategies that use {@code MethodHandle} combinators, we need
+ * to reserve a few empty slots on the parameter lists to to capture the
+ * temporal results. This is why bootstrap methods in this factory do not accept
+ * more than 200 argument slots. Users requiring more than 200 argument slots in
+ * concatenation are expected to split the large concatenation in smaller
+ * expressions.
+ *
+ * @since 9
+ */
+public final class StringConcatFactory {
+
+    /**
+     * Tag used to demarcate an ordinary argument.
+     */
+    private static final char TAG_ARG = '\u0001';
+
+    /**
+     * Tag used to demarcate a constant.
+     */
+    private static final char TAG_CONST = '\u0002';
+
+    /**
+     * Maximum number of argument slots in String Concat call.
+     *
+     * While the maximum number of argument slots that indy call can handle is 253,
+     * we do not use all those slots, to let the strategies with MethodHandle
+     * combinators to use some arguments.
+     */
+    private static final int MAX_INDY_CONCAT_ARG_SLOTS = 200;
+
+    /**
+     * Concatenation strategy to use. See {@link Strategy} for possible options.
+     * This option is controllable with -Djava.lang.invoke.stringConcat JDK option.
+     */
+    private static final Strategy STRATEGY;
+
+    /**
+     * Default strategy to use for concatenation.
+     */
+    private static final Strategy DEFAULT_STRATEGY = Strategy.BC_SB;
+
+    private enum Strategy {
+        /**
+         * Bytecode generator, calling into {@link java.lang.StringBuilder}.
+         */
+        BC_SB,
+
+        /**
+         * Bytecode generator, calling into {@link java.lang.StringBuilder};
+         * but trying to estimate the required storage.
+         */
+        BC_SB_SIZED,
+
+        /**
+         * Bytecode generator, calling into {@link java.lang.StringBuilder};
+         * but computing the required storage exactly.
+         */
+        BC_SB_SIZED_EXACT,
+
+        /**
+         * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
+         * This strategy also tries to estimate the required storage.
+         */
+        MH_SB_SIZED,
+
+        /**
+         * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
+         * This strategy also estimate the required storage exactly.
+         */
+        MH_SB_SIZED_EXACT,
+
+        /**
+         * MethodHandle-based generator, that constructs its own byte[] array from
+         * the arguments. It computes the required storage exactly.
+         */
+        MH_INLINE_SIZED_EXACT
+    }
+
+    /**
+     * Enables debugging: this may print debugging messages, perform additional (non-neutral for performance)
+     * checks, etc.
+     */
+    private static final boolean DEBUG;
+
+    /**
+     * Enables caching of strategy stubs. This may improve the linkage time by reusing the generated
+     * code, at the expense of contaminating the profiles.
+     */
+    private static final boolean CACHE_ENABLE;
+
+    private static final ConcurrentMap<Key, MethodHandle> CACHE;
+
+    static {
+        // Poke the privileged block once, taking everything we need:
+        final Object[] values = new Object[3];
+        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
+            values[0] = System.getProperty("java.lang.invoke.stringConcat");
+            values[1] = Boolean.getBoolean("java.lang.invoke.stringConcat.cache");
+            values[2] = Boolean.getBoolean("java.lang.invoke.stringConcat.debug");
+            return null;
+        });
+
+        final String strategy = (String)  values[0];
+        CACHE_ENABLE          = (Boolean) values[1];
+        DEBUG                 = (Boolean) values[2];
+
+        STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy);
+        CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null;
+    }
+
+    private static final class Key {
+        final MethodType mt;
+        final Recipe recipe;
+
+        public Key(MethodType mt, Recipe recipe) {
+            this.mt = mt;
+            this.recipe = recipe;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (!mt.equals(key.mt)) return false;
+            if (!recipe.equals(key.recipe)) return false;
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = mt.hashCode();
+            result = 31 * result + recipe.hashCode();
+            return result;
+        }
+    }
+
+    /**
+     * Parses the recipe string, and produces the traversable collection of
+     * {@link java.lang.invoke.StringConcatFactory.RecipeElement}-s for generator
+     * strategies. Notably, this class parses out the constants from the recipe
+     * and from other static arguments.
+     */
+    private static final class Recipe {
+        private final List<RecipeElement> elements;
+        private final List<RecipeElement> elementsRev;
+
+        public Recipe(String src, Object[] constants) {
+            List<RecipeElement> el = new ArrayList<>();
+
+            int constC = 0;
+            int argC = 0;
+
+            StringBuilder acc = new StringBuilder();
+
+            for (int i = 0; i < src.length(); i++) {
+                char c = src.charAt(i);
+
+                if (c == TAG_CONST || c == TAG_ARG) {
+                    // Detected a special tag, flush all accumulated characters
+                    // as a constant first:
+                    if (acc.length() > 0) {
+                        el.add(new RecipeElement(acc.toString()));
+                        acc.setLength(0);
+                    }
+                    if (c == TAG_CONST) {
+                        Object cnst = constants[constC++];
+                        el.add(new RecipeElement(cnst));
+                    }
+                    if (c == TAG_ARG) {
+                        el.add(new RecipeElement(argC++));
+                    }
+                } else {
+                    // Not a special characters, this is a constant embedded into
+                    // the recipe itself.
+                    acc.append(c);
+                }
+            }
+
+            // Flush the remaining characters as constant:
+            if (acc.length() > 0) {
+                el.add(new RecipeElement(acc.toString()));
+            }
+
+            elements = new ArrayList<>(el);
+            Collections.reverse(el);
+            elementsRev = el;
+        }
+
+        public Collection<RecipeElement> getElements() {
+            return elements;
+        }
+
+        public Collection<RecipeElement> getElementsReversed() {
+            return elementsRev;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Recipe recipe = (Recipe) o;
+            return elements.equals(recipe.elements);
+        }
+
+        @Override
+        public int hashCode() {
+            return elements.hashCode();
+        }
+    }
+
+    private static final class RecipeElement {
+        private final Object value;
+        private final int argPos;
+        private final Tag tag;
+
+        public RecipeElement(Object cnst) {
+            this.value = Objects.requireNonNull(cnst);
+            this.argPos = -1;
+            this.tag = Tag.CONST;
+        }
+
+        public RecipeElement(int arg) {
+            this.value = null;
+            this.argPos = arg;
+            this.tag = Tag.ARG;
+        }
+
+        public Object getValue() {
+            assert (tag == Tag.CONST);
+            return value;
+        }
+
+        public int getArgPos() {
+            assert (tag == Tag.ARG);
+            return argPos;
+        }
+
+        public Tag getTag() {
+            return tag;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            RecipeElement that = (RecipeElement) o;
+
+            if (tag != that.tag) return false;
+            if (tag == Tag.CONST && (!value.equals(that.value))) return false;
+            if (tag == Tag.ARG && (argPos != that.argPos)) return false;
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            return tag.hashCode();
+        }
+    }
+
+    private enum Tag {
+        CONST, ARG
+    }
+
+    /**
+     * Facilitates the creation of optimized String concatenation methods, that
+     * can be used to efficiently concatenate a known number of arguments of
+     * known types, possibly after type adaptation and partial evaluation of
+     * arguments. Typically used as a <em>bootstrap method</em> for {@code
+     * invokedynamic} call sites, to support the <em>string concatenation</em>
+     * feature of the Java Programming Language.
+     *
+     * <p>When the target of the {@code CallSite} returned from this method is
+     * invoked, it returns the result of String concatenation, taking all
+     * function arguments passed to the linkage method as inputs for
+     * concatenation. The target signature is given by {@code concatType}.
+     * The arguments are concatenated as per requirements stated in JLS 15.18.1
+     * "String Concatenation Operator +". Notably, the inputs are converted as
+     * per JLS 5.1.11 "String Conversion", and combined from left to right.
+     *
+     * <p>Assume the linkage arguments are as follows:
+     *
+     * <ul>
+     *     <li>{@code concatType}, describing the {@code CallSite} signature</li>
+     * </ul>
+     *
+     * <p>Then the following linkage invariants must hold:
+     *
+     * <ul>
+     *     <li>The parameter count in {@code concatType} is less than or equal to 200</li>
+     *
+     *     <li>The return type in {@code concatType} is assignable from {@link java.lang.String}</li>
+     * </ul>
+     *
+     * @param lookup   Represents a lookup context with the accessibility
+     *                 privileges of the caller.  When used with {@code
+     *                 invokedynamic}, this is stacked automatically by the VM.
+     * @param name     The name of the method to implement. This name is
+     *                 arbitrary, and has no meaning for this linkage method.
+     *                 When used with {@code invokedynamic}, this is provided by
+     *                 the {@code NameAndType} of the {@code InvokeDynamic}
+     *                 structure and is stacked automatically by the VM.
+     * @param concatType The expected signature of the {@code CallSite}.  The
+     *                   parameter types represent the types of concatenation
+     *                   arguments; the return type is always assignable from {@link
+     *                   java.lang.String}.  When used with {@code invokedynamic},
+     *                   this is provided by the {@code NameAndType} of the {@code
+     *                   InvokeDynamic} structure and is stacked automatically by
+     *                   the VM.
+     * @return a CallSite whose target can be used to perform String
+     * concatenation, with dynamic concatenation arguments described by the given
+     * {@code concatType}.
+     * @throws StringConcatException If any of the linkage invariants described
+     *                               here are violated.
+     * @throws NullPointerException If any of the incoming arguments is null.
+     *                              This will never happen when a bootstrap method
+     *                              is called with invokedynamic.
+     *
+     * @jls  5.1.11 String Conversion
+     * @jls 15.18.1 String Concatenation Operator +
+     */
+    public static CallSite makeConcat(MethodHandles.Lookup lookup,
+                                      String name,
+                                      MethodType concatType) throws StringConcatException {
+        if (DEBUG) {
+            System.out.println("StringConcatFactory " + STRATEGY + " is here for " + concatType);
+        }
+
+        return doStringConcat(lookup, name, concatType, true, null);
+    }
+
+    /**
+     * Facilitates the creation of optimized String concatenation methods, that
+     * can be used to efficiently concatenate a known number of arguments of
+     * known types, possibly after type adaptation and partial evaluation of
+     * arguments. Typically used as a <em>bootstrap method</em> for {@code
+     * invokedynamic} call sites, to support the <em>string concatenation</em>
+     * feature of the Java Programming Language.
+     *
+     * <p>When the target of the {@code CallSite} returned from this method is
+     * invoked, it returns the result of String concatenation, taking all
+     * function arguments and constants passed to the linkage method as inputs for
+     * concatenation. The target signature is given by {@code concatType}, and
+     * does not include constants. The arguments are concatenated as per requirements
+     * stated in JLS 15.18.1 "String Concatenation Operator +". Notably, the inputs
+     * are converted as per JLS 5.1.11 "String Conversion", and combined from left
+     * to right.
+     *
+     * <p>The concatenation <em>recipe</em> is a String description for the way to
+     * construct a concatenated String from the arguments and constants. The
+     * recipe is processed from left to right, and each character represents an
+     * input to concatenation. Recipe characters mean:
+     *
+     * <ul>
+     *
+     *   <li><em>\1 (Unicode point 0001)</em>: an ordinary argument. This
+     *   input is passed through dynamic argument, and is provided during the
+     *   concatenation method invocation. This input can be null.</li>
+     *
+     *   <li><em>\2 (Unicode point 0002):</em> a constant. This input passed
+     *   through static bootstrap argument. This constant can be any value
+     *   representable in constant pool. If necessary, the factory would call
+     *   {@code toString} to perform a one-time String conversion.</li>
+     *
+     *   <li><em>Any other char value:</em> a single character constant.</li>
+     * </ul>
+     *
+     * <p>Assume the linkage arguments are as follows:
+     *
+     * <ul>
+     *   <li>{@code concatType}, describing the {@code CallSite} signature</li>
+     *   <li>{@code recipe}, describing the String recipe</li>
+     *   <li>{@code constants}, the vararg array of constants</li>
+     * </ul>
+     *
+     * <p>Then the following linkage invariants must hold:
+     *
+     * <ul>
+     *   <li>The parameter count in {@code concatType} is less than or equal to
+     *   200</li>
+     *
+     *   <li>The parameter count in {@code concatType} equals to number of \1 tags
+     *   in {@code recipe}</li>
+     *
+     *   <li>The return type in {@code concatType} is assignable
+     *   from {@link java.lang.String}, and matches the return type of the
+     *   returned {@link MethodHandle}</li>
+     *
+     *   <li>The number of elements in {@code constants} equals to number of \2
+     *   tags in {@code recipe}</li>
+     * </ul>
+     *
+     * @param lookup    Represents a lookup context with the accessibility
+     *                  privileges of the caller. When used with {@code
+     *                  invokedynamic}, this is stacked automatically by the
+     *                  VM.
+     * @param name      The name of the method to implement. This name is
+     *                  arbitrary, and has no meaning for this linkage method.
+     *                  When used with {@code invokedynamic}, this is provided
+     *                  by the {@code NameAndType} of the {@code InvokeDynamic}
+     *                  structure and is stacked automatically by the VM.
+     * @param concatType The expected signature of the {@code CallSite}.  The
+     *                  parameter types represent the types of dynamic concatenation
+     *                  arguments; the return type is always assignable from {@link
+     *                  java.lang.String}.  When used with {@code
+     *                  invokedynamic}, this is provided by the {@code
+     *                  NameAndType} of the {@code InvokeDynamic} structure and
+     *                  is stacked automatically by the VM.
+     * @param recipe    Concatenation recipe, described above.
+     * @param constants A vararg parameter representing the constants passed to
+     *                  the linkage method.
+     * @return a CallSite whose target can be used to perform String
+     * concatenation, with dynamic concatenation arguments described by the given
+     * {@code concatType}.
+     * @throws StringConcatException If any of the linkage invariants described
+     *                               here are violated.
+     * @throws NullPointerException If any of the incoming arguments is null, or
+     *                              any constant in {@code recipe} is null.
+     *                              This will never happen when a bootstrap method
+     *                              is called with invokedynamic.
+     * @apiNote Code generators have three distinct ways to process a constant
+     * string operand S in a string concatenation expression.  First, S can be
+     * materialized as a reference (using ldc) and passed as an ordinary argument
+     * (recipe '\1'). Or, S can be stored in the constant pool and passed as a
+     * constant (recipe '\2') . Finally, if S contains neither of the recipe
+     * tag characters ('\1', '\2') then S can be interpolated into the recipe
+     * itself, causing its characters to be inserted into the result.
+     *
+     * @jls  5.1.11 String Conversion
+     * @jls 15.18.1 String Concatenation Operator +
+     */
+    public static CallSite makeConcatWithConstants(MethodHandles.Lookup lookup,
+                                                   String name,
+                                                   MethodType concatType,
+                                                   String recipe,
+                                                   Object... constants) throws StringConcatException {
+        if (DEBUG) {
+            System.out.println("StringConcatFactory " + STRATEGY + " is here for " + concatType + ", {" + recipe + "}, " + Arrays.toString(constants));
+        }
+
+        return doStringConcat(lookup, name, concatType, false, recipe, constants);
+    }
+
+    private static CallSite doStringConcat(MethodHandles.Lookup lookup,
+                                           String name,
+                                           MethodType concatType,
+                                           boolean generateRecipe,
+                                           String recipe,
+                                           Object... constants) throws StringConcatException {
+        Objects.requireNonNull(lookup, "Lookup is null");
+        Objects.requireNonNull(name, "Name is null");
+        Objects.requireNonNull(concatType, "Concat type is null");
+        Objects.requireNonNull(constants, "Constants are null");
+
+        for (Object o : constants) {
+            Objects.requireNonNull(o, "Cannot accept null constants");
+        }
+
+        int cCount = 0;
+        int oCount = 0;
+        if (generateRecipe) {
+            // Mock the recipe to reuse the concat generator code
+            char[] value = new char[concatType.parameterCount()];
+            Arrays.fill(value, TAG_ARG);
+            recipe = new String(value);
+            oCount = concatType.parameterCount();
+        } else {
+            Objects.requireNonNull(recipe, "Recipe is null");
+
+            for (int i = 0; i < recipe.length(); i++) {
+                char c = recipe.charAt(i);
+                if (c == TAG_CONST) cCount++;
+                if (c == TAG_ARG)   oCount++;
+            }
+        }
+
+        if (oCount != concatType.parameterCount()) {
+            throw new StringConcatException(
+                    "Mismatched number of concat arguments: recipe wants " +
+                            oCount +
+                            " arguments, but signature provides " +
+                            concatType.parameterCount());
+        }
+
+        if (cCount != constants.length) {
+            throw new StringConcatException(
+                    "Mismatched number of concat constants: recipe wants " +
+                            cCount +
+                            " constants, but only " +
+                            constants.length +
+                            " are passed");
+        }
+
+        if (!concatType.returnType().isAssignableFrom(String.class)) {
+            throw new StringConcatException(
+                    "The return type should be compatible with String, but it is " +
+                            concatType.returnType());
+        }
+
+        if (concatType.parameterCount() > MAX_INDY_CONCAT_ARG_SLOTS) {
+            throw new StringConcatException("Too many concat argument slots: " +
+                    concatType.parameterCount() +
+                    ", can only accept " +
+                    MAX_INDY_CONCAT_ARG_SLOTS);
+        }
+
+        MethodType mt = adaptType(concatType);
+
+        Recipe rec = new Recipe(recipe, constants);
+
+        MethodHandle mh;
+        if (CACHE_ENABLE) {
+            Key key = new Key(mt, rec);
+            mh = CACHE.get(key);
+            if (mh == null) {
+                mh = generate(lookup, mt, rec);
+                CACHE.put(key, mh);
+            }
+        } else {
+            mh = generate(lookup, mt, rec);
+        }
+        return new ConstantCallSite(mh.asType(concatType));
+    }
+
+    /**
+     * Adapt method type to an API we are going to use.
+     *
+     * This strips the concrete classes from the signatures, thus preventing
+     * class leakage when we cache the concatenation stubs.
+     *
+     * @param args actual argument types
+     * @return argument types the strategy is going to use
+     */
+    private static MethodType adaptType(MethodType args) {
+        Class<?>[] ptypes = args.parameterArray();
+        boolean changed = false;
+        for (int i = 0; i < ptypes.length; i++) {
+            Class<?> ptype = ptypes[i];
+            if (!ptype.isPrimitive() &&
+                    ptype != String.class &&
+                    ptype != Object.class) { // truncate to Object
+                ptypes[i] = Object.class;
+                changed = true;
+            }
+            // else other primitives or String or Object (unchanged)
+        }
+        return changed
+                ? MethodType.methodType(args.returnType(), ptypes)
+                : args;
+    }
+
+    private static MethodHandle generate(Lookup lookup, MethodType mt, Recipe recipe) throws StringConcatException {
+        try {
+            switch (STRATEGY) {
+                case BC_SB:
+                    return BytecodeStringBuilderStrategy.generate(lookup, mt, recipe, Mode.DEFAULT);
+                case BC_SB_SIZED:
+                    return BytecodeStringBuilderStrategy.generate(lookup, mt, recipe, Mode.SIZED);
+                case BC_SB_SIZED_EXACT:
+                    return BytecodeStringBuilderStrategy.generate(lookup, mt, recipe, Mode.SIZED_EXACT);
+                case MH_SB_SIZED:
+                    return MethodHandleStringBuilderStrategy.generate(mt, recipe, Mode.SIZED);
+                case MH_SB_SIZED_EXACT:
+                    return MethodHandleStringBuilderStrategy.generate(mt, recipe, Mode.SIZED_EXACT);
+                case MH_INLINE_SIZED_EXACT:
+                    return MethodHandleInlineCopyStrategy.generate(mt, recipe);
+                default:
+                    throw new StringConcatException("Concatenation strategy " + STRATEGY + " is not implemented");
+            }
+        } catch (Throwable t) {
+            throw new StringConcatException("Generator failed", t);
+        }
+    }
+
+    private enum Mode {
+        DEFAULT(false, false),
+        SIZED(true, false),
+        SIZED_EXACT(true, true);
+
+        private final boolean sized;
+        private final boolean exact;
+
+        Mode(boolean sized, boolean exact) {
+            this.sized = sized;
+            this.exact = exact;
+        }
+
+        boolean isSized() {
+            return sized;
+        }
+
+        boolean isExact() {
+            return exact;
+        }
+    }
+
+    /**
+     * Bytecode StringBuilder strategy.
+     *
+     * <p>This strategy operates in three modes, gated by {@link Mode}.
+     *
+     * <p><b>{@link Strategy#BC_SB}: "bytecode StringBuilder".</b>
+     *
+     * <p>This strategy spins up the bytecode that has the same StringBuilder
+     * chain javac would otherwise emit. This strategy uses only the public API,
+     * and comes as the baseline for the current JDK behavior. On other words,
+     * this strategy moves the javac generated bytecode to runtime. The
+     * generated bytecode is loaded via Unsafe.defineAnonymousClass, but with
+     * the caller class coming from the BSM -- in other words, the protection
+     * guarantees are inherited from the method where invokedynamic was
+     * originally called. This means, among other things, that the bytecode is
+     * verified for all non-JDK uses.
+     *
+     * <p><b>{@link Strategy#BC_SB_SIZED}: "bytecode StringBuilder, but
+     * sized".</b>
+     *
+     * <p>This strategy acts similarly to {@link Strategy#BC_SB}, but it also
+     * tries to guess the capacity required for StringBuilder to accept all
+     * arguments without resizing. This strategy only makes an educated guess:
+     * it only guesses the space required for known types (e.g. primitives and
+     * Strings), but does not otherwise convert arguments. Therefore, the
+     * capacity estimate may be wrong, and StringBuilder may have to
+     * transparently resize or trim when doing the actual concatenation. While
+     * this does not constitute a correctness issue (in the end, that what BC_SB
+     * has to do anyway), this does pose a potential performance problem.
+     *
+     * <p><b>{@link Strategy#BC_SB_SIZED_EXACT}: "bytecode StringBuilder, but
+     * sized exactly".</b>
+     *
+     * <p>This strategy improves on @link Strategy#BC_SB_SIZED}, by first
+     * converting all arguments to String in order to get the exact capacity
+     * StringBuilder should have. The conversion is done via the public
+     * String.valueOf and/or Object.toString methods, and does not touch any
+     * private String API.
+     */
+    private static final class BytecodeStringBuilderStrategy {
+        static final Unsafe UNSAFE = Unsafe.getUnsafe();
+        static final int CLASSFILE_VERSION = 52;
+        static final String NAME_FACTORY = "concat";
+        static final String CLASS_NAME = "java/lang/String$Concat";
+
+        private BytecodeStringBuilderStrategy() {
+            // no instantiation
+        }
+
+        private static MethodHandle generate(MethodHandles.Lookup lookup, MethodType args, Recipe recipe, Mode mode) throws Exception {
+            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
+
+            cw.visit(CLASSFILE_VERSION,
+                    ACC_SUPER + ACC_PUBLIC + ACC_FINAL + ACC_SYNTHETIC,
+                    CLASS_NAME,
+                    null,
+                    "java/lang/Object",
+                    null
+            );
+
+            MethodVisitor mv = cw.visitMethod(
+                    ACC_PUBLIC + ACC_STATIC + ACC_FINAL,
+                    NAME_FACTORY,
+                    args.toMethodDescriptorString(),
+                    null,
+                    null);
+
+            mv.visitAnnotation("Ljdk/internal/vm/annotation/ForceInline;", true);
+            mv.visitCode();
+
+            Class<?>[] arr = args.parameterArray();
+            boolean[] guaranteedNonNull = new boolean[arr.length];
+
+            if (mode.isExact()) {
+                /*
+                    In exact mode, we need to convert all arguments to their String representations,
+                    as this allows to compute their String sizes exactly. We cannot use private
+                    methods for primitives in here, therefore we need to convert those as well.
+
+                    We also record what arguments are guaranteed to be non-null as the result
+                    of the conversion. String.valueOf does the null checks for us. The only
+                    corner case to take care of is String.valueOf(Object) returning null itself.
+
+                    Also, if any conversion happened, then the slot indices in the incoming
+                    arguments are not equal to the final local maps. The only case this may break
+                    is when converting 2-slot long/double argument to 1-slot String. Therefore,
+                    we get away with tracking modified offset, since no conversion can overwrite
+                    the upcoming the argument.
+                 */
+
+                int off = 0;
+                int modOff = 0;
+                for (int c = 0; c < arr.length; c++) {
+                    Class<?> cl = arr[c];
+                    if (cl == String.class) {
+                        if (off != modOff) {
+                            mv.visitIntInsn(getLoadOpcode(cl), off);
+                            mv.visitIntInsn(ASTORE, modOff);
+                        }
+                    } else {
+                        mv.visitIntInsn(getLoadOpcode(cl), off);
+                        mv.visitMethodInsn(
+                                INVOKESTATIC,
+                                "java/lang/String",
+                                "valueOf",
+                                getStringValueOfDesc(cl),
+                                false
+                        );
+                        mv.visitIntInsn(ASTORE, modOff);
+                        arr[c] = String.class;
+                        guaranteedNonNull[c] = cl.isPrimitive();
+                    }
+                    off += getParameterSize(cl);
+                    modOff += getParameterSize(String.class);
+                }
+            }
+
+            if (mode.isSized()) {
+                /*
+                    When operating in sized mode (this includes exact mode), it makes sense to make
+                    StringBuilder append chains look familiar to OptimizeStringConcat. For that, we
+                    need to do null-checks early, not make the append chain shape simpler.
+                 */
+
+                int off = 0;
+                for (RecipeElement el : recipe.getElements()) {
+                    switch (el.getTag()) {
+                        case CONST: {
+                            // Guaranteed non-null, no null check required.
+                            break;
+                        }
+                        case ARG: {
+                            // Null-checks are needed only for String arguments, and when a previous stage
+                            // did not do implicit null-checks. If a String is null, we eagerly replace it
+                            // with "null" constant. Note, we omit Objects here, because we don't call
+                            // .length() on them down below.
+                            int ac = el.getArgPos();
+                            Class<?> cl = arr[ac];
+                            if (cl == String.class && !guaranteedNonNull[ac]) {
+                                Label l0 = new Label();
+                                mv.visitIntInsn(ALOAD, off);
+                                mv.visitJumpInsn(IFNONNULL, l0);
+                                mv.visitLdcInsn("null");
+                                mv.visitIntInsn(ASTORE, off);
+                                mv.visitLabel(l0);
+                            }
+                            off += getParameterSize(cl);
+                            break;
+                        }
+                        default:
+                            throw new StringConcatException("Unhandled tag: " + el.getTag());
+                    }
+                }
+            }
+
+            // Prepare StringBuilder instance
+            mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
+            mv.visitInsn(DUP);
+
+            if (mode.isSized()) {
+                /*
+                    Sized mode requires us to walk through the arguments, and estimate the final length.
+                    In exact mode, this will operate on Strings only. This code would accumulate the
+                    final length on stack.
+                 */
+                int len = 0;
+                int off = 0;
+
+                mv.visitInsn(ICONST_0);
+
+                for (RecipeElement el : recipe.getElements()) {
+                    switch (el.getTag()) {
+                        case CONST: {
+                            Object cnst = el.getValue();
+                            len += cnst.toString().length();
+                            break;
+                        }
+                        case ARG: {
+                            /*
+                                If an argument is String, then we can call .length() on it. Sized/Exact modes have
+                                converted arguments for us. If an argument is primitive, we can provide a guess
+                                for its String representation size.
+                            */
+                            Class<?> cl = arr[el.getArgPos()];
+                            if (cl == String.class) {
+                                mv.visitIntInsn(ALOAD, off);
+                                mv.visitMethodInsn(
+                                        INVOKEVIRTUAL,
+                                        "java/lang/String",
+                                        "length",
+                                        "()I",
+                                        false
+                                );
+                                mv.visitInsn(IADD);
+                            } else if (cl.isPrimitive()) {
+                                len += estimateSize(cl);
+                            }
+                            off += getParameterSize(cl);
+                            break;
+                        }
+                        default:
+                            throw new StringConcatException("Unhandled tag: " + el.getTag());
+                    }
+                }
+
+                // Constants have non-zero length, mix in
+                if (len > 0) {
+                    iconst(mv, len);
+                    mv.visitInsn(IADD);
+                }
+
+                mv.visitMethodInsn(
+                        INVOKESPECIAL,
+                        "java/lang/StringBuilder",
+                        "<init>",
+                        "(I)V",
+                        false
+                );
+            } else {
+                mv.visitMethodInsn(
+                        INVOKESPECIAL,
+                        "java/lang/StringBuilder",
+                        "<init>",
+                        "()V",
+                        false
+                );
+            }
+
+            // At this point, we have a blank StringBuilder on stack, fill it in with .append calls.
+            {
+                int off = 0;
+                for (RecipeElement el : recipe.getElements()) {
+                    String desc;
+                    switch (el.getTag()) {
+                        case CONST: {
+                            Object cnst = el.getValue();
+                            mv.visitLdcInsn(cnst);
+                            desc = getSBAppendDesc(cnst.getClass());
+                            break;
+                        }
+                        case ARG: {
+                            Class<?> cl = arr[el.getArgPos()];
+                            mv.visitVarInsn(getLoadOpcode(cl), off);
+                            off += getParameterSize(cl);
+                            desc = getSBAppendDesc(cl);
+                            break;
+                        }
+                        default:
+                            throw new StringConcatException("Unhandled tag: " + el.getTag());
+                    }
+                    mv.visitMethodInsn(
+                            INVOKEVIRTUAL,
+                            "java/lang/StringBuilder",
+                            "append",
+                            desc,
+                            false
+                    );
+                }
+            }
+
+            if (DEBUG && mode.isExact()) {
+                /*
+                    Exactness checks compare the final StringBuilder.capacity() with a resulting
+                    String.length(). If these values disagree, that means StringBuilder had to perform
+                    storage trimming, which defeats the purpose of exact strategies.
+                 */
+
+                /*
+                   The logic for this check is as follows:
+
+                     Stack before:     Op:
+                      (SB)              dup, dup
+                      (SB, SB, SB)      capacity()
+                      (int, SB, SB)     swap
+                      (SB, int, SB)     toString()
+                      (S, int, SB)      length()
+                      (int, int, SB)    if_icmpeq
+                      (SB)              <end>
+
+                   Note that it leaves the same StringBuilder on exit, like the one on enter.
+                 */
+
+                mv.visitInsn(DUP);
+                mv.visitInsn(DUP);
+
+                mv.visitMethodInsn(
+                        INVOKEVIRTUAL,
+                        "java/lang/StringBuilder",
+                        "capacity",
+                        "()I",
+                        false
+                );
+
+                mv.visitInsn(SWAP);
+
+                mv.visitMethodInsn(
+                        INVOKEVIRTUAL,
+                        "java/lang/StringBuilder",
+                        "toString",
+                        "()Ljava/lang/String;",
+                        false
+                );
+
+                mv.visitMethodInsn(
+                        INVOKEVIRTUAL,
+                        "java/lang/String",
+                        "length",
+                        "()I",
+                        false
+                );
+
+                Label l0 = new Label();
+                mv.visitJumpInsn(IF_ICMPEQ, l0);
+
+                mv.visitTypeInsn(NEW, "java/lang/AssertionError");
+                mv.visitInsn(DUP);
+                mv.visitLdcInsn("Failed exactness check");
+                mv.visitMethodInsn(INVOKESPECIAL,
+                        "java/lang/AssertionError",
+                        "<init>",
+                        "(Ljava/lang/Object;)V",
+                        false);
+                mv.visitInsn(ATHROW);
+
+                mv.visitLabel(l0);
+            }
+
+            mv.visitMethodInsn(
+                    INVOKEVIRTUAL,
+                    "java/lang/StringBuilder",
+                    "toString",
+                    "()Ljava/lang/String;",
+                    false
+            );
+
+            mv.visitInsn(ARETURN);
+
+            mv.visitMaxs(-1, -1);
+            mv.visitEnd();
+            cw.visitEnd();
+
+            Class<?> targetClass = lookup.lookupClass();
+            final byte[] classBytes = cw.toByteArray();
+            final Class<?> innerClass = UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
+
+            try {
+                UNSAFE.ensureClassInitialized(innerClass);
+                return lookup.findStatic(innerClass, NAME_FACTORY, args);
+            } catch (ReflectiveOperationException e) {
+                throw new StringConcatException("Exception finding constructor", e);
+            }
+        }
+
+        private static String getSBAppendDesc(Class<?> cl) {
+            if (cl.isPrimitive()) {
+                if (cl == Integer.TYPE || cl == Byte.TYPE || cl == Short.TYPE) {
+                    return "(I)Ljava/lang/StringBuilder;";
+                } else if (cl == Boolean.TYPE) {
+                    return "(Z)Ljava/lang/StringBuilder;";
+                } else if (cl == Character.TYPE) {
+                    return "(C)Ljava/lang/StringBuilder;";
+                } else if (cl == Double.TYPE) {
+                    return "(D)Ljava/lang/StringBuilder;";
+                } else if (cl == Float.TYPE) {
+                    return "(F)Ljava/lang/StringBuilder;";
+                } else if (cl == Long.TYPE) {
+                    return "(J)Ljava/lang/StringBuilder;";
+                } else {
+                    throw new IllegalStateException("Unhandled primitive StringBuilder.append: " + cl);
+                }
+            } else if (cl == String.class) {
+                return "(Ljava/lang/String;)Ljava/lang/StringBuilder;";
+            } else {
+                return "(Ljava/lang/Object;)Ljava/lang/StringBuilder;";
+            }
+        }
+
+        private static String getStringValueOfDesc(Class<?> cl) {
+            if (cl.isPrimitive()) {
+                if (cl == Integer.TYPE || cl == Byte.TYPE || cl == Short.TYPE) {
+                    return "(I)Ljava/lang/String;";
+                } else if (cl == Boolean.TYPE) {
+                    return "(Z)Ljava/lang/String;";
+                } else if (cl == Character.TYPE) {
+                    return "(C)Ljava/lang/String;";
+                } else if (cl == Double.TYPE) {
+                    return "(D)Ljava/lang/String;";
+                } else if (cl == Float.TYPE) {
+                    return "(F)Ljava/lang/String;";
+                } else if (cl == Long.TYPE) {
+                    return "(J)Ljava/lang/String;";
+                } else {
+                    throw new IllegalStateException("Unhandled String.valueOf: " + cl);
+                }
+            } else if (cl == String.class) {
+                return "(Ljava/lang/String;)Ljava/lang/String;";
+            } else {
+                return "(Ljava/lang/Object;)Ljava/lang/String;";
+            }
+        }
+
+        /**
+         * The following method is copied from
+         * org.objectweb.asm.commons.InstructionAdapter. Part of ASM: a very small
+         * and fast Java bytecode manipulation framework.
+         * Copyright (c) 2000-2005 INRIA, France Telecom All rights reserved.
+         */
+        private static void iconst(MethodVisitor mv, final int cst) {
+            if (cst >= -1 && cst <= 5) {
+                mv.visitInsn(Opcodes.ICONST_0 + cst);
+            } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
+                mv.visitIntInsn(Opcodes.BIPUSH, cst);
+            } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
+                mv.visitIntInsn(Opcodes.SIPUSH, cst);
+            } else {
+                mv.visitLdcInsn(cst);
+            }
+        }
+
+        private static int getLoadOpcode(Class<?> c) {
+            if (c == Void.TYPE) {
+                throw new InternalError("Unexpected void type of load opcode");
+            }
+            return ILOAD + getOpcodeOffset(c);
+        }
+
+        private static int getOpcodeOffset(Class<?> c) {
+            if (c.isPrimitive()) {
+                if (c == Long.TYPE) {
+                    return 1;
+                } else if (c == Float.TYPE) {
+                    return 2;
+                } else if (c == Double.TYPE) {
+                    return 3;
+                }
+                return 0;
+            } else {
+                return 4;
+            }
+        }
+
+        private static int getParameterSize(Class<?> c) {
+            if (c == Void.TYPE) {
+                return 0;
+            } else if (c == Long.TYPE || c == Double.TYPE) {
+                return 2;
+            }
+            return 1;
+        }
+    }
+
+    /**
+     * MethodHandle StringBuilder strategy.
+     *
+     * <p>This strategy operates in two modes, gated by {@link Mode}.
+     *
+     * <p><b>{@link Strategy#MH_SB_SIZED}: "MethodHandles StringBuilder,
+     * sized".</b>
+     *
+     * <p>This strategy avoids spinning up the bytecode by building the
+     * computation on MethodHandle combinators. The computation is built with
+     * public MethodHandle APIs, resolved from a public Lookup sequence, and
+     * ends up calling the public StringBuilder API. Therefore, this strategy
+     * does not use any private API at all, even the Unsafe.defineAnonymousClass,
+     * since everything is handled under cover by java.lang.invoke APIs.
+     *
+     * <p><b>{@link Strategy#MH_SB_SIZED_EXACT}: "MethodHandles StringBuilder,
+     * sized exactly".</b>
+     *
+     * <p>This strategy improves on @link Strategy#MH_SB_SIZED}, by first
+     * converting all arguments to String in order to get the exact capacity
+     * StringBuilder should have. The conversion is done via the public
+     * String.valueOf and/or Object.toString methods, and does not touch any
+     * private String API.
+     */
+    private static final class MethodHandleStringBuilderStrategy {
+
+        private MethodHandleStringBuilderStrategy() {
+            // no instantiation
+        }
+
+        private static MethodHandle generate(MethodType mt, Recipe recipe, Mode mode) throws Exception {
+            int pc = mt.parameterCount();
+
+            Class<?>[] ptypes = mt.parameterArray();
+            MethodHandle[] filters = new MethodHandle[ptypes.length];
+            for (int i = 0; i < ptypes.length; i++) {
+                MethodHandle filter;
+                switch (mode) {
+                    case SIZED:
+                        // In sized mode, we convert all references and floats/doubles
+                        // to String: there is no specialization for different
+                        // classes in StringBuilder API, and it will convert to
+                        // String internally anyhow.
+                        filter = Stringifiers.forMost(ptypes[i]);
+                        break;
+                    case SIZED_EXACT:
+                        // In exact mode, we convert everything to String:
+                        // this helps to compute the storage exactly.
+                        filter = Stringifiers.forAny(ptypes[i]);
+                        break;
+                    default:
+                        throw new StringConcatException("Not supported");
+                }
+                if (filter != null) {
+                    filters[i] = filter;
+                    ptypes[i] = filter.type().returnType();
+                }
+            }
+
+            List<Class<?>> ptypesList = Arrays.asList(ptypes);
+            MethodHandle[] lengthers = new MethodHandle[pc];
+
+            // Figure out lengths: constants' lengths can be deduced on the spot.
+            // All reference arguments were filtered to String in the combinators below, so we can
+            // call the usual String.length(). Primitive values string sizes can be estimated.
+            int initial = 0;
+            for (RecipeElement el : recipe.getElements()) {
+                switch (el.getTag()) {
+                    case CONST: {
+                        Object cnst = el.getValue();
+                        initial += cnst.toString().length();
+                        break;
+                    }
+                    case ARG: {
+                        final int i = el.getArgPos();
+                        Class<?> type = ptypesList.get(i);
+                        if (type.isPrimitive()) {
+                            MethodHandle est = MethodHandles.constant(int.class, estimateSize(type));
+                            est = MethodHandles.dropArguments(est, 0, type);
+                            lengthers[i] = est;
+                        } else {
+                            lengthers[i] = STRING_LENGTH;
+                        }
+                        break;
+                    }
+                    default:
+                        throw new StringConcatException("Unhandled tag: " + el.getTag());
+                }
+            }
+
+            // Create (StringBuilder, <args>) shape for appending:
+            MethodHandle builder = MethodHandles.dropArguments(MethodHandles.identity(StringBuilder.class), 1, ptypesList);
+
+            // Compose append calls. This is done in reverse because the application order is
+            // reverse as well.
+            for (RecipeElement el : recipe.getElementsReversed()) {
+                MethodHandle appender;
+                switch (el.getTag()) {
+                    case CONST: {
+                        Object constant = el.getValue();
+                        MethodHandle mh = appender(adaptToStringBuilder(constant.getClass()));
+                        appender = MethodHandles.insertArguments(mh, 1, constant);
+                        break;
+                    }
+                    case ARG: {
+                        int ac = el.getArgPos();
+                        appender = appender(ptypesList.get(ac));
+
+                        // Insert dummy arguments to match the prefix in the signature.
+                        // The actual appender argument will be the ac-ith argument.
+                        if (ac != 0) {
+                            appender = MethodHandles.dropArguments(appender, 1, ptypesList.subList(0, ac));
+                        }
+                        break;
+                    }
+                    default:
+                        throw new StringConcatException("Unhandled tag: " + el.getTag());
+                }
+                builder = MethodHandles.foldArguments(builder, appender);
+            }
+
+            // Build the sub-tree that adds the sizes and produces a StringBuilder:
+
+            // a) Start with the reducer that accepts all arguments, plus one
+            //    slot for the initial value. Inject the initial value right away.
+            //    This produces (<ints>)int shape:
+            MethodHandle sum = getReducerFor(pc + 1);
+            MethodHandle adder = MethodHandles.insertArguments(sum, 0, initial);
+
+            // b) Apply lengthers to transform arguments to lengths, producing (<args>)int
+            adder = MethodHandles.filterArguments(adder, 0, lengthers);
+
+            // c) Instantiate StringBuilder (<args>)int -> (<args>)StringBuilder
+            MethodHandle newBuilder = MethodHandles.filterReturnValue(adder, NEW_STRING_BUILDER);
+
+            // d) Fold in StringBuilder constructor, this produces (<args>)StringBuilder
+            MethodHandle mh = MethodHandles.foldArguments(builder, newBuilder);
+
+            // Convert non-primitive arguments to Strings
+            mh = MethodHandles.filterArguments(mh, 0, filters);
+
+            // Convert (<args>)StringBuilder to (<args>)String
+            if (DEBUG && mode.isExact()) {
+                mh = MethodHandles.filterReturnValue(mh, BUILDER_TO_STRING_CHECKED);
+            } else {
+                mh = MethodHandles.filterReturnValue(mh, BUILDER_TO_STRING);
+            }
+
+            return mh;
+        }
+
+        private static MethodHandle getReducerFor(int cnt) {
+            return SUMMERS.computeIfAbsent(cnt, SUMMER);
+        }
+
+        private static MethodHandle appender(Class<?> appendType) {
+            MethodHandle appender = lookupVirtual(MethodHandles.publicLookup(), StringBuilder.class, "append",
+                    StringBuilder.class, adaptToStringBuilder(appendType));
+
+            // appenders should return void, this would not modify the target signature during folding
+            MethodType nt = MethodType.methodType(void.class, StringBuilder.class, appendType);
+            return appender.asType(nt);
+        }
+
+        private static String toStringChecked(StringBuilder sb) {
+            String s = sb.toString();
+            if (s.length() != sb.capacity()) {
+                throw new AssertionError("Exactness check failed: result length = " + s.length() + ", buffer capacity = " + sb.capacity());
+            }
+            return s;
+        }
+
+        private static int sum(int v1, int v2) {
+            return v1 + v2;
+        }
+
+        private static int sum(int v1, int v2, int v3) {
+            return v1 + v2 + v3;
+        }
+
+        private static int sum(int v1, int v2, int v3, int v4) {
+            return v1 + v2 + v3 + v4;
+        }
+
+        private static int sum(int v1, int v2, int v3, int v4, int v5) {
+            return v1 + v2 + v3 + v4 + v5;
+        }
+
+        private static int sum(int v1, int v2, int v3, int v4, int v5, int v6) {
+            return v1 + v2 + v3 + v4 + v5 + v6;
+        }
+
+        private static int sum(int v1, int v2, int v3, int v4, int v5, int v6, int v7) {
+            return v1 + v2 + v3 + v4 + v5 + v6 + v7;
+        }
+
+        private static int sum(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) {
+            return v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8;
+        }
+
+        private static int sum(int initial, int[] vs) {
+            int sum = initial;
+            for (int v : vs) {
+                sum += v;
+            }
+            return sum;
+        }
+
+        private static final ConcurrentMap<Integer, MethodHandle> SUMMERS;
+
+        // This one is deliberately non-lambdified to optimize startup time:
+        private static final Function<Integer, MethodHandle> SUMMER = new Function<Integer, MethodHandle>() {
+            @Override
+            public MethodHandle apply(Integer cnt) {
+                if (cnt == 1) {
+                    return MethodHandles.identity(int.class);
+                } else if (cnt <= 8) {
+                    // Variable-arity collectors are not as efficient as small-count methods,
+                    // unroll some initial sizes.
+                    Class<?>[] cls = new Class<?>[cnt];
+                    Arrays.fill(cls, int.class);
+                    return lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleStringBuilderStrategy.class, "sum", int.class, cls);
+                } else {
+                    return lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleStringBuilderStrategy.class, "sum", int.class, int.class, int[].class)
+                            .asCollector(int[].class, cnt - 1);
+                }
+            }
+        };
+
+        private static final MethodHandle NEW_STRING_BUILDER, STRING_LENGTH, BUILDER_TO_STRING, BUILDER_TO_STRING_CHECKED;
+
+        static {
+            SUMMERS = new ConcurrentHashMap<>();
+            Lookup publicLookup = MethodHandles.publicLookup();
+            NEW_STRING_BUILDER = lookupConstructor(publicLookup, StringBuilder.class, int.class);
+            STRING_LENGTH = lookupVirtual(publicLookup, String.class, "length", int.class);
+            BUILDER_TO_STRING = lookupVirtual(publicLookup, StringBuilder.class, "toString", String.class);
+            if (DEBUG) {
+                BUILDER_TO_STRING_CHECKED = lookupStatic(MethodHandles.Lookup.IMPL_LOOKUP,
+                        MethodHandleStringBuilderStrategy.class, "toStringChecked", String.class, StringBuilder.class);
+            } else {
+                BUILDER_TO_STRING_CHECKED = null;
+            }
+        }
+
+    }
+
+
+    /**
+     * <p><b>{@link Strategy#MH_INLINE_SIZED_EXACT}: "MethodHandles inline,
+     * sized exactly".</b>
+     *
+     * <p>This strategy replicates what StringBuilders are doing: it builds the
+     * byte[] array on its own and passes that byte[] array to String
+     * constructor. This strategy requires access to some private APIs in JDK,
+     * most notably, the read-only Integer/Long.stringSize methods that measure
+     * the character length of the integers, and the private String constructor
+     * that accepts byte[] arrays without copying. While this strategy assumes a
+     * particular implementation details for String, this opens the door for
+     * building a very optimal concatenation sequence. This is the only strategy
+     * that requires porting if there are private JDK changes occur.
+     */
+    private static final class MethodHandleInlineCopyStrategy {
+
+        private MethodHandleInlineCopyStrategy() {
+            // no instantiation
+        }
+
+        static MethodHandle generate(MethodType mt, Recipe recipe) throws Throwable {
+
+            // Create filters and obtain filtered parameter types. Filters would be used in the beginning
+            // to convert the incoming arguments into the arguments we can process (e.g. Objects -> Strings).
+            // The filtered argument type list is used all over in the combinators below.
+            Class<?>[] ptypes = mt.parameterArray();
+            MethodHandle[] filters = null;
+            for (int i = 0; i < ptypes.length; i++) {
+                MethodHandle filter = Stringifiers.forMost(ptypes[i]);
+                if (filter != null) {
+                    if (filters == null) {
+                        filters = new MethodHandle[ptypes.length];
+                    }
+                    filters[i] = filter;
+                    ptypes[i] = filter.type().returnType();
+                }
+            }
+            List<Class<?>> ptypesList = Arrays.asList(ptypes);
+
+            // Start building the combinator tree. The tree "starts" with (<parameters>)String, and "finishes"
+            // with the (int, byte[], byte)String in String helper. The combinators are assembled bottom-up,
+            // which makes the code arguably hard to read.
+
+            // Drop all remaining parameter types, leave only helper arguments:
+            MethodHandle mh;
+
+            mh = MethodHandles.dropArguments(NEW_STRING, 2, ptypes);
+            mh = MethodHandles.dropArguments(mh, 0, int.class);
+
+            // In debug mode, check that remaining index is zero.
+            if (DEBUG) {
+                mh = MethodHandles.filterArgument(mh, 0, CHECK_INDEX);
+            }
+
+            // Mix in prependers. This happens when (int, byte[], byte) = (index, storage, coder) is already
+            // known from the combinators below. We are assembling the string backwards, so "index" is the
+            // *ending* index.
+            for (RecipeElement el : recipe.getElements()) {
+                MethodHandle prepender;
+                switch (el.getTag()) {
+                    case CONST: {
+                        Object cnst = el.getValue();
+                        prepender = MethodHandles.insertArguments(prepender(cnst.getClass()), 3, cnst);
+                        break;
+                    }
+                    case ARG: {
+                        int pos = el.getArgPos();
+                        prepender = selectArgument(prepender(ptypesList.get(pos)), 3, ptypesList, pos);
+                        break;
+                    }
+                    default:
+                        throw new StringConcatException("Unhandled tag: " + el.getTag());
+                }
+
+                // Remove "old" index from arguments
+                mh = MethodHandles.dropArguments(mh, 1, int.class);
+
+                // Do the prepend, and put "new" index at index 0
+                mh = MethodHandles.foldArguments(mh, prepender);
+            }
+
+            // Prepare the argument list for prepending. The tree below would instantiate
+            // the storage byte[] into argument 0, so we need to swap "storage" and "index".
+            // The index at this point equals to "size", and resides at argument 1.
+            {
+                MethodType nmt = mh.type()
+                        .changeParameterType(0, byte[].class)
+                        .changeParameterType(1, int.class);
+                mh = MethodHandles.permuteArguments(mh, nmt, swap10(nmt.parameterCount()));
+            }
+
+            // Fold in byte[] instantiation at argument 0.
+            MethodHandle combiner = MethodHandles.dropArguments(NEW_ARRAY, 2, ptypesList);
+            mh = MethodHandles.foldArguments(mh, combiner);
+
+            // Start combining length and coder mixers.
+            //
+            // Length is easy: constant lengths can be computed on the spot, and all non-constant
+            // shapes have been either converted to Strings, or explicit methods for getting the
+            // string length out of primitives are provided.
+            //
+            // Coders are more interesting. Only Object, String and char arguments (and constants)
+            // can have non-Latin1 encoding. It is easier to blindly convert constants to String,
+            // and deduce the coder from there. Arguments would be either converted to Strings
+            // during the initial filtering, or handled by primitive specializations in CODER_MIXERS.
+            //
+            // The method handle shape after all length and coder mixers is:
+            //   (int, byte, <args>)String = ("index", "coder", <args>)
+            byte initialCoder = 0; // initial coder
+            int initialLen = 0;    // initial length, in characters
+            for (RecipeElement el : recipe.getElements()) {
+                switch (el.getTag()) {
+                    case CONST: {
+                        Object constant = el.getValue();
+                        String s = constant.toString();
+                        initialCoder = (byte) coderMixer(String.class).invoke(initialCoder, s);
+                        initialLen += s.length();
+                        break;
+                    }
+                    case ARG: {
+                        int ac = el.getArgPos();
+
+                        Class<?> argClass = ptypesList.get(ac);
+                        MethodHandle lm = selectArgument(lengthMixer(argClass), 1, ptypesList, ac);
+                        lm = MethodHandles.dropArguments(lm, 0, byte.class); // (*)
+                        lm = MethodHandles.dropArguments(lm, 2, byte.class);
+
+                        MethodHandle cm = selectArgument(coderMixer(argClass),  1, ptypesList, ac);
+                        cm = MethodHandles.dropArguments(cm, 0, int.class);  // (**)
+
+                        // Read this bottom up:
+
+                        // 4. Drop old index and coder, producing ("new-index", "new-coder", <args>)
+                        mh = MethodHandles.dropArguments(mh, 2, int.class, byte.class);
+
+                        // 3. Compute "new-index", producing ("new-index", "new-coder", "old-index", "old-coder", <args>)
+                        //    Length mixer ignores both "new-coder" and "old-coder" due to dropArguments above (*)
+                        mh = MethodHandles.foldArguments(mh, lm);
+
+                        // 2. Compute "new-coder", producing ("new-coder", "old-index", "old-coder", <args>)
+                        //    Coder mixer ignores the "old-index" arg due to dropArguments above (**)
+                        mh = MethodHandles.foldArguments(mh, cm);
+
+                        // 1. The mh shape here is ("old-index", "old-coder", <args>)
+                        break;
+                    }
+                    default:
+                        throw new StringConcatException("Unhandled tag: " + el.getTag());
+                }
+            }
+
+            // Insert initial lengths and coders here.
+            // The method handle shape here is (<args>).
+            mh = MethodHandles.insertArguments(mh, 0, initialLen, initialCoder);
+
+            // Apply filters, converting the arguments:
+            if (filters != null) {
+                mh = MethodHandles.filterArguments(mh, 0, filters);
+            }
+
+            return mh;
+        }
+
+        private static int[] swap10(int count) {
+            int[] perm = new int[count];
+            perm[0] = 1;
+            perm[1] = 0;
+            for (int i = 2; i < count; i++) {
+                perm[i] = i;
+            }
+            return perm;
+        }
+
+        // Adapts: (...prefix..., parameter[pos])R -> (...prefix..., ...parameters...)R
+        private static MethodHandle selectArgument(MethodHandle mh, int prefix, List<Class<?>> ptypes, int pos) {
+            if (pos == 0) {
+                return MethodHandles.dropArguments(mh, prefix + 1, ptypes.subList(1, ptypes.size()));
+            } else if (pos == ptypes.size() - 1) {
+                return MethodHandles.dropArguments(mh, prefix, ptypes.subList(0, ptypes.size() - 1));
+            } else { // 0 < pos < ptypes.size() - 1
+                MethodHandle t = MethodHandles.dropArguments(mh, prefix, ptypes.subList(0, pos));
+                return MethodHandles.dropArguments(t, prefix + 1 + pos, ptypes.subList(pos + 1, ptypes.size()));
+            }
+        }
+
+        @ForceInline
+        private static byte[] newArray(int length, byte coder) {
+            return new byte[length << coder];
+        }
+
+        @ForceInline
+        private static int checkIndex(int index) {
+            if (index != 0) {
+                throw new AssertionError("Exactness check failed: " + index + " characters left in the buffer.");
+            }
+            return index;
+        }
+
+        private static MethodHandle prepender(Class<?> cl) {
+            return PREPENDERS.computeIfAbsent(cl, PREPEND);
+        }
+
+        private static MethodHandle coderMixer(Class<?> cl) {
+            return CODER_MIXERS.computeIfAbsent(cl, CODER_MIX);
+        }
+
+        private static MethodHandle lengthMixer(Class<?> cl) {
+            return LENGTH_MIXERS.computeIfAbsent(cl, LENGTH_MIX);
+        }
+
+        // This one is deliberately non-lambdified to optimize startup time:
+        private static final Function<Class<?>, MethodHandle> PREPEND = new Function<Class<?>, MethodHandle>() {
+            @Override
+            public MethodHandle apply(Class<?> c) {
+                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "prepend", int.class, int.class, byte[].class, byte.class, c);
+            }
+        };
+
+        // This one is deliberately non-lambdified to optimize startup time:
+        private static final Function<Class<?>, MethodHandle> CODER_MIX = new Function<Class<?>, MethodHandle>() {
+            @Override
+            public MethodHandle apply(Class<?> c) {
+                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mixCoder", byte.class, byte.class, c);
+            }
+        };
+
+        // This one is deliberately non-lambdified to optimize startup time:
+        private static final Function<Class<?>, MethodHandle> LENGTH_MIX = new Function<Class<?>, MethodHandle>() {
+            @Override
+            public MethodHandle apply(Class<?> c) {
+                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mixLen", int.class, int.class, c);
+            }
+        };
+
+        private static final MethodHandle NEW_STRING;
+        private static final MethodHandle CHECK_INDEX;
+        private static final MethodHandle NEW_ARRAY;
+        private static final ConcurrentMap<Class<?>, MethodHandle> PREPENDERS;
+        private static final ConcurrentMap<Class<?>, MethodHandle> LENGTH_MIXERS;
+        private static final ConcurrentMap<Class<?>, MethodHandle> CODER_MIXERS;
+        private static final Class<?> STRING_HELPER;
+
+        static {
+            try {
+                STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
+            } catch (ClassNotFoundException e) {
+                throw new AssertionError(e);
+            }
+
+            PREPENDERS = new ConcurrentHashMap<>();
+            LENGTH_MIXERS = new ConcurrentHashMap<>();
+            CODER_MIXERS = new ConcurrentHashMap<>();
+
+            NEW_STRING = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newString", String.class, byte[].class, byte.class);
+            NEW_ARRAY  = lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleInlineCopyStrategy.class, "newArray", byte[].class, int.class, byte.class);
+
+            if (DEBUG) {
+                CHECK_INDEX = lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleInlineCopyStrategy.class, "checkIndex", int.class, int.class);
+            } else {
+                CHECK_INDEX = null;
+            }
+        }
+    }
+
+    /**
+     * Public gateways to public "stringify" methods. These methods have the form String apply(T obj), and normally
+     * delegate to {@code String.valueOf}, depending on argument's type.
+     */
+    private static final class Stringifiers {
+        private Stringifiers() {
+            // no instantiation
+        }
+
+        // This one is deliberately non-lambdified to optimize startup time:
+        private static final Function<Class<?>, MethodHandle> MOST = new Function<Class<?>, MethodHandle>() {
+            @Override
+            public MethodHandle apply(Class<?> cl) {
+                MethodHandle mhObject = lookupStatic(Lookup.PUBLIC_LOOKUP, String.class, "valueOf", String.class, Object.class);
+
+                // We need the additional conversion here, because String.valueOf(Object) may return null.
+                // String conversion rules in Java state we need to produce "null" String in this case.
+                // It can be easily done with applying valueOf the second time.
+                MethodHandle mhObjectNoNulls = MethodHandles.filterReturnValue(mhObject,
+                        mhObject.asType(MethodType.methodType(String.class, String.class)));
+
+                if (cl == String.class) {
+                    return mhObject;
+                } else if (cl == float.class) {
+                    return lookupStatic(Lookup.PUBLIC_LOOKUP, String.class, "valueOf", String.class, float.class);
+                } else if (cl == double.class) {
+                    return lookupStatic(Lookup.PUBLIC_LOOKUP, String.class, "valueOf", String.class, double.class);
+                } else if (!cl.isPrimitive()) {
+                    return mhObjectNoNulls;
+                }
+
+                return null;
+            }
+        };
+
+        // This one is deliberately non-lambdified to optimize startup time:
+        private static final Function<Class<?>, MethodHandle> ANY = new Function<Class<?>, MethodHandle>() {
+            @Override
+            public MethodHandle apply(Class<?> cl) {
+                MethodHandle mh = MOST.apply(cl);
+                if (mh != null) {
+                    return mh;
+                }
+
+                if (cl == byte.class || cl == short.class || cl == int.class) {
+                    return lookupStatic(Lookup.PUBLIC_LOOKUP, String.class, "valueOf", String.class, int.class);
+                } else if (cl == boolean.class) {
+                    return lookupStatic(Lookup.PUBLIC_LOOKUP, String.class, "valueOf", String.class, boolean.class);
+                } else if (cl == char.class) {
+                    return lookupStatic(Lookup.PUBLIC_LOOKUP, String.class, "valueOf", String.class, char.class);
+                } else if (cl == long.class) {
+                    return lookupStatic(Lookup.PUBLIC_LOOKUP, String.class, "valueOf", String.class, long.class);
+                } else {
+                    throw new IllegalStateException("Unknown class: " + cl);
+                }
+            }
+        };
+
+        private static final ConcurrentMap<Class<?>, MethodHandle> STRINGIFIERS_MOST = new ConcurrentHashMap<>();
+        private static final ConcurrentMap<Class<?>, MethodHandle> STRINGIFIERS_ANY = new ConcurrentHashMap<>();
+
+        /**
+         * Returns a stringifier for references and floats/doubles only.
+         * Always returns null for other primitives.
+         *
+         * @param t class to stringify
+         * @return stringifier; null, if not available
+         */
+        static MethodHandle forMost(Class<?> t) {
+            return STRINGIFIERS_MOST.computeIfAbsent(t, MOST);
+        }
+
+        /**
+         * Returns a stringifier for any type. Never returns null.
+         *
+         * @param t class to stringify
+         * @return stringifier
+         */
+        static MethodHandle forAny(Class<?> t) {
+            return STRINGIFIERS_ANY.computeIfAbsent(t, ANY);
+        }
+    }
+
+    /* ------------------------------- Common utilities ------------------------------------ */
+
+    private static MethodHandle lookupStatic(Lookup lookup, Class<?> refc, String name, Class<?> rtype, Class<?>... ptypes) {
+        try {
+            return lookup.findStatic(refc, name, MethodType.methodType(rtype, ptypes));
+        } catch (NoSuchMethodException | IllegalAccessException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    private static MethodHandle lookupVirtual(Lookup lookup, Class<?> refc, String name, Class<?> rtype, Class<?>... ptypes) {
+        try {
+            return lookup.findVirtual(refc, name, MethodType.methodType(rtype, ptypes));
+        } catch (NoSuchMethodException | IllegalAccessException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    private static MethodHandle lookupConstructor(Lookup lookup, Class<?> refc, Class<?> ptypes) {
+        try {
+            return lookup.findConstructor(refc, MethodType.methodType(void.class, ptypes));
+        } catch (NoSuchMethodException | IllegalAccessException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    private static int estimateSize(Class<?> cl) {
+        if (cl == Integer.TYPE) {
+            return 11; // "-2147483648"
+        } else if (cl == Boolean.TYPE) {
+            return 5; // "false"
+        } else if (cl == Byte.TYPE) {
+            return 4; // "-128"
+        } else if (cl == Character.TYPE) {
+            return 1; // duh
+        } else if (cl == Short.TYPE) {
+            return 6; // "-32768"
+        } else if (cl == Double.TYPE) {
+            return 26; // apparently, no larger than this, see FloatingDecimal.BinaryToASCIIBuffer.buffer
+        } else if (cl == Float.TYPE) {
+            return 26; // apparently, no larger than this, see FloatingDecimal.BinaryToASCIIBuffer.buffer
+        } else if (cl == Long.TYPE)  {
+            return 20; // "-9223372036854775808"
+        } else {
+            throw new IllegalArgumentException("Cannot estimate the size for " + cl);
+        }
+    }
+
+    private static Class<?> adaptToStringBuilder(Class<?> c) {
+        if (c.isPrimitive()) {
+            if (c == Byte.TYPE || c == Short.TYPE) {
+                return int.class;
+            }
+        } else {
+            if (c != String.class) {
+                return Object.class;
+            }
+        }
+        return c;
+    }
+
+    private StringConcatFactory() {
+        // no instantiation
+    }
+
+}
--- a/src/java.base/share/classes/java/lang/ref/Reference.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/lang/ref/Reference.java	Tue Feb 02 12:12:52 2016 -0800
@@ -26,10 +26,10 @@
 package java.lang.ref;
 
 import jdk.internal.vm.annotation.DontInline;
-import sun.misc.Cleaner;
 import jdk.internal.HotSpotIntrinsicCandidate;
 import jdk.internal.misc.JavaLangRefAccess;
 import jdk.internal.misc.SharedSecrets;
+import jdk.internal.ref.Cleaner;
 
 /**
  * Abstract base class for reference objects.  This class defines the
--- a/src/java.base/share/classes/java/net/URI.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/net/URI.java	Tue Feb 02 12:12:52 2016 -0800
@@ -1080,11 +1080,8 @@
      *          If a protocol handler for the URL could not be found,
      *          or if some other error occurred while constructing the URL
      */
-    public URL toURL()
-        throws MalformedURLException {
-        if (!isAbsolute())
-            throw new IllegalArgumentException("URI is not absolute");
-        return new URL(toString());
+    public URL toURL() throws MalformedURLException {
+        return URL.fromURI(this);
     }
 
     // -- Component access methods --
--- a/src/java.base/share/classes/java/net/URL.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/net/URL.java	Tue Feb 02 12:12:52 2016 -0800
@@ -36,6 +36,7 @@
 import java.io.ObjectStreamField;
 import java.io.ObjectInputStream.GetField;
 import java.util.Iterator;
+import java.util.Locale;
 import java.util.NoSuchElementException;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
@@ -405,7 +406,7 @@
             }
         }
 
-        protocol = protocol.toLowerCase();
+        protocol = protocol.toLowerCase(Locale.ROOT);
         this.protocol = protocol;
         if (host != null) {
 
@@ -579,8 +580,7 @@
             for (i = start ; !aRef && (i < limit) &&
                      ((c = spec.charAt(i)) != '/') ; i++) {
                 if (c == ':') {
-
-                    String s = spec.substring(start, i).toLowerCase();
+                    String s = spec.substring(start, i).toLowerCase(Locale.ROOT);
                     if (isValidProtocol(s)) {
                         newProtocol = s;
                         start = i + 1;
@@ -659,6 +659,44 @@
         }
     }
 
+    /**
+     * Creates a URL from a URI, as if by invoking {@code uri.toURL()}.
+     *
+     * @see java.net.URI#toURL()
+     */
+    static URL fromURI(URI uri) throws MalformedURLException {
+        if (!uri.isAbsolute()) {
+            throw new IllegalArgumentException("URI is not absolute");
+        }
+        String protocol = uri.getScheme();
+
+        // In general we need to go via Handler.parseURL, but for the jrt
+        // protocol we enforce that the Handler is not overrideable and can
+        // optimize URI to URL conversion.
+        //
+        // Case-sensitive comparison for performance; malformed protocols will
+        // be handled correctly by the slow path.
+        if (protocol.equals("jrt") && !uri.isOpaque()
+                && uri.getRawFragment() == null) {
+
+            String query = uri.getRawQuery();
+            String path = uri.getRawPath();
+            String file = (query == null) ? path : path + "?" + query;
+
+            // URL represent undefined host as empty string while URI use null
+            String host = uri.getHost();
+            if (host == null) {
+                host = "";
+            }
+
+            int port = uri.getPort();
+
+            return new URL("jrt", host, port, file, null);
+        } else {
+            return new URL((URL)null, uri.toString(), null);
+        }
+    }
+
     /*
      * Returns true if specified string is a valid protocol name.
      */
@@ -1275,11 +1313,28 @@
         }
     }
 
-    private static final String[] NON_OVERRIDEABLE_PROTOCOLS = {"file", "jrt"};
-    private static boolean isOverrideable(String protocol) {
-        for (String p : NON_OVERRIDEABLE_PROTOCOLS)
-            if (protocol.equalsIgnoreCase(p))
+
+    /**
+     * Non-overrideable protocols: "jrt" and "file"
+     *
+     * Character-based comparison for performance reasons; also ensures
+     * case-insensitive comparison in a locale-independent fashion.
+     */
+    static boolean isOverrideable(String protocol) {
+        if (protocol.length() == 3) {
+            if ((Character.toLowerCase(protocol.charAt(0)) == 'j') &&
+                    (Character.toLowerCase(protocol.charAt(1)) == 'r') &&
+                    (Character.toLowerCase(protocol.charAt(2)) == 't')) {
                 return false;
+            }
+        } else if (protocol.length() == 4) {
+            if ((Character.toLowerCase(protocol.charAt(0)) == 'f') &&
+                    (Character.toLowerCase(protocol.charAt(1)) == 'i') &&
+                    (Character.toLowerCase(protocol.charAt(2)) == 'l') &&
+                    (Character.toLowerCase(protocol.charAt(3)) == 'e')) {
+                return false;
+            }
+        }
         return true;
     }
 
--- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Tue Feb 02 12:12:52 2016 -0800
@@ -28,9 +28,9 @@
 package java.nio;
 
 import java.io.FileDescriptor;
-import sun.misc.Cleaner;
 import jdk.internal.misc.Unsafe;
 import jdk.internal.misc.VM;
+import jdk.internal.ref.Cleaner;
 import sun.nio.ch.DirectBuffer;
 
 
--- a/src/java.base/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java	Tue Feb 02 12:12:52 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,7 @@
     /**
      * Read the file owner.
      *
-     * <p> It it implementation specific if the file owner can be a {@link
+     * <p> It is implementation specific if the file owner can be a {@link
      * GroupPrincipal group}.
      *
      * @return  the file owner
@@ -78,7 +78,7 @@
     /**
      * Updates the file owner.
      *
-     * <p> It it implementation specific if the file owner can be a {@link
+     * <p> It is implementation specific if the file owner can be a {@link
      * GroupPrincipal group}. To ensure consistent and correct behavior
      * across platforms it is recommended that this method should only be used
      * to set the file owner to a user principal that is not a group.
--- a/src/java.base/share/classes/java/time/LocalDate.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/time/LocalDate.java	Tue Feb 02 12:12:52 2016 -0800
@@ -100,6 +100,8 @@
 import java.time.zone.ZoneOffsetTransition;
 import java.time.zone.ZoneRules;
 import java.util.Objects;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
 
 /**
  * A date without a time-zone in the ISO-8601 calendar system,
@@ -1716,6 +1718,89 @@
     }
 
     /**
+     * Returns a sequential ordered stream of dates. The returned stream starts from this date
+     * (inclusive) and goes to {@code endExclusive} (exclusive) by an incremental step of 1 day.
+     * <p>
+     * This method is equivalent to {@code datesUntil(endExclusive, Period.ofDays(1))}.
+     *
+     * @param endExclusive  the end date, exclusive, not null
+     * @return a sequential {@code Stream} for the range of {@code LocalDate} values
+     * @throws IllegalArgumentException if end date is before this date
+     * @since 9
+     */
+    public Stream<LocalDate> datesUntil(LocalDate endExclusive) {
+        long end = endExclusive.toEpochDay();
+        long start = toEpochDay();
+        if (end < start) {
+            throw new IllegalArgumentException(endExclusive + " < " + this);
+        }
+        return LongStream.range(start, end).mapToObj(LocalDate::ofEpochDay);
+    }
+
+    /**
+     * Returns a sequential ordered stream of dates by given incremental step. The returned stream
+     * starts from this date (inclusive) and goes to {@code endExclusive} (exclusive).
+     * <p>
+     * The n-th date which appears in the stream is equal to {@code this.plus(step.multipliedBy(n))}
+     * (but the result of step multiplication never overflows). For example, if this date is
+     * {@code 2015-01-31}, the end date is {@code 2015-05-01} and the step is 1 month, then the
+     * stream contains {@code 2015-01-31}, {@code 2015-02-28}, {@code 2015-03-31}, and
+     * {@code 2015-04-30}.
+     *
+     * @param endExclusive  the end date, exclusive, not null
+     * @param step  the non-zero, non-negative {@code Period} which represents the step.
+     * @return a sequential {@code Stream} for the range of {@code LocalDate} values
+     * @throws IllegalArgumentException if step is zero, or {@code step.getDays()} and
+     *             {@code step.toTotalMonths()} have opposite sign, or end date is before this date
+     *             and step is positive, or end date is after this date and step is negative
+     * @since 9
+     */
+    public Stream<LocalDate> datesUntil(LocalDate endExclusive, Period step) {
+        if (step.isZero()) {
+            throw new IllegalArgumentException("step is zero");
+        }
+        long end = endExclusive.toEpochDay();
+        long start = toEpochDay();
+        long until = end - start;
+        long months = step.toTotalMonths();
+        long days = step.getDays();
+        if ((months < 0 && days > 0) || (months > 0 && days < 0)) {
+            throw new IllegalArgumentException("period months and days are of opposite sign");
+        }
+        if (until == 0) {
+            return Stream.empty();
+        }
+        int sign = months > 0 || days > 0 ? 1 : -1;
+        if (sign < 0 ^ until < 0) {
+            throw new IllegalArgumentException(endExclusive + (sign < 0 ? " > " : " < ") + this);
+        }
+        if (months == 0) {
+            long steps = (until - sign) / days; // non-negative
+            return LongStream.rangeClosed(0, steps).mapToObj(
+                    n -> LocalDate.ofEpochDay(start + n * days));
+        }
+        // 48699/1600 = 365.2425/12, no overflow, non-negative result
+        long steps = until * 1600 / (months * 48699 + days * 1600) + 1;
+        long addMonths = months * steps;
+        long addDays = days * steps;
+        long maxAddMonths = months > 0 ? MAX.getProlepticMonth() - getProlepticMonth()
+                : getProlepticMonth() - MIN.getProlepticMonth();
+        // adjust steps estimation
+        if (addMonths * sign > maxAddMonths
+                || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) {
+            steps--;
+            addMonths -= months;
+            addDays -= days;
+            if (addMonths * sign > maxAddMonths
+                    || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) {
+                steps--;
+            }
+        }
+        return LongStream.rangeClosed(0, steps).mapToObj(
+                n -> this.plusMonths(months * n).plusDays(days * n));
+    }
+
+    /**
      * Formats this date using the specified formatter.
      * <p>
      * This date will be passed to the formatter to produce a string.
--- a/src/java.base/share/classes/java/util/ArrayList.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/util/ArrayList.java	Tue Feb 02 12:12:52 2016 -0800
@@ -207,39 +207,19 @@
      * necessary, to ensure that it can hold at least the number of elements
      * specified by the minimum capacity argument.
      *
-     * @param   minCapacity   the desired minimum capacity
+     * @param minCapacity the desired minimum capacity
      */
     public void ensureCapacity(int minCapacity) {
-        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
-            // any size if not default element table
-            ? 0
-            // larger than default for default empty table. It's already
-            // supposed to be at default size.
-            : DEFAULT_CAPACITY;
-
-        if (minCapacity > minExpand) {
-            ensureExplicitCapacity(minCapacity);
+        if (minCapacity > elementData.length
+            && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
+                 && minCapacity <= DEFAULT_CAPACITY)) {
+            modCount++;
+            grow(minCapacity);
         }
     }
 
-    private void ensureCapacityInternal(int minCapacity) {
-        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
-            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
-        }
-
-        ensureExplicitCapacity(minCapacity);
-    }
-
-    private void ensureExplicitCapacity(int minCapacity) {
-        modCount++;
-
-        // overflow-conscious code
-        if (minCapacity - elementData.length > 0)
-            grow(minCapacity);
-    }
-
     /**
-     * The maximum size of array to allocate.
+     * The maximum size of array to allocate (unless necessary).
      * Some VMs reserve some header words in an array.
      * Attempts to allocate larger arrays may result in
      * OutOfMemoryError: Requested array size exceeds VM limit
@@ -251,25 +231,48 @@
      * number of elements specified by the minimum capacity argument.
      *
      * @param minCapacity the desired minimum capacity
+     * @throws OutOfMemoryError if minCapacity is less than zero
      */
-    private void grow(int minCapacity) {
+    private Object[] grow(int minCapacity) {
+        return elementData = Arrays.copyOf(elementData,
+                                           newCapacity(minCapacity));
+    }
+
+    private Object[] grow() {
+        return grow(size + 1);
+    }
+
+    /**
+     * Returns a capacity at least as large as the given minimum capacity.
+     * Returns the current capacity increased by 50% if that suffices.
+     * Will not return a capacity greater than MAX_ARRAY_SIZE unless
+     * the given minimum capacity is greater than MAX_ARRAY_SIZE.
+     *
+     * @param minCapacity the desired minimum capacity
+     * @throws OutOfMemoryError if minCapacity is less than zero
+     */
+    private int newCapacity(int minCapacity) {
         // overflow-conscious code
         int oldCapacity = elementData.length;
         int newCapacity = oldCapacity + (oldCapacity >> 1);
-        if (newCapacity - minCapacity < 0)
-            newCapacity = minCapacity;
-        if (newCapacity - MAX_ARRAY_SIZE > 0)
-            newCapacity = hugeCapacity(minCapacity);
-        // minCapacity is usually close to size, so this is a win:
-        elementData = Arrays.copyOf(elementData, newCapacity);
+        if (newCapacity - minCapacity <= 0) {
+            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
+                return Math.max(DEFAULT_CAPACITY, minCapacity);
+            if (minCapacity < 0) // overflow
+                throw new OutOfMemoryError();
+            return minCapacity;
+        }
+        return (newCapacity - MAX_ARRAY_SIZE <= 0)
+            ? newCapacity
+            : hugeCapacity(minCapacity);
     }
 
     private static int hugeCapacity(int minCapacity) {
         if (minCapacity < 0) // overflow
             throw new OutOfMemoryError();
-        return (minCapacity > MAX_ARRAY_SIZE) ?
-            Integer.MAX_VALUE :
-            MAX_ARRAY_SIZE;
+        return (minCapacity > MAX_ARRAY_SIZE)
+            ? Integer.MAX_VALUE
+            : MAX_ARRAY_SIZE;
     }
 
     /**
@@ -452,14 +455,26 @@
     }
 
     /**
+     * This helper method split out from add(E) to keep method
+     * bytecode size under 35 (the -XX:MaxInlineSize default value),
+     * which helps when add(E) is called in a C1-compiled loop.
+     */
+    private void add(E e, Object[] elementData, int s) {
+        if (s == elementData.length)
+            elementData = grow();
+        elementData[s] = e;
+        size = s + 1;
+    }
+
+    /**
      * Appends the specified element to the end of this list.
      *
      * @param e element to be appended to this list
      * @return {@code true} (as specified by {@link Collection#add})
      */
     public boolean add(E e) {
-        ensureCapacityInternal(size + 1);  // Increments modCount!!
-        elementData[size++] = e;
+        modCount++;
+        add(e, elementData, size);
         return true;
     }
 
@@ -474,12 +489,16 @@
      */
     public void add(int index, E element) {
         rangeCheckForAdd(index);
-
-        ensureCapacityInternal(size + 1);  // Increments modCount!!
-        System.arraycopy(elementData, index, elementData, index + 1,
-                         size - index);
+        modCount++;
+        final int s;
+        Object[] elementData;
+        if ((s = size) == (elementData = this.elementData).length)
+            elementData = grow();
+        System.arraycopy(elementData, index,
+                         elementData, index + 1,
+                         s - index);
         elementData[index] = element;
-        size++;
+        size = s + 1;
     }
 
     /**
@@ -578,11 +597,17 @@
      */
     public boolean addAll(Collection<? extends E> c) {
         Object[] a = c.toArray();
+        modCount++;
         int numNew = a.length;
-        ensureCapacityInternal(size + numNew);  // Increments modCount
-        System.arraycopy(a, 0, elementData, size, numNew);
-        size += numNew;
-        return numNew != 0;
+        if (numNew == 0)
+            return false;
+        Object[] elementData;
+        final int s;
+        if (numNew > (elementData = this.elementData).length - (s = size))
+            elementData = grow(s + numNew);
+        System.arraycopy(a, 0, elementData, s, numNew);
+        size = s + numNew;
+        return true;
     }
 
     /**
@@ -604,17 +629,23 @@
         rangeCheckForAdd(index);
 
         Object[] a = c.toArray();
+        modCount++;
         int numNew = a.length;
-        ensureCapacityInternal(size + numNew);  // Increments modCount
+        if (numNew == 0)
+            return false;
+        Object[] elementData;
+        final int s;
+        if (numNew > (elementData = this.elementData).length - (s = size))
+            elementData = grow(s + numNew);
 
-        int numMoved = size - index;
+        int numMoved = s - index;
         if (numMoved > 0)
-            System.arraycopy(elementData, index, elementData, index + numNew,
+            System.arraycopy(elementData, index,
+                             elementData, index + numNew,
                              numMoved);
-
         System.arraycopy(a, 0, elementData, index, numNew);
-        size += numNew;
-        return numNew != 0;
+        size = s + numNew;
+        return true;
     }
 
     /**
@@ -786,7 +817,6 @@
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
-        elementData = EMPTY_ELEMENTDATA;
 
         // Read in size, and any hidden stuff
         s.defaultReadObject();
@@ -795,14 +825,19 @@
         s.readInt(); // ignored
 
         if (size > 0) {
-            // be like clone(), allocate array based upon size not capacity
-            ensureCapacityInternal(size);
+            // like clone(), allocate array based upon size not capacity
+            Object[] elements = new Object[size];
 
-            Object[] a = elementData;
             // Read in all elements in the proper order.
-            for (int i=0; i<size; i++) {
-                a[i] = s.readObject();
+            for (int i = 0; i < size; i++) {
+                elements[i] = s.readObject();
             }
+
+            elementData = elements;
+        } else if (size == 0) {
+            elementData = EMPTY_ELEMENTDATA;
+        } else {
+            throw new java.io.InvalidObjectException("Invalid size: " + size);
         }
     }
 
--- a/src/java.base/share/classes/java/util/EnumMap.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/util/EnumMap.java	Tue Feb 02 12:12:52 2016 -0800
@@ -25,7 +25,6 @@
 
 package java.util;
 
-import java.util.Map.Entry;
 import jdk.internal.misc.SharedSecrets;
 
 /**
@@ -125,8 +124,6 @@
         return (V)(value == NULL ? null : value);
     }
 
-    private static final Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
-
     /**
      * Creates an empty enum map with the specified key type.
      *
--- a/src/java.base/share/classes/java/util/EnumSet.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/util/EnumSet.java	Tue Feb 02 12:12:52 2016 -0800
@@ -92,8 +92,6 @@
      */
     final Enum<?>[] universe;
 
-    private static Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
-
     EnumSet(Class<E>elementType, Enum<?>[] universe) {
         this.elementType = elementType;
         this.universe    = universe;
@@ -421,6 +419,9 @@
     private static class SerializationProxy <E extends Enum<E>>
         implements java.io.Serializable
     {
+
+        private static final Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
+
         /**
          * The element type of this enum set.
          *
--- a/src/java.base/share/classes/java/util/Map.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/util/Map.java	Tue Feb 02 12:12:52 2016 -0800
@@ -649,7 +649,7 @@
             try {
                 k = entry.getKey();
                 v = entry.getValue();
-            } catch(IllegalStateException ise) {
+            } catch (IllegalStateException ise) {
                 // this usually means the entry is no longer in the map.
                 throw new ConcurrentModificationException(ise);
             }
@@ -704,7 +704,7 @@
             try {
                 k = entry.getKey();
                 v = entry.getValue();
-            } catch(IllegalStateException ise) {
+            } catch (IllegalStateException ise) {
                 // this usually means the entry is no longer in the map.
                 throw new ConcurrentModificationException(ise);
             }
@@ -714,7 +714,7 @@
 
             try {
                 entry.setValue(v);
-            } catch(IllegalStateException ise) {
+            } catch (IllegalStateException ise) {
                 // this usually means the entry is no longer in the map.
                 throw new ConcurrentModificationException(ise);
             }
@@ -887,7 +887,7 @@
      * or atomicity properties of this method. Any implementation providing
      * atomicity guarantees must override this method and document its
      * concurrency properties.
-      *
+     *
      * @param key key with which the specified value is associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with the specified key, or
@@ -984,6 +984,9 @@
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
      *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @since 1.8
      */
     default V computeIfAbsent(K key,
@@ -1058,6 +1061,9 @@
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
      *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @since 1.8
      */
     default V computeIfPresent(K key,
@@ -1103,7 +1109,7 @@
      * <pre> {@code
      * V oldValue = map.get(key);
      * V newValue = remappingFunction.apply(key, oldValue);
-     * if (oldValue != null ) {
+     * if (oldValue != null) {
      *    if (newValue != null)
      *       map.put(key, newValue);
      *    else
@@ -1147,6 +1153,9 @@
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
      *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @since 1.8
      */
     default V compute(K key,
@@ -1239,6 +1248,9 @@
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
      *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     *         (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified key is null and this map
      *         does not support null keys or the value or remappingFunction is
      *         null
@@ -1251,7 +1263,7 @@
         V oldValue = get(key);
         V newValue = (oldValue == null) ? value :
                    remappingFunction.apply(oldValue, value);
-        if(newValue == null) {
+        if (newValue == null) {
             remove(key);
         } else {
             put(key, newValue);
--- a/src/java.base/share/classes/java/util/Queue.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/util/Queue.java	Tue Feb 02 12:12:52 2016 -0800
@@ -129,14 +129,6 @@
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
- * @see java.util.Collection
- * @see LinkedList
- * @see PriorityQueue
- * @see java.util.concurrent.LinkedBlockingQueue
- * @see java.util.concurrent.BlockingQueue
- * @see java.util.concurrent.ArrayBlockingQueue
- * @see java.util.concurrent.LinkedBlockingQueue
- * @see java.util.concurrent.PriorityBlockingQueue
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this queue
--- a/src/java.base/share/classes/java/util/Vector.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/util/Vector.java	Tue Feb 02 12:12:52 2016 -0800
@@ -233,42 +233,56 @@
     public synchronized void ensureCapacity(int minCapacity) {
         if (minCapacity > 0) {
             modCount++;
-            ensureCapacityHelper(minCapacity);
+            if (minCapacity > elementData.length)
+                grow(minCapacity);
         }
     }
 
     /**
-     * This implements the unsynchronized semantics of ensureCapacity.
-     * Synchronized methods in this class can internally call this
-     * method for ensuring capacity without incurring the cost of an
-     * extra synchronization.
-     *
-     * @see #ensureCapacity(int)
-     */
-    private void ensureCapacityHelper(int minCapacity) {
-        // overflow-conscious code
-        if (minCapacity - elementData.length > 0)
-            grow(minCapacity);
-    }
-
-    /**
-     * The maximum size of array to allocate.
+     * The maximum size of array to allocate (unless necessary).
      * Some VMs reserve some header words in an array.
      * Attempts to allocate larger arrays may result in
      * OutOfMemoryError: Requested array size exceeds VM limit
      */
     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 
-    private void grow(int minCapacity) {
+    /**
+     * Increases the capacity to ensure that it can hold at least the
+     * number of elements specified by the minimum capacity argument.
+     *
+     * @param minCapacity the desired minimum capacity
+     * @throws OutOfMemoryError if minCapacity is less than zero
+     */
+    private Object[] grow(int minCapacity) {
+        return elementData = Arrays.copyOf(elementData,
+                                           newCapacity(minCapacity));
+    }
+
+    private Object[] grow() {
+        return grow(elementCount + 1);
+    }
+
+    /**
+     * Returns a capacity at least as large as the given minimum capacity.
+     * Will not return a capacity greater than MAX_ARRAY_SIZE unless
+     * the given minimum capacity is greater than MAX_ARRAY_SIZE.
+     *
+     * @param minCapacity the desired minimum capacity
+     * @throws OutOfMemoryError if minCapacity is less than zero
+     */
+    private int newCapacity(int minCapacity) {
         // overflow-conscious code
         int oldCapacity = elementData.length;
         int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                          capacityIncrement : oldCapacity);
-        if (newCapacity - minCapacity < 0)
-            newCapacity = minCapacity;
-        if (newCapacity - MAX_ARRAY_SIZE > 0)
-            newCapacity = hugeCapacity(minCapacity);
-        elementData = Arrays.copyOf(elementData, newCapacity);
+        if (newCapacity - minCapacity <= 0) {
+            if (minCapacity < 0) // overflow
+                throw new OutOfMemoryError();
+            return minCapacity;
+        }
+        return (newCapacity - MAX_ARRAY_SIZE <= 0)
+            ? newCapacity
+            : hugeCapacity(minCapacity);
     }
 
     private static int hugeCapacity(int minCapacity) {
@@ -290,13 +304,10 @@
      */
     public synchronized void setSize(int newSize) {
         modCount++;
-        if (newSize > elementCount) {
-            ensureCapacityHelper(newSize);
-        } else {
-            for (int i = newSize ; i < elementCount ; i++) {
-                elementData[i] = null;
-            }
-        }
+        if (newSize > elementData.length)
+            grow(newSize);
+        for (int i = newSize; i < elementCount; i++)
+            elementData[i] = null;
         elementCount = newSize;
     }
 
@@ -604,11 +615,16 @@
             throw new ArrayIndexOutOfBoundsException(index
                                                      + " > " + elementCount);
         }
-        ensureCapacityHelper(elementCount + 1);
-        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
+        modCount++;
+        final int s = elementCount;
+        Object[] elementData = this.elementData;
+        if (s == elementData.length)
+            elementData = grow();
+        System.arraycopy(elementData, index,
+                         elementData, index + 1,
+                         s - index);
         elementData[index] = obj;
-        modCount++;
-        elementCount++;
+        elementCount = s + 1;
     }
 
     /**
@@ -623,9 +639,8 @@
      * @param   obj   the component to be added
      */
     public synchronized void addElement(E obj) {
-        ensureCapacityHelper(elementCount + 1);
         modCount++;
-        elementData[elementCount++] = obj;
+        add(obj, elementData, elementCount);
     }
 
     /**
@@ -781,6 +796,18 @@
     }
 
     /**
+     * This helper method split out from add(E) to keep method
+     * bytecode size under 35 (the -XX:MaxInlineSize default value),
+     * which helps when add(E) is called in a C1-compiled loop.
+     */
+    private void add(E e, Object[] elementData, int s) {
+        if (s == elementData.length)
+            elementData = grow();
+        elementData[s] = e;
+        elementCount = s + 1;
+    }
+
+    /**
      * Appends the specified element to the end of this Vector.
      *
      * @param e element to be appended to this Vector
@@ -788,9 +815,8 @@
      * @since 1.2
      */
     public synchronized boolean add(E e) {
-        ensureCapacityHelper(elementCount + 1);
         modCount++;
-        elementData[elementCount++] = e;
+        add(e, elementData, elementCount);
         return true;
     }
 
@@ -891,16 +917,19 @@
      */
     public boolean addAll(Collection<? extends E> c) {
         Object[] a = c.toArray();
+        modCount++;
         int numNew = a.length;
-        if (numNew > 0) {
-            synchronized (this) {
-                ensureCapacityHelper(elementCount + numNew);
-                System.arraycopy(a, 0, elementData, elementCount, numNew);
-                modCount++;
-                elementCount += numNew;
-            }
+        if (numNew == 0)
+            return false;
+        synchronized (this) {
+            Object[] elementData = this.elementData;
+            final int s = elementCount;
+            if (numNew > elementData.length - s)
+                elementData = grow(s + numNew);
+            System.arraycopy(a, 0, elementData, s, numNew);
+            elementCount = s + numNew;
+            return true;
         }
-        return numNew > 0;
     }
 
     /**
@@ -969,21 +998,23 @@
             throw new ArrayIndexOutOfBoundsException(index);
 
         Object[] a = c.toArray();
+        modCount++;
         int numNew = a.length;
+        if (numNew == 0)
+            return false;
+        Object[] elementData = this.elementData;
+        final int s = elementCount;
+        if (numNew > elementData.length - s)
+            elementData = grow(s + numNew);
 
-        if (numNew > 0) {
-            ensureCapacityHelper(elementCount + numNew);
-
-            int numMoved = elementCount - index;
-            if (numMoved > 0)
-                System.arraycopy(elementData, index, elementData,
-                        index + numNew, numMoved);
-
-             System.arraycopy(a, 0, elementData, index, numNew);
-             elementCount += numNew;
-             modCount++;
-        }
-        return numNew > 0;
+        int numMoved = s - index;
+        if (numMoved > 0)
+            System.arraycopy(elementData, index,
+                             elementData, index + numNew,
+                             numMoved);
+        System.arraycopy(a, 0, elementData, index, numNew);
+        elementCount = s + numNew;
+        return true;
     }
 
     /**
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java	Tue Feb 02 12:12:52 2016 -0800
@@ -301,19 +301,15 @@
      *
      * @implSpec
      * The default implementation is equivalent to the following steps for this
-     * {@code map}, then returning the current value or {@code null} if now
-     * absent:
+     * {@code map}:
      *
      * <pre> {@code
-     * if (map.get(key) == null) {
-     *   V newValue = mappingFunction.apply(key);
-     *   if (newValue != null)
-     *     return map.putIfAbsent(key, newValue);
-     * }}</pre>
-     *
-     * The default implementation may retry these steps when multiple
-     * threads attempt updates including potentially calling the mapping
-     * function multiple times.
+     * V oldValue, newValue;
+     * return ((oldValue = map.get(key)) == null
+     *         && (newValue = mappingFunction.apply(key)) != null
+     *         && (oldValue = map.putIfAbsent(key, newValue)) == null)
+     *   ? newValue
+     *   : oldValue;}</pre>
      *
      * <p>This implementation assumes that the ConcurrentMap cannot contain null
      * values and {@code get()} returning null unambiguously means the key is
@@ -323,16 +319,19 @@
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
      * @since 1.8
      */
     @Override
     default V computeIfAbsent(K key,
             Function<? super K, ? extends V> mappingFunction) {
         Objects.requireNonNull(mappingFunction);
-        V v, newValue;
-        return ((v = get(key)) == null &&
-                (newValue = mappingFunction.apply(key)) != null &&
-                (v = putIfAbsent(key, newValue)) == null) ? newValue : v;
+        V oldValue, newValue;
+        return ((oldValue = get(key)) == null
+                && (newValue = mappingFunction.apply(key)) != null
+                && (oldValue = putIfAbsent(key, newValue)) == null)
+            ? newValue
+            : oldValue;
     }
 
     /**
@@ -340,22 +339,19 @@
      *
      * @implSpec
      * The default implementation is equivalent to performing the following
-     * steps for this {@code map}, then returning the current value or
-     * {@code null} if now absent:
+     * steps for this {@code map}:
      *
      * <pre> {@code
-     * if (map.get(key) != null) {
-     *   V oldValue = map.get(key);
+     * for (V oldValue; (oldValue = map.get(key)) != null; ) {
      *   V newValue = remappingFunction.apply(key, oldValue);
-     *   if (newValue != null)
-     *     map.replace(key, oldValue, newValue);
-     *   else
-     *     map.remove(key, oldValue);
-     * }}</pre>
-     *
-     * The default implementation may retry these steps when multiple threads
-     * attempt updates including potentially calling the remapping function
-     * multiple times.
+     *   if ((newValue == null)
+     *       ? map.remove(key, oldValue)
+     *       : map.replace(key, oldValue, newValue))
+     *     return newValue;
+     * }
+     * return null;}</pre>
+     * When multiple threads attempt updates, map operations and the
+     * remapping function may be called multiple times.
      *
      * <p>This implementation assumes that the ConcurrentMap cannot contain null
      * values and {@code get()} returning null unambiguously means the key is
@@ -365,22 +361,21 @@
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
      * @since 1.8
      */
     @Override
     default V computeIfPresent(K key,
             BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
         Objects.requireNonNull(remappingFunction);
-        V oldValue;
-        while ((oldValue = get(key)) != null) {
+        for (V oldValue; (oldValue = get(key)) != null; ) {
             V newValue = remappingFunction.apply(key, oldValue);
-            if (newValue != null) {
-                if (replace(key, oldValue, newValue))
-                    return newValue;
-            } else if (remove(key, oldValue))
-                return null;
+            if ((newValue == null)
+                ? remove(key, oldValue)
+                : replace(key, oldValue, newValue))
+                return newValue;
         }
-        return oldValue;
+        return null;
     }
 
     /**
@@ -388,27 +383,23 @@
      *
      * @implSpec
      * The default implementation is equivalent to performing the following
-     * steps for this {@code map}, then returning the current value or
-     * {@code null} if absent:
+     * steps for this {@code map}:
      *
      * <pre> {@code
-     * V oldValue = map.get(key);
-     * V newValue = remappingFunction.apply(key, oldValue);
-     * if (oldValue != null ) {
-     *   if (newValue != null)
-     *     map.replace(key, oldValue, newValue);
-     *   else
-     *     map.remove(key, oldValue);
-     * } else {
-     *   if (newValue != null)
-     *     map.putIfAbsent(key, newValue);
-     *   else
+     * for (;;) {
+     *   V oldValue = map.get(key);
+     *   V newValue = remappingFunction.apply(key, oldValue);
+     *   if (newValue != null) {
+     *     if ((oldValue != null)
+     *       ? map.replace(key, oldValue, newValue)
+     *       : map.putIfAbsent(key, newValue) == null)
+     *       return newValue;
+     *   } else if (oldValue == null || map.remove(key, oldValue)) {
      *     return null;
+     *   }
      * }}</pre>
-     *
-     * The default implementation may retry these steps when multiple
-     * threads attempt updates including potentially calling the remapping
-     * function multiple times.
+     * When multiple threads attempt updates, map operations and the
+     * remapping function may be called multiple times.
      *
      * <p>This implementation assumes that the ConcurrentMap cannot contain null
      * values and {@code get()} returning null unambiguously means the key is
@@ -418,50 +409,29 @@
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
      * @since 1.8
      */
     @Override
     default V compute(K key,
-            BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
-        Objects.requireNonNull(remappingFunction);
-        V oldValue = get(key);
-        for (;;) {
-            V newValue = remappingFunction.apply(key, oldValue);
-            if (newValue == null) {
-                // delete mapping
-                if (oldValue != null || containsKey(key)) {
-                    // something to remove
-                    if (remove(key, oldValue)) {
-                        // removed the old value as expected
-                        return null;
+                      BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        retry: for (;;) {
+            V oldValue = get(key);
+            // if putIfAbsent fails, opportunistically use its return value
+            haveOldValue: for (;;) {
+                V newValue = remappingFunction.apply(key, oldValue);
+                if (newValue != null) {
+                    if (oldValue != null) {
+                        if (replace(key, oldValue, newValue))
+                            return newValue;
                     }
-
-                    // some other value replaced old value. try again.
-                    oldValue = get(key);
-                } else {
-                    // nothing to do. Leave things as they were.
+                    else if ((oldValue = putIfAbsent(key, newValue)) == null)
+                        return newValue;
+                    else continue haveOldValue;
+                } else if (oldValue == null || remove(key, oldValue)) {
                     return null;
                 }
-            } else {
-                // add or replace old mapping
-                if (oldValue != null) {
-                    // replace
-                    if (replace(key, oldValue, newValue)) {
-                        // replaced as expected.
-                        return newValue;
-                    }
-
-                    // some other value replaced old value. try again.
-                    oldValue = get(key);
-                } else {
-                    // add (replace if oldValue was null)
-                    if ((oldValue = putIfAbsent(key, newValue)) == null) {
-                        // replaced
-                        return newValue;
-                    }
-
-                    // some other value replaced old value. try again.
-                }
+                continue retry;
             }
         }
     }
@@ -471,21 +441,25 @@
      *
      * @implSpec
      * The default implementation is equivalent to performing the following
-     * steps for this {@code map}, then returning the current value or
-     * {@code null} if absent:
+     * steps for this {@code map}:
      *
      * <pre> {@code
-     * V oldValue = map.get(key);
-     * V newValue = (oldValue == null) ? value :
-     *     remappingFunction.apply(oldValue, value);
-     * if (newValue == null)
-     *   map.remove(key);
-     * else
-     *   map.put(key, newValue);}</pre>
-     *
-     * <p>The default implementation may retry these steps when multiple
-     * threads attempt updates including potentially calling the remapping
-     * function multiple times.
+     * for (;;) {
+     *   V oldValue = map.get(key);
+     *   if (oldValue != null) {
+     *     V newValue = remappingFunction.apply(oldValue, value);
+     *     if (newValue != null) {
+     *       if (map.replace(key, oldValue, newValue))
+     *         return newValue;
+     *     } else if (map.remove(key, oldValue)) {
+     *       return null;
+     *     }
+     *   } else if (map.putIfAbsent(key, value) == null) {
+     *     return value;
+     *   }
+     * }}</pre>
+     * When multiple threads attempt updates, map operations and the
+     * remapping function may be called multiple times.
      *
      * <p>This implementation assumes that the ConcurrentMap cannot contain null
      * values and {@code get()} returning null unambiguously means the key is
@@ -495,6 +469,7 @@
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
      * @since 1.8
      */
     @Override
@@ -502,20 +477,23 @@
             BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
         Objects.requireNonNull(remappingFunction);
         Objects.requireNonNull(value);
-        V oldValue = get(key);
-        for (;;) {
-            if (oldValue != null) {
-                V newValue = remappingFunction.apply(oldValue, value);
-                if (newValue != null) {
-                    if (replace(key, oldValue, newValue))
-                        return newValue;
-                } else if (remove(key, oldValue)) {
-                    return null;
-                }
-                oldValue = get(key);
-            } else {
-                if ((oldValue = putIfAbsent(key, value)) == null) {
-                    return value;
+        retry: for (;;) {
+            V oldValue = get(key);
+            // if putIfAbsent fails, opportunistically use its return value
+            haveOldValue: for (;;) {
+                if (oldValue != null) {
+                    V newValue = remappingFunction.apply(oldValue, value);
+                    if (newValue != null) {
+                        if (replace(key, oldValue, newValue))
+                            return newValue;
+                    } else if (remove(key, oldValue)) {
+                        return null;
+                    }
+                    continue retry;
+                } else {
+                    if ((oldValue = putIfAbsent(key, value)) == null)
+                        return value;
+                    continue haveOldValue;
                 }
             }
         }
--- a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java	Tue Feb 02 12:12:52 2016 -0800
@@ -35,6 +35,9 @@
 
 package java.util.concurrent;
 
+import java.time.temporal.ChronoUnit;
+import java.util.Objects;
+
 /**
  * A {@code TimeUnit} represents time durations at a given unit of
  * granularity and provides utility methods to convert across units,
@@ -390,4 +393,48 @@
         }
     }
 
+    /**
+     * Converts this {@code TimeUnit} to the equivalent {@code ChronoUnit}.
+     *
+     * @return the converted equivalent ChronoUnit
+     * @since 9
+     */
+    public ChronoUnit toChronoUnit() {
+        switch (this) {
+        case NANOSECONDS:  return ChronoUnit.NANOS;
+        case MICROSECONDS: return ChronoUnit.MICROS;
+        case MILLISECONDS: return ChronoUnit.MILLIS;
+        case SECONDS:      return ChronoUnit.SECONDS;
+        case MINUTES:      return ChronoUnit.MINUTES;
+        case HOURS:        return ChronoUnit.HOURS;
+        case DAYS:         return ChronoUnit.DAYS;
+        default: throw new AssertionError();
+        }
+    }
+
+    /**
+     * Converts a {@code ChronoUnit} to the equivalent {@code TimeUnit}.
+     *
+     * @param chronoUnit the ChronoUnit to convert
+     * @return the converted equivalent TimeUnit
+     * @throws IllegalArgumentException if {@code chronoUnit} has no
+     *         equivalent TimeUnit
+     * @throws NullPointerException if {@code chronoUnit} is null
+     * @since 9
+     */
+    public static TimeUnit of(ChronoUnit chronoUnit) {
+        switch (Objects.requireNonNull(chronoUnit, "chronoUnit")) {
+        case NANOS:   return TimeUnit.NANOSECONDS;
+        case MICROS:  return TimeUnit.MICROSECONDS;
+        case MILLIS:  return TimeUnit.MILLISECONDS;
+        case SECONDS: return TimeUnit.SECONDS;
+        case MINUTES: return TimeUnit.MINUTES;
+        case HOURS:   return TimeUnit.HOURS;
+        case DAYS:    return TimeUnit.DAYS;
+        default:
+            throw new IllegalArgumentException(
+                "No TimeUnit equivalent for " + chronoUnit);
+        }
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/ref/Cleaner.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.ref;
+
+import java.lang.ref.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+
+/**
+ * General-purpose phantom-reference-based cleaners.
+ *
+ * <p> Cleaners are a lightweight and more robust alternative to finalization.
+ * They are lightweight because they are not created by the VM and thus do not
+ * require a JNI upcall to be created, and because their cleanup code is
+ * invoked directly by the reference-handler thread rather than by the
+ * finalizer thread.  They are more robust because they use phantom references,
+ * the weakest type of reference object, thereby avoiding the nasty ordering
+ * problems inherent to finalization.
+ *
+ * <p> A cleaner tracks a referent object and encapsulates a thunk of arbitrary
+ * cleanup code.  Some time after the GC detects that a cleaner's referent has
+ * become phantom-reachable, the reference-handler thread will run the cleaner.
+ * Cleaners may also be invoked directly; they are thread safe and ensure that
+ * they run their thunks at most once.
+ *
+ * <p> Cleaners are not a replacement for finalization.  They should be used
+ * only when the cleanup code is extremely simple and straightforward.
+ * Nontrivial cleaners are inadvisable since they risk blocking the
+ * reference-handler thread and delaying further cleanup and finalization.
+ *
+ *
+ * @author Mark Reinhold
+ */
+
+public class Cleaner
+    extends PhantomReference<Object>
+    implements Runnable
+{
+
+    // Dummy reference queue, needed because the PhantomReference constructor
+    // insists that we pass a queue.  Nothing will ever be placed on this queue
+    // since the reference handler invokes cleaners explicitly.
+    //
+    private static final ReferenceQueue<Object> dummyQueue = new ReferenceQueue<>();
+
+    // Doubly-linked list of live cleaners, which prevents the cleaners
+    // themselves from being GC'd before their referents
+    //
+    private static Cleaner first = null;
+
+    private Cleaner
+        next = null,
+        prev = null;
+
+    private static synchronized Cleaner add(Cleaner cl) {
+        if (first != null) {
+            cl.next = first;
+            first.prev = cl;
+        }
+        first = cl;
+        return cl;
+    }
+
+    private static synchronized boolean remove(Cleaner cl) {
+
+        // If already removed, do nothing
+        if (cl.next == cl)
+            return false;
+
+        // Update list
+        if (first == cl) {
+            if (cl.next != null)
+                first = cl.next;
+            else
+                first = cl.prev;
+        }
+        if (cl.next != null)
+            cl.next.prev = cl.prev;
+        if (cl.prev != null)
+            cl.prev.next = cl.next;
+
+        // Indicate removal by pointing the cleaner to itself
+        cl.next = cl;
+        cl.prev = cl;
+        return true;
+
+    }
+
+    private final Runnable thunk;
+
+    private Cleaner(Object referent, Runnable thunk) {
+        super(referent, dummyQueue);
+        this.thunk = thunk;
+    }
+
+    /**
+     * Creates a new cleaner.
+     *
+     * @param  ob the referent object to be cleaned
+     * @param  thunk
+     *         The cleanup code to be run when the cleaner is invoked.  The
+     *         cleanup code is run directly from the reference-handler thread,
+     *         so it should be as simple and straightforward as possible.
+     *
+     * @return  The new cleaner
+     */
+    public static Cleaner create(Object ob, Runnable thunk) {
+        if (thunk == null)
+            return null;
+        return add(new Cleaner(ob, thunk));
+    }
+
+    /**
+     * Runs this cleaner, if it has not been run before.
+     */
+    public void clean() {
+        if (!remove(this))
+            return;
+        try {
+            thunk.run();
+        } catch (final Throwable x) {
+            AccessController.doPrivileged(new PrivilegedAction<>() {
+                    public Void run() {
+                        if (System.err != null)
+                            new Error("Cleaner terminated abnormally", x)
+                                .printStackTrace();
+                        System.exit(1);
+                        return null;
+                    }});
+        }
+    }
+
+    @Override public void run() {
+        SecurityManager security = System.getSecurityManager();
+        if (security != null)
+            security.checkPackageAccess("jdk.internal.ref");
+        this.clean();
+    }
+
+}
--- a/src/java.base/share/classes/sun/misc/Cleaner.java	Tue Feb 02 16:33:03 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.lang.ref.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-
-/**
- * General-purpose phantom-reference-based cleaners.
- *
- * <p> Cleaners are a lightweight and more robust alternative to finalization.
- * They are lightweight because they are not created by the VM and thus do not
- * require a JNI upcall to be created, and because their cleanup code is
- * invoked directly by the reference-handler thread rather than by the
- * finalizer thread.  They are more robust because they use phantom references,
- * the weakest type of reference object, thereby avoiding the nasty ordering
- * problems inherent to finalization.
- *
- * <p> A cleaner tracks a referent object and encapsulates a thunk of arbitrary
- * cleanup code.  Some time after the GC detects that a cleaner's referent has
- * become phantom-reachable, the reference-handler thread will run the cleaner.
- * Cleaners may also be invoked directly; they are thread safe and ensure that
- * they run their thunks at most once.
- *
- * <p> Cleaners are not a replacement for finalization.  They should be used
- * only when the cleanup code is extremely simple and straightforward.
- * Nontrivial cleaners are inadvisable since they risk blocking the
- * reference-handler thread and delaying further cleanup and finalization.
- *
- *
- * @author Mark Reinhold
- */
-
-public class Cleaner
-    extends PhantomReference<Object>
-{
-
-    // Dummy reference queue, needed because the PhantomReference constructor
-    // insists that we pass a queue.  Nothing will ever be placed on this queue
-    // since the reference handler invokes cleaners explicitly.
-    //
-    private static final ReferenceQueue<Object> dummyQueue = new ReferenceQueue<>();
-
-    // Doubly-linked list of live cleaners, which prevents the cleaners
-    // themselves from being GC'd before their referents
-    //
-    private static Cleaner first = null;
-
-    private Cleaner
-        next = null,
-        prev = null;
-
-    private static synchronized Cleaner add(Cleaner cl) {
-        if (first != null) {
-            cl.next = first;
-            first.prev = cl;
-        }
-        first = cl;
-        return cl;
-    }
-
-    private static synchronized boolean remove(Cleaner cl) {
-
-        // If already removed, do nothing
-        if (cl.next == cl)
-            return false;
-
-        // Update list
-        if (first == cl) {
-            if (cl.next != null)
-                first = cl.next;
-            else
-                first = cl.prev;
-        }
-        if (cl.next != null)
-            cl.next.prev = cl.prev;
-        if (cl.prev != null)
-            cl.prev.next = cl.next;
-
-        // Indicate removal by pointing the cleaner to itself
-        cl.next = cl;
-        cl.prev = cl;
-        return true;
-
-    }
-
-    private final Runnable thunk;
-
-    private Cleaner(Object referent, Runnable thunk) {
-        super(referent, dummyQueue);
-        this.thunk = thunk;
-    }
-
-    /**
-     * Creates a new cleaner.
-     *
-     * @param  ob the referent object to be cleaned
-     * @param  thunk
-     *         The cleanup code to be run when the cleaner is invoked.  The
-     *         cleanup code is run directly from the reference-handler thread,
-     *         so it should be as simple and straightforward as possible.
-     *
-     * @return  The new cleaner
-     */
-    public static Cleaner create(Object ob, Runnable thunk) {
-        if (thunk == null)
-            return null;
-        return add(new Cleaner(ob, thunk));
-    }
-
-    /**
-     * Runs this cleaner, if it has not been run before.
-     */
-    public void clean() {
-        if (!remove(this))
-            return;
-        try {
-            thunk.run();
-        } catch (final Throwable x) {
-            AccessController.doPrivileged(new PrivilegedAction<>() {
-                    public Void run() {
-                        if (System.err != null)
-                            new Error("Cleaner terminated abnormally", x)
-                                .printStackTrace();
-                        System.exit(1);
-                        return null;
-                    }});
-        }
-    }
-
-}
--- a/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java	Tue Feb 02 12:12:52 2016 -0800
@@ -25,7 +25,7 @@
 
 package sun.nio.ch;
 
-import sun.misc.Cleaner;
+import jdk.internal.ref.Cleaner;
 
 
 public interface DirectBuffer {
--- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java	Tue Feb 02 12:12:52 2016 -0800
@@ -47,7 +47,7 @@
 import jdk.internal.misc.JavaIOFileDescriptorAccess;
 import jdk.internal.misc.JavaNioAccess;
 import jdk.internal.misc.SharedSecrets;
-import sun.misc.Cleaner;
+import jdk.internal.ref.Cleaner;
 import sun.security.action.GetPropertyAction;
 
 public class FileChannelImpl
--- a/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java	Tue Feb 02 12:12:52 2016 -0800
@@ -26,7 +26,7 @@
 package sun.nio.ch;
 
 import java.nio.ByteBuffer;
-import sun.misc.*;
+import jdk.internal.ref.Cleaner;
 
 
 /**
--- a/src/java.base/share/classes/sun/nio/ch/Util.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/sun/nio/ch/Util.java	Tue Feb 02 12:12:52 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
 import java.security.PrivilegedAction;
 import java.util.*;
 import jdk.internal.misc.Unsafe;
-import sun.misc.Cleaner;
+import jdk.internal.ref.Cleaner;
 import sun.security.action.GetPropertyAction;
 
 
@@ -44,6 +44,9 @@
     // The number of temp buffers in our pool
     private static final int TEMP_BUF_POOL_SIZE = IOUtil.IOV_MAX;
 
+    // The max size allowed for a cached temp buffer, in bytes
+    private static final long MAX_CACHED_BUFFER_SIZE = getMaxCachedBufferSize();
+
     // Per-thread cache of temporary direct buffers
     private static ThreadLocal<BufferCache> bufferCache =
         new ThreadLocal<BufferCache>()
@@ -55,6 +58,52 @@
     };
 
     /**
+     * Returns the max size allowed for a cached temp buffers, in
+     * bytes. It defaults to Long.MAX_VALUE. It can be set with the
+     * jdk.nio.maxCachedBufferSize property. Even though
+     * ByteBuffer.capacity() returns an int, we're using a long here
+     * for potential future-proofing.
+     */
+    private static long getMaxCachedBufferSize() {
+        String s = java.security.AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                @Override
+                public String run() {
+                    return System.getProperty("jdk.nio.maxCachedBufferSize");
+                }
+            });
+        if (s != null) {
+            try {
+                long m = Long.parseLong(s);
+                if (m >= 0) {
+                    return m;
+                } else {
+                    // if it's negative, ignore the system property
+                }
+            } catch (NumberFormatException e) {
+                // if the string is not well formed, ignore the system property
+            }
+        }
+        return Long.MAX_VALUE;
+    }
+
+    /**
+     * Returns true if a buffer of this size is too large to be
+     * added to the buffer cache, false otherwise.
+     */
+    private static boolean isBufferTooLarge(int size) {
+        return size > MAX_CACHED_BUFFER_SIZE;
+    }
+
+    /**
+     * Returns true if the buffer is too large to be added to the
+     * buffer cache, false otherwise.
+     */
+    private static boolean isBufferTooLarge(ByteBuffer buf) {
+        return isBufferTooLarge(buf.capacity());
+    }
+
+    /**
      * A simple cache of direct buffers.
      */
     private static class BufferCache {
@@ -80,6 +129,9 @@
          * size (or null if no suitable buffer is found).
          */
         ByteBuffer get(int size) {
+            // Don't call this if the buffer would be too large.
+            assert !isBufferTooLarge(size);
+
             if (count == 0)
                 return null;  // cache is empty
 
@@ -117,6 +169,9 @@
         }
 
         boolean offerFirst(ByteBuffer buf) {
+            // Don't call this if the buffer is too large.
+            assert !isBufferTooLarge(buf);
+
             if (count >= TEMP_BUF_POOL_SIZE) {
                 return false;
             } else {
@@ -128,6 +183,9 @@
         }
 
         boolean offerLast(ByteBuffer buf) {
+            // Don't call this if the buffer is too large.
+            assert !isBufferTooLarge(buf);
+
             if (count >= TEMP_BUF_POOL_SIZE) {
                 return false;
             } else {
@@ -156,6 +214,15 @@
      * Returns a temporary buffer of at least the given size
      */
     public static ByteBuffer getTemporaryDirectBuffer(int size) {
+        // If a buffer of this size is too large for the cache, there
+        // should not be a buffer in the cache that is at least as
+        // large. So we'll just create a new one. Also, we don't have
+        // to remove the buffer from the cache (as this method does
+        // below) given that we won't put the new buffer in the cache.
+        if (isBufferTooLarge(size)) {
+            return ByteBuffer.allocateDirect(size);
+        }
+
         BufferCache cache = bufferCache.get();
         ByteBuffer buf = cache.get(size);
         if (buf != null) {
@@ -185,6 +252,13 @@
      * likely to be returned by a subsequent call to getTemporaryDirectBuffer.
      */
     static void offerFirstTemporaryDirectBuffer(ByteBuffer buf) {
+        // If the buffer is too large for the cache we don't have to
+        // check the cache. We'll just free it.
+        if (isBufferTooLarge(buf)) {
+            free(buf);
+            return;
+        }
+
         assert buf != null;
         BufferCache cache = bufferCache.get();
         if (!cache.offerFirst(buf)) {
@@ -200,6 +274,13 @@
      * cache in same order that they were obtained.
      */
     static void offerLastTemporaryDirectBuffer(ByteBuffer buf) {
+        // If the buffer is too large for the cache we don't have to
+        // check the cache. We'll just free it.
+        if (isBufferTooLarge(buf)) {
+            free(buf);
+            return;
+        }
+
         assert buf != null;
         BufferCache cache = bufferCache.get();
         if (!cache.offerLast(buf)) {
--- a/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java	Tue Feb 02 12:12:52 2016 -0800
@@ -59,7 +59,11 @@
         AccessController.doPrivileged(new PrivilegedAction<>() {
             @Override
             public Object run() {
-                Thread thr = new Thread(null, thisRunnable, "FileSystemWatchService", 0, false);
+                Thread thr = new Thread(null,
+                                        thisRunnable,
+                                        "FileSystemWatchService",
+                                        0,
+                                        false);
                 thr.setDaemon(true);
                 thr.start();
                 return null;
@@ -216,11 +220,11 @@
                 throw new ClosedWatchServiceException();
             }
             requestList.add(req);
+
+            // wakeup thread
+            wakeup();
         }
 
-        // wakeup thread
-        wakeup();
-
         // wait for result
         Object result = req.awaitResult();
 
@@ -244,6 +248,7 @@
                 // if in process of shutdown then reject request
                 if (shutdown) {
                     req.release(new ClosedWatchServiceException());
+                    continue;
                 }
 
                 switch (req.type()) {
--- a/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java	Tue Feb 02 12:12:52 2016 -0800
@@ -26,7 +26,7 @@
 package sun.nio.fs;
 
 import jdk.internal.misc.Unsafe;
-import sun.misc.Cleaner;
+import jdk.internal.ref.Cleaner;
 
 /**
  * A light-weight buffer in native memory.
--- a/src/java.base/share/classes/sun/reflect/ConstantPool.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/sun/reflect/ConstantPool.java	Tue Feb 02 12:12:52 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -36,6 +36,10 @@
   public int      getSize()                      { return getSize0            (constantPoolOop);        }
   public Class<?> getClassAt         (int index) { return getClassAt0         (constantPoolOop, index); }
   public Class<?> getClassAtIfLoaded (int index) { return getClassAtIfLoaded0 (constantPoolOop, index); }
+  // Returns a class reference index for a method or a field.
+  public int getClassRefIndexAt(int index) {
+      return getClassRefIndexAt0(constantPoolOop, index);
+  }
   // Returns either a Method or Constructor.
   // Static initializers are returned as Method objects.
   public Member   getMethodAt        (int index) { return getMethodAt0        (constantPoolOop, index); }
@@ -45,13 +49,56 @@
   // Fetches the class name, member (field, method or interface
   // method) name, and type descriptor as an array of three Strings
   public String[] getMemberRefInfoAt (int index) { return getMemberRefInfoAt0 (constantPoolOop, index); }
+  // Returns a name and type reference index for a method, a field or an invokedynamic.
+  public int getNameAndTypeRefIndexAt(int index) {
+      return getNameAndTypeRefIndexAt0(constantPoolOop, index);
+  }
+  // Fetches the name and type from name_and_type index as an array of two Strings
+  public String[] getNameAndTypeRefInfoAt(int index) {
+      return getNameAndTypeRefInfoAt0(constantPoolOop, index);
+  }
   public int      getIntAt           (int index) { return getIntAt0           (constantPoolOop, index); }
   public long     getLongAt          (int index) { return getLongAt0          (constantPoolOop, index); }
   public float    getFloatAt         (int index) { return getFloatAt0         (constantPoolOop, index); }
   public double   getDoubleAt        (int index) { return getDoubleAt0        (constantPoolOop, index); }
   public String   getStringAt        (int index) { return getStringAt0        (constantPoolOop, index); }
   public String   getUTF8At          (int index) { return getUTF8At0          (constantPoolOop, index); }
+  public Tag getTagAt(int index) {
+      return Tag.valueOf(getTagAt0(constantPoolOop, index));
+  }
 
+  public static enum Tag {
+      UTF8(1),
+      INTEGER(3),
+      FLOAT(4),
+      LONG(5),
+      DOUBLE(6),
+      CLASS(7),
+      STRING(8),
+      FIELDREF(9),
+      METHODREF(10),
+      INTERFACEMETHODREF(11),
+      NAMEANDTYPE(12),
+      METHODHANDLE(15),
+      METHODTYPE(16),
+      INVOKEDYNAMIC(18),
+      INVALID(0);
+
+      private final int tagCode;
+
+      private Tag(int tagCode) {
+          this.tagCode = tagCode;
+      }
+
+      private static Tag valueOf(byte v) {
+          for (Tag tag : Tag.values()) {
+              if (tag.tagCode == v) {
+                  return tag;
+              }
+          }
+          throw new IllegalArgumentException("Unknown constant pool tag code " + v);
+      }
+   }
   //---------------------------------------------------------------------------
   // Internals only below this point
   //
@@ -66,15 +113,19 @@
   private native int      getSize0            (Object constantPoolOop);
   private native Class<?> getClassAt0         (Object constantPoolOop, int index);
   private native Class<?> getClassAtIfLoaded0 (Object constantPoolOop, int index);
+  private native int      getClassRefIndexAt0 (Object constantPoolOop, int index);
   private native Member   getMethodAt0        (Object constantPoolOop, int index);
   private native Member   getMethodAtIfLoaded0(Object constantPoolOop, int index);
   private native Field    getFieldAt0         (Object constantPoolOop, int index);
   private native Field    getFieldAtIfLoaded0 (Object constantPoolOop, int index);
   private native String[] getMemberRefInfoAt0 (Object constantPoolOop, int index);
+  private native int      getNameAndTypeRefIndexAt0(Object constantPoolOop, int index);
+  private native String[] getNameAndTypeRefInfoAt0(Object constantPoolOop, int index);
   private native int      getIntAt0           (Object constantPoolOop, int index);
   private native long     getLongAt0          (Object constantPoolOop, int index);
   private native float    getFloatAt0         (Object constantPoolOop, int index);
   private native double   getDoubleAt0        (Object constantPoolOop, int index);
   private native String   getStringAt0        (Object constantPoolOop, int index);
   private native String   getUTF8At0          (Object constantPoolOop, int index);
+  private native byte     getTagAt0           (Object constantPoolOop, int index);
 }
--- a/src/java.base/share/classes/sun/security/jca/ProviderList.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/classes/sun/security/jca/ProviderList.java	Tue Feb 02 12:12:52 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -653,6 +653,7 @@
         String type = null;
         String algorithm;
         String provider;
+        String alternateName = null;
 
         PreferredEntry(String t, String p) {
             int i = t.indexOf('.');
@@ -664,6 +665,11 @@
             }
 
             provider = p;
+            if (algorithm.compareToIgnoreCase("SHA1") == 0) {
+                alternateName = "SHA-1";
+            } else if (algorithm.compareToIgnoreCase("SHA-1") == 0) {
+                alternateName = "SHA1";
+            }
         }
 
         boolean match(String t, String a) {
@@ -685,6 +691,15 @@
                 return true;
             }
 
+            if (alternateName != null &&
+                    a.compareToIgnoreCase(alternateName) == 0) {
+                if (debug != null) {
+                    debug.println("Config entry found (alternateName):  " +
+                            toString());
+                }
+                return true;
+            }
+
             // No match
             return false;
         }
--- a/src/java.base/share/conf/security/java.security	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/conf/security/java.security	Tue Feb 02 12:12:52 2016 -0800
@@ -109,7 +109,8 @@
 #   jdk.security.provider.preferred=AES/GCM/NoPadding:SunJCE, \
 #         MessageDigest.SHA-256:SUN
 #ifdef solaris-sparc
-jdk.security.provider.preferred=AES:SunJCE, SHA-256:SUN, SHA-384:SUN, SHA-512:SUN
+jdk.security.provider.preferred=AES:SunJCE, SHA1:SUN, SHA-224:SUN, \
+      SHA-256:SUN, SHA-384:SUN, SHA-512:SUN
 #endif
 #ifdef solaris-x86
 jdk.security.provider.preferred=AES:SunJCE, RSA:SunRsaSign
--- a/src/java.base/share/native/include/jvm.h	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/native/include/jvm.h	Tue Feb 02 12:12:52 2016 -0800
@@ -63,7 +63,7 @@
  *    class.
  */
 
-#define JVM_INTERFACE_VERSION 4
+#define JVM_INTERFACE_VERSION 5
 
 JNIEXPORT jint JNICALL
 JVM_GetInterfaceVersion(void);
@@ -502,6 +502,9 @@
 JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAtIfLoaded
 (JNIEnv *env, jobject unused, jobject jcpool, jint index);
 
+JNIEXPORT jint JNICALL JVM_ConstantPoolGetClassRefIndexAt
+(JNIEnv *env, jobject obj, jobject unused, jint index);
+
 JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAt
 (JNIEnv *env, jobject unused, jobject jcpool, jint index);
 
@@ -517,6 +520,12 @@
 JNIEXPORT jobjectArray JNICALL JVM_ConstantPoolGetMemberRefInfoAt
 (JNIEnv *env, jobject unused, jobject jcpool, jint index);
 
+JNIEXPORT jint JNICALL JVM_ConstantPoolGetNameAndTypeRefIndexAt
+(JNIEnv *env, jobject obj, jobject unused, jint index);
+
+JNIEXPORT jobjectArray JNICALL JVM_ConstantPoolGetNameAndTypeRefInfoAt
+(JNIEnv *env, jobject obj, jobject unused, jint index);
+
 JNIEXPORT jint JNICALL JVM_ConstantPoolGetIntAt
 (JNIEnv *env, jobject unused, jobject jcpool, jint index);
 
@@ -535,6 +544,9 @@
 JNIEXPORT jstring JNICALL JVM_ConstantPoolGetUTF8At
 (JNIEnv *env, jobject unused, jobject jcpool, jint index);
 
+JNIEXPORT jbyte JNICALL JVM_ConstantPoolGetTagAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
 /*
  * Parameter reflection
  */
--- a/src/java.base/share/native/libjava/ConstantPool.c	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.base/share/native/libjava/ConstantPool.c	Tue Feb 02 12:12:52 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -44,6 +44,12 @@
   return JVM_ConstantPoolGetClassAtIfLoaded(env, unused, jcpool, index);
 }
 
+JNIEXPORT jint JNICALL Java_sun_reflect_ConstantPool_getClassRefIndexAt0
+(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+    return JVM_ConstantPoolGetClassRefIndexAt(env, unused, jcpool, index);
+}
+
 JNIEXPORT jobject JNICALL Java_sun_reflect_ConstantPool_getMethodAt0
 (JNIEnv *env, jobject unused, jobject jcpool, jint index)
 {
@@ -74,6 +80,18 @@
   return JVM_ConstantPoolGetMemberRefInfoAt(env, unused, jcpool, index);
 }
 
+JNIEXPORT jint JNICALL Java_sun_reflect_ConstantPool_getNameAndTypeRefIndexAt0
+(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+    return JVM_ConstantPoolGetNameAndTypeRefIndexAt(env, unused, jcpool, index);
+}
+
+JNIEXPORT jobjectArray JNICALL Java_sun_reflect_ConstantPool_getNameAndTypeRefInfoAt0
+(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+  return JVM_ConstantPoolGetNameAndTypeRefInfoAt(env, unused, jcpool, index);
+}
+
 JNIEXPORT jint JNICALL Java_sun_reflect_ConstantPool_getIntAt0
 (JNIEnv *env, jobject unused, jobject jcpool, jint index)
 {
@@ -109,3 +127,10 @@
 {
   return JVM_ConstantPoolGetUTF8At(env, unused, jcpool, index);
 }
+
+JNIEXPORT jbyte JNICALL Java_sun_reflect_ConstantPool_getTagAt0
+(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+  return JVM_ConstantPoolGetTagAt(env, unused, jcpool, index);
+}
+
--- a/src/java.management/share/classes/java/lang/management/ManagementFactory.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.management/share/classes/java/lang/management/ManagementFactory.java	Tue Feb 02 12:12:52 2016 -0800
@@ -519,9 +519,13 @@
      * {@code MBeanServerConnection} where
      * {@link java.io.IOException IOException} may be thrown
      * when the communication problem occurs with the connector server.
-     * An application remotely accesses the platform MXBeans using
-     * proxy should prepare to catch {@code IOException} as if
-     * accessing with the {@code MBeanServerConnector} interface.</li>
+     * If thrown, {@link java.io.IOException IOException} will be wrappped in
+     * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}.
+     * An application remotely accessing the platform MXBeans using
+     * proxy should prepare to catch {@code UndeclaredThrowableException} and
+     * handle its {@linkplain java.lang.reflect.UndeclaredThrowableException#getCause() cause}
+     * as if that cause had been thrown by the {@code MBeanServerConnection}
+     * interface.</li>
      *
      * <li>When a client application is designed to remotely access MXBeans
      * for a running virtual machine whose version is different than
@@ -530,7 +534,11 @@
      * {@link java.io.InvalidObjectException InvalidObjectException}
      * which is thrown when an MXBean proxy receives a name of an
      * enum constant which is missing in the enum class loaded in
-     * the client application. </li>
+     * the client application.   If thrown,
+     * {@link java.io.InvalidObjectException InvalidObjectException} will be
+     * wrappped in
+     * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}.
+     * </li>
      *
      * <li>{@link javax.management.MBeanServerInvocationHandler
      * MBeanServerInvocationHandler} or its
--- a/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java	Tue Feb 02 12:12:52 2016 -0800
@@ -2250,7 +2250,7 @@
         return attributes != null ?
                 attributes.asList().stream()
                         .map(Attribute::getName)
-                        .collect(Collectors.joining("[", ", ", "]"))
+                        .collect(Collectors.joining(", ", "[", "]"))
                 : "[]";
     }
 }
--- a/src/java.prefs/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.prefs/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java	Tue Feb 02 12:12:52 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,6 @@
 import java.util.Timer;
 import java.util.TimerTask;
 import java.lang.ref.WeakReference;
-import sun.misc.ManagedLocalsThread;
 
 
 /*
@@ -344,7 +343,8 @@
     {
         if (timer == null) {
             timer = new Timer(true); // daemon
-            Thread flushThread = new ManagedLocalsThread() {
+            Thread flushThread =
+                new Thread(null, null, "Flush Thread", 0, false) {
                 @Override
                 public void run() {
                     flushWorld();
--- a/src/java.prefs/share/classes/java/util/prefs/AbstractPreferences.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.prefs/share/classes/java/util/prefs/AbstractPreferences.java	Tue Feb 02 12:12:52 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
 import java.io.*;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import sun.misc.ManagedLocalsThread;
 // These imports needed only as a workaround for a JavaDoc bug
 import java.lang.Integer;
 import java.lang.Long;
@@ -1515,7 +1514,11 @@
      * A single background thread ("the event notification thread") monitors
      * the event queue and delivers events that are placed on the queue.
      */
-    private static class EventDispatchThread extends ManagedLocalsThread {
+    private static class EventDispatchThread extends Thread {
+        private EventDispatchThread() {
+            super(null, null, "Event Dispatch Thread", 0, false);
+        }
+
         public void run() {
             while(true) {
                 // Wait on eventQueue till an event is present
--- a/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java	Tue Feb 02 12:12:52 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,6 @@
 import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
-import sun.misc.ManagedLocalsThread;
 import sun.util.logging.PlatformLogger;
 
 /**
@@ -443,7 +442,8 @@
         // Add shutdown hook to flush cached prefs on normal termination
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
-                Runtime.getRuntime().addShutdownHook(new ManagedLocalsThread() {
+                Runtime.getRuntime().addShutdownHook(
+                    new Thread(null, null, "Sync Timer Thread", 0, false) {
                     public void run() {
                         syncTimer.cancel();
                         syncWorld();
--- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java	Tue Feb 02 16:33:03 2016 +0300
+++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java	Tue Feb 02 12:12:52 2016 -0800
@@ -373,22 +373,22 @@
                             }
                             SocketChannel chan = schan.accept();
 
-                            // Set TCP_NODELAY, if appropriate
-                            if (ServerConfig.noDelay()) {
-                                chan.socket().setTcpNoDelay(true);
+                            // optimist there's a channel
+                            if (chan != null) {
+                                // Set TCP_NODELAY, if appropriate
+                                if (ServerConfig.noDelay()) {
+                                    chan.socket().setTcpNoDelay(true);
+                                }
+                                chan.configureBlocking (false);
+                                SelectionKey newkey =
+                                    chan.register (selector, SelectionKey.OP_READ);
+                                HttpConnection c = new HttpConnection ();
+                                c.selectionKey = newkey;
+                                c.setChannel (chan);
+                                newkey.attach (c);
+                                requestStarted (c);
+                                allConnections.add (c);
                             }
-
-                            if (chan == null) {
-                                continue; /* cancel something ? */
-                            }
-                            chan.configureBlocking (false);
-                            SelectionKey newkey = chan.register (selector, SelectionKey.OP_READ);
-                            HttpConnection c = new HttpConnection ();
-                            c.selectionKey = newkey;
-                            c.setChannel (chan);
-                            newkey.attach (c);
-                            requestStarted (c);
-                            allConnections.add (c);
                         } else {
                             try {
                                 if (key.isReadable()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/AbstractOptionSpec.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static java.util.Collections.*;
+
+import jdk.internal.joptsimple.internal.Reflection;
+import jdk.internal.joptsimple.internal.ReflectionException;
+
+import static jdk.internal.joptsimple.internal.Strings.*;
+
+/**
+ * @param <V> represents the type of the arguments this option accepts
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+abstract class AbstractOptionSpec<V> implements OptionSpec<V>, OptionDescriptor {
+    private final List<String> options = new ArrayList<String>();
+    private final String description;
+    private boolean forHelp;
+
+    protected AbstractOptionSpec( String option ) {
+        this( singletonList( option ), EMPTY );
+    }
+
+    protected AbstractOptionSpec( Collection<String> options, String description ) {
+        arrangeOptions( options );
+
+        this.description = description;
+    }
+
+    public final Collection<String> options() {
+        return unmodifiableList( options );
+    }
+
+    public final List<V> values( OptionSet detectedOptions ) {
+        return detectedOptions.valuesOf( this );
+    }
+
+    public final V value( OptionSet detectedOptions ) {
+        return detectedOptions.valueOf( this );
+    }
+
+    public String description() {
+        return description;
+    }
+
+    public final AbstractOptionSpec<V> forHelp() {
+        forHelp = true;
+        return this;
+    }
+
+    public final boolean isForHelp() {
+        return forHelp;
+    }
+
+    public boolean representsNonOptions() {
+        return false;
+    }
+
+    protected abstract V convert( String argument );
+
+    protected V convertWith( ValueConverter<V> converter, String argument ) {
+        try {
+            return Reflection.convertWith( converter, argument );
+        }
+        catch ( ReflectionException ex ) {
+            throw new OptionArgumentConversionException( options(), argument, ex );
+        }
+        catch ( ValueConversionException ex ) {
+            throw new OptionArgumentConversionException( options(), argument, ex );
+        }
+    }
+
+    protected String argumentTypeIndicatorFrom( ValueConverter<V> converter ) {
+        if ( converter == null )
+            return null;
+
+        String pattern = converter.valuePattern();
+        return pattern == null ? converter.valueType().getName() : pattern;
+    }
+
+    abstract void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions,
+        String detectedArgument );
+
+    private void arrangeOptions( Collection<String> unarranged ) {
+        if ( unarranged.size() == 1 ) {
+            options.addAll( unarranged );
+            return;
+        }
+
+        List<String> shortOptions = new ArrayList<String>();
+        List<String> longOptions = new ArrayList<String>();
+
+        for ( String each : unarranged ) {
+            if ( each.length() == 1 )
+                shortOptions.add( each );
+            else
+                longOptions.add( each );
+        }
+
+        sort( shortOptions );
+        sort( longOptions );
+
+        options.addAll( shortOptions );
+        options.addAll( longOptions );
+    }
+
+    @Override
+    public boolean equals( Object that ) {
+        if ( !( that instanceof AbstractOptionSpec<?> ) )
+            return false;
+
+        AbstractOptionSpec<?> other = (AbstractOptionSpec<?>) that;
+        return options.equals( other.options );
+    }
+
+    @Override
+    public int hashCode() {
+        return options.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return options.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/AlternativeLongOptionSpec.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import static java.util.Collections.*;
+
+import static jdk.internal.joptsimple.ParserRules.*;
+
+/**
+ * Represents the <kbd>"-W"</kbd> form of long option specification.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class AlternativeLongOptionSpec extends ArgumentAcceptingOptionSpec<String> {
+    AlternativeLongOptionSpec() {
+        super( singletonList( RESERVED_FOR_EXTENSIONS ), true, "Alternative form of long options" );
+
+        describedAs( "opt=value" );
+    }
+
+    @Override
+    protected void detectOptionArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) {
+        if ( !arguments.hasMore() )
+            throw new OptionMissingRequiredArgumentException( options() );
+
+        arguments.treatNextAsLongOption();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/ArgumentAcceptingOptionSpec.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import static java.util.Collections.*;
+
+import static jdk.internal.joptsimple.internal.Objects.*;
+import static jdk.internal.joptsimple.internal.Reflection.*;
+import static jdk.internal.joptsimple.internal.Strings.*;
+
+/**
+ * <p>Specification of an option that accepts an argument.</p>
+ *
+ * <p>Instances are returned from {@link OptionSpecBuilder} methods to allow the formation of parser directives as
+ * sentences in a "fluent interface" language. For example:</p>
+ *
+ * <pre>
+ *   <code>
+ *   OptionParser parser = new OptionParser();
+ *   parser.accepts( "c" ).withRequiredArg().<strong>ofType( Integer.class )</strong>;
+ *   </code>
+ * </pre>
+ *
+ * <p>If no methods are invoked on an instance of this class, then that instance's option will treat its argument as
+ * a {@link String}.</p>
+ *
+ * @param <V> represents the type of the arguments this option accepts
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public abstract class ArgumentAcceptingOptionSpec<V> extends AbstractOptionSpec<V> {
+    private static final char NIL_VALUE_SEPARATOR = '\u0000';
+
+    private boolean optionRequired;
+    private final boolean argumentRequired;
+    private ValueConverter<V> converter;
+    private String argumentDescription = "";
+    private String valueSeparator = String.valueOf( NIL_VALUE_SEPARATOR );
+    private final List<V> defaultValues = new ArrayList<V>();
+
+    ArgumentAcceptingOptionSpec( String option, boolean argumentRequired ) {
+        super( option );
+
+        this.argumentRequired = argumentRequired;
+    }
+
+    ArgumentAcceptingOptionSpec( Collection<String> options, boolean argumentRequired, String description ) {
+        super( options, description );
+
+        this.argumentRequired = argumentRequired;
+    }
+
+    /**
+     * <p>Specifies a type to which arguments of this spec's option are to be converted.</p>
+     *
+     * <p>JOpt Simple accepts types that have either:</p>
+     *
+     * <ol>
+     *   <li>a public static method called {@code valueOf} which accepts a single argument of type {@link String}
+     *   and whose return type is the same as the class on which the method is declared.  The {@code java.lang}
+     *   primitive wrapper classes have such methods.</li>
+     *
+     *   <li>a public constructor which accepts a single argument of type {@link String}.</li>
+     * </ol>
+     *
+     * <p>This class converts arguments using those methods in that order; that is, {@code valueOf} would be invoked
+     * before a one-{@link String}-arg constructor would.</p>
+     *
+     * <p>Invoking this method will trump any previous calls to this method or to
+     * {@link #withValuesConvertedBy(ValueConverter)}.</p>
+     *
+     * @param <T> represents the runtime class of the desired option argument type
+     * @param argumentType desired type of arguments to this spec's option
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     * @throws NullPointerException if the type is {@code null}
+     * @throws IllegalArgumentException if the type does not have the standard conversion methods
+     */
+    public final <T> ArgumentAcceptingOptionSpec<T> ofType( Class<T> argumentType ) {
+        return withValuesConvertedBy( findConverter( argumentType ) );
+    }
+
+    /**
+     * <p>Specifies a converter to use to translate arguments of this spec's option into Java objects.  This is useful
+     * when converting to types that do not have the requisite factory method or constructor for
+     * {@link #ofType(Class)}.</p>
+     *
+     * <p>Invoking this method will trump any previous calls to this method or to {@link #ofType(Class)}.
+     *
+     * @param <T> represents the runtime class of the desired option argument type
+     * @param aConverter the converter to use
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     * @throws NullPointerException if the converter is {@code null}
+     */
+    @SuppressWarnings( "unchecked" )
+    public final <T> ArgumentAcceptingOptionSpec<T> withValuesConvertedBy( ValueConverter<T> aConverter ) {
+        if ( aConverter == null )
+            throw new NullPointerException( "illegal null converter" );
+
+        converter = (ValueConverter<V>) aConverter;
+        return (ArgumentAcceptingOptionSpec<T>) this;
+    }
+
+    /**
+     * <p>Specifies a description for the argument of the option that this spec represents.  This description is used
+     * when generating help information about the parser.</p>
+     *
+     * @param description describes the nature of the argument of this spec's option
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     */
+    public final ArgumentAcceptingOptionSpec<V> describedAs( String description ) {
+        argumentDescription = description;
+        return this;
+    }
+
+    /**
+     * <p>Specifies a value separator for the argument of the option that this spec represents.  This allows a single
+     * option argument to represent multiple values for the option.  For example:</p>
+     *
+     * <pre>
+     *   <code>
+     *   parser.accepts( "z" ).withRequiredArg()
+     *       .<strong>withValuesSeparatedBy( ',' )</strong>;
+     *   OptionSet options = parser.parse( new String[] { "-z", "foo,bar,baz", "-z",
+     *       "fizz", "-z", "buzz" } );
+     *   </code>
+     * </pre>
+     *
+     * <p>Then {@code options.valuesOf( "z" )} would yield the list {@code [foo, bar, baz, fizz, buzz]}.</p>
+     *
+     * <p>You cannot use Unicode U+0000 as the separator.</p>
+     *
+     * @param separator a character separator
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     * @throws IllegalArgumentException if the separator is Unicode U+0000
+     */
+    public final ArgumentAcceptingOptionSpec<V> withValuesSeparatedBy( char separator ) {
+        if ( separator == NIL_VALUE_SEPARATOR )
+            throw new IllegalArgumentException( "cannot use U+0000 as separator" );
+
+        valueSeparator = String.valueOf( separator );
+        return this;
+    }
+
+    /**
+     * <p>Specifies a value separator for the argument of the option that this spec represents.  This allows a single
+     * option argument to represent multiple values for the option.  For example:</p>
+     *
+     * <pre>
+     *   <code>
+     *   parser.accepts( "z" ).withRequiredArg()
+     *       .<strong>withValuesSeparatedBy( ":::" )</strong>;
+     *   OptionSet options = parser.parse( new String[] { "-z", "foo:::bar:::baz", "-z",
+     *       "fizz", "-z", "buzz" } );
+     *   </code>
+     * </pre>
+     *
+     * <p>Then {@code options.valuesOf( "z" )} would yield the list {@code [foo, bar, baz, fizz, buzz]}.</p>
+     *
+     * <p>You cannot use Unicode U+0000 in the separator.</p>
+     *
+     * @param separator a string separator
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     * @throws IllegalArgumentException if the separator contains Unicode U+0000
+     */
+    public final ArgumentAcceptingOptionSpec<V> withValuesSeparatedBy( String separator ) {
+        if ( separator.indexOf( NIL_VALUE_SEPARATOR ) != -1 )
+            throw new IllegalArgumentException( "cannot use U+0000 in separator" );
+
+        valueSeparator = separator;
+        return this;
+    }
+
+    /**
+     * Specifies a set of default values for the argument of the option that this spec represents.
+     *
+     * @param value the first in the set of default argument values for this spec's option
+     * @param values the (optional) remainder of the set of default argument values for this spec's option
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     * @throws NullPointerException if {@code value}, {@code values}, or any elements of {@code values} are
+     * {@code null}
+     */
+    @SuppressWarnings("unchecked")
+    public ArgumentAcceptingOptionSpec<V> defaultsTo( V value, V... values ) {
+        addDefaultValue( value );
+        defaultsTo( values );
+
+        return this;
+    }
+
+    /**
+     * Specifies a set of default values for the argument of the option that this spec represents.
+     *
+     * @param values the set of default argument values for this spec's option
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     * @throws NullPointerException if {@code values} or any elements of {@code values} are {@code null}
+     */
+    public ArgumentAcceptingOptionSpec<V> defaultsTo( V[] values ) {
+        for ( V each : values )
+            addDefaultValue( each );
+
+        return this;
+    }
+
+    /**
+     * Marks this option as required. An {@link OptionException} will be thrown when
+     * {@link OptionParser#parse(java.lang.String...)} is called, if an option is marked as required and not specified
+     * on the command line.
+     *
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     */
+    public ArgumentAcceptingOptionSpec<V> required() {
+        optionRequired = true;
+        return this;
+    }
+
+    public boolean isRequired() {
+        return optionRequired;
+    }
+
+    private void addDefaultValue( V value ) {
+        ensureNotNull( value );
+        defaultValues.add( value );
+    }
+
+    @Override
+    final void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions,
+        String detectedArgument ) {
+
+        if ( isNullOrEmpty( detectedArgument ) )
+            detectOptionArgument( parser, arguments, detectedOptions );
+        else
+            addArguments( detectedOptions, detectedArgument );
+    }
+
+    protected void addArguments( OptionSet detectedOptions, String detectedArgument ) {
+        StringTokenizer lexer = new StringTokenizer( detectedArgument, valueSeparator );
+        if ( !lexer.hasMoreTokens() )
+            detectedOptions.addWithArgument( this, detectedArgument );
+        else {
+            while ( lexer.hasMoreTokens() )
+                detectedOptions.addWithArgument( this, lexer.nextToken() );
+        }
+    }
+
+    protected abstract void detectOptionArgument( OptionParser parser, ArgumentList arguments,
+        OptionSet detectedOptions );
+
+    @Override
+    protected final V convert( String argument ) {
+        return convertWith( converter, argument );
+    }
+
+    protected boolean canConvertArgument( String argument ) {
+        StringTokenizer lexer = new StringTokenizer( argument, valueSeparator );
+
+        try {
+            while ( lexer.hasMoreTokens() )
+                convert( lexer.nextToken() );
+            return true;
+        }
+        catch ( OptionException ignored ) {
+            return false;
+        }
+    }
+
+    protected boolean isArgumentOfNumberType() {
+        return converter != null && Number.class.isAssignableFrom( converter.valueType() );
+    }
+
+    public boolean acceptsArguments() {
+        return true;
+    }
+
+    public boolean requiresArgument() {
+        return argumentRequired;
+    }
+
+    public String argumentDescription() {
+        return argumentDescription;
+    }
+
+    public String argumentTypeIndicator() {
+        return argumentTypeIndicatorFrom( converter );
+    }
+
+    public List<V> defaultValues() {
+        return unmodifiableList( defaultValues );
+    }
+
+    @Override
+    public boolean equals( Object that ) {
+        if ( !super.equals( that ) )
+            return false;
+
+        ArgumentAcceptingOptionSpec<?> other = (ArgumentAcceptingOptionSpec<?>) that;
+        return requiresArgument() == other.requiresArgument();
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode() ^ ( argumentRequired ? 0 : 1 );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/ArgumentList.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import static jdk.internal.joptsimple.ParserRules.*;
+
+/**
+ * <p>Wrapper for an array of command line arguments.</p>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class ArgumentList {
+    private final String[] arguments;
+    private int currentIndex;
+
+    ArgumentList( String... arguments ) {
+        this.arguments = arguments.clone();
+    }
+
+    boolean hasMore() {
+        return currentIndex < arguments.length;
+    }
+
+    String next() {
+        return arguments[ currentIndex++ ];
+    }
+
+    String peek() {
+        return arguments[ currentIndex ];
+    }
+
+    void treatNextAsLongOption() {
+        if ( HYPHEN_CHAR != arguments[ currentIndex ].charAt( 0 ) )
+            arguments[ currentIndex ] = DOUBLE_HYPHEN + arguments[ currentIndex ];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/BuiltinHelpFormatter.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import jdk.internal.joptsimple.internal.Rows;
+import jdk.internal.joptsimple.internal.Strings;
+
+import static jdk.internal.joptsimple.ParserRules.*;
+import static jdk.internal.joptsimple.internal.Classes.*;
+import static jdk.internal.joptsimple.internal.Strings.*;
+
+/**
+ * <p>A help formatter that allows configuration of overall row width and column separator width.</p>
+ *
+ * <p>The formatter produces a two-column output. The left column is for the options, and the right column for their
+ * descriptions. The formatter will allow as much space as possible for the descriptions, by minimizing the option
+ * column's width, no greater than slightly less than half the overall desired width.</p>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class BuiltinHelpFormatter implements HelpFormatter {
+    private final Rows nonOptionRows;
+    private final Rows optionRows;
+
+    /**
+     * Makes a formatter with a pre-configured overall row width and column separator width.
+     */
+    BuiltinHelpFormatter() {
+        this( 80, 2 );
+    }
+
+    /**
+     * Makes a formatter with a given overall row width and column separator width.
+     *
+     * @param desiredOverallWidth how many characters wide to make the overall help display
+     * @param desiredColumnSeparatorWidth how many characters wide to make the separation between option column and
+     * description column
+     */
+    public BuiltinHelpFormatter( int desiredOverallWidth, int desiredColumnSeparatorWidth ) {
+        nonOptionRows = new Rows( desiredOverallWidth * 2, 0 );
+        optionRows = new Rows( desiredOverallWidth, desiredColumnSeparatorWidth );
+    }
+
+    public String format( Map<String, ? extends OptionDescriptor> options ) {
+        Comparator<OptionDescriptor> comparator =
+            new Comparator<OptionDescriptor>() {
+                public int compare( OptionDescriptor first, OptionDescriptor second ) {
+                    return first.options().iterator().next().compareTo( second.options().iterator().next() );
+                }
+            };
+
+        Set<OptionDescriptor> sorted = new TreeSet<OptionDescriptor>( comparator );
+        sorted.addAll( options.values() );
+
+        addRows( sorted );
+
+        return formattedHelpOutput();
+    }
+
+    private String formattedHelpOutput() {
+        StringBuilder formatted = new StringBuilder();
+        String nonOptionDisplay = nonOptionRows.render();
+        if ( !Strings.isNullOrEmpty( nonOptionDisplay ) )
+            formatted.append( nonOptionDisplay ).append( LINE_SEPARATOR );
+        formatted.append( optionRows.render() );
+
+        return formatted.toString();
+    }
+
+    private void addRows( Collection<? extends OptionDescriptor> options ) {
+        addNonOptionsDescription( options );
+
+        if ( options.isEmpty() )
+            optionRows.add( "No options specified", "" );
+        else {
+            addHeaders( options );
+            addOptions( options );
+        }
+
+        fitRowsToWidth();
+    }
+
+    private void addNonOptionsDescription( Collection<? extends OptionDescriptor> options ) {
+        OptionDescriptor nonOptions = findAndRemoveNonOptionsSpec( options );
+        if ( shouldShowNonOptionArgumentDisplay( nonOptions ) ) {
+            nonOptionRows.add( "Non-option arguments:", "" );
+            nonOptionRows.add(createNonOptionArgumentsDisplay(nonOptions), "");
+        }
+    }
+
+    private boolean shouldShowNonOptionArgumentDisplay( OptionDescriptor nonOptions ) {
+        return !Strings.isNullOrEmpty( nonOptions.description() )
+            || !Strings.isNullOrEmpty( nonOptions.argumentTypeIndicator() )
+            || !Strings.isNullOrEmpty( nonOptions.argumentDescription() );
+    }
+
+    private String createNonOptionArgumentsDisplay(OptionDescriptor nonOptions) {
+        StringBuilder buffer = new StringBuilder();
+        maybeAppendOptionInfo( buffer, nonOptions );
+        maybeAppendNonOptionsDescription( buffer, nonOptions );
+
+        return buffer.toString();
+    }
+
+    private void maybeAppendNonOptionsDescription( StringBuilder buffer, OptionDescriptor nonOptions ) {
+        buffer.append( buffer.length() > 0 && !Strings.isNullOrEmpty( nonOptions.description() ) ? " -- " : "" )
+            .append( nonOptions.description() );
+    }
+
+    private OptionDescriptor findAndRemoveNonOptionsSpec( Collection<? extends OptionDescriptor> options ) {
+        for ( Iterator<? extends OptionDescriptor> it = options.iterator(); it.hasNext(); ) {
+            OptionDescriptor next = it.next();
+            if ( next.representsNonOptions() ) {
+                it.remove();
+                return next;
+            }
+        }
+
+        throw new AssertionError( "no non-options argument spec" );
+    }
+
+    private void addHeaders( Collection<? extends OptionDescriptor> options ) {
+        if ( hasRequiredOption( options ) ) {
+            optionRows.add("Option (* = required)", "Description");
+            optionRows.add("---------------------", "-----------");
+        } else {
+            optionRows.add("Option", "Description");
+            optionRows.add("------", "-----------");
+        }
+    }
+
+    private boolean hasRequiredOption( Collection<? extends OptionDescriptor> options ) {
+        for ( OptionDescriptor each : options ) {
+            if ( each.isRequired() )
+                return true;
+        }
+
+        return false;
+    }
+
+    private void addOptions( Collection<? extends OptionDescriptor> options ) {
+        for ( OptionDescriptor each : options ) {
+            if ( !each.representsNonOptions() )
+                optionRows.add( createOptionDisplay( each ), createDescriptionDisplay( each ) );
+        }
+    }
+
+    private String createOptionDisplay( OptionDescriptor descriptor ) {
+        StringBuilder buffer = new StringBuilder( descriptor.isRequired() ? "* " : "" );
+
+        for ( Iterator<String> i = descriptor.options().iterator(); i.hasNext(); ) {
+            String option = i.next();
+            buffer.append( option.length() > 1 ? DOUBLE_HYPHEN : HYPHEN );
+            buffer.append( option );
+
+            if ( i.hasNext() )
+                buffer.append( ", " );
+        }
+
+        maybeAppendOptionInfo( buffer, descriptor );
+
+        return buffer.toString();
+    }
+
+    private void maybeAppendOptionInfo( StringBuilder buffer, OptionDescriptor descriptor ) {
+        String indicator = extractTypeIndicator( descriptor );
+        String description = descriptor.argumentDescription();
+        if ( indicator != null || !isNullOrEmpty( description ) )
+            appendOptionHelp( buffer, indicator, description, descriptor.requiresArgument() );
+    }
+
+    private String extractTypeIndicator( OptionDescriptor descriptor ) {
+        String indicator = descriptor.argumentTypeIndicator();
+
+        if ( !isNullOrEmpty( indicator ) && !String.class.getName().equals( indicator ) )
+            return shortNameOf( indicator );
+
+        return null;
+    }
+
+    private void appendOptionHelp( StringBuilder buffer, String typeIndicator, String description, boolean required ) {
+        if ( required )
+            appendTypeIndicator( buffer, typeIndicator, description, '<', '>' );
+        else
+            appendTypeIndicator( buffer, typeIndicator, description, '[', ']' );
+    }
+
+    private void appendTypeIndicator( StringBuilder buffer, String typeIndicator, String description,
+                                      char start, char end ) {
+        buffer.append( ' ' ).append( start );
+        if ( typeIndicator != null )
+            buffer.append( typeIndicator );
+
+        if ( !Strings.isNullOrEmpty( description ) ) {
+            if ( typeIndicator != null )
+                buffer.append( ": " );
+
+            buffer.append( description );
+        }
+
+        buffer.append( end );
+    }
+
+    private String createDescriptionDisplay( OptionDescriptor descriptor ) {
+        List<?> defaultValues = descriptor.defaultValues();
+        if ( defaultValues.isEmpty() )
+            return descriptor.description();
+
+        String defaultValuesDisplay = createDefaultValuesDisplay( defaultValues );
+        return ( descriptor.description() + ' ' + surround( "default: " + defaultValuesDisplay, '(', ')' ) ).trim();
+    }
+
+    private String createDefaultValuesDisplay( List<?> defaultValues ) {
+        return defaultValues.size() == 1 ? defaultValues.get( 0 ).toString() : defaultValues.toString();
+    }
+
+    private void fitRowsToWidth() {
+        nonOptionRows.fitToWidth();
+        optionRows.fitToWidth();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/HelpFormatter.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Map;
+
+/**
+ * <p>Represents objects charged with taking a set of option descriptions and producing some help text from them.</p>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public interface HelpFormatter {
+    /**
+     * Produces help text, given a set of option descriptors.
+     *
+     * @param options descriptors for the configured options of a parser
+     * @return text to be used as help
+     * @see OptionParser#printHelpOn(java.io.Writer)
+     * @see OptionParser#formatHelpWith(HelpFormatter)
+     */
+    String format( Map<String, ? extends OptionDescriptor> options );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/IllegalOptionSpecificationException.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import static java.util.Collections.*;
+
+/**
+ * Thrown when the option parser is asked to recognize an option with illegal characters in it.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class IllegalOptionSpecificationException extends OptionException {
+    private static final long serialVersionUID = -1L;
+
+    IllegalOptionSpecificationException( String option ) {
+        super( singletonList( option ) );
+    }
+
+    @Override
+    public String getMessage() {
+        return singleOptionMessage() + " is not a legal option character";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/MissingRequiredOptionException.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Collection;
+
+/**
+ * Thrown when an option is marked as required, but not specified on the command line.
+ *
+ * @author <a href="https://github.com/TC1">Emils Solmanis</a>
+ */
+class MissingRequiredOptionException extends OptionException {
+    private static final long serialVersionUID = -1L;
+
+    protected MissingRequiredOptionException( Collection<String> options ) {
+        super( options );
+    }
+
+    @Override
+    public String getMessage() {
+        return "Missing required option(s) " + multipleOptionMessage();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/MultipleArgumentsForOptionException.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Collection;
+
+/**
+ * Thrown when asking an {@link OptionSet} for a single argument of an option when many have been specified.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class MultipleArgumentsForOptionException extends OptionException {
+    private static final long serialVersionUID = -1L;
+
+    MultipleArgumentsForOptionException( Collection<String> options ) {
+        super( options );
+    }
+
+    @Override
+    public String getMessage() {
+        return "Found multiple arguments for option " + multipleOptionMessage() + ", but you asked for only one";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/NoArgumentOptionSpec.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Collection;
+import java.util.List;
+
+import static java.util.Collections.*;
+
+/**
+ * A specification for an option that does not accept arguments.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class NoArgumentOptionSpec extends AbstractOptionSpec<Void> {
+    NoArgumentOptionSpec( String option ) {
+        this( singletonList( option ), "" );
+    }
+
+    NoArgumentOptionSpec( Collection<String> options, String description ) {
+        super( options, description );
+    }
+
+    @Override
+    void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions,
+        String detectedArgument ) {
+
+        detectedOptions.add( this );
+    }
+
+    public boolean acceptsArguments() {
+        return false;
+    }
+
+    public boolean requiresArgument() {
+        return false;
+    }
+
+    public boolean isRequired() {
+        return false;
+    }
+
+    public String argumentDescription() {
+        return "";
+    }
+
+    public String argumentTypeIndicator() {
+        return "";
+    }
+
+    @Override
+    protected Void convert( String argument ) {
+        return null;
+    }
+
+    public List<Void> defaultValues() {
+        return emptyList();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/NonOptionArgumentSpec.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.List;
+
+import static java.util.Arrays.*;
+import static java.util.Collections.*;
+import static jdk.internal.joptsimple.internal.Reflection.*;
+
+/**
+ * <p>Specification of a command line's non-option arguments.</p>
+ *
+ * <p>Instances are returned from {@link OptionParser} methods to allow the formation of parser directives as
+ * sentences in a "fluent interface" language. For example:</p>
+ *
+ * <pre>
+ *   <code>
+ *   OptionParser parser = new OptionParser();
+ *   parser.nonOptions( "files to be processed" ).<strong>ofType( File.class )</strong>;
+ *   </code>
+ * </pre>
+ *
+ * <p>If no methods are invoked on an instance of this class, then that instance's option will treat the non-option
+ * arguments as {@link String}s.</p>
+ *
+ * @param <V> represents the type of the non-option arguments
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class NonOptionArgumentSpec<V> extends AbstractOptionSpec<V> {
+    static final String NAME = "[arguments]";
+
+    private ValueConverter<V> converter;
+    private String argumentDescription = "";
+
+    NonOptionArgumentSpec() {
+        this("");
+    }
+
+    NonOptionArgumentSpec( String description ) {
+        super( asList( NAME ), description );
+    }
+
+    /**
+     * <p>Specifies a type to which the non-option arguments are to be converted.</p>
+     *
+     * <p>JOpt Simple accepts types that have either:</p>
+     *
+     * <ol>
+     *   <li>a public static method called {@code valueOf} which accepts a single argument of type {@link String}
+     *   and whose return type is the same as the class on which the method is declared.  The {@code java.lang}
+     *   primitive wrapper classes have such methods.</li>
+     *
+     *   <li>a public constructor which accepts a single argument of type {@link String}.</li>
+     * </ol>
+     *
+     * <p>This class converts arguments using those methods in that order; that is, {@code valueOf} would be invoked
+     * before a one-{@link String}-arg constructor would.</p>
+     *
+     * <p>Invoking this method will trump any previous calls to this method or to
+     * {@link #withValuesConvertedBy(ValueConverter)}.</p>
+     *
+     * @param <T> represents the runtime class of the desired option argument type
+     * @param argumentType desired type of arguments to this spec's option
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     * @throws NullPointerException if the type is {@code null}
+     * @throws IllegalArgumentException if the type does not have the standard conversion methods
+     */
+    @SuppressWarnings( "unchecked" )
+    public <T> NonOptionArgumentSpec<T> ofType( Class<T> argumentType ) {
+        converter = (ValueConverter<V>) findConverter( argumentType );
+        return (NonOptionArgumentSpec<T>) this;
+    }
+
+    /**
+     * <p>Specifies a converter to use to translate non-option arguments into Java objects.  This is useful
+     * when converting to types that do not have the requisite factory method or constructor for
+     * {@link #ofType(Class)}.</p>
+     *
+     * <p>Invoking this method will trump any previous calls to this method or to {@link #ofType(Class)}.
+     *
+     * @param <T> represents the runtime class of the desired non-option argument type
+     * @param aConverter the converter to use
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     * @throws NullPointerException if the converter is {@code null}
+     */
+    @SuppressWarnings( "unchecked" )
+    public final <T> NonOptionArgumentSpec<T> withValuesConvertedBy( ValueConverter<T> aConverter ) {
+        if ( aConverter == null )
+            throw new NullPointerException( "illegal null converter" );
+
+        converter = (ValueConverter<V>) aConverter;
+        return (NonOptionArgumentSpec<T>) this;
+    }
+
+    /**
+     * <p>Specifies a description for the non-option arguments that this spec represents.  This description is used
+     * when generating help information about the parser.</p>
+     *
+     * @param description describes the nature of the argument of this spec's option
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     */
+    public NonOptionArgumentSpec<V> describedAs( String description ) {
+        argumentDescription = description;
+        return this;
+    }
+
+    @Override
+    protected final V convert( String argument ) {
+        return convertWith( converter, argument );
+    }
+
+    @Override
+    void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions,
+        String detectedArgument ) {
+
+        detectedOptions.addWithArgument( this, detectedArgument );
+    }
+
+    public List<?> defaultValues() {
+        return emptyList();
+    }
+
+    public boolean isRequired() {
+        return false;
+    }
+
+    public boolean acceptsArguments() {
+        return false;
+    }
+
+    public boolean requiresArgument() {
+        return false;
+    }
+
+    public String argumentDescription() {
+        return argumentDescription;
+    }
+
+    public String argumentTypeIndicator() {
+        return argumentTypeIndicatorFrom( converter );
+    }
+
+    public boolean representsNonOptions() {
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionArgumentConversionException.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Collection;
+
+/**
+ * Thrown when a problem occurs converting an argument of an option from {@link String} to another type.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class OptionArgumentConversionException extends OptionException {
+    private static final long serialVersionUID = -1L;
+
+    private final String argument;
+
+    OptionArgumentConversionException( Collection<String> options, String argument, Throwable cause ) {
+        super( options, cause );
+
+        this.argument = argument;
+    }
+
+    @Override
+    public String getMessage() {
+        return "Cannot parse argument '" + argument + "' of option " + multipleOptionMessage();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionDeclarer.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Collection;
+
+/**
+ * Trains the option parser. This interface aids integration with other code which may expose declaration of options but
+ * not actual command-line parsing.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ * @see OptionParser
+ */
+public interface OptionDeclarer {
+    /**
+     * Tells the parser to recognize the given option.
+     *
+     * <p>This method returns an instance of {@link OptionSpecBuilder} to allow the formation of parser directives
+     * as sentences in a fluent interface language. For example:</p>
+     *
+     * <pre><code>
+     *   OptionDeclarer parser = new OptionParser();
+     *   parser.<strong>accepts( "c" )</strong>.withRequiredArg().ofType( Integer.class );
+     * </code></pre>
+     *
+     * <p>If no methods are invoked on the returned {@link OptionSpecBuilder}, then the parser treats the option as
+     * accepting no argument.</p>
+     *
+     * @param option the option to recognize
+     * @return an object that can be used to flesh out more detail about the option
+     * @throws OptionException if the option contains illegal characters
+     * @throws NullPointerException if the option is {@code null}
+     */
+    OptionSpecBuilder accepts( String option );
+
+    /**
+     * Tells the parser to recognize the given option.
+     *
+     * @see #accepts(String)
+     * @param option the option to recognize
+     * @param description a string that describes the purpose of the option. This is used when generating help
+     * information about the parser.
+     * @return an object that can be used to flesh out more detail about the option
+     * @throws OptionException if the option contains illegal characters
+     * @throws NullPointerException if the option is {@code null}
+     */
+    OptionSpecBuilder accepts( String option, String description );
+
+    /**
+     * Tells the parser to recognize the given options, and treat them as synonymous.
+     *
+     * @see #accepts(String)
+     * @param options the options to recognize and treat as synonymous
+     * @return an object that can be used to flesh out more detail about the options
+     * @throws OptionException if any of the options contain illegal characters
+     * @throws NullPointerException if the option list or any of its elements are {@code null}
+     */
+    OptionSpecBuilder acceptsAll( Collection<String> options );
+
+    /**
+     * Tells the parser to recognize the given options, and treat them as synonymous.
+     *
+     * @see #acceptsAll(Collection)
+     * @param options the options to recognize and treat as synonymous
+     * @param description a string that describes the purpose of the option.  This is used when generating help
+     * information about the parser.
+     * @return an object that can be used to flesh out more detail about the options
+     * @throws OptionException if any of the options contain illegal characters
+     * @throws NullPointerException if the option list or any of its elements are {@code null}
+     * @throws IllegalArgumentException if the option list is empty
+     */
+    OptionSpecBuilder acceptsAll( Collection<String> options, String description );
+
+    /**
+     * Gives an object that represents an access point for non-option arguments on a command line.
+     *
+     * @return an object that can be used to flesh out more detail about the non-option arguments
+     */
+    NonOptionArgumentSpec<String> nonOptions();
+
+    /**
+     * Gives an object that represents an access point for non-option arguments on a command line.
+     *
+     * @see #nonOptions()
+     * @param description a string that describes the purpose of the non-option arguments. This is used when generating
+     * help information about the parser.
+     * @return an object that can be used to flesh out more detail about the non-option arguments
+     */
+    NonOptionArgumentSpec<String> nonOptions( String description );
+
+    /**
+     * Tells the parser whether or not to behave "POSIX-ly correct"-ly.
+     *
+     * @param setting {@code true} if the parser should behave "POSIX-ly correct"-ly
+     */
+    void posixlyCorrect( boolean setting );
+
+    /**
+     * <p>Tells the parser to treat unrecognized options as non-option arguments.</p>
+     *
+     * <p>If not called, then the parser raises an {@link OptionException} when it encounters an unrecognized
+     * option.</p>
+     */
+    void allowsUnrecognizedOptions();
+
+    /**
+     * Tells the parser either to recognize or ignore <kbd>"-W"</kbd>-style long options.
+     *
+     * @param recognize {@code true} if the parser is to recognize the special style of long options
+     */
+    void recognizeAlternativeLongOptions( boolean recognize );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionDescriptor.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Describes options that an option parser recognizes, in ways that might be useful to {@linkplain HelpFormatter
+ * help screens}.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public interface OptionDescriptor {
+    /**
+     * A set of options that are mutually synonymous.
+     *
+     * @return synonymous options
+     */
+    Collection<String> options();
+
+    /**
+     * Description of this option's purpose.
+     *
+     * @return a description for the option
+     */
+    String description();
+
+    /**
+     * What values will the option take if none are specified on the command line?
+     *
+     * @return any default values for the option
+     */
+    List<?> defaultValues();
+
+    /**
+     * Is this option {@linkplain ArgumentAcceptingOptionSpec#required() required} on a command line?
+     *
+     * @return whether the option is required
+     */
+    boolean isRequired();
+
+    /**
+     * Does this option {@linkplain ArgumentAcceptingOptionSpec accept arguments}?
+     *
+     * @return whether the option accepts arguments
+     */
+    boolean acceptsArguments();
+
+    /**
+     * Does this option {@linkplain OptionSpecBuilder#withRequiredArg() require an argument}?
+     *
+     * @return whether the option requires an argument
+     */
+    boolean requiresArgument();
+
+    /**
+     * Gives a short {@linkplain ArgumentAcceptingOptionSpec#describedAs(String) description} of the option's argument.
+     *
+     * @return a description for the option's argument
+     */
+    String argumentDescription();
+
+    /**
+     * Gives an indication of the {@linkplain ArgumentAcceptingOptionSpec#ofType(Class) expected type} of the option's
+     * argument.
+     *
+     * @return a description for the option's argument type
+     */
+    String argumentTypeIndicator();
+
+    /**
+     * Tells whether this object represents the non-option arguments of a command line.
+     *
+     * @return {@code true} if this represents non-option arguments
+     */
+    boolean representsNonOptions();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionException.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import static java.util.Collections.*;
+
+import static jdk.internal.joptsimple.internal.Strings.*;
+
+/**
+ * Thrown when a problem occurs during option parsing.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public abstract class OptionException extends RuntimeException {
+    private static final long serialVersionUID = -1L;
+
+    private final List<String> options = new ArrayList<String>();
+
+    protected OptionException( Collection<String> options ) {
+        this.options.addAll( options );
+    }
+
+    protected OptionException( Collection<String> options, Throwable cause ) {
+        super( cause );
+
+        this.options.addAll( options );
+    }
+
+    /**
+     * Gives the option being considered when the exception was created.
+     *
+     * @return the option being considered when the exception was created
+     */
+    public Collection<String> options() {
+        return unmodifiableCollection( options );
+    }
+
+    protected final String singleOptionMessage() {
+        return singleOptionMessage( options.get( 0 ) );
+    }
+
+    protected final String singleOptionMessage( String option ) {
+        return SINGLE_QUOTE + option + SINGLE_QUOTE;
+    }
+
+    protected final String multipleOptionMessage() {
+        StringBuilder buffer = new StringBuilder( "[" );
+
+        for ( Iterator<String> iter = options.iterator(); iter.hasNext(); ) {
+            buffer.append( singleOptionMessage( iter.next() ) );
+            if ( iter.hasNext() )
+                buffer.append( ", " );
+        }
+
+        buffer.append( ']' );
+
+        return buffer.toString();
+    }
+
+    static OptionException unrecognizedOption( String option ) {
+        return new UnrecognizedOptionException( option );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionMissingRequiredArgumentException.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Collection;
+
+/**
+ * Thrown when the option parser discovers an option that requires an argument, but that argument is missing.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class OptionMissingRequiredArgumentException extends OptionException {
+    private static final long serialVersionUID = -1L;
+
+    OptionMissingRequiredArgumentException( Collection<String> options ) {
+        super( options );
+    }
+
+    @Override
+    public String getMessage() {
+        return "Option " + multipleOptionMessage() + " requires an argument";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionParser.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import jdk.internal.joptsimple.internal.AbbreviationMap;
+import jdk.internal.joptsimple.util.KeyValuePair;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static java.util.Collections.*;
+import static jdk.internal.joptsimple.OptionException.*;
+import static jdk.internal.joptsimple.OptionParserState.*;
+import static jdk.internal.joptsimple.ParserRules.*;
+
+/**
+ * <p>Parses command line arguments, using a syntax that attempts to take from the best of POSIX {@code getopt()}
+ * and GNU {@code getopt_long()}.</p>
+ *
+ * <p>This parser supports short options and long options.</p>
+ *
+ * <ul>
+ *   <li><dfn>Short options</dfn> begin with a single hyphen ("<kbd>-</kbd>") followed by a single letter or digit,
+ *   or question mark ("<kbd>?</kbd>"), or dot ("<kbd>.</kbd>").</li>
+ *
+ *   <li>Short options can accept single arguments. The argument can be made required or optional. The option's
+ *   argument can occur:
+ *     <ul>
+ *       <li>in the slot after the option, as in <kbd>-d /tmp</kbd></li>
+ *       <li>right up against the option, as in <kbd>-d/tmp</kbd></li>
+ *       <li>right up against the option separated by an equals sign (<kbd>"="</kbd>), as in <kbd>-d=/tmp</kbd></li>
+ *     </ul>
+ *   To specify <em>n</em> arguments for an option, specify the option <em>n</em> times, once for each argument,
+ *   as in <kbd>-d /tmp -d /var -d /opt</kbd>; or, when using the
+ *   {@linkplain ArgumentAcceptingOptionSpec#withValuesSeparatedBy(char) "separated values"} clause of the "fluent
+ *   interface" (see below), give multiple values separated by a given character as a single argument to the
+ *   option.</li>
+ *
+ *   <li>Short options can be clustered, so that <kbd>-abc</kbd> is treated as <kbd>-a -b -c</kbd>. If a short option
+ *   in the cluster can accept an argument, the remaining characters are interpreted as the argument for that
+ *   option.</li>
+ *
+ *   <li>An argument consisting only of two hyphens (<kbd>"--"</kbd>) signals that the remaining arguments are to be
+ *   treated as non-options.</li>
+ *
+ *   <li>An argument consisting only of a single hyphen is considered a non-option argument (though it can be an
+ *   argument of an option). Many Unix programs treat single hyphens as stand-ins for the standard input or standard
+ *   output streams.</li>
+ *
+ *   <li><dfn>Long options</dfn> begin with two hyphens (<kbd>"--"</kbd>), followed by multiple letters, digits,
+ *   hyphens, question marks, or dots. A hyphen cannot be the first character of a long option specification when
+ *   configuring the parser.</li>
+ *
+ *   <li>You can abbreviate long options, so long as the abbreviation is unique.</li>
+ *
+ *   <li>Long options can accept single arguments.  The argument can be made required or optional.  The option's
+ *   argument can occur:
+ *     <ul>
+ *       <li>in the slot after the option, as in <kbd>--directory /tmp</kbd></li>
+ *       <li>right up against the option separated by an equals sign (<kbd>"="</kbd>), as in
+ *       <kbd>--directory=/tmp</kbd>
+ *     </ul>
+ *   Specify multiple arguments for a long option in the same manner as for short options (see above).</li>
+ *
+ *   <li>You can use a single hyphen (<kbd>"-"</kbd>) instead of a double hyphen (<kbd>"--"</kbd>) for a long
+ *   option.</li>
+ *
+ *   <li>The option <kbd>-W</kbd> is reserved.  If you tell the parser to {@linkplain
+ *   #recognizeAlternativeLongOptions(boolean) recognize alternative long options}, then it will treat, for example,
+ *   <kbd>-W foo=bar</kbd> as the long option <kbd>foo</kbd> with argument <kbd>bar</kbd>, as though you had written
+ *   <kbd>--foo=bar</kbd>.</li>
+ *
+ *   <li>You can specify <kbd>-W</kbd> as a valid short option, or use it as an abbreviation for a long option, but
+ *   {@linkplain #recognizeAlternativeLongOptions(boolean) recognizing alternative long options} will always supersede
+ *   this behavior.</li>
+ *
+ *   <li>You can specify a given short or long option multiple times on a single command line. The parser collects
+ *   any arguments specified for those options as a list.</li>
+ *
+ *   <li>If the parser detects an option whose argument is optional, and the next argument "looks like" an option,
+ *   that argument is not treated as the argument to the option, but as a potentially valid option. If, on the other
+ *   hand, the optional argument is typed as a derivative of {@link Number}, then that argument is treated as the
+ *   negative number argument of the option, even if the parser recognizes the corresponding numeric option.
+ *   For example:
+ *   <pre><code>
+ *     OptionParser parser = new OptionParser();
+ *     parser.accepts( "a" ).withOptionalArg().ofType( Integer.class );
+ *     parser.accepts( "2" );
+ *     OptionSet options = parser.parse( "-a", "-2" );
+ *   </code></pre>
+ *   In this case, the option set contains <kbd>"a"</kbd> with argument <kbd>-2</kbd>, not both <kbd>"a"</kbd> and
+ *   <kbd>"2"</kbd>. Swapping the elements in the <em>args</em> array gives the latter.</li>
+ * </ul>
+ *
+ * <p>There are two ways to tell the parser what options to recognize:</p>
+ *
+ * <ol>
+ *   <li>A "fluent interface"-style API for specifying options, available since version 2. Sentences in this fluent
+ *   interface language begin with a call to {@link #accepts(String) accepts} or {@link #acceptsAll(Collection)
+ *   acceptsAll} methods; calls on the ensuing chain of objects describe whether the options can take an argument,
+ *   whether the argument is required or optional, to what type arguments of the options should be converted if any,
+ *   etc. Since version 3, these calls return an instance of {@link OptionSpec}, which can subsequently be used to
+ *   retrieve the arguments of the associated option in a type-safe manner.</li>
+ *
+ *   <li>Since version 1, a more concise way of specifying short options has been to use the special {@linkplain
+ *   #OptionParser(String) constructor}. Arguments of options specified in this manner will be of type {@link String}.
+ *   Here are the rules for the format of the specification strings this constructor accepts:
+ *
+ *     <ul>
+ *       <li>Any letter or digit is treated as an option character.</li>
+ *
+ *       <li>An option character can be immediately followed by an asterisk (*) to indicate that the option is a
+ *       "help" option.</li>
+ *
+ *       <li>If an option character (with possible trailing asterisk) is followed by a single colon (<kbd>":"</kbd>),
+ *       then the option requires an argument.</li>
+ *
+ *       <li>If an option character (with possible trailing asterisk) is followed by two colons (<kbd>"::"</kbd>),
+ *       then the option accepts an optional argument.</li>
+ *
+ *       <li>Otherwise, the option character accepts no argument.</li>
+ *
+ *       <li>If the option specification string begins with a plus sign (<kbd>"+"</kbd>), the parser will behave
+ *       "POSIX-ly correct".</li>
+ *
+ *       <li>If the option specification string contains the sequence <kbd>"W;"</kbd> (capital W followed by a
+ *       semicolon), the parser will recognize the alternative form of long options.</li>
+ *     </ul>
+ *   </li>
+ * </ol>
+ *
+ * <p>Each of the options in a list of options given to {@link #acceptsAll(Collection) acceptsAll} is treated as a
+ * synonym of the others.  For example:
+ *   <pre>
+ *     <code>
+ *     OptionParser parser = new OptionParser();
+ *     parser.acceptsAll( asList( "w", "interactive", "confirmation" ) );
+ *     OptionSet options = parser.parse( "-w" );
+ *     </code>
+ *   </pre>
+ * In this case, <code>options.{@link OptionSet#has(String) has}</code> would answer {@code true} when given arguments
+ * <kbd>"w"</kbd>, <kbd>"interactive"</kbd>, and <kbd>"confirmation"</kbd>. The {@link OptionSet} would give the same
+ * responses to these arguments for its other methods as well.</p>
+ *
+ * <p>By default, as with GNU {@code getopt()}, the parser allows intermixing of options and non-options. If, however,
+ * the parser has been created to be "POSIX-ly correct", then the first argument that does not look lexically like an
+ * option, and is not a required argument of a preceding option, signals the end of options. You can still bind
+ * optional arguments to their options using the abutting (for short options) or <kbd>=</kbd> syntax.</p>
+ *
+ * <p>Unlike GNU {@code getopt()}, this parser does not honor the environment variable {@code POSIXLY_CORRECT}.
+ * "POSIX-ly correct" parsers are configured by either:</p>
+ *
+ * <ol>
+ *   <li>using the method {@link #posixlyCorrect(boolean)}, or</li>
+ *
+ *   <li>using the {@linkplain #OptionParser(String) constructor} with an argument whose first character is a plus sign
+ *   (<kbd>"+"</kbd>)</li>
+ * </ol>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ * @see <a href="http://www.gnu.org/software/libc/manual">The GNU C Library</a>
+ */
+public class OptionParser implements OptionDeclarer {
+    private final AbbreviationMap<AbstractOptionSpec<?>> recognizedOptions;
+    private final Map<Collection<String>, Set<OptionSpec<?>>> requiredIf;
+    private final Map<Collection<String>, Set<OptionSpec<?>>> requiredUnless;
+    private OptionParserState state;
+    private boolean posixlyCorrect;
+    private boolean allowsUnrecognizedOptions;
+    private HelpFormatter helpFormatter = new BuiltinHelpFormatter();
+
+    /**
+     * Creates an option parser that initially recognizes no options, and does not exhibit "POSIX-ly correct"
+     * behavior.
+     */
+    public OptionParser() {
+        recognizedOptions = new AbbreviationMap<AbstractOptionSpec<?>>();
+        requiredIf = new HashMap<Collection<String>, Set<OptionSpec<?>>>();
+        requiredUnless = new HashMap<Collection<String>, Set<OptionSpec<?>>>();
+        state = moreOptions( false );
+
+        recognize( new NonOptionArgumentSpec<String>() );
+    }
+
+    /**
+     * Creates an option parser and configures it to recognize the short options specified in the given string.
+     *
+     * Arguments of options specified this way will be of type {@link String}.
+     *
+     * @param optionSpecification an option specification
+     * @throws NullPointerException if {@code optionSpecification} is {@code null}
+     * @throws OptionException if the option specification contains illegal characters or otherwise cannot be
+     * recognized
+     */
+    public OptionParser( String optionSpecification ) {
+        this();
+
+        new OptionSpecTokenizer( optionSpecification ).configure( this );
+    }
+
+    public OptionSpecBuilder accepts( String option ) {
+        return acceptsAll( singletonList( option ) );
+    }
+
+    public OptionSpecBuilder accepts( String option, String description ) {
+        return acceptsAll( singletonList( option ), description );
+    }
+
+    public OptionSpecBuilder acceptsAll( Collection<String> options ) {
+        return acceptsAll( options, "" );
+    }
+
+    public OptionSpecBuilder acceptsAll( Collection<String> options, String description ) {
+        if ( options.isEmpty() )
+            throw new IllegalArgumentException( "need at least one option" );
+
+        ensureLegalOptions( options );
+
+        return new OptionSpecBuilder( this, options, description );
+    }
+
+    public NonOptionArgumentSpec<String> nonOptions() {
+        NonOptionArgumentSpec<String> spec = new NonOptionArgumentSpec<String>();
+
+        recognize( spec );
+
+        return spec;
+    }
+
+    public NonOptionArgumentSpec<String> nonOptions( String description ) {
+        NonOptionArgumentSpec<String> spec = new NonOptionArgumentSpec<String>( description );
+
+        recognize( spec );
+
+        return spec;
+    }
+
+    public void posixlyCorrect( boolean setting ) {
+        posixlyCorrect = setting;
+        state = moreOptions( setting );
+    }
+
+    boolean posixlyCorrect() {
+        return posixlyCorrect;
+    }
+
+    public void allowsUnrecognizedOptions() {
+        allowsUnrecognizedOptions = true;
+    }
+
+    boolean doesAllowsUnrecognizedOptions() {
+        return allowsUnrecognizedOptions;
+    }
+
+    public void recognizeAlternativeLongOptions( boolean recognize ) {
+        if ( recognize )
+            recognize( new AlternativeLongOptionSpec() );
+        else
+            recognizedOptions.remove( String.valueOf( RESERVED_FOR_EXTENSIONS ) );
+    }
+
+    void recognize( AbstractOptionSpec<?> spec ) {
+        recognizedOptions.putAll( spec.options(), spec );
+    }
+
+    /**
+     * Writes information about the options this parser recognizes to the given output sink.
+     *
+     * The output sink is flushed, but not closed.
+     *
+     * @param sink the sink to write information to
+     * @throws IOException if there is a problem writing to the sink
+     * @throws NullPointerException if {@code sink} is {@code null}
+     * @see #printHelpOn(Writer)
+     */
+    public void printHelpOn( OutputStream sink ) throws IOException {
+        printHelpOn( new OutputStreamWriter( sink ) );
+    }
+
+    /**
+     * Writes information about the options this parser recognizes to the given output sink.
+     *
+     * The output sink is flushed, but not closed.
+     *
+     * @param sink the sink to write information to
+     * @throws IOException if there is a problem writing to the sink
+     * @throws NullPointerException if {@code sink} is {@code null}
+     * @see #printHelpOn(OutputStream)
+     */
+    public void printHelpOn( Writer sink ) throws IOException {
+        sink.write( helpFormatter.format( recognizedOptions.toJavaUtilMap() ) );
+        sink.flush();
+    }
+
+    /**
+     * Tells the parser to use the given formatter when asked to {@linkplain #printHelpOn(java.io.Writer) print help}.
+     *
+     * @param formatter the formatter to use for printing help
+     * @throws NullPointerException if the formatter is {@code null}
+     */
+    public void formatHelpWith( HelpFormatter formatter ) {
+        if ( formatter == null )
+            throw new NullPointerException();
+
+        helpFormatter = formatter;
+    }
+
+    /**
+     * Retrieves all the options which have been configured for the parser.
+     *
+     * @return a {@link Map} containing all the configured options and their corresponding {@link OptionSpec}
+     */
+    public Map<String, OptionSpec<?>> recognizedOptions() {
+        return new HashMap<String, OptionSpec<?>>( recognizedOptions.toJavaUtilMap() );
+    }
+
+    /**
+     * Parses the given command line arguments according to the option specifications given to the parser.
+     *
+     * @param arguments arguments to parse
+     * @return an {@link OptionSet} describing the parsed options, their arguments, and any non-option arguments found
+     * @throws OptionException if problems are detected while parsing
+     * @throws NullPointerException if the argument list is {@code null}
+     */
+    public OptionSet parse( String... arguments ) {
+        ArgumentList argumentList = new ArgumentList( arguments );
+        OptionSet detected = new OptionSet( recognizedOptions.toJavaUtilMap() );
+        detected.add( recognizedOptions.get( NonOptionArgumentSpec.NAME ) );
+
+        while ( argumentList.hasMore() )
+            state.handleArgument( this, argumentList, detected );
+
+        reset();
+
+        ensureRequiredOptions( detected );
+
+        return detected;
+    }
+
+    private void ensureRequiredOptions( OptionSet options ) {
+        Collection<String> missingRequiredOptions = missingRequiredOptions( options );
+        boolean helpOptionPresent = isHelpOptionPresent( options );
+
+        if ( !missingRequiredOptions.isEmpty() && !helpOptionPresent )
+            throw new MissingRequiredOptionException( missingRequiredOptions );
+    }
+
+    private Collection<String> missingRequiredOptions( OptionSet options ) {
+        Collection<String> missingRequiredOptions = new HashSet<String>();
+
+        for ( AbstractOptionSpec<?> each : recognizedOptions.toJavaUtilMap().values() ) {
+            if ( each.isRequired() && !options.has( each ) )
+                missingRequiredOptions.addAll( each.options() );
+        }
+
+        for ( Map.Entry<Collection<String>, Set<OptionSpec<?>>> eachEntry : requiredIf.entrySet() ) {
+            AbstractOptionSpec<?> required = specFor( eachEntry.getKey().iterator().next() );
+
+            if ( optionsHasAnyOf( options, eachEntry.getValue() ) && !options.has( required ) ) {
+                missingRequiredOptions.addAll( required.options() );
+            }
+        }
+
+        for ( Map.Entry<Collection<String>, Set<OptionSpec<?>>> eachEntry : requiredUnless.entrySet() ) {
+            AbstractOptionSpec<?> required = specFor( eachEntry.getKey().iterator().next() );
+
+            if ( !optionsHasAnyOf( options, eachEntry.getValue() ) && !options.has( required ) ) {
+                missingRequiredOptions.addAll( required.options() );
+            }
+        }
+
+        return missingRequiredOptions;
+    }
+
+    private boolean optionsHasAnyOf( OptionSet options, Collection<OptionSpec<?>> specs ) {
+        for ( OptionSpec<?> each : specs ) {
+            if ( options.has( each ) )
+                return true;
+        }
+
+        return false;
+    }
+
+    private boolean isHelpOptionPresent( OptionSet options ) {
+        boolean helpOptionPresent = false;
+        for ( AbstractOptionSpec<?> each : recognizedOptions.toJavaUtilMap().values() ) {
+            if ( each.isForHelp() && options.has( each ) ) {
+                helpOptionPresent = true;
+                break;
+            }
+        }
+        return helpOptionPresent;
+    }
+
+    void handleLongOptionToken( String candidate, ArgumentList arguments, OptionSet detected ) {
+        KeyValuePair optionAndArgument = parseLongOptionWithArgument( candidate );
+
+        if ( !isRecognized( optionAndArgument.key ) )
+            throw unrecognizedOption( optionAndArgument.key );
+
+        AbstractOptionSpec<?> optionSpec = specFor( optionAndArgument.key );
+        optionSpec.handleOption( this, arguments, detected, optionAndArgument.value );
+    }
+
+    void handleShortOptionToken( String candidate, ArgumentList arguments, OptionSet detected ) {
+        KeyValuePair optionAndArgument = parseShortOptionWithArgument( candidate );
+
+        if ( isRecognized( optionAndArgument.key ) ) {
+            specFor( optionAndArgument.key ).handleOption( this, arguments, detected, optionAndArgument.value );
+        }
+        else
+            handleShortOptionCluster( candidate, arguments, detected );
+    }
+
+    private void handleShortOptionCluster( String candidate, ArgumentList arguments, OptionSet detected ) {
+        char[] options = extractShortOptionsFrom( candidate );
+        validateOptionCharacters( options );
+
+        for ( int i = 0; i < options.length; i++ ) {
+            AbstractOptionSpec<?> optionSpec = specFor( options[ i ] );
+
+            if ( optionSpec.acceptsArguments() && options.length > i + 1 ) {
+                String detectedArgument = String.valueOf( options, i + 1, options.length - 1 - i );
+                optionSpec.handleOption( this, arguments, detected, detectedArgument );
+                break;
+            }
+
+            optionSpec.handleOption( this, arguments, detected, null );
+        }
+    }
+
+    void handleNonOptionArgument( String candidate, ArgumentList arguments, OptionSet detectedOptions ) {
+        specFor( NonOptionArgumentSpec.NAME ).handleOption( this, arguments, detectedOptions, candidate );
+    }
+
+    void noMoreOptions() {
+        state = OptionParserState.noMoreOptions();
+    }
+
+    boolean looksLikeAnOption( String argument ) {
+        return isShortOptionToken( argument ) || isLongOptionToken( argument );
+    }
+
+    boolean isRecognized( String option ) {
+        return recognizedOptions.contains( option );
+    }
+
+    void requiredIf( Collection<String> precedentSynonyms, String required ) {
+        requiredIf( precedentSynonyms, specFor( required ) );
+    }
+
+    void requiredIf( Collection<String> precedentSynonyms, OptionSpec<?> required ) {
+        putRequiredOption( precedentSynonyms, required, requiredIf );
+    }
+
+    void requiredUnless( Collection<String> precedentSynonyms, String required ) {
+        requiredUnless( precedentSynonyms, specFor( required ) );
+    }
+
+    void requiredUnless( Collection<String> precedentSynonyms, OptionSpec<?> required ) {
+        putRequiredOption( precedentSynonyms, required, requiredUnless );
+    }
+
+    private void putRequiredOption( Collection<String> precedentSynonyms, OptionSpec<?> required,
+        Map<Collection<String>, Set<OptionSpec<?>>> target ) {
+
+        for ( String each : precedentSynonyms ) {
+            AbstractOptionSpec<?> spec = specFor( each );
+            if ( spec == null )
+                throw new UnconfiguredOptionException( precedentSynonyms );
+        }
+
+        Set<OptionSpec<?>> associated = target.get( precedentSynonyms );
+        if ( associated == null ) {
+            associated = new HashSet<OptionSpec<?>>();
+            target.put( precedentSynonyms, associated );
+        }
+
+        associated.add( required );
+    }
+
+    private AbstractOptionSpec<?> specFor( char option ) {
+        return specFor( String.valueOf( option ) );
+    }
+
+    private AbstractOptionSpec<?> specFor( String option ) {
+        return recognizedOptions.get( option );
+    }
+
+    private void reset() {
+        state = moreOptions( posixlyCorrect );
+    }
+
+    private static char[] extractShortOptionsFrom( String argument ) {
+        char[] options = new char[ argument.length() - 1 ];
+        argument.getChars( 1, argument.length(), options, 0 );
+
+        return options;
+    }
+
+    private void validateOptionCharacters( char[] options ) {
+        for ( char each : options ) {
+            String option = String.valueOf( each );
+
+            if ( !isRecognized( option ) )
+                throw unrecognizedOption( option );
+
+            if ( specFor( option ).acceptsArguments() )
+                return;
+        }
+    }
+
+    private static KeyValuePair parseLongOptionWithArgument( String argument ) {
+        return KeyValuePair.valueOf( argument.substring( 2 ) );
+    }
+
+    private static KeyValuePair parseShortOptionWithArgument( String argument ) {
+        return KeyValuePair.valueOf( argument.substring( 1 ) );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionParserState.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import static jdk.internal.joptsimple.ParserRules.*;
+
+/**
+ * Abstraction of parser state; mostly serves to model how a parser behaves depending on whether end-of-options
+ * has been detected.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+abstract class OptionParserState {
+    static OptionParserState noMoreOptions() {
+        return new OptionParserState() {
+            @Override
+            protected void handleArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) {
+                parser.handleNonOptionArgument( arguments.next(), arguments, detectedOptions );
+            }
+        };
+    }
+
+    static OptionParserState moreOptions( final boolean posixlyCorrect ) {
+        return new OptionParserState() {
+            @Override
+            protected void handleArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) {
+                String candidate = arguments.next();
+                try {
+                    if ( isOptionTerminator( candidate ) ) {
+                        parser.noMoreOptions();
+                        return;
+                    } else if ( isLongOptionToken( candidate ) ) {
+                        parser.handleLongOptionToken( candidate, arguments, detectedOptions );
+                        return;
+                    } else if ( isShortOptionToken( candidate ) ) {
+                        parser.handleShortOptionToken( candidate, arguments, detectedOptions );
+                        return;
+                    }
+                } catch ( UnrecognizedOptionException e ) {
+                    if ( !parser.doesAllowsUnrecognizedOptions() )
+                        throw e;
+                }
+
+                if ( posixlyCorrect )
+                    parser.noMoreOptions();
+
+                parser.handleNonOptionArgument( candidate, arguments, detectedOptions );
+            }
+        };
+    }
+
+    protected abstract void handleArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionSet.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.*;
+
+import static java.util.Collections.*;
+
+import static jdk.internal.joptsimple.internal.Objects.*;
+
+/**
+ * Representation of a group of detected command line options, their arguments, and non-option arguments.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSet {
+    private final List<OptionSpec<?>> detectedSpecs;
+    private final Map<String, AbstractOptionSpec<?>> detectedOptions;
+    private final Map<AbstractOptionSpec<?>, List<String>> optionsToArguments;
+    private final Map<String, AbstractOptionSpec<?>> recognizedSpecs;
+    private final Map<String, List<?>> defaultValues;
+
+    /*
+     * Package-private because clients don't create these.
+     */
+    OptionSet( Map<String, AbstractOptionSpec<?>> recognizedSpecs ) {
+        detectedSpecs = new ArrayList<OptionSpec<?>>();
+        detectedOptions = new HashMap<String, AbstractOptionSpec<?>>();
+        optionsToArguments = new IdentityHashMap<AbstractOptionSpec<?>, List<String>>();
+        defaultValues = defaultValues( recognizedSpecs );
+        this.recognizedSpecs = recognizedSpecs;
+    }
+
+    /**
+     * Tells whether any options were detected.
+     *
+     * @return {@code true} if any options were detected
+     */
+    public boolean hasOptions() {
+        return !detectedOptions.isEmpty();
+    }
+
+    /**
+     * Tells whether the given option was detected.
+     *
+     * @param option the option to search for
+     * @return {@code true} if the option was detected
+     * @see #has(OptionSpec)
+     */
+    public boolean has( String option ) {
+        return detectedOptions.containsKey( option );
+    }
+
+    /**
+     * Tells whether the given option was detected.
+     *
+     * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+     *
+     * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[])} default argument value}
+     * for an option does not cause this method to return {@code true} if the option was not detected on the command
+     * line.</p>
+     *
+     * @param option the option to search for
+     * @return {@code true} if the option was detected
+     * @see #has(String)
+     */
+    public boolean has( OptionSpec<?> option ) {
+        return optionsToArguments.containsKey( option );
+    }
+
+    /**
+     * Tells whether there are any arguments associated with the given option.
+     *
+     * @param option the option to search for
+     * @return {@code true} if the option was detected and at least one argument was detected for the option
+     * @see #hasArgument(OptionSpec)
+     */
+    public boolean hasArgument( String option ) {
+        AbstractOptionSpec<?> spec = detectedOptions.get( option );
+        return spec != null && hasArgument( spec );
+    }
+
+    /**
+     * Tells whether there are any arguments associated with the given option.
+     *
+     * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+     *
+     * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value}
+     * for an option does not cause this method to return {@code true} if the option was not detected on the command
+     * line, or if the option can take an optional argument but did not have one on the command line.</p>
+     *
+     * @param option the option to search for
+     * @return {@code true} if the option was detected and at least one argument was detected for the option
+     * @throws NullPointerException if {@code option} is {@code null}
+     * @see #hasArgument(String)
+     */
+    public boolean hasArgument( OptionSpec<?> option ) {
+        ensureNotNull( option );
+
+        List<String> values = optionsToArguments.get( option );
+        return values != null && !values.isEmpty();
+    }
+
+    /**
+     * Gives the argument associated with the given option.  If the option was given an argument type, the argument
+     * will take on that type; otherwise, it will be a {@link String}.
+     *
+     * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value}
+     * for an option will cause this method to return that default value even if the option was not detected on the
+     * command line, or if the option can take an optional argument but did not have one on the command line.</p>
+     *
+     * @param option the option to search for
+     * @return the argument of the given option; {@code null} if no argument is present, or that option was not
+     * detected
+     * @throws NullPointerException if {@code option} is {@code null}
+     * @throws OptionException if more than one argument was detected for the option
+     */
+    public Object valueOf( String option ) {
+        ensureNotNull( option );
+
+        AbstractOptionSpec<?> spec = detectedOptions.get( option );
+        if ( spec == null ) {
+            List<?> defaults = defaultValuesFor( option );
+            return defaults.isEmpty() ? null : defaults.get( 0 );
+        }
+
+        return valueOf( spec );
+    }
+
+    /**
+     * Gives the argument associated with the given option.
+     *
+     * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+     *
+     * @param <V> represents the type of the arguments the given option accepts
+     * @param option the option to search for
+     * @return the argument of the given option; {@code null} if no argument is present, or that option was not
+     * detected
+     * @throws OptionException if more than one argument was detected for the option
+     * @throws NullPointerException if {@code option} is {@code null}
+     * @throws ClassCastException if the arguments of this option are not of the expected type
+     */
+    public <V> V valueOf( OptionSpec<V> option ) {
+        ensureNotNull( option );
+
+        List<V> values = valuesOf( option );
+        switch ( values.size() ) {
+            case 0:
+                return null;
+            case 1:
+                return values.get( 0 );
+            default:
+                throw new MultipleArgumentsForOptionException( option.options() );
+        }
+    }
+
+    /**
+     * <p>Gives any arguments associated with the given option.  If the option was given an argument type, the
+     * arguments will take on that type; otherwise, they will be {@link String}s.</p>
+     *
+     * @param option the option to search for
+     * @return the arguments associated with the option, as a list of objects of the type given to the arguments; an
+     * empty list if no such arguments are present, or if the option was not detected
+     * @throws NullPointerException if {@code option} is {@code null}
+     */
+    public List<?> valuesOf( String option ) {
+        ensureNotNull( option );
+
+        AbstractOptionSpec<?> spec = detectedOptions.get( option );
+        return spec == null ? defaultValuesFor( option ) : valuesOf( spec );
+    }
+
+    /**
+     * <p>Gives any arguments associated with the given option.  If the option was given an argument type, the
+     * arguments will take on that type; otherwise, they will be {@link String}s.</p>
+     *
+     * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+     *
+     * @param <V> represents the type of the arguments the given option accepts
+     * @param option the option to search for
+     * @return the arguments associated with the option; an empty list if no such arguments are present, or if the
+     * option was not detected
+     * @throws NullPointerException if {@code option} is {@code null}
+     * @throws OptionException if there is a problem converting the option's arguments to the desired type; for
+     * example, if the type does not implement a correct conversion constructor or method
+     */
+    public <V> List<V> valuesOf( OptionSpec<V> option ) {
+        ensureNotNull( option );
+
+        List<String> values = optionsToArguments.get( option );
+        if ( values == null || values.isEmpty() )
+            return defaultValueFor( option );
+
+        AbstractOptionSpec<V> spec = (AbstractOptionSpec<V>) option;
+        List<V> convertedValues = new ArrayList<V>();
+        for ( String each : values )
+            convertedValues.add( spec.convert( each ) );
+
+        return unmodifiableList( convertedValues );
+    }
+
+    /**
+     * Gives the set of options that were detected, in the form of {@linkplain OptionSpec}s, in the order in which the
+     * options were found on the command line.
+     *
+     * @return the set of detected command line options
+     */
+    public List<OptionSpec<?>> specs() {
+        List<OptionSpec<?>> specs = detectedSpecs;
+        specs.remove( detectedOptions.get( NonOptionArgumentSpec.NAME ) );
+
+        return unmodifiableList( specs );
+    }
+
+    /**
+     * Gives all declared options as a map of string to {@linkplain OptionSpec}.
+     *
+     * @return the declared options as a map
+     */
+    public Map<OptionSpec<?>, List<?>> asMap() {
+        Map<OptionSpec<?>, List<?>> map = new HashMap<OptionSpec<?>, List<?>>();
+        for ( AbstractOptionSpec<?> spec : recognizedSpecs.values() )
+            if ( !spec.representsNonOptions() )
+                map.put( spec, valuesOf( spec ) );
+        return unmodifiableMap( map );
+    }
+
+    /**
+     * @return the detected non-option arguments
+     */
+    public List<?> nonOptionArguments() {
+        return unmodifiableList( valuesOf( detectedOptions.get( NonOptionArgumentSpec.NAME ) ) );
+    }
+
+    void add( AbstractOptionSpec<?> spec ) {
+        addWithArgument( spec, null );
+    }
+
+    void addWithArgument( AbstractOptionSpec<?> spec, String argument ) {
+        detectedSpecs.add( spec );
+
+        for ( String each : spec.options() )
+            detectedOptions.put( each, spec );
+
+        List<String> optionArguments = optionsToArguments.get( spec );
+
+        if ( optionArguments == null ) {
+            optionArguments = new ArrayList<String>();
+            optionsToArguments.put( spec, optionArguments );
+        }
+
+        if ( argument != null )
+            optionArguments.add( argument );
+    }
+
+    @Override
+    public boolean equals( Object that ) {
+        if ( this == that )
+            return true;
+
+        if ( that == null || !getClass().equals( that.getClass() ) )
+            return false;
+
+        OptionSet other = (OptionSet) that;
+        Map<AbstractOptionSpec<?>, List<String>> thisOptionsToArguments =
+            new HashMap<AbstractOptionSpec<?>, List<String>>( optionsToArguments );
+        Map<AbstractOptionSpec<?>, List<String>> otherOptionsToArguments =
+            new HashMap<AbstractOptionSpec<?>, List<String>>( other.optionsToArguments );
+        return detectedOptions.equals( other.detectedOptions )
+            && thisOptionsToArguments.equals( otherOptionsToArguments );
+    }
+
+    @Override
+    public int hashCode() {
+        Map<AbstractOptionSpec<?>, List<String>> thisOptionsToArguments =
+            new HashMap<AbstractOptionSpec<?>, List<String>>( optionsToArguments );
+        return detectedOptions.hashCode() ^ thisOptionsToArguments.hashCode();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private <V> List<V> defaultValuesFor( String option ) {
+        if ( defaultValues.containsKey( option ) )
+            return (List<V>) defaultValues.get( option );
+
+        return emptyList();
+    }
+
+    private <V> List<V> defaultValueFor( OptionSpec<V> option ) {
+        return defaultValuesFor( option.options().iterator().next() );
+    }
+
+    private static Map<String, List<?>> defaultValues( Map<String, AbstractOptionSpec<?>> recognizedSpecs ) {
+        Map<String, List<?>> defaults = new HashMap<String, List<?>>();
+        for ( Map.Entry<String, AbstractOptionSpec<?>> each : recognizedSpecs.entrySet() )
+            defaults.put( each.getKey(), each.getValue().defaultValues() );
+        return defaults;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionSpec.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Describes options that an option parser recognizes.
+ *
+ * <p>Instances of this interface are returned by the "fluent interface" methods to allow retrieval of option arguments
+ * in a type-safe manner.  Here's an example:</p>
+ *
+ * <pre><code>
+ *     OptionParser parser = new OptionParser();
+ *     <strong>OptionSpec&lt;Integer&gt;</strong> count =
+ *         parser.accepts( "count" ).withRequiredArg().ofType( Integer.class );
+ *     OptionSet options = parser.parse( "--count", "2" );
+ *     assert options.has( count );
+ *     int countValue = options.valueOf( count );
+ *     assert countValue == count.value( options );
+ *     List&lt;Integer&gt; countValues = options.valuesOf( count );
+ *     assert countValues.equals( count.values( options ) );
+ * </code></pre>
+ *
+ * @param <V> represents the type of the arguments this option accepts
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public interface OptionSpec<V> {
+    /**
+     * Gives any arguments associated with the given option in the given set of detected options.
+     *
+     * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value}
+     * for this option will cause this method to return that default value even if this option was not detected on the
+     * command line, or if this option can take an optional argument but did not have one on the command line.</p>
+     *
+     * @param detectedOptions the detected options to search in
+     * @return the arguments associated with this option; an empty list if no such arguments are present, or if this
+     * option was not detected
+     * @throws OptionException if there is a problem converting this option's arguments to the desired type; for
+     * example, if the type does not implement a correct conversion constructor or method
+     * @throws NullPointerException if {@code detectedOptions} is {@code null}
+     * @see OptionSet#valuesOf(OptionSpec)
+     */
+    List<V> values( OptionSet detectedOptions );
+
+    /**
+     * Gives the argument associated with the given option in the given set of detected options.
+     *
+     * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value}
+     * for this option will cause this method to return that default value even if this option was not detected on the
+     * command line, or if this option can take an optional argument but did not have one on the command line.</p>
+     *
+     * @param detectedOptions the detected options to search in
+     * @return the argument of the this option; {@code null} if no argument is present, or that option was not detected
+     * @throws OptionException if more than one argument was detected for the option
+     * @throws NullPointerException if {@code detectedOptions} is {@code null}
+     * @throws ClassCastException if the arguments of this option are not of the expected type
+     * @see OptionSet#valueOf(OptionSpec)
+     */
+    V value( OptionSet detectedOptions );
+
+    /**
+     * @return the string representations of this option
+     */
+    Collection<String> options();
+
+    /**
+     * Tells whether this option is designated as a "help" option. The presence of a "help" option on a command line
+     * means that missing "required" options will not cause parsing to fail.
+     *
+     * @return whether this option is designated as a "help" option
+     */
+    boolean isForHelp();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionSpecBuilder.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Allows callers to specify whether a given option accepts arguments (required or optional).
+ *
+ * <p>Instances are returned from {@link OptionParser#accepts(String)} to allow the formation of parser directives as
+ * sentences in a "fluent interface" language.  For example:</p>
+ *
+ * <pre><code>
+ *   OptionParser parser = new OptionParser();
+ *   parser.accepts( "c" ).<strong>withRequiredArg()</strong>.ofType( Integer.class );
+ * </code></pre>
+ *
+ * <p>If no methods are invoked on an instance of this class, then that instance's option will accept no argument.</p>
+ *
+ * <p>Note that you should not use the fluent interface clauses in a way that would defeat the typing of option
+ * arguments:</p>
+ *
+ * <pre><code>
+ *   OptionParser parser = new OptionParser();
+ *   ArgumentAcceptingOptionSpec&lt;String&gt; optionC =
+ *       parser.accepts( "c" ).withRequiredArg();
+ *   <strong>optionC.ofType( Integer.class );  // DON'T THROW AWAY THE TYPE!</strong>
+ *
+ *   String value = parser.parse( "-c", "2" ).valueOf( optionC );  // ClassCastException
+ * </code></pre>
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+public class OptionSpecBuilder extends NoArgumentOptionSpec {
+    private final OptionParser parser;
+
+    OptionSpecBuilder( OptionParser parser, Collection<String> options, String description ) {
+        super( options, description );
+
+        this.parser = parser;
+        attachToParser();
+    }
+
+    private void attachToParser() {
+        parser.recognize( this );
+    }
+
+    /**
+     * Informs an option parser that this builder's option requires an argument.
+     *
+     * @return a specification for the option
+     */
+    public ArgumentAcceptingOptionSpec<String> withRequiredArg() {
+        ArgumentAcceptingOptionSpec<String> newSpec =
+            new RequiredArgumentOptionSpec<String>( options(), description() );
+        parser.recognize( newSpec );
+
+        return newSpec;
+    }
+
+    /**
+     * Informs an option parser that this builder's option accepts an optional argument.
+     *
+     * @return a specification for the option
+     */
+    public ArgumentAcceptingOptionSpec<String> withOptionalArg() {
+        ArgumentAcceptingOptionSpec<String> newSpec =
+            new OptionalArgumentOptionSpec<String>( options(), description() );
+        parser.recognize( newSpec );
+
+        return newSpec;
+    }
+
+    /**
+     * <p>Informs an option parser that this builder's option is required if the given option is present on the command
+     * line.</p>
+     *
+     * <p>For a given option, you <em>should not</em> mix this with {@link #requiredUnless(String, String...)
+     * requiredUnless} to avoid conflicts.</p>
+     *
+     * @param dependent an option whose presence on a command line makes this builder's option required
+     * @param otherDependents other options whose presence on a command line makes this builder's option required
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     * @throws OptionException if any of the dependent options haven't been configured in the parser yet
+     */
+    public OptionSpecBuilder requiredIf( String dependent, String... otherDependents ) {
+        List<String> dependents = validatedDependents( dependent, otherDependents );
+        for ( String each : dependents ) {
+            parser.requiredIf( options(), each );
+        }
+
+        return this;
+    }
+
+    /**
+     * <p>Informs an option parser that this builder's option is required if the given option is present on the command
+     * line.</p>
+     *
+     * <p>For a given option, you <em>should not</em> mix this with {@link #requiredUnless(OptionSpec, OptionSpec[])
+     * requiredUnless} to avoid conflicts.</p>
+     *
+     * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+     *
+     * @param dependent the option whose presence on a command line makes this builder's option required
+     * @param otherDependents other options whose presence on a command line makes this builder's option required
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     */
+    public OptionSpecBuilder requiredIf( OptionSpec<?> dependent, OptionSpec<?>... otherDependents ) {
+        parser.requiredIf( options(), dependent );
+        for ( OptionSpec<?> each : otherDependents )
+            parser.requiredIf( options(), each );
+
+        return this;
+    }
+
+    /**
+     * <p>Informs an option parser that this builder's option is required if the given option is absent on the command
+     * line.</p>
+     *
+     * <p>For a given option, you <em>should not</em> mix this with {@link #requiredIf(OptionSpec, OptionSpec[])
+     * requiredIf} to avoid conflicts.</p>
+     *
+     * @param dependent an option whose absence on a command line makes this builder's option required
+     * @param otherDependents other options whose absence on a command line makes this builder's option required
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     * @throws OptionException if any of the dependent options haven't been configured in the parser yet
+     */
+    public OptionSpecBuilder requiredUnless( String dependent, String... otherDependents ) {
+        List<String> dependents = validatedDependents( dependent, otherDependents );
+        for ( String each : dependents ) {
+            parser.requiredUnless( options(), each );
+        }
+        return this;
+    }
+
+    /**
+     * <p>Informs an option parser that this builder's option is required if the given option is absent on the command
+     * line.</p>
+     *
+     * <p>For a given option, you <em>should not</em> mix this with {@link #requiredIf(OptionSpec, OptionSpec[])
+     * requiredIf} to avoid conflicts.</p>
+     *
+     * <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
+     *
+     * @param dependent the option whose absence on a command line makes this builder's option required
+     * @param otherDependents other options whose absence on a command line makes this builder's option required
+     * @return self, so that the caller can add clauses to the fluent interface sentence
+     */
+    public OptionSpecBuilder requiredUnless( OptionSpec<?> dependent, OptionSpec<?>... otherDependents ) {
+        parser.requiredUnless( options(), dependent );
+        for ( OptionSpec<?> each : otherDependents )
+            parser.requiredUnless( options(), each );
+
+        return this;
+    }
+
+    private List<String> validatedDependents( String dependent, String... otherDependents ) {
+        List<String> dependents = new ArrayList<String>();
+        dependents.add( dependent );
+        Collections.addAll( dependents, otherDependents );
+
+        for ( String each : dependents ) {
+            if ( !parser.isRecognized( each ) )
+                throw new UnconfiguredOptionException( each );
+        }
+
+        return dependents;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionSpecTokenizer.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.NoSuchElementException;
+
+import static jdk.internal.joptsimple.ParserRules.*;
+
+/**
+ * Tokenizes a short option specification string.
+ *
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class OptionSpecTokenizer {
+    private static final char POSIXLY_CORRECT_MARKER = '+';
+    private static final char HELP_MARKER = '*';
+
+    private String specification;
+    private int index;
+
+    OptionSpecTokenizer( String specification ) {
+        if ( specification == null )
+            throw new NullPointerException( "null option specification" );
+
+        this.specification = specification;
+    }
+
+    boolean hasMore() {
+        return index < specification.length();
+    }
+
+    AbstractOptionSpec<?> next() {
+        if ( !hasMore() )
+            throw new NoSuchElementException();
+
+
+        String optionCandidate = String.valueOf( specification.charAt( index ) );
+        index++;
+
+        AbstractOptionSpec<?> spec;
+        if ( RESERVED_FOR_EXTENSIONS.equals( optionCandidate ) ) {
+            spec = handleReservedForExtensionsToken();
+
+            if ( spec != null )
+                return spec;
+        }
+
+        ensureLegalOption( optionCandidate );
+
+        if ( hasMore() ) {
+            boolean forHelp = false;
+            if ( specification.charAt( index ) == HELP_MARKER ) {
+                forHelp = true;
+                ++index;
+            }
+            spec = hasMore() && specification.charAt( index ) == ':'
+                ? handleArgumentAcceptingOption( optionCandidate )
+                : new NoArgumentOptionSpec( optionCandidate );
+            if ( forHelp )
+                spec.forHelp();
+        } else
+            spec = new NoArgumentOptionSpec( optionCandidate );
+
+        return spec;
+    }
+
+    void configure( OptionParser parser ) {
+        adjustForPosixlyCorrect( parser );
+
+        while ( hasMore() )
+            parser.recognize( next() );
+    }
+
+    private void adjustForPosixlyCorrect( OptionParser parser ) {
+        if ( POSIXLY_CORRECT_MARKER == specification.charAt( 0 ) ) {
+            parser.posixlyCorrect( true );
+            specification = specification.substring( 1 );
+        }
+    }
+
+    private AbstractOptionSpec<?> handleReservedForExtensionsToken() {
+        if ( !hasMore() )
+            return new NoArgumentOptionSpec( RESERVED_FOR_EXTENSIONS );
+
+        if ( specification.charAt( index ) == ';' ) {
+            ++index;
+            return new AlternativeLongOptionSpec();
+        }
+
+        return null;
+    }
+
+    private AbstractOptionSpec<?> handleArgumentAcceptingOption( String candidate ) {
+        index++;
+
+        if ( hasMore() && specification.charAt( index ) == ':' ) {
+            index++;
+            return new OptionalArgumentOptionSpec<String>( candidate );
+        }
+
+        return new RequiredArgumentOptionSpec<String>( candidate );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionalArgumentOptionSpec.java	Tue Feb 02 12:12:52 2016 -0800
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2004-2014 Paul R. Holser, Jr.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package jdk.internal.joptsimple;
+
+import java.util.Collection;
+
+/**
+ * Specification of an option that accepts an optional argument.
+ *
+ * @param <V> represents the type of the arguments this option accepts
+ * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
+ */
+class OptionalArgumentOptionSpec<V> extends ArgumentAcceptingOptionSpec<V> {
+    OptionalArgumentOptionSpec( String option ) {
+        super( option, false );
+    }
+
+    OptionalArgumentOptionSpec( Collection<String> options, String description ) {
+        super( options, false, description );
+    }
+
+    @Override
+    protected void detectOptionArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) {
+        if ( arguments.hasMore() ) {
+            String nextArgument = arguments.peek();
+
+            if ( !parser.looksLikeAnOption( nextArgument ) )
+                handleOptionArgument( parser, detectedOptions, arguments );
+            else if ( isArgumentOfNumberType() && canConvertArgument( nextArgument ) )
+                addArguments( detectedOptions, arguments.next() );