changeset 15005:b12b4d46866d

Merge
author amurillo
date Thu, 07 Jul 2016 18:35:29 +0000
parents 67d03b02b35a ecacc79ccd57
children 848c94ca6394
files src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmGlobalPool.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmModulePool.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ControlFlow.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ForNameFolding.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ReflectionOptimizer.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/Utils.java test/sun/security/tools/keytool/printssl.sh test/tools/jlink/JLinkOptimTest.java test/tools/jlink/asmplugin/AddForgetResourcesTest.java test/tools/jlink/asmplugin/AsmPluginTestBase.java test/tools/jlink/asmplugin/BasicTest.java test/tools/jlink/asmplugin/IdentityPluginTest.java test/tools/jlink/asmplugin/NegativeTest.java test/tools/jlink/asmplugin/PackageMappingTest.java test/tools/jlink/asmplugin/SortingTest.java test/tools/jlink/asmplugin/VisitorTest.java
diffstat 123 files changed, 16178 insertions(+), 9385 deletions(-) [+]
line wrap: on
line diff
--- a/make/gensrc/GensrcVarHandles.gmk	Thu Jul 07 18:21:23 2016 +0000
+++ b/make/gensrc/GensrcVarHandles.gmk	Thu Jul 07 18:35:29 2016 +0000
@@ -38,12 +38,14 @@
 
   $1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandle$$($1_Type)s.java
 
-  ifneq ($$(findstring $$($1_Type), Object Int Long), )
-    $1_ARGS += -KCAS
+  $1_ARGS += -KCAS
+
+  ifneq ($$(findstring $$($1_Type), Byte Short Char Int Long Float Double), )
+    $1_ARGS += -KAtomicAdd
   endif
 
-  ifneq ($$(findstring $$($1_Type), Int Long), )
-    $1_ARGS += -KAtomicAdd
+  ifneq ($$(findstring $$($1_Type), Byte Short Char), )
+    $1_ARGS += -KShorterThanInt
   endif
 
   $$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandle.java.template $(BUILD_TOOLS_JDK)
--- a/src/java.base/share/classes/java/lang/ThreadGroup.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/lang/ThreadGroup.java	Thu Jul 07 18:35:29 2016 +0000
@@ -60,7 +60,6 @@
     int maxPriority;
     boolean destroyed;
     boolean daemon;
-    boolean vmAllowSuspension;
 
     int nUnstartedThreads = 0;
     int nthreads;
@@ -121,7 +120,6 @@
         this.name = name;
         this.maxPriority = parent.maxPriority;
         this.daemon = parent.daemon;
-        this.vmAllowSuspension = parent.vmAllowSuspension;
         this.parent = parent;
         parent.add(this);
     }
@@ -1075,10 +1073,6 @@
      */
     @Deprecated(since="1.2")
     public boolean allowThreadSuspension(boolean b) {
-        this.vmAllowSuspension = b;
-        if (!b) {
-            VM.unsuspendSomeThreads();
-        }
         return true;
     }
 
--- a/src/java.base/share/classes/java/lang/annotation/AnnotationTypeMismatchException.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/lang/annotation/AnnotationTypeMismatchException.java	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, 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
@@ -44,7 +44,7 @@
     /**
      * The {@code Method} object for the annotation element.
      */
-    private final Method element;
+    private final transient Method element;
 
     /**
      * The (erroneous) type of data found in the annotation.  This string
@@ -57,10 +57,12 @@
      * Constructs an AnnotationTypeMismatchException for the specified
      * annotation type element and found data type.
      *
-     * @param element the {@code Method} object for the annotation element
+     * @param element the {@code Method} object for the annotation
+     * element, may be {@code null}
      * @param foundType the (erroneous) type of data found in the annotation.
      *        This string may, but is not required to, contain the value
-     *        as well.  The exact format of the string is unspecified.
+     *        as well.  The exact format of the string is unspecified,
+     *        may be {@code null}.
      */
     public AnnotationTypeMismatchException(Method element, String foundType) {
         super("Incorrectly typed data found for annotation element " + element
@@ -71,8 +73,11 @@
 
     /**
      * Returns the {@code Method} object for the incorrectly typed element.
+     * The value may be unavailable if this exception has been
+     * serialized and then read back in.
      *
-     * @return the {@code Method} object for the incorrectly typed element
+     * @return the {@code Method} object for the incorrectly typed
+     * element, or {@code null} if unavailable
      */
     public Method element() {
         return this.element;
@@ -81,7 +86,8 @@
     /**
      * Returns the type of data found in the incorrectly typed element.
      * The returned string may, but is not required to, contain the value
-     * as well.  The exact format of the string is unspecified.
+     * as well.  The exact format of the string is unspecified and the string
+     * may be {@code null}.
      *
      * @return the type of data found in the incorrectly typed element
      */
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Jul 07 18:35:29 2016 +0000
@@ -751,11 +751,25 @@
         classFileEpilogue();
         bogusMethod(lambdaForm);
 
-        final byte[] classFile = cw.toByteArray();
+        final byte[] classFile;
+        try {
+            classFile = cw.toByteArray();
+        } catch (RuntimeException e) {
+            // ASM throws RuntimeException if something goes wrong - capture these and wrap them in a meaningful
+            // exception to support falling back to LambdaForm interpretation
+            throw new BytecodeGenerationException(e);
+        }
         maybeDump(className, classFile);
         return classFile;
     }
 
+    @SuppressWarnings("serial")
+    static final class BytecodeGenerationException extends RuntimeException {
+        BytecodeGenerationException(Exception cause) {
+            super(cause);
+        }
+    }
+
     void emitArrayLoad(Name name)   { emitArrayOp(name, Opcodes.AALOAD);      }
     void emitArrayStore(Name name)  { emitArrayOp(name, Opcodes.AASTORE);     }
     void emitArrayLength(Name name) { emitArrayOp(name, Opcodes.ARRAYLENGTH); }
--- a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java	Thu Jul 07 18:35:29 2016 +0000
@@ -25,6 +25,7 @@
 
 package java.lang.invoke;
 
+import jdk.internal.perf.PerfCounter;
 import jdk.internal.vm.annotation.DontInline;
 import jdk.internal.vm.annotation.Stable;
 import sun.invoke.util.Wrapper;
@@ -39,8 +40,7 @@
 
 import static java.lang.invoke.LambdaForm.BasicType.*;
 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
-import static java.lang.invoke.MethodHandleStatics.debugEnabled;
-import static java.lang.invoke.MethodHandleStatics.newInternalError;
+import static java.lang.invoke.MethodHandleStatics.*;
 
 /**
  * The symbolic, non-executable form of a method handle's invocation semantics.
@@ -396,7 +396,7 @@
     /** Customize LambdaForm for a particular MethodHandle */
     LambdaForm customize(MethodHandle mh) {
         LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh);
-        if (COMPILE_THRESHOLD > 0 && isCompiled) {
+        if (COMPILE_THRESHOLD >= 0 && isCompiled) {
             // If shared LambdaForm has been compiled, compile customized version as well.
             customForm.compileToBytecode();
         }
@@ -411,7 +411,7 @@
         }
         assert(transformCache != null); // Customized LambdaForm should always has a link to uncustomized version.
         LambdaForm uncustomizedForm = (LambdaForm)transformCache;
-        if (COMPILE_THRESHOLD > 0 && isCompiled) {
+        if (COMPILE_THRESHOLD >= 0 && isCompiled) {
             // If customized LambdaForm has been compiled, compile uncustomized version as well.
             uncustomizedForm.compileToBytecode();
         }
@@ -717,7 +717,7 @@
      * as a sort of pre-invocation linkage step.)
      */
     public void prepare() {
-        if (COMPILE_THRESHOLD == 0 && !isCompiled) {
+        if (COMPILE_THRESHOLD == 0 && !forceInterpretation() && !isCompiled) {
             compileToBytecode();
         }
         if (this.vmentry != null) {
@@ -736,10 +736,22 @@
         // TO DO: Maybe add invokeGeneric, invokeWithArguments
     }
 
+    private static @Stable PerfCounter LF_FAILED;
+
+    private static PerfCounter failedCompilationCounter() {
+        if (LF_FAILED == null) {
+            LF_FAILED = PerfCounter.newPerfCounter("java.lang.invoke.failedLambdaFormCompilations");
+        }
+        return LF_FAILED;
+    }
+
     /** Generate optimizable bytecode for this form. */
-    MemberName compileToBytecode() {
+    void compileToBytecode() {
+        if (forceInterpretation()) {
+            return; // this should not be compiled
+        }
         if (vmentry != null && isCompiled) {
-            return vmentry;  // already compiled somehow
+            return;  // already compiled somehow
         }
         MethodType invokerType = methodType();
         assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
@@ -748,9 +760,16 @@
             if (TRACE_INTERPRETER)
                 traceInterpreter("compileToBytecode", this);
             isCompiled = true;
-            return vmentry;
-        } catch (Error | Exception ex) {
-            throw newInternalError(this.toString(), ex);
+        } catch (InvokerBytecodeGenerator.BytecodeGenerationException bge) {
+            // bytecode generation failed - mark this LambdaForm as to be run in interpretation mode only
+            invocationCounter = -1;
+            failedCompilationCounter().increment();
+            if (LOG_LF_COMPILATION_FAILURE) {
+                System.out.println("LambdaForm compilation failed: " + this);
+                bge.printStackTrace(System.out);
+            }
+        } catch (Error | Exception e) {
+            throw newInternalError(this.toString(), e);
         }
     }
 
@@ -856,7 +875,11 @@
     static {
         COMPILE_THRESHOLD = Math.max(-1, MethodHandleStatics.COMPILE_THRESHOLD);
     }
-    private int invocationCounter = 0;
+    private int invocationCounter = 0; // a value of -1 indicates LambdaForm interpretation mode forever
+
+    private boolean forceInterpretation() {
+        return invocationCounter == -1;
+    }
 
     @Hidden
     @DontInline
@@ -896,7 +919,7 @@
 
     private void checkInvocationCounter() {
         if (COMPILE_THRESHOLD != 0 &&
-            invocationCounter < COMPILE_THRESHOLD) {
+            !forceInterpretation() && invocationCounter < COMPILE_THRESHOLD) {
             invocationCounter++;  // benign race
             if (invocationCounter >= COMPILE_THRESHOLD) {
                 // Replace vmentry with a bytecode version of this LF.
@@ -906,7 +929,7 @@
     }
     Object interpretWithArgumentsTracing(Object... argumentValues) throws Throwable {
         traceInterpreter("[ interpretWithArguments", this, argumentValues);
-        if (invocationCounter < COMPILE_THRESHOLD) {
+        if (!forceInterpretation() && invocationCounter < COMPILE_THRESHOLD) {
             int ctr = invocationCounter++;  // benign race
             traceInterpreter("| invocationCounter", ctr);
             if (invocationCounter >= COMPILE_THRESHOLD) {
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,11 @@
 
 package java.lang.invoke;
 
-import java.util.Properties;
 import jdk.internal.misc.Unsafe;
 import sun.security.action.GetPropertyAction;
 
+import java.util.Properties;
+
 /**
  * This class consists exclusively of static names internal to the
  * method handle implementation.
@@ -46,6 +47,7 @@
     static final boolean TRACE_INTERPRETER;
     static final boolean TRACE_METHOD_LINKAGE;
     static final int COMPILE_THRESHOLD;
+    static final boolean LOG_LF_COMPILATION_FAILURE;
     static final int DONT_INLINE_THRESHOLD;
     static final int PROFILE_LEVEL;
     static final boolean PROFILE_GWT;
@@ -64,6 +66,8 @@
                 props.getProperty("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE"));
         COMPILE_THRESHOLD = Integer.parseInt(
                 props.getProperty("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", "0"));
+        LOG_LF_COMPILATION_FAILURE = Boolean.parseBoolean(
+                props.getProperty("java.lang.invoke.MethodHandle.LOG_LF_COMPILATION_FAILURE", "false"));
         DONT_INLINE_THRESHOLD = Integer.parseInt(
                 props.getProperty("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", "30"));
         PROFILE_LEVEL = Integer.parseInt(
@@ -87,7 +91,8 @@
         return (DEBUG_METHOD_HANDLE_NAMES |
                 DUMP_CLASS_FILES |
                 TRACE_INTERPRETER |
-                TRACE_METHOD_LINKAGE);
+                TRACE_METHOD_LINKAGE |
+                LOG_LF_COMPILATION_FAILURE);
     }
 
     // handy shared exception makers (they simplify the common case code)
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Thu Jul 07 18:35:29 2016 +0000
@@ -1208,22 +1208,43 @@
          * <ul>
          * <li>if the field is declared {@code final}, then the write, atomic
          *     update, and numeric atomic update access modes are unsupported.
-         * <li>if the field type is anything other than {@code int},
-         *     {@code long} or a reference type, then atomic update access modes
-         *     are unsupported.  (Future major platform releases of the JDK may
-         *     support additional types for certain currently unsupported access
-         *     modes.)
-         * <li>if the field type is anything other than {@code int} or
-         *     {@code long}, then numeric atomic update access modes are
-         *     unsupported.  (Future major platform releases of the JDK may
-         *     support additional numeric types for certain currently
-         *     unsupported access modes.)
+         * <li>if the field type is anything other than {@code byte},
+         *     {@code short}, {@code char}, {@code int} or {@code long},
+         *     {@code float}, or {@code double} then numeric atomic update
+         *     access modes are unsupported.
          * </ul>
          * <p>
          * If the field is declared {@code volatile} then the returned VarHandle
          * will override access to the field (effectively ignore the
          * {@code volatile} declaration) in accordance to it's specified
          * access modes.
+         * <p>
+         * If the field type is {@code float} or {@code double} then numeric
+         * and atomic update access modes compare values using their bitwise
+         * representation (see {@link Float#floatToRawIntBits} and
+         * {@link Double#doubleToRawLongBits}, respectively).
+         * @apiNote
+         * Bitwise comparison of {@code float} values or {@code double} values,
+         * as performed by the numeric and atomic update access modes, differ
+         * from the primitive {@code ==} operator and the {@link Float#equals}
+         * and {@link Double#equals} methods, specifically with respect to
+         * comparing NaN values or comparing {@code -0.0} with {@code +0.0}.
+         * Care should be taken when performing a compare and set or a compare
+         * and exchange operation with such values since the operation may
+         * unexpectedly fail.
+         * There are many possible NaN values that are considered to be
+         * {@code NaN} in Java, although no IEEE 754 floating-point operation
+         * provided by Java can distinguish between them.  Operation failure can
+         * occur if the expected or witness value is a NaN value and it is
+         * transformed (perhaps in a platform specific manner) into another NaN
+         * value, and thus has a different bitwise representation (see
+         * {@link Float#intBitsToFloat} or {@link Double#longBitsToDouble} for more
+         * details).
+         * The values {@code -0.0} and {@code +0.0} have different bitwise
+         * representations but are considered equal when using the primitive
+         * {@code ==} operator.  Operation failure can occur if, for example, a
+         * numeric algorithm computes an expected value to be say {@code -0.0}
+         * and previously computed the witness value to be say {@code +0.0}.
          * @param recv the receiver class, of type {@code R}, that declares the
          * non-static field
          * @param name the field's name
@@ -1306,22 +1327,43 @@
          * <ul>
          * <li>if the field is declared {@code final}, then the write, atomic
          *     update, and numeric atomic update access modes are unsupported.
-         * <li>if the field type is anything other than {@code int},
-         *     {@code long} or a reference type, then atomic update access modes
-         *     are unsupported.  (Future major platform releases of the JDK may
-         *     support additional types for certain currently unsupported access
-         *     modes.)
-         * <li>if the field type is anything other than {@code int} or
-         *     {@code long}, then numeric atomic update access modes are
-         *     unsupported.  (Future major platform releases of the JDK may
-         *     support additional numeric types for certain currently
-         *     unsupported access modes.)
+         * <li>if the field type is anything other than {@code byte},
+         *     {@code short}, {@code char}, {@code int} or {@code long},
+         *     {@code float}, or {@code double}, then numeric atomic update
+         *     access modes are unsupported.
          * </ul>
          * <p>
          * If the field is declared {@code volatile} then the returned VarHandle
          * will override access to the field (effectively ignore the
          * {@code volatile} declaration) in accordance to it's specified
          * access modes.
+         * <p>
+         * If the field type is {@code float} or {@code double} then numeric
+         * and atomic update access modes compare values using their bitwise
+         * representation (see {@link Float#floatToRawIntBits} and
+         * {@link Double#doubleToRawLongBits}, respectively).
+         * @apiNote
+         * Bitwise comparison of {@code float} values or {@code double} values,
+         * as performed by the numeric and atomic update access modes, differ
+         * from the primitive {@code ==} operator and the {@link Float#equals}
+         * and {@link Double#equals} methods, specifically with respect to
+         * comparing NaN values or comparing {@code -0.0} with {@code +0.0}.
+         * Care should be taken when performing a compare and set or a compare
+         * and exchange operation with such values since the operation may
+         * unexpectedly fail.
+         * There are many possible NaN values that are considered to be
+         * {@code NaN} in Java, although no IEEE 754 floating-point operation
+         * provided by Java can distinguish between them.  Operation failure can
+         * occur if the expected or witness value is a NaN value and it is
+         * transformed (perhaps in a platform specific manner) into another NaN
+         * value, and thus has a different bitwise representation (see
+         * {@link Float#intBitsToFloat} or {@link Double#longBitsToDouble} for more
+         * details).
+         * The values {@code -0.0} and {@code +0.0} have different bitwise
+         * representations but are considered equal when using the primitive
+         * {@code ==} operator.  Operation failure can occur if, for example, a
+         * numeric algorithm computes an expected value to be say {@code -0.0}
+         * and previously computed the witness value to be say {@code +0.0}.
          * @param decl the class that declares the static field
          * @param name the field's name
          * @param type the field's type, of type {@code T}
@@ -1590,22 +1632,43 @@
          * <ul>
          * <li>if the field is declared {@code final}, then the write, atomic
          *     update, and numeric atomic update access modes are unsupported.
-         * <li>if the field type is anything other than {@code int},
-         *     {@code long} or a reference type, then atomic update access modes
-         *     are unsupported.  (Future major platform releases of the JDK may
-         *     support additional types for certain currently unsupported access
-         *     modes.)
-         * <li>if the field type is anything other than {@code int} or
-         *     {@code long}, then numeric atomic update access modes are
-         *     unsupported.  (Future major platform releases of the JDK may
-         *     support additional numeric types for certain currently
-         *     unsupported access modes.)
+         * <li>if the field type is anything other than {@code byte},
+         *     {@code short}, {@code char}, {@code int} or {@code long},
+         *     {@code float}, or {@code double} then numeric atomic update
+         *     access modes are unsupported.
          * </ul>
          * <p>
          * If the field is declared {@code volatile} then the returned VarHandle
          * will override access to the field (effectively ignore the
          * {@code volatile} declaration) in accordance to it's specified
          * access modes.
+         * <p>
+         * If the field type is {@code float} or {@code double} then numeric
+         * and atomic update access modes compare values using their bitwise
+         * representation (see {@link Float#floatToRawIntBits} and
+         * {@link Double#doubleToRawLongBits}, respectively).
+         * @apiNote
+         * Bitwise comparison of {@code float} values or {@code double} values,
+         * as performed by the numeric and atomic update access modes, differ
+         * from the primitive {@code ==} operator and the {@link Float#equals}
+         * and {@link Double#equals} methods, specifically with respect to
+         * comparing NaN values or comparing {@code -0.0} with {@code +0.0}.
+         * Care should be taken when performing a compare and set or a compare
+         * and exchange operation with such values since the operation may
+         * unexpectedly fail.
+         * There are many possible NaN values that are considered to be
+         * {@code NaN} in Java, although no IEEE 754 floating-point operation
+         * provided by Java can distinguish between them.  Operation failure can
+         * occur if the expected or witness value is a NaN value and it is
+         * transformed (perhaps in a platform specific manner) into another NaN
+         * value, and thus has a different bitwise representation (see
+         * {@link Float#intBitsToFloat} or {@link Double#longBitsToDouble} for more
+         * details).
+         * The values {@code -0.0} and {@code +0.0} have different bitwise
+         * representations but are considered equal when using the primitive
+         * {@code ==} operator.  Operation failure can occur if, for example, a
+         * numeric algorithm computes an expected value to be say {@code -0.0}
+         * and previously computed the witness value to be say {@code +0.0}.
          * @param f the reflected field, with a field of type {@code T}, and
          * a declaring class of type {@code R}
          * @return a VarHandle giving access to non-static fields or a static
@@ -2289,17 +2352,38 @@
      * Certain access modes of the returned VarHandle are unsupported under
      * the following conditions:
      * <ul>
-     * <li>if the component type is anything other than {@code int},
-     *     {@code long} or a reference type, then atomic update access modes
-     *     are unsupported.  (Future major platform releases of the JDK may
-     *     support additional types for certain currently unsupported access
-     *     modes.)
-     * <li>if the component type is anything other than {@code int} or
-     *     {@code long}, then numeric atomic update access modes are
-     *     unsupported.  (Future major platform releases of the JDK may
-     *     support additional numeric types for certain currently
-     *     unsupported access modes.)
+     * <li>if the component type is anything other than {@code byte},
+     *     {@code short}, {@code char}, {@code int} or {@code long},
+     *     {@code float}, or {@code double} then numeric atomic update access
+     *     modes are unsupported.
      * </ul>
+     * <p>
+     * If the component type is {@code float} or {@code double} then numeric
+     * and atomic update access modes compare values using their bitwise
+     * representation (see {@link Float#floatToRawIntBits} and
+     * {@link Double#doubleToRawLongBits}, respectively).
+     * @apiNote
+     * Bitwise comparison of {@code float} values or {@code double} values,
+     * as performed by the numeric and atomic update access modes, differ
+     * from the primitive {@code ==} operator and the {@link Float#equals}
+     * and {@link Double#equals} methods, specifically with respect to
+     * comparing NaN values or comparing {@code -0.0} with {@code +0.0}.
+     * Care should be taken when performing a compare and set or a compare
+     * and exchange operation with such values since the operation may
+     * unexpectedly fail.
+     * There are many possible NaN values that are considered to be
+     * {@code NaN} in Java, although no IEEE 754 floating-point operation
+     * provided by Java can distinguish between them.  Operation failure can
+     * occur if the expected or witness value is a NaN value and it is
+     * transformed (perhaps in a platform specific manner) into another NaN
+     * value, and thus has a different bitwise representation (see
+     * {@link Float#intBitsToFloat} or {@link Double#longBitsToDouble} for more
+     * details).
+     * The values {@code -0.0} and {@code +0.0} have different bitwise
+     * representations but are considered equal when using the primitive
+     * {@code ==} operator.  Operation failure can occur if, for example, a
+     * numeric algorithm computes an expected value to be say {@code -0.0}
+     * and previously computed the witness value to be say {@code +0.0}.
      * @param arrayClass the class of an array, of type {@code T[]}
      * @return a VarHandle giving access to elements of an array
      * @throws NullPointerException if the arrayClass is null
@@ -2363,16 +2447,11 @@
      * int misalignedAtIndex = (misalignedAtZeroIndex + index) % sizeOfT;
      * boolean isMisaligned = misalignedAtIndex != 0;
      * }</pre>
-     *
-     * @implNote
-     * The variable types {@code float} and {@code double} are supported as if
-     * by transformation to and access with the variable types {@code int} and
-     * {@code long} respectively.  For example, the transformation of a
-     * {@code double} value to a long value is performed as if using
-     * {@link Double#doubleToRawLongBits(double)}, and the reverse
-     * transformation is performed as if using
-     * {@link Double#longBitsToDouble(long)}.
-     *
+     * <p>
+     * If the variable type is {@code float} or {@code double} then atomic
+     * update access modes compare values using their bitwise representation
+     * (see {@link Float#floatToRawIntBits} and
+     * {@link Double#doubleToRawLongBits}, respectively).
      * @param viewArrayClass the view array class, with a component type of
      * type {@code T}
      * @param byteOrder the endianness of the view array elements, as
@@ -2449,16 +2528,11 @@
      * int misalignedAtIndex = bb.alignmentOffset(index, sizeOfT);
      * boolean isMisaligned = misalignedAtIndex != 0;
      * }</pre>
-     *
-     * @implNote
-     * The variable types {@code float} and {@code double} are supported as if
-     * by transformation to and access with the variable types {@code int} and
-     * {@code long} respectively.  For example, the transformation of a
-     * {@code double} value to a long value is performed as if using
-     * {@link Double#doubleToRawLongBits(double)}, and the reverse
-     * transformation is performed as if using
-     * {@link Double#longBitsToDouble(long)}.
-     *
+     * <p>
+     * If the variable type is {@code float} or {@code double} then atomic
+     * update access modes compare values using their bitwise representation
+     * (see {@link Float#floatToRawIntBits} and
+     * {@link Double#doubleToRawLongBits}, respectively).
      * @param viewArrayClass the view array class, with a component type of
      * type {@code T}
      * @param byteOrder the endianness of the view array elements, as
@@ -3353,7 +3427,8 @@
      * @return a possibly adapted method handle
      * @throws NullPointerException if either argument is null
      * @throws IllegalArgumentException if any element of {@code newTypes} is {@code void.class},
-     *         or if either index is out of range in its corresponding list,
+     *         or if {@code skip} is negative or greater than the arity of the target,
+     *         or if {@code pos} is negative or greater than the newTypes list size,
      *         or if the non-skipped target parameter types match the new types at {@code pos}
      * @since 9
      */
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Thu Jul 07 18:35:29 2016 +0000
@@ -139,7 +139,7 @@
  * {@link #weakCompareAndSetAcquire weakCompareAndSetAcquire},
  * {@link #weakCompareAndSetRelease weakCompareAndSetRelease},
  * {@link #compareAndExchangeAcquire compareAndExchangeAcquire},
- * {@link #compareAndExchangeVolatile compareAndExchangeVolatile},
+ * {@link #compareAndExchange compareAndExchange},
  * {@link #compareAndExchangeRelease compareAndExchangeRelease},
  * {@link #getAndSet getAndSet}.
  * <li>numeric atomic update access modes that, for example, atomically get and
@@ -706,9 +706,9 @@
      * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)T}.
      *
      * <p>The symbolic type descriptor at the call site of {@code
-     * compareAndExchangeVolatile}
+     * compareAndExchange}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE)}
+     * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE)}
      * on this VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
@@ -729,7 +729,7 @@
     public final native
     @MethodHandle.PolymorphicSignature
     @HotSpotIntrinsicCandidate
-    Object compareAndExchangeVolatile(Object... args);
+    Object compareAndExchange(Object... args);
 
     /**
      * Atomically sets the value of a variable to the {@code newValue} with the
@@ -1199,9 +1199,9 @@
         /**
          * The access mode whose access is specified by the corresponding
          * method
-         * {@link VarHandle#compareAndExchangeVolatile VarHandle.compareAndExchangeVolatile}
+         * {@link VarHandle#compareAndExchange VarHandle.compareAndExchange}
          */
-        COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE),
+        COMPARE_AND_EXCHANGE("compareAndExchange", AccessType.COMPARE_AND_EXCHANGE),
         /**
          * The access mode whose access is specified by the corresponding
          * method
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Thu Jul 07 18:35:29 2016 +0000
@@ -132,7 +132,7 @@
         }
 
         @ForceInline
-        static $type$ compareAndExchangeVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+        static $type$ compareAndExchange(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
             return UNSAFE.compareAndExchange$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
                                                handle.fieldOffset,
                                                {#if[Object]?handle.fieldType.cast(expected):expected},
@@ -205,9 +205,9 @@
 
         @ForceInline
         static $type$ addAndGet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
-            return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+            return {#if[ShorterThanInt]?($type$)}(UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
                                        handle.fieldOffset,
-                                       value) + value;
+                                       value) + value);
         }
 #end[AtomicAdd]
 
@@ -313,7 +313,7 @@
 
 
         @ForceInline
-        static $type$ compareAndExchangeVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+        static $type$ compareAndExchange(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
             return UNSAFE.compareAndExchange$Type$Volatile(handle.base,
                                                handle.fieldOffset,
                                                {#if[Object]?handle.fieldType.cast(expected):expected},
@@ -386,9 +386,9 @@
 
         @ForceInline
         static $type$ addAndGet(FieldStaticReadWrite handle, $type$ value) {
-            return UNSAFE.getAndAdd$Type$(handle.base,
+            return {#if[ShorterThanInt]?($type$)}(UNSAFE.getAndAdd$Type$(handle.base,
                                        handle.fieldOffset,
-                                       value) + value;
+                                       value) + value);
         }
 #end[AtomicAdd]
 
@@ -523,7 +523,7 @@
         }
 
         @ForceInline
-        static $type$ compareAndExchangeVolatile(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+        static $type$ compareAndExchange(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
 #if[Object]
             Object[] array = (Object[]) handle.arrayType.cast(oarray);
 #else[Object]
@@ -646,9 +646,9 @@
 #else[Object]
             $type$[] array = ($type$[]) oarray;
 #end[Object]
-            return UNSAFE.getAndAdd$Type$(array,
+            return {#if[ShorterThanInt]?($type$)}(UNSAFE.getAndAdd$Type$(array,
                     (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
-                    value) + value;
+                    value) + value);
         }
 #end[AtomicAdd]
 
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template	Thu Jul 07 18:35:29 2016 +0000
@@ -193,7 +193,7 @@
         }
 
         @ForceInline
-        static $type$ compareAndExchangeVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+        static $type$ compareAndExchange(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
             byte[] ba = (byte[]) oba;
             return convEndian(handle.be,
                               UNSAFE.compareAndExchange$RawType$Volatile(
@@ -436,7 +436,7 @@
         }
 
         @ForceInline
-        static $type$ compareAndExchangeVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+        static $type$ compareAndExchange(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
             ByteBuffer bb = (ByteBuffer) obb;
             return convEndian(handle.be,
                               UNSAFE.compareAndExchange$RawType$Volatile(
--- a/src/java.base/share/classes/java/text/DateFormatSymbols.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/text/DateFormatSymbols.java	Thu Jul 07 18:35:29 2016 +0000
@@ -418,7 +418,7 @@
      * Gets short month strings. For example: "Jan", "Feb", etc.
      *
      * <p>If the language requires different forms for formatting and
-     * stand-alone usages, This method returns short month names in
+     * stand-alone usages, this method returns short month names in
      * the formatting form. For example, the preferred abbreviation
      * for January in the Catalan language is <em>de gen.</em> in the
      * formatting form, while it is <em>gen.</em> in the stand-alone
--- a/src/java.base/share/classes/java/text/SimpleDateFormat.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/java/text/SimpleDateFormat.java	Thu Jul 07 18:35:29 2016 +0000
@@ -276,9 +276,16 @@
  *     it is interpreted as a <a href="#number">number</a>.<br>
  *     <ul>
  *     <li>Letter <em>M</em> produces context-sensitive month names, such as the
- *         embedded form of names. If a {@code DateFormatSymbols} has been set
- *         explicitly with constructor {@link #SimpleDateFormat(String,
- *         DateFormatSymbols)} or method {@link
+ *         embedded form of names. Letter <em>M</em> is context-sensitive in the
+ *         sense that when it is used in the standalone pattern, for example,
+ *         "MMMM", it gives the standalone form of a month name and when it is
+ *         used in the pattern containing other field(s), for example, "d MMMM",
+ *         it gives the format form of a month name. For example, January in the
+ *         Catalan language is "de gener" in the format form while it is "gener"
+ *         in the standalone form. In this case, "MMMM" will produce "gener" and
+ *         the month part of the "d MMMM" will produce "de gener". If a
+ *         {@code DateFormatSymbols} has been set explicitly with constructor
+ *         {@link #SimpleDateFormat(String,DateFormatSymbols)} or method {@link
  *         #setDateFormatSymbols(DateFormatSymbols)}, the month names given by
  *         the {@code DateFormatSymbols} are used.</li>
  *     <li>Letter <em>L</em> produces the standalone form of month names.</li>
--- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Thu Jul 07 18:35:29 2016 +0000
@@ -25,16 +25,14 @@
 
 package jdk.internal.misc;
 
+import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
+import jdk.internal.vm.annotation.ForceInline;
+
 import java.lang.reflect.Field;
 import java.security.ProtectionDomain;
 
-import jdk.internal.reflect.CallerSensitive;
-import jdk.internal.reflect.Reflection;
-import jdk.internal.misc.VM;
-
-import jdk.internal.HotSpotIntrinsicCandidate;
-import jdk.internal.vm.annotation.ForceInline;
-
 
 /**
  * A collection of methods for performing low-level, unsafe operations.
@@ -1400,6 +1398,453 @@
         return compareAndSwapInt(o, offset, expected, x);
     }
 
+    @HotSpotIntrinsicCandidate
+    public final byte compareAndExchangeByteVolatile(Object o, long offset,
+                                                     byte expected,
+                                                     byte x) {
+        long wordOffset = offset & ~3;
+        int shift = (int) (offset & 3) << 3;
+        if (BE) {
+            shift = 24 - shift;
+        }
+        int mask           = 0xFF << shift;
+        int maskedExpected = (expected & 0xFF) << shift;
+        int maskedX        = (x & 0xFF) << shift;
+        int fullWord;
+        do {
+            fullWord = getIntVolatile(o, wordOffset);
+            if ((fullWord & mask) != maskedExpected)
+                return (byte) ((fullWord & mask) >> shift);
+        } while (!weakCompareAndSwapIntVolatile(o, wordOffset,
+                                                fullWord, (fullWord & ~mask) | maskedX));
+        return expected;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final boolean compareAndSwapByte(Object o, long offset,
+                                            byte expected,
+                                            byte x) {
+        return compareAndExchangeByteVolatile(o, offset, expected, x) == expected;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapByteVolatile(Object o, long offset,
+                                                        byte expected,
+                                                        byte x) {
+        return compareAndSwapByte(o, offset, expected, x);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapByteAcquire(Object o, long offset,
+                                                       byte expected,
+                                                       byte x) {
+        return weakCompareAndSwapByteVolatile(o, offset, expected, x);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapByteRelease(Object o, long offset,
+                                                       byte expected,
+                                                       byte x) {
+        return weakCompareAndSwapByteVolatile(o, offset, expected, x);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapByte(Object o, long offset,
+                                                        byte expected,
+                                                        byte x) {
+        return weakCompareAndSwapByteVolatile(o, offset, expected, x);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final byte compareAndExchangeByteAcquire(Object o, long offset,
+                                                    byte expected,
+                                                    byte x) {
+        return compareAndExchangeByteVolatile(o, offset, expected, x);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final byte compareAndExchangeByteRelease(Object o, long offset,
+                                                    byte expected,
+                                                    byte x) {
+        return compareAndExchangeByteVolatile(o, offset, expected, x);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final short compareAndExchangeShortVolatile(Object o, long offset,
+                                             short expected,
+                                             short x) {
+        if ((offset & 3) == 3) {
+            throw new IllegalArgumentException("Update spans the word, not supported");
+        }
+        long wordOffset = offset & ~3;
+        int shift = (int) (offset & 3) << 3;
+        if (BE) {
+            shift = 16 - shift;
+        }
+        int mask           = 0xFFFF << shift;
+        int maskedExpected = (expected & 0xFFFF) << shift;
+        int maskedX        = (x & 0xFFFF) << shift;
+        int fullWord;
+        do {
+            fullWord = getIntVolatile(o, wordOffset);
+            if ((fullWord & mask) != maskedExpected) {
+                return (short) ((fullWord & mask) >> shift);
+            }
+        } while (!weakCompareAndSwapIntVolatile(o, wordOffset,
+                                                fullWord, (fullWord & ~mask) | maskedX));
+        return expected;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final boolean compareAndSwapShort(Object o, long offset,
+                                             short expected,
+                                             short x) {
+        return compareAndExchangeShortVolatile(o, offset, expected, x) == expected;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapShortVolatile(Object o, long offset,
+                                                         short expected,
+                                                         short x) {
+        return compareAndSwapShort(o, offset, expected, x);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapShortAcquire(Object o, long offset,
+                                                        short expected,
+                                                        short x) {
+        return weakCompareAndSwapShortVolatile(o, offset, expected, x);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapShortRelease(Object o, long offset,
+                                                        short expected,
+                                                        short x) {
+        return weakCompareAndSwapShortVolatile(o, offset, expected, x);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapShort(Object o, long offset,
+                                                 short expected,
+                                                 short x) {
+        return weakCompareAndSwapShortVolatile(o, offset, expected, x);
+    }
+
+
+    @HotSpotIntrinsicCandidate
+    public final short compareAndExchangeShortAcquire(Object o, long offset,
+                                                     short expected,
+                                                     short x) {
+        return compareAndExchangeShortVolatile(o, offset, expected, x);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final short compareAndExchangeShortRelease(Object o, long offset,
+                                                    short expected,
+                                                    short x) {
+        return compareAndExchangeShortVolatile(o, offset, expected, x);
+    }
+
+    @ForceInline
+    private char s2c(short s) {
+        return (char) s;
+    }
+
+    @ForceInline
+    private short c2s(char s) {
+        return (short) s;
+    }
+
+    @ForceInline
+    public final boolean compareAndSwapChar(Object o, long offset,
+                                            char expected,
+                                            char x) {
+        return compareAndSwapShort(o, offset, c2s(expected), c2s(x));
+    }
+
+    @ForceInline
+    public final char compareAndExchangeCharVolatile(Object o, long offset,
+                                            char expected,
+                                            char x) {
+        return s2c(compareAndExchangeShortVolatile(o, offset, c2s(expected), c2s(x)));
+    }
+
+    @ForceInline
+    public final char compareAndExchangeCharAcquire(Object o, long offset,
+                                            char expected,
+                                            char x) {
+        return s2c(compareAndExchangeShortAcquire(o, offset, c2s(expected), c2s(x)));
+    }
+
+    @ForceInline
+    public final char compareAndExchangeCharRelease(Object o, long offset,
+                                            char expected,
+                                            char x) {
+        return s2c(compareAndExchangeShortRelease(o, offset, c2s(expected), c2s(x)));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapCharVolatile(Object o, long offset,
+                                            char expected,
+                                            char x) {
+        return weakCompareAndSwapShortVolatile(o, offset, c2s(expected), c2s(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapCharAcquire(Object o, long offset,
+                                            char expected,
+                                            char x) {
+        return weakCompareAndSwapShortAcquire(o, offset, c2s(expected), c2s(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapCharRelease(Object o, long offset,
+                                            char expected,
+                                            char x) {
+        return weakCompareAndSwapShortRelease(o, offset, c2s(expected), c2s(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapChar(Object o, long offset,
+                                            char expected,
+                                            char x) {
+        return weakCompareAndSwapShort(o, offset, c2s(expected), c2s(x));
+    }
+
+    @ForceInline
+    private boolean byte2bool(byte b) {
+        return b > 0;
+    }
+
+    @ForceInline
+    private byte bool2byte(boolean b) {
+        return b ? (byte)1 : (byte)0;
+    }
+
+    @ForceInline
+    public final boolean compareAndSwapBoolean(Object o, long offset,
+                                               boolean expected,
+                                               boolean x) {
+        return compareAndSwapByte(o, offset, bool2byte(expected), bool2byte(x));
+    }
+
+    @ForceInline
+    public final boolean compareAndExchangeBooleanVolatile(Object o, long offset,
+                                                        boolean expected,
+                                                        boolean x) {
+        return byte2bool(compareAndExchangeByteVolatile(o, offset, bool2byte(expected), bool2byte(x)));
+    }
+
+    @ForceInline
+    public final boolean compareAndExchangeBooleanAcquire(Object o, long offset,
+                                                    boolean expected,
+                                                    boolean x) {
+        return byte2bool(compareAndExchangeByteAcquire(o, offset, bool2byte(expected), bool2byte(x)));
+    }
+
+    @ForceInline
+    public final boolean compareAndExchangeBooleanRelease(Object o, long offset,
+                                                       boolean expected,
+                                                       boolean x) {
+        return byte2bool(compareAndExchangeByteRelease(o, offset, bool2byte(expected), bool2byte(x)));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapBooleanVolatile(Object o, long offset,
+                                                           boolean expected,
+                                                           boolean x) {
+        return weakCompareAndSwapByteVolatile(o, offset, bool2byte(expected), bool2byte(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapBooleanAcquire(Object o, long offset,
+                                                          boolean expected,
+                                                          boolean x) {
+        return weakCompareAndSwapByteAcquire(o, offset, bool2byte(expected), bool2byte(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapBooleanRelease(Object o, long offset,
+                                                          boolean expected,
+                                                          boolean x) {
+        return weakCompareAndSwapByteRelease(o, offset, bool2byte(expected), bool2byte(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapBoolean(Object o, long offset,
+                                                   boolean expected,
+                                                   boolean x) {
+        return weakCompareAndSwapByte(o, offset, bool2byte(expected), bool2byte(x));
+    }
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @ForceInline
+    public final boolean compareAndSwapFloat(Object o, long offset,
+                                             float expected,
+                                             float x) {
+        return compareAndSwapInt(o, offset,
+                                 Float.floatToRawIntBits(expected),
+                                 Float.floatToRawIntBits(x));
+    }
+
+    @ForceInline
+    public final float compareAndExchangeFloatVolatile(Object o, long offset,
+                                                       float expected,
+                                                       float x) {
+        int w = compareAndExchangeIntVolatile(o, offset,
+                                              Float.floatToRawIntBits(expected),
+                                              Float.floatToRawIntBits(x));
+        return Float.intBitsToFloat(w);
+    }
+
+    @ForceInline
+    public final float compareAndExchangeFloatAcquire(Object o, long offset,
+                                                  float expected,
+                                                  float x) {
+        int w = compareAndExchangeIntAcquire(o, offset,
+                                             Float.floatToRawIntBits(expected),
+                                             Float.floatToRawIntBits(x));
+        return Float.intBitsToFloat(w);
+    }
+
+    @ForceInline
+    public final float compareAndExchangeFloatRelease(Object o, long offset,
+                                                  float expected,
+                                                  float x) {
+        int w = compareAndExchangeIntRelease(o, offset,
+                                             Float.floatToRawIntBits(expected),
+                                             Float.floatToRawIntBits(x));
+        return Float.intBitsToFloat(w);
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapFloat(Object o, long offset,
+                                               float expected,
+                                               float x) {
+        return weakCompareAndSwapInt(o, offset,
+                                     Float.floatToRawIntBits(expected),
+                                     Float.floatToRawIntBits(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapFloatAcquire(Object o, long offset,
+                                                      float expected,
+                                                      float x) {
+        return weakCompareAndSwapIntAcquire(o, offset,
+                                            Float.floatToRawIntBits(expected),
+                                            Float.floatToRawIntBits(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapFloatRelease(Object o, long offset,
+                                                      float expected,
+                                                      float x) {
+        return weakCompareAndSwapIntRelease(o, offset,
+                                            Float.floatToRawIntBits(expected),
+                                            Float.floatToRawIntBits(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapFloatVolatile(Object o, long offset,
+                                                       float expected,
+                                                       float x) {
+        return weakCompareAndSwapIntVolatile(o, offset,
+                                             Float.floatToRawIntBits(expected),
+                                             Float.floatToRawIntBits(x));
+    }
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @ForceInline
+    public final boolean compareAndSwapDouble(Object o, long offset,
+                                              double expected,
+                                              double x) {
+        return compareAndSwapLong(o, offset,
+                                  Double.doubleToRawLongBits(expected),
+                                  Double.doubleToRawLongBits(x));
+    }
+
+    @ForceInline
+    public final double compareAndExchangeDoubleVolatile(Object o, long offset,
+                                                         double expected,
+                                                         double x) {
+        long w = compareAndExchangeLongVolatile(o, offset,
+                                                Double.doubleToRawLongBits(expected),
+                                                Double.doubleToRawLongBits(x));
+        return Double.longBitsToDouble(w);
+    }
+
+    @ForceInline
+    public final double compareAndExchangeDoubleAcquire(Object o, long offset,
+                                                        double expected,
+                                                        double x) {
+        long w = compareAndExchangeLongAcquire(o, offset,
+                                               Double.doubleToRawLongBits(expected),
+                                               Double.doubleToRawLongBits(x));
+        return Double.longBitsToDouble(w);
+    }
+
+    @ForceInline
+    public final double compareAndExchangeDoubleRelease(Object o, long offset,
+                                                        double expected,
+                                                        double x) {
+        long w = compareAndExchangeLongRelease(o, offset,
+                                               Double.doubleToRawLongBits(expected),
+                                               Double.doubleToRawLongBits(x));
+        return Double.longBitsToDouble(w);
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapDouble(Object o, long offset,
+                                                  double expected,
+                                                  double x) {
+        return weakCompareAndSwapLong(o, offset,
+                                     Double.doubleToRawLongBits(expected),
+                                     Double.doubleToRawLongBits(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapDoubleAcquire(Object o, long offset,
+                                                         double expected,
+                                                         double x) {
+        return weakCompareAndSwapLongAcquire(o, offset,
+                                             Double.doubleToRawLongBits(expected),
+                                             Double.doubleToRawLongBits(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapDoubleRelease(Object o, long offset,
+                                                         double expected,
+                                                         double x) {
+        return weakCompareAndSwapLongRelease(o, offset,
+                                             Double.doubleToRawLongBits(expected),
+                                             Double.doubleToRawLongBits(x));
+    }
+
+    @ForceInline
+    public final boolean weakCompareAndSwapDoubleVolatile(Object o, long offset,
+                                                          double expected,
+                                                          double x) {
+        return weakCompareAndSwapLongVolatile(o, offset,
+                                              Double.doubleToRawLongBits(expected),
+                                              Double.doubleToRawLongBits(x));
+    }
+
     /**
      * Atomically updates Java variable to {@code x} if it is currently
      * holding {@code expected}.
@@ -1840,7 +2285,7 @@
         int v;
         do {
             v = getIntVolatile(o, offset);
-        } while (!compareAndSwapInt(o, offset, v, v + delta));
+        } while (!weakCompareAndSwapIntVolatile(o, offset, v, v + delta));
         return v;
     }
 
@@ -1860,7 +2305,60 @@
         long v;
         do {
             v = getLongVolatile(o, offset);
-        } while (!compareAndSwapLong(o, offset, v, v + delta));
+        } while (!weakCompareAndSwapLongVolatile(o, offset, v, v + delta));
+        return v;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final byte getAndAddByte(Object o, long offset, byte delta) {
+        byte v;
+        do {
+            v = getByteVolatile(o, offset);
+        } while (!weakCompareAndSwapByteVolatile(o, offset, v, (byte) (v + delta)));
+        return v;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final short getAndAddShort(Object o, long offset, short delta) {
+        short v;
+        do {
+            v = getShortVolatile(o, offset);
+        } while (!weakCompareAndSwapShortVolatile(o, offset, v, (short) (v + delta)));
+        return v;
+    }
+
+    @ForceInline
+    public final char getAndAddChar(Object o, long offset, char delta) {
+        return (char) getAndAddShort(o, offset, (short) delta);
+    }
+
+    @ForceInline
+    public final float getAndAddFloat(Object o, long offset, float delta) {
+        int expectedBits;
+        float v;
+        do {
+            // Load and CAS with the raw bits to avoid issues with NaNs and
+            // possible bit conversion from signaling NaNs to quiet NaNs that
+            // may result in the loop not terminating.
+            expectedBits = getIntVolatile(o, offset);
+            v = Float.intBitsToFloat(expectedBits);
+        } while (!weakCompareAndSwapIntVolatile(o, offset,
+                                                expectedBits, Float.floatToRawIntBits(v + delta)));
+        return v;
+    }
+
+    @ForceInline
+    public final double getAndAddDouble(Object o, long offset, double delta) {
+        long expectedBits;
+        double v;
+        do {
+            // Load and CAS with the raw bits to avoid issues with NaNs and
+            // possible bit conversion from signaling NaNs to quiet NaNs that
+            // may result in the loop not terminating.
+            expectedBits = getLongVolatile(o, offset);
+            v = Double.longBitsToDouble(expectedBits);
+        } while (!weakCompareAndSwapLongVolatile(o, offset,
+                                                 expectedBits, Double.doubleToRawLongBits(v + delta)));
         return v;
     }
 
@@ -1880,7 +2378,7 @@
         int v;
         do {
             v = getIntVolatile(o, offset);
-        } while (!compareAndSwapInt(o, offset, v, newValue));
+        } while (!weakCompareAndSwapIntVolatile(o, offset, v, newValue));
         return v;
     }
 
@@ -1900,7 +2398,7 @@
         long v;
         do {
             v = getLongVolatile(o, offset);
-        } while (!compareAndSwapLong(o, offset, v, newValue));
+        } while (!weakCompareAndSwapLongVolatile(o, offset, v, newValue));
         return v;
     }
 
@@ -1920,10 +2418,49 @@
         Object v;
         do {
             v = getObjectVolatile(o, offset);
-        } while (!compareAndSwapObject(o, offset, v, newValue));
+        } while (!weakCompareAndSwapObjectVolatile(o, offset, v, newValue));
         return v;
     }
 
+    @HotSpotIntrinsicCandidate
+    public final byte getAndSetByte(Object o, long offset, byte newValue) {
+        byte v;
+        do {
+            v = getByteVolatile(o, offset);
+        } while (!weakCompareAndSwapByteVolatile(o, offset, v, newValue));
+        return v;
+    }
+
+    @ForceInline
+    public final boolean getAndSetBoolean(Object o, long offset, boolean newValue) {
+        return byte2bool(getAndSetByte(o, offset, bool2byte(newValue)));
+    }
+
+    @HotSpotIntrinsicCandidate
+    public final short getAndSetShort(Object o, long offset, short newValue) {
+        short v;
+        do {
+            v = getShortVolatile(o, offset);
+        } while (!weakCompareAndSwapShortVolatile(o, offset, v, newValue));
+        return v;
+    }
+
+    @ForceInline
+    public final char getAndSetChar(Object o, long offset, char newValue) {
+        return s2c(getAndSetShort(o, offset, c2s(newValue)));
+    }
+
+    @ForceInline
+    public final float getAndSetFloat(Object o, long offset, float newValue) {
+        int v = getAndSetInt(o, offset, Float.floatToRawIntBits(newValue));
+        return Float.intBitsToFloat(v);
+    }
+
+    @ForceInline
+    public final double getAndSetDouble(Object o, long offset, double newValue) {
+        long v = getAndSetLong(o, offset, Double.doubleToRawLongBits(newValue));
+        return Double.longBitsToDouble(v);
+    }
 
     /**
      * Ensures that loads before the fence will not be reordered with loads and
--- a/src/java.base/share/classes/jdk/internal/misc/VM.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/jdk/internal/misc/VM.java	Thu Jul 07 18:35:29 2016 +0000
@@ -30,120 +30,6 @@
 
 public class VM {
 
-    /* The following methods used to be native methods that instruct
-     * the VM to selectively suspend certain threads in low-memory
-     * situations. They are inherently dangerous and not implementable
-     * on native threads. We removed them in JDK 1.2. The skeletons
-     * remain so that existing applications that use these methods
-     * will still work.
-     */
-    private static boolean suspended = false;
-
-    /** @deprecated */
-    @Deprecated
-    public static boolean threadsSuspended() {
-        return suspended;
-    }
-
-    @SuppressWarnings("deprecation")
-    public static boolean allowThreadSuspension(ThreadGroup g, boolean b) {
-        return g.allowThreadSuspension(b);
-    }
-
-    /** @deprecated */
-    @Deprecated
-    public static boolean suspendThreads() {
-        suspended = true;
-        return true;
-    }
-
-    // Causes any suspended threadgroups to be resumed.
-    /** @deprecated */
-    @Deprecated
-    public static void unsuspendThreads() {
-        suspended = false;
-    }
-
-    // Causes threadgroups no longer marked suspendable to be resumed.
-    /** @deprecated */
-    @Deprecated
-    public static void unsuspendSomeThreads() {
-    }
-
-    /* Deprecated fields and methods -- Memory advice not supported in 1.2 */
-
-    /** @deprecated */
-    @Deprecated
-    public static final int STATE_GREEN = 1;
-
-    /** @deprecated */
-    @Deprecated
-    public static final int STATE_YELLOW = 2;
-
-    /** @deprecated */
-    @Deprecated
-    public static final int STATE_RED = 3;
-
-    /** @deprecated */
-    @Deprecated
-    public static final int getState() {
-        return STATE_GREEN;
-    }
-
-    /** @deprecated */
-    @Deprecated
-    public static void registerVMNotification(VMNotification n) { }
-
-    /** @deprecated */
-    @Deprecated
-    public static void asChange(int as_old, int as_new) { }
-
-    /** @deprecated */
-    @Deprecated
-    public static void asChange_otherthread(int as_old, int as_new) { }
-
-    /*
-     * Not supported in 1.2 because these will have to be exported as
-     * JVM functions, and we are not sure we want do that. Leaving
-     * here so it can be easily resurrected -- just remove the //
-     * comments.
-     */
-
-    /**
-     * Resume Java profiling.  All profiling data is added to any
-     * earlier profiling, unless <code>resetJavaProfiler</code> is
-     * called in between.  If profiling was not started from the
-     * command line, <code>resumeJavaProfiler</code> will start it.
-     * <p>
-     *
-     * NOTE: Profiling must be enabled from the command line for a
-     * java.prof report to be automatically generated on exit; if not,
-     * writeJavaProfilerReport must be invoked to write a report.
-     *
-     * @see     resetJavaProfiler
-     * @see     writeJavaProfilerReport
-     */
-
-    // public native static void resumeJavaProfiler();
-
-    /**
-     * Suspend Java profiling.
-     */
-    // public native static void suspendJavaProfiler();
-
-    /**
-     * Initialize Java profiling.  Any accumulated profiling
-     * information is discarded.
-     */
-    // public native static void resetJavaProfiler();
-
-    /**
-     * Write the current profiling contents to the file "java.prof".
-     * If the file already exists, it will be overwritten.
-     */
-    // public native static void writeJavaProfilerReport();
-
-
     // the init level when the VM is fully initialized
     private static final int JAVA_LANG_SYSTEM_INITED     = 1;
     private static final int MODULE_SYSTEM_INITED        = 2;
--- a/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -351,11 +351,14 @@
             new LinkedHashMap<>();
         for (TypeAnnotation t : typeAnnos) {
             Annotation a = t.getAnnotation();
-            Class<? extends Annotation> klass = a.annotationType();
-            AnnotationType type = AnnotationType.getInstance(klass);
-            if (type.retention() == RetentionPolicy.RUNTIME)
-                if (result.put(klass, a) != null)
+            if (a != null) {
+                Class<? extends Annotation> klass = a.annotationType();
+                AnnotationType type = AnnotationType.getInstance(klass);
+                if (type.retention() == RetentionPolicy.RUNTIME &&
+                    result.put(klass, a) != null) {
                     throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
+                }
+            }
         }
         return result;
     }
--- a/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java	Thu Jul 07 18:35:29 2016 +0000
@@ -377,11 +377,12 @@
 
             instantiateIfNecessary(null);
 
-            // Step 7: Auto reseed
+            // Step 7: Auto reseed (reseedCounter might overflow)
             // Double checked locking, safe because reseedCounter is volatile
-            if (reseedCounter > reseedInterval || pr) {
+            if (reseedCounter < 0 || reseedCounter > reseedInterval || pr) {
                 synchronized (this) {
-                    if (reseedCounter > reseedInterval || pr) {
+                    if (reseedCounter < 0 || reseedCounter > reseedInterval
+                            || pr) {
                         reseedAlgorithm(getEntropyInput(pr), ai);
                         ai = null;
                     }
--- a/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java	Thu Jul 07 18:35:29 2016 +0000
@@ -27,7 +27,8 @@
 
 import sun.security.util.HexDumpEncoder;
 
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 
 public abstract class AbstractHashDrbg extends AbstractDrbg {
@@ -113,16 +114,13 @@
         // 800-90Ar1 10.1.2.3: Hmac_DRBG Instantiate Process.
 
         // Step 1: entropy_input || nonce || personalization_string.
-        byte[] seed = Arrays.copyOf(entropy, entropy.length + nonce.length +
-                ((personalizationString == null) ? 0
-                        : personalizationString.length));
-        System.arraycopy(nonce, 0, seed, entropy.length, nonce.length);
+        List<byte[]> inputs = new ArrayList<>(3);
+        inputs.add(entropy);
+        inputs.add(nonce);
         if (personalizationString != null) {
-            System.arraycopy(personalizationString, 0,
-                    seed, entropy.length + nonce.length,
-                    personalizationString.length);
+            inputs.add(personalizationString);
         }
-        hashReseedInternal(seed);
+        hashReseedInternal(inputs);
     }
 
     @Override
@@ -140,13 +138,17 @@
         // 800-90Ar1 10.1.2.4: Hmac_DRBG Reseed Process.
 
         // Step 1: entropy_input || additional_input.
+        List<byte[]> inputs = new ArrayList<>(2);
+        inputs.add(ei);
         if (additionalInput != null) {
-            ei = Arrays.copyOf(ei, ei.length + additionalInput.length);
-            System.arraycopy(additionalInput, 0, ei,
-                    ei.length - additionalInput.length, additionalInput.length);
+            inputs.add(additionalInput);
         }
-        hashReseedInternal(ei);
+        hashReseedInternal(inputs);
     }
 
-    protected abstract void hashReseedInternal(byte[] seed);
+    /**
+     * Operates on multiple inputs.
+     * @param inputs not null, each element neither null
+     */
+    protected abstract void hashReseedInternal(List<byte[]> inputs);
 }
--- a/src/java.base/share/classes/sun/security/provider/CtrDrbg.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/provider/CtrDrbg.java	Thu Jul 07 18:35:29 2016 +0000
@@ -242,6 +242,11 @@
             if (personalizationString == null) {
                 more = nonce;
             } else {
+                if (nonce.length + personalizationString.length < 0) {
+                    // Length must be represented as a 32 bit integer in df()
+                    throw new IllegalArgumentException(
+                            "nonce plus personalization string is too long");
+                }
                 more = Arrays.copyOf(
                         nonce, nonce.length + personalizationString.length);
                 System.arraycopy(personalizationString, 0, more, nonce.length,
@@ -256,50 +261,73 @@
         reseedAlgorithm(ei, more);
     }
 
+    /**
+     * Block_cipher_df in 10.3.2
+     *
+     * @param input the input string
+     * @return the output block (always of seedLen)
+     */
     private byte[] df(byte[] input) {
+        // 800-90Ar1 10.3.2
+        // 2. L = len (input_string)/8
         int l = input.length;
+        // 3. N = number_of_bits_to_return/8
         int n = seedLen;
-        int slen = 4 + 4 + l + 1;
-        byte[] s = new byte[(slen + blockLen - 1) / blockLen * blockLen];
-        s[0] = (byte)(l >> 24);
-        s[1] = (byte)(l >> 16);
-        s[2] = (byte)(l >> 8);
-        s[3] = (byte)(l);
-        s[4] = (byte)(n >> 24);
-        s[5] = (byte)(n >> 16);
-        s[6] = (byte)(n >> 8);
-        s[7] = (byte)(n);
-        System.arraycopy(input, 0, s, 8, l);
-        s[8+l] = (byte)0x80;
+        // 4. S = L || N || input_string || 0x80
+        byte[] ln = new byte[8];
+        ln[0] = (byte)(l >> 24);
+        ln[1] = (byte)(l >> 16);
+        ln[2] = (byte)(l >> 8);
+        ln[3] = (byte)(l);
+        ln[4] = (byte)(n >> 24);
+        ln[5] = (byte)(n >> 16);
+        ln[6] = (byte)(n >> 8);
+        ln[7] = (byte)(n);
 
+        // 5. Zero padding of S
+        // Not necessary, see bcc
+
+        // 8. K = leftmost (0x00010203...1D1E1F, keylen).
         byte[] k = new byte[keyLen];
         for (int i = 0; i < k.length; i++) {
             k[i] = (byte)i;
         }
 
+        // 6. temp = the Null String
         byte[] temp = new byte[seedLen];
 
+        // 7. i = 0
         for (int i = 0; i * blockLen < temp.length; i++) {
-            byte[] iv = new byte[blockLen + s.length];
+            // 9.1 IV = i || 0^(outlen - len (i)). outLen is blockLen
+            byte[] iv = new byte[blockLen];
             iv[0] = (byte)(i >> 24);
             iv[1] = (byte)(i >> 16);
             iv[2] = (byte)(i >> 8);
             iv[3] = (byte)(i);
-            System.arraycopy(s, 0, iv, blockLen, s.length);
+
             int tailLen = temp.length - blockLen*i;
             if (tailLen > blockLen) {
                 tailLen = blockLen;
             }
-            System.arraycopy(bcc(k, iv), 0, temp, blockLen*i, tailLen);
+            // 9.2 temp = temp || BCC (K, (IV || S)).
+            System.arraycopy(bcc(k, iv, ln, input, new byte[]{(byte)0x80}),
+                    0, temp, blockLen*i, tailLen);
         }
 
+        // 10. K = leftmost(temp, keylen)
         k = Arrays.copyOf(temp, keyLen);
+
+        // 11. x = select(temp, keylen+1, keylen+outlen)
         byte[] x = Arrays.copyOfRange(temp, keyLen, temp.length);
 
+        // 12. temp = the Null string
+        // No need to clean up, temp will be overwritten
+
         for (int i = 0; i * blockLen < seedLen; i++) {
             try {
                 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(k, keyAlg));
                 int tailLen = temp.length - blockLen*i;
+                // 14. requested_bits = leftmost(temp, nuumber_of_bits_to_return)
                 if (tailLen > blockLen) {
                     tailLen = blockLen;
                 }
@@ -309,21 +337,45 @@
                 throw new InternalError(e);
             }
         }
+
+        // 15. Return
         return temp;
     }
 
-    private byte[] bcc(byte[] k, byte[] data) {
+    /**
+     * Block_Encrypt in 10.3.3
+     *
+     * @param k the key
+     * @param data after concatenated, the data to be operated upon. This is
+     *             a series of byte[], each with an arbitrary length. Note
+     *             that the full length is not necessarily a multiple of
+     *             outlen. XOR with zero is no-op.
+     * @return the result
+     */
+    private byte[] bcc(byte[] k, byte[]... data) {
         byte[] chain = new byte[blockLen];
-        int n = data.length / blockLen;
-        for (int i = 0; i < n; i++) {
-            byte[] inputBlock = Arrays.copyOfRange(
-                    data, i * blockLen, i * blockLen + blockLen);
-            for (int j = 0; j < blockLen; j++) {
-                inputBlock[j] ^= chain[j];
+        int n1 = 0; // index in data
+        int n2 = 0; // index in data[n1]
+        // pack blockLen of bytes into chain from data[][], again and again
+        while (n1 < data.length) {
+            int j;
+            out: for (j = 0; j < blockLen; j++) {
+                while (n2 >= data[n1].length) {
+                    n1++;
+                    if (n1 >= data.length) {
+                        break out;
+                    }
+                    n2 = 0;
+                }
+                chain[j] ^= data[n1][n2];
+                n2++;
+            }
+            if (j == 0) { // all data happens to be consumed in the last loop
+                break;
             }
             try {
                 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(k, keyAlg));
-                chain = cipher.doFinal(inputBlock);
+                chain = cipher.doFinal(chain);
             } catch (GeneralSecurityException e) {
                 throw new InternalError(e);
             }
@@ -341,6 +393,11 @@
 
             // Step 1: cat bytes
             if (additionalInput != null) {
+                if (ei.length + additionalInput.length < 0) {
+                    // Length must be represented as a 32 bit integer in df()
+                    throw new IllegalArgumentException(
+                            "entropy plus additional input is too long");
+                }
                 byte[] temp = Arrays.copyOf(
                         ei, ei.length + additionalInput.length);
                 System.arraycopy(additionalInput, 0, temp, ei.length,
@@ -430,10 +487,10 @@
 
         // Step 3. temp = Null
         int pos = 0;
+        int len = result.length;
 
         // Step 4. Loop
-        while (pos < result.length) {
-            int tailLen = result.length - pos;
+        while (len > 0) {
             // Step 4.1. Increment
             addOne(v, ctrLen);
             try {
@@ -443,10 +500,15 @@
 
                 // Step 4.3 and 5. Cat bytes and leftmost
                 System.arraycopy(out, 0, result, pos,
-                        (tailLen > blockLen) ? blockLen : tailLen);
+                        (len > blockLen) ? blockLen : len);
             } catch (GeneralSecurityException e) {
                 throw new InternalError(e);
             }
+            len -= blockLen;
+            if (len <= 0) {
+                // shortcut, so that pos needn't be updated
+                break;
+            }
             pos += blockLen;
         }
 
--- a/src/java.base/share/classes/sun/security/provider/HashDrbg.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/provider/HashDrbg.java	Thu Jul 07 18:35:29 2016 +0000
@@ -31,7 +31,9 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.SecureRandomParameters;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 public class HashDrbg extends AbstractHashDrbg {
 
@@ -70,7 +72,7 @@
         }
     }
 
-    private byte[] hashDf(int requested, byte[]... inputs) {
+    private byte[] hashDf(int requested, List<byte[]> inputs) {
         return hashDf(digest, outLen, requested, inputs);
     }
 
@@ -79,6 +81,9 @@
      * The function is used inside Hash_DRBG, and can also be used as an
      * approved conditioning function as described in 800-90B 6.4.2.2.
      *
+     * Note: In each current call, requested is seedLen, therefore small,
+     * no need to worry about overflow.
+     *
      * @param digest a {@code MessageDigest} object in reset state
      * @param outLen {@link MessageDigest#getDigestLength} of {@code digest}
      * @param requested requested output length, in bytes
@@ -86,12 +91,18 @@
      * @return the condensed/expanded output
      */
     public static byte[] hashDf(MessageDigest digest, int outLen,
-                                int requested, byte[]... inputs) {
+                                int requested, List<byte[]> inputs) {
+        // 1. temp = the Null string.
+        // 2. len = upper_int(no_of_bits_to_return / outLen)
         int len = (requested + outLen - 1) / outLen;
         byte[] temp = new byte[len * outLen];
+        // 3. counter = 0x01
         int counter = 1;
 
+        // 4. For i = 1 to len do
         for (int i=0; i<len; i++) {
+            // 4.1 temp = temp
+            //      || Hash (counter || no_of_bits_to_return || input_string).
             digest.update((byte) counter);
             digest.update((byte)(requested >> 21)); // requested*8 as int32
             digest.update((byte)(requested >> 13));
@@ -105,14 +116,17 @@
             } catch (DigestException e) {
                 throw new AssertionError("will not happen", e);
             }
+            // 4.2 counter = counter + 1
             counter++;
         }
+        // 5. requested_bits = leftmost (temp, no_of_bits_to_return).
         return temp.length == requested? temp: Arrays.copyOf(temp, requested);
+        // 6. Return
     }
 
     // This method is used by both instantiation and reseeding.
     @Override
-    protected final synchronized void hashReseedInternal(byte[] input) {
+    protected final synchronized void hashReseedInternal(List<byte[]> inputs) {
 
         // 800-90Ar1 10.1.1.2: Instantiate Process.
         // 800-90Ar1 10.1.1.3: Reseed Process.
@@ -121,16 +135,21 @@
         // Step 2: seed = Hash_df (seed_material, seedlen).
         if (v != null) {
             // Step 1 of 10.1.1.3: Prepend 0x01 || V
-            seed = hashDf(seedLen, ONE, v, input);
+            inputs.add(0, ONE);
+            inputs.add(1, v);
+            seed = hashDf(seedLen, inputs);
         } else {
-            seed = hashDf(seedLen, input);
+            seed = hashDf(seedLen, inputs);
         }
 
         // Step 3. V = seed.
         v = seed;
 
         // Step 4. C = Hash_df ((0x00 || V), seedlen).
-        c = hashDf(seedLen, ZERO, v);
+        inputs = new ArrayList<>(2);
+        inputs.add(ZERO);
+        inputs.add(v);
+        c = hashDf(seedLen, inputs);
 
         // Step 5. reseed_counter = 1.
         reseedCounter = 1;
@@ -197,7 +216,7 @@
         }
 
         // Step 3. Hashgen (requested_number_of_bits, V).
-        hashGen(result, result.length, v);
+        hashGen(result, v);
 
         // Step 4. H = Hash (0x03 || V).
         digest.update((byte)3);
@@ -222,10 +241,7 @@
     }
 
     // 800-90Ar1 10.1.1.4: Hashgen
-    private void hashGen(byte[] output, int len, byte[] v) {
-
-        // Step 1. m
-        int m = (len + outLen - 1) / outLen;
+    private void hashGen(byte[] output, byte[] v) {
 
         // Step 2. data = V
         byte[] data = v;
@@ -233,32 +249,36 @@
         // Step 3: W is output not filled
 
         // Step 4: For i = 1 to m
-        for (int i = 0; i < m; i++) {
-            int tailLen = len - i * outLen;
-            if (tailLen < outLen) {
+        int pos = 0;
+        int len = output.length;
+
+        while (len > 0) {
+            if (len < outLen) {
                 // Step 4.1 w = Hash (data).
                 // Step 4.2 W = W || w.
-                System.arraycopy(digest.digest(data), 0, output, i * outLen,
-                        tailLen);
+                System.arraycopy(digest.digest(data), 0, output, pos,
+                        len);
             } else {
                 try {
                     // Step 4.1 w = Hash (data).
                     digest.update(data);
                     // Step 4.2 digest into right position, no need to cat
-                    digest.digest(output, i*outLen, outLen);
+                    digest.digest(output, pos, outLen);
                 } catch (DigestException e) {
                     throw new AssertionError("will not happen", e);
                 }
             }
-            // Unless this is the last around, we will need to increment data.
-            // but we cannot change v, so a copy is made.
-            if (i != m - 1) {
-                if (data == v) {
-                    data = Arrays.copyOf(v, v.length);
-                }
-                // Step 4.3 data = (data + 1) mod 2^seedlen.
-                addBytes(data, seedLen, ONE);
+            len -= outLen;
+            if (len <= 0) {
+                // shortcut, so that data and pos needn't be updated
+                break;
             }
+            // Step 4.3 data = (data + 1) mod 2^seedlen.
+            if (data == v) {
+                data = Arrays.copyOf(v, v.length);
+            }
+            addBytes(data, seedLen, ONE);
+            pos += outLen;
         }
 
         // Step 5: No need to truncate
--- a/src/java.base/share/classes/sun/security/provider/HmacDrbg.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/provider/HmacDrbg.java	Thu Jul 07 18:35:29 2016 +0000
@@ -32,6 +32,8 @@
 import java.security.NoSuchProviderException;
 import java.security.SecureRandomParameters;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 public class HmacDrbg extends AbstractHashDrbg {
 
@@ -56,7 +58,7 @@
     }
 
     // 800-90Ar1 10.1.2.2: HMAC_DRBG Update Process
-    private void update(byte[]... inputs) {
+    private void update(List<byte[]> inputs) {
         try {
             // Step 1. K = HMAC (K, V || 0x00 || provided_data).
             mac.init(new SecretKeySpec(k, macAlg));
@@ -71,7 +73,7 @@
             mac.init(new SecretKeySpec(k, macAlg));
             v = mac.doFinal(v);
 
-            if (inputs.length != 0) {
+            if (!inputs.isEmpty()) {
                 // Step 4. K = HMAC (K, V || 0x01 || provided_data).
                 mac.update(v);
                 mac.update((byte) 1);
@@ -116,7 +118,7 @@
 
     // This method is used by both instantiation and reseeding.
     @Override
-    protected final synchronized void hashReseedInternal(byte[] input) {
+    protected final synchronized void hashReseedInternal(List<byte[]> input) {
 
         // 800-90Ar1 10.1.2.3: Instantiate Process.
         // 800-90Ar1 10.1.2.4: Reseed Process.
@@ -156,16 +158,15 @@
 
         // Step 2. HMAC_DRBG_Update
         if (additionalInput != null) {
-            update(additionalInput);
+            update(Collections.singletonList(additionalInput));
         }
 
         // Step 3. temp = Null.
         int pos = 0;
+        int len = result.length;
 
         // Step 4. Loop
-        while (pos < result.length) {
-            int tailLen = result.length - pos;
-
+        while (len > 0) {
             // Step 4.1 V = HMAC (Key, V).
             try {
                 mac.init(new SecretKeySpec(k, macAlg));
@@ -175,7 +176,13 @@
             v = mac.doFinal(v);
             // Step 4.2 temp = temp || V.
             System.arraycopy(v, 0, result, pos,
-                    tailLen > outLen ? outLen : tailLen);
+                    len > outLen ? outLen : len);
+
+            len -= outLen;
+            if (len <= 0) {
+                // shortcut, so that pos needn't be updated
+                break;
+            }
             pos += outLen;
         }
 
@@ -183,9 +190,9 @@
 
         // Step 6. HMAC_DRBG_Update (additional_input, Key, V).
         if (additionalInput != null) {
-            update(additionalInput);
+            update(Collections.singletonList(additionalInput));
         } else {
-            update();
+            update(Collections.emptyList());
         }
 
         // Step 7. reseed_counter = reseed_counter + 1.
--- a/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Thu Jul 07 18:35:29 2016 +0000
@@ -27,6 +27,7 @@
 
 import java.security.AlgorithmConstraints;
 import java.security.CryptoPrimitive;
+import java.security.Timestamp;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
@@ -77,6 +78,7 @@
     private final PublicKey trustedPubKey;
     private final Date pkixdate;
     private PublicKey prevPubKey;
+    private final Timestamp jarTimestamp;
 
     private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
         Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
@@ -142,6 +144,29 @@
         this.trustedPubKey = null;
         this.constraints = constraints;
         this.pkixdate = null;
+        this.jarTimestamp = null;
+    }
+
+    /**
+     * Create a new {@code AlgorithmChecker} with the given
+     * {@code Timestamp}.
+     * <p>
+     * Note that this constructor will be used to check a certification
+     * path for signed JAR files that are timestamped.
+     *
+     * @param jarTimestamp Timestamp passed for JAR timestamp constraint
+     *                     checking. Set to null if not applicable.
+     */
+    public AlgorithmChecker(Timestamp jarTimestamp) {
+        this.prevPubKey = null;
+        this.trustedPubKey = null;
+        this.constraints = certPathDefaultConstraints;
+        if (jarTimestamp == null) {
+            throw new IllegalArgumentException(
+                    "Timestamp cannot be null");
+        }
+        this.pkixdate = jarTimestamp.getTimestamp();
+        this.jarTimestamp = jarTimestamp;
     }
 
     /**
@@ -162,7 +187,7 @@
 
         if (anchor == null) {
             throw new IllegalArgumentException(
-                        "The trust anchor cannot be null");
+                    "The trust anchor cannot be null");
         }
 
         if (anchor.getTrustedCert() != null) {
@@ -179,6 +204,7 @@
         this.prevPubKey = trustedPubKey;
         this.constraints = constraints;
         this.pkixdate = pkixdate;
+        this.jarTimestamp = null;
     }
 
     /**
@@ -209,6 +235,10 @@
         return AnchorCertificates.contains(cert);
     }
 
+    Timestamp getJarTimestamp() {
+        return jarTimestamp;
+    }
+
     @Override
     public void init(boolean forward) throws CertPathValidatorException {
         //  Note that this class does not support forward mode.
@@ -296,8 +326,7 @@
         // permits() will throw exception on failure.
         certPathDefaultConstraints.permits(primitives,
                 new CertConstraintParameters((X509Certificate)cert,
-                        trustedMatch, pkixdate));
-                // new CertConstraintParameters(x509Cert, trustedMatch));
+                        trustedMatch, pkixdate, jarTimestamp));
         // If there is no previous key, set one and exit
         if (prevPubKey == null) {
             prevPubKey = currPubKey;
@@ -442,7 +471,7 @@
      * Check the signature algorithm with the specified public key.
      *
      * @param key the public key to verify the CRL signature
-     * @param crl the target CRL
+     * @param algorithmId signature algorithm Algorithm ID
      */
     static void check(PublicKey key, AlgorithmId algorithmId)
                         throws CertPathValidatorException {
--- a/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 
 import java.security.InvalidAlgorithmParameterException;
 import java.security.PublicKey;
+import java.security.Timestamp;
 import java.security.cert.*;
 import java.security.interfaces.DSAPublicKey;
 import java.util.*;
@@ -85,6 +86,7 @@
         private CertSelector constraints;
         private Set<TrustAnchor> anchors;
         private List<X509Certificate> certs;
+        private Timestamp timestamp;
 
         ValidatorParams(CertPath cp, PKIXParameters params)
             throws InvalidAlgorithmParameterException
@@ -100,6 +102,10 @@
         ValidatorParams(PKIXParameters params)
             throws InvalidAlgorithmParameterException
         {
+            if (params instanceof PKIXTimestampParameters) {
+                timestamp = ((PKIXTimestampParameters) params).getTimestamp();
+            }
+
             this.anchors = params.getTrustAnchors();
             // Make sure that none of the trust anchors include name constraints
             // (not supported).
@@ -189,6 +195,10 @@
         PKIXParameters getPKIXParameters() {
             return params;
         }
+
+        Timestamp timestamp() {
+            return timestamp;
+        }
     }
 
     static class BuilderParams extends ValidatorParams {
--- a/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Thu Jul 07 18:35:29 2016 +0000
@@ -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
@@ -172,7 +172,11 @@
         List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>();
         // add standard checkers that we will be using
         certPathCheckers.add(untrustedChecker);
-        certPathCheckers.add(new AlgorithmChecker(anchor, params.date()));
+        if (params.timestamp() == null) {
+            certPathCheckers.add(new AlgorithmChecker(anchor, params.date()));
+        } else {
+            certPathCheckers.add(new AlgorithmChecker(params.timestamp()));
+        }
         certPathCheckers.add(new KeyChecker(certPathLen,
                                             params.targetCertConstraints()));
         certPathCheckers.add(new ConstraintsChecker(certPathLen));
@@ -189,8 +193,14 @@
                                              rootNode);
         certPathCheckers.add(pc);
         // default value for date is current time
-        BasicChecker bc = new BasicChecker(anchor, params.date(),
-                                           params.sigProvider(), false);
+        BasicChecker bc;
+        if (params.timestamp() == null) {
+            bc = new BasicChecker(anchor, params.date(), params.sigProvider(),
+                    false);
+        } else {
+            bc = new BasicChecker(anchor, params.timestamp().getTimestamp(),
+                    params.sigProvider(), false);
+        }
         certPathCheckers.add(bc);
 
         boolean revCheckerAdded = false;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java	Thu Jul 07 18:35:29 2016 +0000
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package sun.security.provider.certpath;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.Timestamp;
+import java.security.cert.CertSelector;
+import java.security.cert.CertStore;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.PKIXCertPathChecker;
+import java.security.cert.TrustAnchor;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class is a wrapper for PKIXBuilderParameters so that a Timestamp object
+ * can be passed alone when PKIXCertPath is checking signed jar files.
+ */
+
+public class PKIXTimestampParameters extends PKIXBuilderParameters {
+
+    private final PKIXBuilderParameters p;
+    private Timestamp jarTimestamp;
+
+    public PKIXTimestampParameters(PKIXBuilderParameters params,
+            Timestamp timestamp) throws InvalidAlgorithmParameterException {
+        super(params.getTrustAnchors(), null);
+        p = params;
+        jarTimestamp = timestamp;
+    }
+
+    public Timestamp getTimestamp() {
+        return jarTimestamp;
+    }
+    public void setTimestamp(Timestamp t) {
+        jarTimestamp = t;
+    }
+
+    @Override
+    public void setDate(Date d) {
+        p.setDate(d);
+    }
+
+    @Override
+    public void addCertPathChecker(PKIXCertPathChecker c) {
+        p.addCertPathChecker(c);
+    }
+
+    @Override
+    public void setMaxPathLength(int maxPathLength) {
+        p.setMaxPathLength(maxPathLength);
+    }
+
+    @Override
+    public int getMaxPathLength() {
+        return p.getMaxPathLength();
+    }
+
+    @Override
+    public String toString() {
+        return p.toString();
+    }
+
+    @Override
+    public Set<TrustAnchor> getTrustAnchors() {
+        return p.getTrustAnchors();
+    }
+
+    @Override
+    public void setTrustAnchors(Set<TrustAnchor> trustAnchors)
+            throws InvalidAlgorithmParameterException {
+        // To avoid problems with PKIXBuilderParameter's constructors
+        if (p == null) {
+            return;
+        }
+        p.setTrustAnchors(trustAnchors);
+    }
+
+    @Override
+    public Set<String> getInitialPolicies() {
+        return p.getInitialPolicies();
+    }
+
+    @Override
+    public void setInitialPolicies(Set<String> initialPolicies) {
+        p.setInitialPolicies(initialPolicies);
+    }
+
+    @Override
+    public void setCertStores(List<CertStore> stores) {
+        p.setCertStores(stores);
+    }
+
+    @Override
+    public void addCertStore(CertStore store) {
+        p.addCertStore(store);
+    }
+
+    @Override
+    public List<CertStore> getCertStores() {
+        return p.getCertStores();
+    }
+
+    @Override
+    public void setRevocationEnabled(boolean val) {
+        p.setRevocationEnabled(val);
+    }
+
+    @Override
+    public boolean isRevocationEnabled() {
+        return p.isRevocationEnabled();
+    }
+
+    @Override
+    public void setExplicitPolicyRequired(boolean val) {
+        p.setExplicitPolicyRequired(val);
+    }
+
+    @Override
+    public boolean isExplicitPolicyRequired() {
+        return p.isExplicitPolicyRequired();
+    }
+
+    @Override
+    public void setPolicyMappingInhibited(boolean val) {
+        p.setPolicyMappingInhibited(val);
+    }
+
+    @Override
+    public boolean isPolicyMappingInhibited() {
+        return p.isPolicyMappingInhibited();
+    }
+
+    @Override
+    public void setAnyPolicyInhibited(boolean val) {
+        p.setAnyPolicyInhibited(val);
+    }
+
+    @Override
+    public boolean isAnyPolicyInhibited() {
+        return p.isAnyPolicyInhibited();
+    }
+
+    @Override
+    public void setPolicyQualifiersRejected(boolean qualifiersRejected) {
+        p.setPolicyQualifiersRejected(qualifiersRejected);
+    }
+
+    @Override
+    public boolean getPolicyQualifiersRejected() {
+        return p.getPolicyQualifiersRejected();
+    }
+
+    @Override
+    public Date getDate() {
+        return p.getDate();
+    }
+
+    @Override
+    public void setCertPathCheckers(List<PKIXCertPathChecker> checkers) {
+        p.setCertPathCheckers(checkers);
+    }
+
+    @Override
+    public List<PKIXCertPathChecker> getCertPathCheckers() {
+        return p.getCertPathCheckers();
+    }
+
+    @Override
+    public String getSigProvider() {
+        return p.getSigProvider();
+    }
+
+    @Override
+    public void setSigProvider(String sigProvider) {
+        p.setSigProvider(sigProvider);
+    }
+
+    @Override
+    public CertSelector getTargetCertConstraints() {
+        return p.getTargetCertConstraints();
+    }
+
+    @Override
+    public void setTargetCertConstraints(CertSelector selector) {
+        // To avoid problems with PKIXBuilderParameter's constructors
+        if (p == null) {
+            return;
+        }
+        p.setTargetCertConstraints(selector);
+    }
+
+}
--- a/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java	Thu Jul 07 18:35:29 2016 +0000
@@ -25,6 +25,7 @@
 
 package sun.security.util;
 
+import java.security.Timestamp;
 import java.security.cert.X509Certificate;
 import java.util.Date;
 
@@ -40,16 +41,19 @@
     private final boolean trustedMatch;
     // PKIXParameter date
     private final Date pkixDate;
+    // Timestamp of the signed JAR file
+    private final Timestamp jarTimestamp;
 
     public CertConstraintParameters(X509Certificate c, boolean match,
-            Date pkixdate) {
+            Date pkixdate, Timestamp jarTime) {
         cert = c;
         trustedMatch = match;
         pkixDate = pkixdate;
+        jarTimestamp = jarTime;
     }
 
     public CertConstraintParameters(X509Certificate c) {
-        this(c, false, null);
+        this(c, false, null, null);
     }
 
     // Returns if the trust anchor has a match if anchor checking is enabled.
@@ -65,4 +69,8 @@
         return pkixDate;
     }
 
+    public Timestamp getJARTimestamp() {
+        return jarTimestamp;
+    }
+
 }
--- a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Thu Jul 07 18:35:29 2016 +0000
@@ -594,7 +594,9 @@
                  throws CertPathValidatorException {
              Date currentDate;
 
-             if (cp.getPKIXParamDate() != null) {
+             if (cp.getJARTimestamp() != null) {
+                 currentDate = cp.getJARTimestamp().getTimestamp();
+             } else if (cp.getPKIXParamDate() != null) {
                  currentDate = cp.getPKIXParamDate();
              } else {
                  currentDate = new Date();
--- a/src/java.base/share/classes/sun/security/validator/PKIXValidator.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/validator/PKIXValidator.java	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 import javax.security.auth.x500.X500Principal;
 import sun.security.action.GetBooleanAction;
 import sun.security.provider.certpath.AlgorithmChecker;
+import sun.security.provider.certpath.PKIXTimestampParameters;
 
 /**
  * Validator implementation built on the PKIX CertPath API. This
@@ -194,13 +195,23 @@
                 ("null or zero-length certificate chain");
         }
 
+        // Check if 'parameter' affects 'pkixParameters'
+        PKIXBuilderParameters pkixParameters = null;
+        if (parameter instanceof Timestamp && plugin) {
+            try {
+                pkixParameters = new PKIXTimestampParameters(
+                        (PKIXBuilderParameters) parameterTemplate.clone(),
+                        (Timestamp) parameter);
+            } catch (InvalidAlgorithmParameterException e) {
+                // ignore exception
+            }
+        } else {
+            pkixParameters = (PKIXBuilderParameters) parameterTemplate.clone();
+        }
+
         // add new algorithm constraints checker
-        PKIXBuilderParameters pkixParameters =
-                    (PKIXBuilderParameters) parameterTemplate.clone();
-        AlgorithmChecker algorithmChecker = null;
         if (constraints != null) {
-            algorithmChecker = new AlgorithmChecker(constraints);
-            pkixParameters.addCertPathChecker(algorithmChecker);
+            pkixParameters.addCertPathChecker(new AlgorithmChecker(constraints));
         }
 
         // attach it to the PKIXBuilderParameters.
--- a/src/java.base/share/classes/sun/security/validator/Validator.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/java.base/share/classes/sun/security/validator/Validator.java	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -221,13 +221,6 @@
      * Validate the given certificate chain. If otherCerts is non-null, it is
      * a Collection of additional X509Certificates that could be helpful for
      * path building.
-     * <p>
-     * Parameter is an additional parameter with variant specific meaning.
-     * Currently, it is only defined for TLS_SERVER variant validators, where
-     * it must be non null and the name of the TLS key exchange algorithm being
-     * used (see JSSE X509TrustManager specification). In the future, it
-     * could be used to pass in a PKCS#7 object for code signing to check time
-     * stamps.
      *
      * @return a non-empty chain that was used to validate the path. The
      * end entity cert is at index 0, the trust anchor at index n-1.
@@ -254,12 +247,12 @@
      *        represented with a zero-length byte array.
      * @param constraints algorithm constraints for certification path
      *        processing
-     * @param parameter an additional parameter with variant specific meaning.
-     *        Currently, it is only defined for TLS_SERVER variant validators,
-     *        where it must be non null and the name of the TLS key exchange
-     *        algorithm being used (see JSSE X509TrustManager specification).
-     *        In the future, it could be used to pass in a PKCS#7 object for
-     *        code signing to check time stamps.
+     * @param parameter an additional parameter object to pass specific data.
+     *        This parameter object maybe one of the two below:
+     *        1) TLS_SERVER variant validators, where it must be non null and
+     *        the name of the TLS key exchange algorithm being used
+     *        (see JSSE X509TrustManager specification).
+     *        2) {@code Timestamp} object from a signed JAR file.
      * @return a non-empty chain that was used to validate the path. The
      *        end entity cert is at index 0, the trust anchor at index n-1.
      */
--- a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -870,8 +870,9 @@
  "onuncaught=y|n                   debug on any uncaught?            n\n"
  "timeout=<timeout value>          for listen/attach in milliseconds n\n"
  "mutf8=y|n                        output modified utf-8             n\n"
- "quiet=y|n                        control over terminal messages    n\n"
- "\n"
+ "quiet=y|n                        control over terminal messages    n\n"));
+
+    TTY_MESSAGE((
  "Obsolete Options\n"
  "----------------\n"
  "strict=y|n\n"
@@ -914,7 +915,9 @@
  "                               locations     = 0x020\n"
  "                               callbacks     = 0x040\n"
  "                               errors        = 0x080\n"
- "                               everything    = 0xfff\n"
+ "                               everything    = 0xfff"));
+
+    TTY_MESSAGE((
  "debugflags=flags             debug flags (bitmask)           none\n"
  "                               USE_ITERATE_THROUGH_HEAP 0x01\n"
  "\n"
--- a/src/jdk.jdwp.agent/share/native/libjdwp/error_messages.c	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/error_messages.c	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, 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
@@ -50,8 +50,12 @@
 #include "utf_util.h"
 #include "proc_md.h"
 
-/* Maximim length of a message */
-#define MAX_MESSAGE_LEN MAXPATHLEN*2+512
+/* Maximum number of bytes in a message, including the trailing zero.
+ * Do not print very long messages as they could be truncated.
+ * Use at most one pathname per message. NOTE, we use MAXPATHLEN*2
+ * in case each character in the pathname takes 2 bytes.
+ */
+#define MAX_MESSAGE_BUF MAXPATHLEN*2+512
 
 /* Print message in platform encoding (assume all input is UTF-8 safe)
  *    NOTE: This function is at the lowest level of the call tree.
@@ -61,17 +65,16 @@
 vprint_message(FILE *fp, const char *prefix, const char *suffix,
                const char *format, va_list ap)
 {
-    jbyte  utf8buf[MAX_MESSAGE_LEN+1];
+    jbyte  utf8buf[MAX_MESSAGE_BUF];
     int    len;
-    char   pbuf[MAX_MESSAGE_LEN+1];
+    char   pbuf[MAX_MESSAGE_BUF];
 
     /* Fill buffer with single UTF-8 string */
-    (void)vsnprintf((char*)utf8buf, MAX_MESSAGE_LEN, format, ap);
-    utf8buf[MAX_MESSAGE_LEN] = 0;
+    (void)vsnprintf((char*)utf8buf, sizeof(utf8buf), format, ap);
     len = (int)strlen((char*)utf8buf);
 
     /* Convert to platform encoding (ignore errors, dangerous area) */
-    (void)utf8ToPlatform(utf8buf, len, pbuf, MAX_MESSAGE_LEN);
+    (void)utf8ToPlatform(utf8buf, len, pbuf, (int)sizeof(pbuf));
 
     (void)fprintf(fp, "%s%s%s", prefix, pbuf, suffix);
 }
--- a/src/jdk.jdwp.agent/share/native/libjdwp/transport.c	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/transport.c	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,8 +67,7 @@
         maxlen = len+len/2+2; /* Should allow for plenty of room */
         utf8msg = (jbyte*)jvmtiAllocate(maxlen+1);
         if (utf8msg != NULL) {
-           (void)utf8FromPlatform(msg, len, utf8msg, maxlen);
-           utf8msg[maxlen] = 0;
+           (void)utf8FromPlatform(msg, len, utf8msg, maxlen+1);
         }
     }
     if (rv == JDWPTRANSPORT_ERROR_NONE) {
--- a/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.c	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.c	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -350,16 +350,20 @@
 
 /*
  * Convert UTF-8 to a platform string
+ * NOTE: outputBufSize includes the space for the trailing 0.
  */
-int JNICALL utf8ToPlatform(jbyte *utf8, int len, char* output, int outputMaxLen) {
+int JNICALL utf8ToPlatform(jbyte *utf8, int len, char* output, int outputBufSize) {
     int wlen;
     int plen;
     WCHAR* wstr;
     UINT codepage;
+    int outputMaxLen;
 
     UTF_ASSERT(utf8);
     UTF_ASSERT(output);
-    UTF_ASSERT(outputMaxLen > len);
+    UTF_ASSERT(len >= 0);
+    UTF_ASSERT(outputBufSize > len);
+    outputMaxLen = outputBufSize - 1; // leave space for trailing 0
 
     /* Zero length is ok, but we don't need to do much */
     if ( len == 0 ) {
@@ -394,16 +398,20 @@
 
 /*
  * Convert Platform Encoding to UTF-8.
+ * NOTE: outputBufSize includes the space for the trailing 0.
  */
-int JNICALL utf8FromPlatform(char *str, int len, jbyte *output, int outputMaxLen) {
+int JNICALL utf8FromPlatform(char *str, int len, jbyte *output, int outputBufSize) {
     int wlen;
     int plen;
     WCHAR* wstr;
     UINT codepage;
+    int outputMaxLen;
 
     UTF_ASSERT(str);
     UTF_ASSERT(output);
-    UTF_ASSERT(outputMaxLen > len);
+    UTF_ASSERT(len >= 0);
+    UTF_ASSERT(outputBufSize > len);
+    outputMaxLen = outputBufSize - 1; // leave space for trailing 0
 
     /* Zero length is ok, but we don't need to do much */
     if ( len == 0 ) {
@@ -449,18 +457,21 @@
 /*
  * Do iconv() conversion.
  *    Returns length or -1 if output overflows.
+ * NOTE: outputBufSize includes the space for the trailing 0.
  */
-static int iconvConvert(conv_direction drn, char *bytes, size_t len, char *output, size_t outputMaxLen) {
+static int iconvConvert(conv_direction drn, char *bytes, size_t len, char *output, size_t outputBufSize) {
 
     static char *codeset = 0;
     iconv_t func;
     size_t bytes_converted;
     size_t inLeft, outLeft;
     char *inbuf, *outbuf;
+    int outputMaxLen;
 
     UTF_ASSERT(bytes);
     UTF_ASSERT(output);
-    UTF_ASSERT(outputMaxLen > len);
+    UTF_ASSERT(outputBufSize > len);
+    outputMaxLen = outputBufSize - 1; // leave space for trailing 0
 
     /* Zero length is ok, but we don't need to do much */
     if ( len == 0 ) {
@@ -524,17 +535,19 @@
 /*
  * Convert UTF-8 to Platform Encoding.
  *    Returns length or -1 if output overflows.
+ * NOTE: outputBufSize includes the space for the trailing 0.
  */
-int JNICALL utf8ToPlatform(jbyte *utf8, int len, char *output, int outputMaxLen) {
-    return iconvConvert(FROM_UTF8, (char*)utf8, len, output, outputMaxLen);
+int JNICALL utf8ToPlatform(jbyte *utf8, int len, char *output, int outputBufSize) {
+    return iconvConvert(FROM_UTF8, (char*)utf8, len, output, outputBufSize);
 }
 
 /*
  * Convert Platform Encoding to UTF-8.
  *    Returns length or -1 if output overflows.
+ * NOTE: outputBufSize includes the space for the trailing 0.
  */
-int JNICALL utf8FromPlatform(char *str, int len, jbyte *output, int outputMaxLen) {
-    return iconvConvert(TO_UTF8, str, len, (char*) output, outputMaxLen);
+int JNICALL utf8FromPlatform(char *str, int len, jbyte *output, int outputBufSize) {
+    return iconvConvert(TO_UTF8, str, len, (char*) output, outputBufSize);
 }
 
 #endif
--- a/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.h	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.h	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 int JNICALL utf8mToUtf8sLength(jbyte *string, int length);
 void JNICALL utf8mToUtf8s(jbyte *string, int length, jbyte *newString, int newLength);
 
-int JNICALL utf8ToPlatform(jbyte *utf8, int len, char* output, int outputMaxLen);
-int JNICALL utf8FromPlatform(char *str, int len, jbyte *output, int outputMaxLen);
+int JNICALL utf8ToPlatform(jbyte *utf8, int len, char* output, int outputBufSize);
+int JNICALL utf8FromPlatform(char *str, int len, jbyte *output, int outputBufSize);
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java	Thu Jul 07 18:35:29 2016 +0000
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.Plugin.Category;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import static jdk.internal.org.objectweb.asm.ClassReader.*;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.Type;
+import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
+import jdk.internal.org.objectweb.asm.tree.ClassNode;
+import jdk.internal.org.objectweb.asm.tree.InsnList;
+import jdk.internal.org.objectweb.asm.tree.LabelNode;
+import jdk.internal.org.objectweb.asm.tree.LdcInsnNode;
+import jdk.internal.org.objectweb.asm.tree.LineNumberNode;
+import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
+import jdk.internal.org.objectweb.asm.tree.MethodNode;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.Plugin;
+
+public final class ClassForNamePlugin implements Plugin {
+    public static final String NAME = "class-for-name";
+
+    private static String binaryClassName(String path) {
+        return path.substring(path.indexOf('/', 1) + 1,
+                              path.length() - ".class".length());
+    }
+
+    private static int getAccess(ModuleEntry resource) {
+        ClassReader cr = new ClassReader(resource.getBytes());
+
+        return cr.getAccess();
+    }
+
+    private static String getPackage(String binaryName) {
+        int index = binaryName.lastIndexOf("/");
+
+        return index == -1 ? "" : binaryName.substring(0, index);
+    }
+
+    private ModuleEntry transform(ModuleEntry resource, Map<String, ModuleEntry> classes) {
+        byte[] inBytes = resource.getBytes();
+        ClassReader cr = new ClassReader(inBytes);
+        ClassNode cn = new ClassNode();
+        cr.accept(cn, EXPAND_FRAMES);
+        List<MethodNode> ms = cn.methods;
+        boolean modified = false;
+        LdcInsnNode ldc = null;
+
+        String thisPackage = getPackage(binaryClassName(resource.getPath()));
+
+        for (MethodNode mn : ms) {
+            InsnList il = mn.instructions;
+            Iterator<AbstractInsnNode> it = il.iterator();
+
+            while (it.hasNext()) {
+                AbstractInsnNode insn = it.next();
+
+                if (insn instanceof LdcInsnNode) {
+                    ldc = (LdcInsnNode)insn;
+                } else if (insn instanceof MethodInsnNode && ldc != null) {
+                    MethodInsnNode min = (MethodInsnNode)insn;
+
+                    if (min.getOpcode() == Opcodes.INVOKESTATIC &&
+                        min.name.equals("forName") &&
+                        min.owner.equals("java/lang/Class") &&
+                        min.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
+                        String ldcClassName = ldc.cst.toString();
+                        String thatClassName = ldcClassName.replaceAll("\\.", "/");
+                        ModuleEntry thatClass = classes.get(thatClassName);
+
+                        if (thatClass != null) {
+                            int thatAccess = getAccess(thatClass);
+                            String thatPackage = getPackage(thatClassName);
+
+                            if ((thatAccess & Opcodes.ACC_PRIVATE) != Opcodes.ACC_PRIVATE &&
+                                ((thatAccess & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC ||
+                                  thisPackage.equals(thatPackage))) {
+                                Type type = Type.getObjectType(thatClassName);
+                                il.remove(ldc);
+                                il.set(min, new LdcInsnNode(type));
+                                modified = true;
+                            }
+                        }
+                    }
+
+                    ldc = null;
+                } else if (!(insn instanceof LabelNode) &&
+                           !(insn instanceof LineNumberNode)) {
+                    ldc = null;
+                }
+
+            }
+        }
+
+        if (modified) {
+            ClassWriter cw = new ClassWriter(cr, 0);
+            cn.accept(cw);
+            byte[] outBytes = cw.toByteArray();
+
+            return resource.create(outBytes);
+        }
+
+        return resource;
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void visit(ModulePool in, ModulePool out) {
+        Objects.requireNonNull(in);
+        Objects.requireNonNull(out);
+        Map<String, ModuleEntry> classes = in.entries()
+            .filter(resource -> resource != null &&
+                    resource.getPath().endsWith(".class") &&
+                    !resource.getPath().endsWith("/module-info.class"))
+            .collect(Collectors.toMap(resource -> binaryClassName(resource.getPath()),
+                                      resource -> resource));
+        in.entries()
+            .filter(resource -> resource != null)
+            .forEach(resource -> {
+                String path = resource.getPath();
+
+                if (path.endsWith(".class") && !path.endsWith("/module-info.class")) {
+                    out.add(transform(resource, classes));
+                } else {
+                    out.add(resource);
+                }
+            });
+    }
+
+    @Override
+    public Category getType() {
+        return Category.TRANSFORMER;
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return false;
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+
+    }
+}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,285 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.Consumer;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
-import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
-import jdk.tools.jlink.internal.plugins.optim.ForNameFolding;
-import jdk.tools.jlink.internal.plugins.optim.ReflectionOptimizer.TypeResolver;
-import jdk.tools.jlink.plugin.PluginException;
-
-/**
- *
- * Optimize Classes following various strategies. Strategies are implementation
- * of <code>ClassOptimizer</code> and <code>MethodOptimizer</code>.
- */
-public final class OptimizationPlugin extends AsmPlugin {
-
-    public static final String NAME = "class-optim";
-    public static final String LOG  = "log";
-    public static final String ALL = "all";
-    public static final String FORNAME_REMOVAL = "forName-folding";
-
-    /**
-     * Default resolver. A resolver that retrieve types that are in an
-     * accessible package, are public or are located in the same package as the
-     * caller.
-     */
-    private static final class DefaultTypeResolver implements TypeResolver {
-
-        private final Set<String> packages;
-        private final AsmPools pools;
-
-        DefaultTypeResolver(AsmPools pools, AsmModulePool modulePool) {
-            Objects.requireNonNull(pools);
-            Objects.requireNonNull(modulePool);
-            this.pools = pools;
-            packages = pools.getGlobalPool().getAccessiblePackages(modulePool.getModuleName());
-        }
-
-        @Override
-        public ClassReader resolve(ClassNode cn, MethodNode mn, String type) {
-            int classIndex = cn.name.lastIndexOf("/");
-            String callerPkg = classIndex == -1 ? ""
-                    : cn.name.substring(0, classIndex);
-            int typeClassIndex = type.lastIndexOf("/");
-            String pkg = typeClassIndex == - 1 ? ""
-                    : type.substring(0, typeClassIndex);
-            ClassReader reader = null;
-            if (packages.contains(pkg) || pkg.equals(callerPkg)) {
-                ClassReader r = pools.getGlobalPool().getClassReader(type);
-                if (r != null) {
-                    // if not private
-                    if ((r.getAccess() & Opcodes.ACC_PRIVATE)
-                            != Opcodes.ACC_PRIVATE) {
-                        // public
-                        if (((r.getAccess() & Opcodes.ACC_PUBLIC)
-                                == Opcodes.ACC_PUBLIC)) {
-                            reader = r;
-                        } else if (pkg.equals(callerPkg)) {
-                            reader = r;
-                        }
-                    }
-                }
-            }
-            return reader;
-        }
-    }
-
-    public interface Optimizer {
-
-        void close() throws IOException;
-    }
-
-    public interface ClassOptimizer extends Optimizer {
-
-        boolean optimize(Consumer<String> logger, AsmPools pools,
-                AsmModulePool modulePool,
-                ClassNode cn) throws Exception;
-    }
-
-    public interface MethodOptimizer extends Optimizer {
-
-        boolean optimize(Consumer<String> logger, AsmPools pools,
-                AsmModulePool modulePool,
-                ClassNode cn, MethodNode m, TypeResolver resolver) throws Exception;
-    }
-
-    private List<Optimizer> optimizers = new ArrayList<>();
-
-    private OutputStream stream;
-    private int numMethods;
-
-    private void log(String content) {
-        if (stream != null) {
-            try {
-                content = content + "\n";
-                stream.write(content.getBytes(StandardCharsets.UTF_8));
-            } catch (IOException ex) {
-                System.err.println(ex);
-            }
-        }
-    }
-
-    private void close() throws IOException {
-        log("Num analyzed methods " + numMethods);
-
-        for (Optimizer optimizer : optimizers) {
-            try {
-                optimizer.close();
-            } catch (IOException ex) {
-                System.err.println("Error closing optimizer " + ex);
-            }
-        }
-        if (stream != null) {
-            stream.close();
-        }
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-    public void visit(AsmPools pools) {
-        try {
-            for (AsmModulePool p : pools.getModulePools()) {
-                DefaultTypeResolver resolver = new DefaultTypeResolver(pools, p);
-                p.visitClassReaders((reader) -> {
-                    ClassWriter w = null;
-                    try {
-                        w = optimize(pools, p, reader, resolver);
-                    } catch (IOException ex) {
-                        throw new PluginException("Problem optimizing "
-                                + reader.getClassName(), ex);
-                    }
-                    return w;
-                });
-            }
-        } finally {
-            try {
-                close();
-            } catch (IOException ex) {
-                throw new UncheckedIOException(ex);
-            }
-        }
-    }
-
-    private ClassWriter optimize(AsmPools pools, AsmModulePool modulePool,
-            ClassReader reader, TypeResolver resolver)
-            throws IOException {
-        ClassNode cn = new ClassNode();
-        ClassWriter writer = null;
-        if ((reader.getAccess() & Opcodes.ACC_INTERFACE) == 0) {
-            reader.accept(cn, ClassReader.EXPAND_FRAMES);
-            boolean optimized = false;
-            for (Optimizer optimizer : optimizers) {
-                if (optimizer instanceof ClassOptimizer) {
-                    try {
-                        boolean optim = ((ClassOptimizer) optimizer).
-                                optimize(this::log, pools, modulePool, cn);
-                        if (optim) {
-                            optimized = true;
-                        }
-                    } catch (Throwable ex) {
-                        throw new PluginException("Exception optimizing "
-                                + reader.getClassName(), ex);
-                    }
-                } else {
-                    MethodOptimizer moptimizer = (MethodOptimizer) optimizer;
-                    for (MethodNode m : cn.methods) {
-                        if ((m.access & Opcodes.ACC_ABSTRACT) == 0
-                                && (m.access & Opcodes.ACC_NATIVE) == 0) {
-                            numMethods += 1;
-                            try {
-                                boolean optim = moptimizer.
-                                        optimize(this::log, pools, modulePool, cn,
-                                                m, resolver);
-                                if (optim) {
-                                    optimized = true;
-                                }
-                            } catch (Throwable ex) {
-                                throw new PluginException("Exception optimizing "
-                                        + reader.getClassName() + "." + m.name, ex);
-                            }
-
-                        }
-                    }
-                }
-            }
-
-            if (optimized) {
-                writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
-                try {
-                    // add a validation layer in between to check for class vallidity
-                    CheckClassAdapter ca = new CheckClassAdapter(writer);
-                    cn.accept(ca);
-                } catch (Exception ex) {
-                    throw new PluginException("Exception optimizing class " + cn.name, ex);
-                }
-            }
-        }
-        return writer;
-    }
-
-    @Override
-    public String getDescription() {
-        return PluginsResourceBundle.getDescription(NAME);
-    }
-
-    @Override
-    public boolean hasArguments() {
-        return true;
-    }
-
-    @Override
-    public String getArgumentsDescription() {
-       return PluginsResourceBundle.getArgument(NAME);
-    }
-
-    @Override
-    public void configure(Map<String, String> config) {
-        String strategies = config.get(NAME);
-        String[] arr = strategies.split(",");
-        for (String s : arr) {
-            if (s.equals(ALL)) {
-                optimizers.clear();
-                optimizers.add(new ForNameFolding());
-                break;
-            } else if (s.equals(FORNAME_REMOVAL)) {
-                optimizers.add(new ForNameFolding());
-            } else {
-                throw new IllegalArgumentException("Unknown optimization: " + s);
-            }
-        }
-        String f = config.get(LOG);
-        if (f != null) {
-            try {
-                stream = new FileOutputStream(f);
-            } catch (IOException ex) {
-                throw new UncheckedIOException(ex);
-            }
-        }
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmGlobalPool.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins.asm;
-
-import java.util.Set;
-
-/**
- * A pool containing all class and resource files.
- */
-public interface AsmGlobalPool extends AsmPool {
-
-    /**
-     * Associate a package to a module, useful when adding new classes in new
-     * packages. WARNING: In order to properly handle new package and/or new
-     * module, module-info class must be added and/or updated.
-     *
-     * @param pkg The new package, following java binary syntax (/-separated
-     * path name).
-     * @param module An existing or new module.
-     * @throws jdk.tools.jlink.plugins.PluginException If a mapping already
-     * exist for this package.
-     */
-    public void addPackageModuleMapping(String pkg, String module);
-
-    /**
-     * Return the set of accessible packages for a given module.
-     *
-     * @param module The module from which packages are accessible.
-     * @return Set of packages or null if the module is not found.
-     */
-    public Set<String> getAccessiblePackages(String module);
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmModulePool.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins.asm;
-
-import java.lang.module.ModuleDescriptor;
-import java.util.Set;
-import jdk.internal.org.objectweb.asm.ClassReader;
-
-/**
- * A pool for a given module
- */
-public interface AsmModulePool extends AsmPool {
-
-    /**
-     * Associate a package to this module, useful when adding new classes in new
-     * packages. WARNING: In order to properly handle new package and/or new
-     * module, module-info class must be added and/or updated.
-     *
-     * @param pkg The new package, following java binary syntax (/-separated
-     * path name).
-     * @throws jdk.tools.jlink.plugins.PluginException If a mapping already
-     * exist for this package.
-     */
-    public void addPackage(String pkg);
-
-    /**
-     * The module name of this pool.
-     * @return The module name;
-     */
-    public String getModuleName();
-
-    /**
-     * Lookup the class in this pool and the required pools. NB: static module
-     * readability can be different at execution time.
-     *
-     * @param binaryName The class to lookup.
-     * @return The reader or null if not found
-     * @throws jdk.tools.jlink.plugins.PluginException
-     */
-    public ClassReader getClassReaderInDependencies(String binaryName);
-
-    /**
-     * Lookup the class in the exported packages of this module. "public
-     * requires" modules are looked up. NB: static module readability can be
-     * different at execution time.
-     *
-     * @param callerModule Name of calling module.
-     * @param binaryName The class to lookup.
-     * @return The reader or null if not found
-     * @throws jdk.tools.jlink.plugins.PluginException
-     */
-    public ClassReader getExportedClassReader(String callerModule,
-            String binaryName);
-
-    /**
-     * The module descriptor.
-     *
-     * @return The module descriptor;
-     */
-    public ModuleDescriptor getDescriptor();
-
-    /**
-     * Retrieve the internal and exported packages.
-     *
-     * @return
-     */
-    public Set<String> getAllPackages();
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins.asm;
-
-import java.util.Objects;
-import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-
-/**
- * Extend this class to develop your own plugin in order to transform jimage
- * resources.
- *
- */
-public abstract class AsmPlugin implements Plugin {
-
-    public AsmPlugin() {
-    }
-
-    @Override
-    public void visit(ModulePool allContent, ModulePool outResources) {
-        Objects.requireNonNull(allContent);
-        Objects.requireNonNull(outResources);
-        ModulePoolImpl resources = new ModulePoolImpl(allContent.getByteOrder());
-        allContent.entries().forEach(md -> {
-            if(md.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
-                resources.add(md);
-            } else {
-                outResources.add(md);
-            }
-        });
-        AsmPools pools = new AsmPools(resources);
-        visit(pools);
-        pools.fillOutputResources(outResources);
-    }
-
-    /**
-     * This is the method to implement in order to
-     * apply Asm transformation to jimage contained classes.
-     * @param pools The pool of Asm classes and other resource files.
-     * @param strings To add a string to the jimage strings table.
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public abstract void visit(AsmPools pools);
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins.asm;
-
-import java.util.Collection;
-import java.util.List;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-
-/**
- * A pool of ClassReader and other resource files.
- * This class allows to transform and sort classes and resource files.
- * <p>
- * Classes in the class pool are named following java binary name specification.
- * For example, java.lang.Object class is named java/lang/Object
- * <p>
- * Module information has been stripped out from class and other resource files
- * (.properties, binary files, ...).</p>
- */
-public interface AsmPool {
-
-    /**
-     * A resource that is not a class file.
-     * <p>
-     * The path of a resource is a /-separated path name that identifies the
-     * resource. For example com.foo.bar.Bundle.properties resource name is
-     * com/foo/bar/Bundle.properties </p>
-     * <p>
-     */
-    public class ResourceFile {
-
-        private final String path;
-        private final byte[] content;
-
-        public ResourceFile(String path, byte[] content) {
-            this.path = path;
-            this.content = content;
-        }
-
-        public String getPath() {
-            return path;
-        }
-
-        public byte[] getContent() {
-            return content;
-        }
-    }
-
-    /**
-     * To visit each Class contained in the pool
-     */
-    public interface ClassReaderVisitor {
-
-        /**
-         * Called for each ClassReader located in the pool.
-         *
-         * @param reader A class reader.
-         * @return A writer or null if the class has not been transformed.
-         */
-        public ClassWriter visit(ClassReader reader);
-    }
-
-    /**
-     * To visit each Resource contained in the pool
-     */
-    public interface ResourceFileVisitor {
-
-        /**
-         * Called for each Resource file located in the pool.
-         *
-         * @param reader A resource file.
-         * @return A resource file or null if the resource has not been
-         * transformed.
-         */
-        public ResourceFile visit(ResourceFile reader);
-    }
-
-    /**
-     * Contains the transformed classes. When the jimage file is generated,
-     * transformed classes take precedence on unmodified ones.
-     */
-    public interface WritableClassPool {
-
-        /**
-         * Add a class to the pool, if a class already exists, it is replaced.
-         *
-         * @param writer The class writer.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public void addClass(ClassWriter writer);
-
-        /**
-         * The class will be not added to the jimage file.
-         *
-         * @param className The class name to forget.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public void forgetClass(String className);
-
-        /**
-         * Get a transformed class.
-         *
-         * @param binaryName The java class binary name
-         * @return The ClassReader or null if the class is not found.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public ClassReader getClassReader(String binaryName);
-
-        /**
-         * Get a transformed class.
-         *
-         * @param res A class resource.
-         * @return The ClassReader or null if the class is not found.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public ClassReader getClassReader(ModuleEntry res);
-
-        /**
-         * Returns all the classes contained in the writable pool.
-         *
-         * @return The collection of classes.
-         */
-        public Collection<ModuleEntry> getClasses();
-    }
-
-    /**
-     * Contains the transformed resources. When the jimage file is generated,
-     * transformed resources take precedence on unmodified ones.
-     */
-    public interface WritableResourcePool {
-
-        /**
-         * Add a resource, if the resource exists, it is replaced.
-         *
-         * @param resFile The resource file to add.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public void addResourceFile(ResourceFile resFile);
-
-        /**
-         * The resource will be not added to the jimage file.
-         *
-         * @param resourceName
-         * @throws jdk.tools.jlink.plugin.PluginException If the resource to
-         * forget doesn't exist or is null.
-         */
-        public void forgetResourceFile(String resourceName);
-
-        /**
-         * Get a transformed resource.
-         *
-         * @param name The java resource name
-         * @return The Resource or null if the resource is not found.
-         */
-        public ResourceFile getResourceFile(String name);
-
-        /**
-         * Get a transformed resource.
-         *
-         * @param res The java resource
-         * @return The Resource or null if the resource is not found.
-         */
-        public ResourceFile getResourceFile(ModuleEntry res);
-
-        /**
-         * Returns all the resources contained in the writable pool.
-         *
-         * @return The array of resources.
-         */
-        public Collection<ModuleEntry> getResourceFiles();
-    }
-
-    /**
-     * To order the classes and resources within a jimage file.
-     */
-    public interface Sorter {
-
-        /**
-         * @param resources The resources will be added to the jimage following
-         * the order of this ResourcePool.
-         * @return The resource paths ordered in the way to use for storage in the jimage.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public List<String> sort(ModulePool resources);
-    }
-
-    /**
-     * The writable pool used to store transformed resources.
-     *
-     * @return The writable pool.
-     */
-    public WritableClassPool getTransformedClasses();
-
-    /**
-     * The writable pool used to store transformed resource files.
-     *
-     * @return The writable pool.
-     */
-    public WritableResourcePool getTransformedResourceFiles();
-
-    /**
-     * Set a sorter instance to sort all files. If no sorter is set, then input
-     * Resources will be added in the order they have been received followed by
-     * newly added resources.
-     *
-     * @param sorter
-     */
-    public void setSorter(Sorter sorter);
-
-    /**
-     * Returns the classes contained in the pool.
-     *
-     * @return The classes.
-     */
-    public Collection<ModuleEntry> getClasses();
-
-    /**
-     * Returns the resources contained in the pool. Resources are all the file
-     * that are not classes (eg: properties file, binary files, ...)
-     *
-     * @return The array of resource files.
-     */
-    public Collection<ModuleEntry> getResourceFiles();
-
-    /**
-     * Retrieves a resource based on the binary name. This name doesn't contain
-     * the module name.
-     * <b>NB:</b> When dealing with resources that have the same name in various
-     * modules (eg: META-INFO/*), you should use the <code>ResourcePool</code>
-     * referenced from this <code>AsmClassPool</code>.
-     *
-     * @param binaryName Name of a Java resource or null if the resource doesn't
-     * exist.
-     * @return
-     */
-    public ResourceFile getResourceFile(String binaryName);
-
-    /**
-     * Retrieves a resource for the passed resource.
-     *
-     * @param res The resource
-     * @return The resource file or null if it doesn't exist.
-     */
-    public ResourceFile getResourceFile(ModuleEntry res);
-
-    /**
-     * Retrieve a ClassReader from the pool.
-     *
-     * @param binaryName Class binary name
-     * @return A reader or null if the class is unknown
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public ClassReader getClassReader(String binaryName);
-
-    /**
-     * Retrieve a ClassReader from the pool.
-     *
-     * @param res A resource.
-     * @return A reader or null if the class is unknown
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public ClassReader getClassReader(ModuleEntry res);
-
-    /**
-     * To visit the set of ClassReaders.
-     *
-     * @param visitor The visitor.
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public void visitClassReaders(ClassReaderVisitor visitor);
-
-    /**
-     * To visit the set of ClassReaders.
-     *
-     * @param visitor The visitor.
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public void visitResourceFiles(ResourceFileVisitor visitor);
-
-    /**
-     * Returns the pool of all the resources (transformed and unmodified).
-     * The input resources are replaced by the transformed ones.
-     * If a sorter has been set, it is used to sort the returned resources.
-     *
-     * @param output The pool used to fill the jimage.
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public void fillOutputResources(ModulePool output);
-
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,698 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins.asm;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Requires;
-import java.lang.module.ModuleDescriptor.Requires.Modifier;
-import java.lang.module.ModuleDescriptor.Exports;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.tools.jlink.internal.ImageFileCreator;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
-
-/**
- * A pool of ClassReader and other resource files. This class allows to
- * transform and sort classes and resource files.
- * <p>
- * Classes in the class pool are named following java binary name specification.
- * For example, java.lang.Object class is named java/lang/Object
- * <p>
- * Module information has been stripped out from class and other resource files
- * (.properties, binary files, ...).</p>
- */
-final class AsmPoolImpl implements AsmModulePool {
-
-    /**
-     * Contains the transformed classes. When the jimage file is generated,
-     * transformed classes take precedence on unmodified ones.
-     */
-    public final class WritableClassPoolImpl implements WritableClassPool {
-
-        private WritableClassPoolImpl() {
-        }
-
-        /**
-         * Add a class to the pool, if a class already exists, it is replaced.
-         *
-         * @param writer The class writer.
-         * @throws java.io.IOException
-         */
-        @Override
-        public void addClass(ClassWriter writer) {
-            Objects.requireNonNull(writer);
-            // Retrieve the className
-            ClassReader reader = newClassReader(writer.toByteArray());
-            String className = reader.getClassName();
-            String path;
-            if (className.endsWith("module-info")) {
-                // remove the module name contained in the class name
-                className = className.substring(className.indexOf("/") + 1);
-                path = "/" + moduleName + "/" + className;
-            } else {
-                path = toClassNamePath(className);
-            }
-
-            byte[] content = writer.toByteArray();
-            ModuleEntry res = ModuleEntry.create(path, content);
-            transformedClasses.put(className, res);
-        }
-
-        /**
-         * The class will be not added to the jimage file.
-         *
-         * @param className The class name to forget.
-         */
-        @Override
-        public void forgetClass(String className) {
-            Objects.requireNonNull(className);
-            // do we have a resource?
-            ModuleEntry res = transformedClasses.get(className);
-            if (res == null) {
-                res = inputClasses.get(className);
-                if (res == null) {
-                    throw new PluginException("Unknown class " + className);
-                }
-            }
-            String path = toClassNamePath(className);
-            forgetResources.add(path);
-            // Just in case it has been added.
-            transformedClasses.remove(className);
-        }
-
-        /**
-         * Get a transformed class.
-         *
-         * @param binaryName The java class binary name
-         * @return The ClassReader or null if the class is not found.
-         */
-        @Override
-        public ClassReader getClassReader(String binaryName) {
-            Objects.requireNonNull(binaryName);
-            ModuleEntry res = transformedClasses.get(binaryName);
-            ClassReader reader = null;
-            if (res != null) {
-                reader = getClassReader(res);
-            }
-            return reader;
-        }
-
-        /**
-         * Returns all the classes contained in the writable pool.
-         *
-         * @return The array of transformed classes.
-         */
-        @Override
-        public Collection<ModuleEntry> getClasses() {
-            List<ModuleEntry> classes = new ArrayList<>();
-            for (Entry<String, ModuleEntry> entry : transformedClasses.entrySet()) {
-                classes.add(entry.getValue());
-            }
-            return classes;
-        }
-
-        @Override
-        public ClassReader getClassReader(ModuleEntry res) {
-            return newClassReader(res.getBytes());
-        }
-    }
-
-    /**
-     * Contains the transformed resources. When the jimage file is generated,
-     * transformed resources take precedence on unmodified ones.
-     */
-    public final class WritableResourcePoolImpl implements WritableResourcePool {
-
-        private WritableResourcePoolImpl() {
-        }
-
-        /**
-         * Add a resource, if the resource exists, it is replaced.
-         *
-         * @param resFile The resource file to add.
-         */
-        @Override
-        public void addResourceFile(ResourceFile resFile) {
-            Objects.requireNonNull(resFile);
-            String path = toResourceNamePath(resFile.getPath());
-            ModuleEntry res = ModuleEntry.create(path, resFile.getContent());
-            transformedResources.put(resFile.getPath(), res);
-        }
-
-        /**
-         * The resource will be not added to the jimage file.
-         *
-         * @param resourceName
-         * @throws java.io.IOException
-         */
-        @Override
-        public void forgetResourceFile(String resourceName) {
-            Objects.requireNonNull(resourceName);
-            String path = toResourceNamePath(resourceName);
-            // do we have a resource?
-            ModuleEntry res = transformedResources.get(resourceName);
-            if (res == null) {
-                res = inputResources.get(resourceName);
-                if (res == null) {
-                    throw new PluginException("Unknown resource " + resourceName);
-                }
-            }
-            forgetResources.add(path);
-            // Just in case it has been added.
-            transformedResources.remove(resourceName);
-        }
-
-        /**
-         * Get a transformed resource.
-         *
-         * @param name The java resource name
-         * @return The Resource or null if the resource is not found.
-         */
-        @Override
-        public ResourceFile getResourceFile(String name) {
-            Objects.requireNonNull(name);
-            ModuleEntry res = transformedResources.get(name);
-            ResourceFile resFile = null;
-            if (res != null) {
-                resFile = getResourceFile(res);
-            }
-            return resFile;
-        }
-
-        /**
-         * Returns all the resources contained in the writable pool.
-         *
-         * @return The array of transformed classes.
-         */
-        @Override
-        public Collection<ModuleEntry> getResourceFiles() {
-            List<ModuleEntry> resources = new ArrayList<>();
-            for (Entry<String, ModuleEntry> entry : transformedResources.entrySet()) {
-                resources.add(entry.getValue());
-            }
-            return resources;
-        }
-
-        @Override
-        public ResourceFile getResourceFile(ModuleEntry res) {
-            return new ResourceFile(toJavaBinaryResourceName(res.getPath()),
-                    res.getBytes());
-        }
-    }
-
-    private final ModulePool jimageResources;
-    private final Map<String, ModuleEntry> inputClasses;
-    private final Map<String, ModuleEntry> inputResources;
-    private final Map<String, String> inputClassPackageMapping;
-    private final Map<String, String> inputOtherPackageMapping;
-
-    private final WritableClassPool transClassesPool
-            = new WritableClassPoolImpl();
-    private final WritableResourcePool transResourcesPool
-            = new WritableResourcePoolImpl();
-
-    private Sorter sorter;
-
-    private final Map<String, ModuleEntry> transformedClasses
-            =            new LinkedHashMap<>();
-    private final Map<String, ModuleEntry> transformedResources
-            =            new LinkedHashMap<>();
-    private final List<String> forgetResources = new ArrayList<>();
-    private final Map<String, String> newPackageMapping = new HashMap<>();
-
-    private final String moduleName;
-
-    private final ModuleDescriptor descriptor;
-    private final AsmPools pools;
-
-    /**
-     * A new Asm pool.
-     *
-     * @param inputResources The raw resources to build the pool from.
-     * @param moduleName The name of a module.
-     * @param pools The resource pools.
-     * @param descriptor The module descriptor.
-     */
-    AsmPoolImpl(ModulePool inputResources, String moduleName,
-            AsmPools pools,
-            ModuleDescriptor descriptor) {
-        Objects.requireNonNull(inputResources);
-        Objects.requireNonNull(moduleName);
-        Objects.requireNonNull(pools);
-        Objects.requireNonNull(descriptor);
-        this.jimageResources = inputResources;
-        this.moduleName = moduleName;
-        this.pools = pools;
-        this.descriptor = descriptor;
-        Map<String, ModuleEntry> classes = new LinkedHashMap<>();
-        Map<String, ModuleEntry> resources = new LinkedHashMap<>();
-        Map<String, String> packageClassToModule = new HashMap<>();
-        Map<String, String> packageOtherToModule = new HashMap<>();
-        inputResources.entries().forEach(res -> {
-            if (res.getPath().endsWith(".class")) {
-                classes.put(toJavaBinaryClassName(res.getPath()), res);
-            } else {
-                resources.put(toJavaBinaryResourceName(res.getPath()), res);
-            }
-            String[] split = ImageFileCreator.splitPath(res.getPath());
-            if (ImageFileCreator.isClassPackage(res.getPath())) {
-                packageClassToModule.put(split[1], res.getModule());
-            } else {
-                // Keep a map of other resources
-                // Same resource names such as META-INF/* should be handled with full path name.
-                if (!split[1].isEmpty()) {
-                    packageOtherToModule.put(split[1], res.getModule());
-                }
-            }
-        });
-        this.inputClasses = Collections.unmodifiableMap(classes);
-        this.inputResources = Collections.unmodifiableMap(resources);
-
-        this.inputClassPackageMapping = Collections.unmodifiableMap(packageClassToModule);
-        this.inputOtherPackageMapping = Collections.unmodifiableMap(packageOtherToModule);
-    }
-
-    @Override
-    public String getModuleName() {
-        return moduleName;
-    }
-
-    /**
-     * The writable pool used to store transformed resources.
-     *
-     * @return The writable pool.
-     */
-    @Override
-    public WritableClassPool getTransformedClasses() {
-        return transClassesPool;
-    }
-
-    /**
-     * The writable pool used to store transformed resource files.
-     *
-     * @return The writable pool.
-     */
-    @Override
-    public WritableResourcePool getTransformedResourceFiles() {
-        return transResourcesPool;
-    }
-
-    /**
-     * Set a sorter instance to sort all files. If no sorter is set, then input
-     * Resources will be added in the order they have been received followed by
-     * newly added resources.
-     *
-     * @param sorter
-     */
-    @Override
-    public void setSorter(Sorter sorter) {
-        this.sorter = sorter;
-    }
-
-    /**
-     * Returns the classes contained in the pool.
-     *
-     * @return The array of classes.
-     */
-    @Override
-    public Collection<ModuleEntry> getClasses() {
-        return inputClasses.values();
-    }
-
-    /**
-     * Returns the resources contained in the pool. Resources are all the file
-     * that are not classes (eg: properties file, binary files, ...)
-     *
-     * @return The array of classes.
-     */
-    @Override
-    public Collection<ModuleEntry> getResourceFiles() {
-        return inputResources.values();
-    }
-
-    /**
-     * Retrieves a resource based on the binary name. This name doesn't contain
-     * the module name.
-     * <b>NB:</b> When dealing with resources that have the same name in various
-     * modules (eg: META-INFO/*), you should use the <code>ResourcePool</code>
-     * referenced from this <code>AsmClassPool</code>.
-     *
-     * @param binaryName Name of a Java resource or null if the resource doesn't
-     * exist.
-     * @return
-     */
-    @Override
-    public ResourceFile getResourceFile(String binaryName) {
-        Objects.requireNonNull(binaryName);
-        ModuleEntry res = inputResources.get(binaryName);
-        ResourceFile resFile = null;
-        if (res != null) {
-            resFile = getResourceFile(res);
-        }
-        return resFile;
-    }
-
-    /**
-     * Retrieve a ClassReader from the pool.
-     *
-     * @param binaryName Class binary name
-     * @return A reader or null if the class is unknown
-     */
-    @Override
-    public ClassReader getClassReader(String binaryName) {
-        Objects.requireNonNull(binaryName);
-        ModuleEntry res = inputClasses.get(binaryName);
-        ClassReader reader = null;
-        if (res != null) {
-            reader = getClassReader(res);
-        }
-        return reader;
-    }
-
-    @Override
-    public ResourceFile getResourceFile(ModuleEntry res) {
-        return new ResourceFile(toJavaBinaryResourceName(res.getPath()),
-                res.getBytes());
-    }
-
-    @Override
-    public ClassReader getClassReader(ModuleEntry res) {
-        return newClassReader(res.getBytes());
-    }
-
-    /**
-     * Lookup the class in this pool and the required pools. NB: static module
-     * readability can be different at execution time.
-     *
-     * @param binaryName The class to lookup.
-     * @return The reader or null if not found
-     */
-    @Override
-    public ClassReader getClassReaderInDependencies(String binaryName) {
-        Objects.requireNonNull(binaryName);
-        ClassReader reader = getClassReader(binaryName);
-        if (reader == null) {
-            for (Requires requires : descriptor.requires()) {
-                AsmModulePool pool = pools.getModulePool(requires.name());
-                reader = pool.getExportedClassReader(moduleName, binaryName);
-                if (reader != null) {
-                    break;
-                }
-            }
-        }
-        return reader;
-    }
-
-    /**
-     * Lookup the class in the exported packages of this module. "public
-     * requires" modules are looked up. NB: static module readability can be
-     * different at execution time.
-     *
-     * @param callerModule Name of calling module.
-     * @param binaryName The class to lookup.
-     * @return The reader or null if not found
-     */
-    @Override
-    public ClassReader getExportedClassReader(String callerModule, String binaryName) {
-        Objects.requireNonNull(callerModule);
-        Objects.requireNonNull(binaryName);
-        boolean exported = false;
-        ClassReader clazz = null;
-        for (Exports e : descriptor.exports()) {
-            String pkg = e.source();
-            Set<String> targets = e.targets();
-            System.out.println("PKG " + pkg);
-            if (targets.isEmpty() || targets.contains(callerModule)) {
-                if (binaryName.startsWith(pkg)) {
-                    String className = binaryName.substring(pkg.length());
-                    System.out.println("CLASS " + className);
-                    exported = !className.contains(".");
-                }
-                if (exported) {
-                    break;
-                }
-            }
-        }
-        // public requires (re-export)
-        if (!exported) {
-            for (Requires requires : descriptor.requires()) {
-                if (requires.modifiers().contains(Modifier.PUBLIC)) {
-                    AsmModulePool pool = pools.getModulePool(requires.name());
-                    clazz = pool.getExportedClassReader(moduleName, binaryName);
-                    if (clazz != null) {
-                        break;
-                    }
-                }
-            }
-        } else {
-            clazz = getClassReader(binaryName);
-        }
-        return clazz;
-
-    }
-
-    @Override
-    public ModuleDescriptor getDescriptor() {
-        return descriptor;
-    }
-
-    /**
-     * To visit the set of ClassReaders.
-     *
-     * @param visitor The visitor.
-     */
-    @Override
-    public void visitClassReaders(ClassReaderVisitor visitor) {
-        Objects.requireNonNull(visitor);
-        for (ModuleEntry res : getClasses()) {
-            ClassReader reader = newClassReader(res.getBytes());
-            ClassWriter writer = visitor.visit(reader);
-            if (writer != null) {
-
-                getTransformedClasses().addClass(writer);
-            }
-        }
-    }
-
-    /**
-     * To visit the set of ClassReaders.
-     *
-     * @param visitor The visitor.
-     */
-    @Override
-    public void visitResourceFiles(ResourceFileVisitor visitor) {
-        Objects.requireNonNull(visitor);
-        for (ModuleEntry resource : getResourceFiles()) {
-            ResourceFile resFile
-                    = new ResourceFile(toJavaBinaryResourceName(resource.getPath()),
-                            resource.getBytes());
-            ResourceFile res = visitor.visit(resFile);
-            if (res != null) {
-                getTransformedResourceFiles().addResourceFile(res);
-            }
-        }
-    }
-
-    /**
-     * Returns the pool of all the resources (transformed and unmodified). The
-     * input resources are replaced by the transformed ones. If a sorter has
-     * been set, it is used to sort the returned resources.     *
-     */
-    @Override
-    public void fillOutputResources(ModulePool outputResources) {
-        List<String> added = new ArrayList<>();
-        // If the sorter is null, use the input order.
-        // New resources are added at the end
-        // First input classes that have not been removed
-        ModulePool output = new ModulePoolImpl(outputResources.getByteOrder(),
-                ((ModulePoolImpl)outputResources).getStringTable());
-        jimageResources.entries().forEach(inResource -> {
-            if (!forgetResources.contains(inResource.getPath())) {
-                ModuleEntry resource = inResource;
-                // Do we have a transformed class with the same name?
-                ModuleEntry res = transformedResources.
-                        get(toJavaBinaryResourceName(inResource.getPath()));
-                if (res != null) {
-                    resource = res;
-                } else {
-                    res = transformedClasses.
-                            get(toJavaBinaryClassName(inResource.getPath()));
-                    if (res != null) {
-                        resource = res;
-                    }
-                }
-                output.add(resource);
-                added.add(resource.getPath());
-            }
-        });
-        // Then new resources
-        for (Map.Entry<String, ModuleEntry> entry : transformedResources.entrySet()) {
-            ModuleEntry resource = entry.getValue();
-            if (!forgetResources.contains(resource.getPath())) {
-                if (!added.contains(resource.getPath())) {
-                    output.add(resource);
-                }
-            }
-        }
-        // And new classes
-        for (Map.Entry<String, ModuleEntry> entry : transformedClasses.entrySet()) {
-            ModuleEntry resource = entry.getValue();
-            if (!forgetResources.contains(resource.getPath())) {
-                if (!added.contains(resource.getPath())) {
-                    output.add(resource);
-                }
-            }
-        }
-
-        AsmPools.sort(outputResources, output, sorter);
-    }
-
-    /**
-     * Associate a package to this module, useful when adding new classes in new
-     * packages. WARNING: In order to properly handle new package and/or new
-     * module, module-info class must be added and/or updated.
-     *
-     * @param pkg The new package, following java binary syntax (/-separated
-     * path name).
-     * @throws PluginException If a mapping already exist for this package.
-     */
-    @Override
-    public void addPackage(String pkg) {
-        Objects.requireNonNull(pkg);
-        Objects.requireNonNull(moduleName);
-        pkg = pkg.replaceAll("/", ".");
-        String mod = newPackageMapping.get(pkg);
-        if (mod != null) {
-            throw new PluginException(mod + " module already contains package " + pkg);
-        }
-        newPackageMapping.put(pkg, moduleName);
-    }
-
-    @Override
-    public Set<String> getAllPackages() {
-        ModuleDescriptor desc = getDescriptor();
-        Set<String> packages = new HashSet<>();
-        for (String p : desc.conceals()) {
-            packages.add(p.replaceAll("\\.", "/"));
-        }
-        for (String p : newPackageMapping.keySet()) {
-            packages.add(p.replaceAll("\\.", "/"));
-        }
-        for (Exports ex : desc.exports()) {
-            packages.add(ex.source().replaceAll("\\.", "/"));
-        }
-        return packages;
-    }
-
-    private static ClassReader newClassReader(byte[] bytes) {
-        try {
-            ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
-            ClassReader reader = new ClassReader(stream);
-            return reader;
-        } catch (IOException ex) {
-            throw new UncheckedIOException(ex);
-        }
-    }
-
-    private static String toJavaBinaryClassName(String path) {
-        if (path.endsWith("module-info.class")) {
-            path = removeClassExtension(path);
-        } else {
-            path = removeModuleName(path);
-            path = removeClassExtension(path);
-        }
-        return path;
-    }
-
-    private static String toJavaBinaryResourceName(String path) {
-        if (!path.endsWith("module-info.class")) {
-            path = removeModuleName(path);
-        }
-        return path;
-    }
-
-    private static String removeClassExtension(String path) {
-        return path.substring(0, path.length() - ".class".length());
-    }
-
-    private static String removeModuleName(String path) {
-        path = path.substring(1);
-        return path.substring(path.indexOf("/") + 1, path.length());
-    }
-
-    private String toClassNamePath(String className) {
-        return toResourceNamePath(className) + ".class";
-    }
-
-    /**
-     * Entry point to manage resource<->module association.
-     */
-    private String toResourceNamePath(String resourceName) {
-        if (!resourceName.startsWith("/")) {
-            resourceName = "/" + resourceName;
-        }
-        String pkg = toPackage(resourceName);
-        String module = inputClassPackageMapping.get(pkg);
-        if (module == null) {
-            module = newPackageMapping.get(pkg);
-            if (module == null) {
-                module = inputOtherPackageMapping.get(pkg);
-                if (module == null) {
-                    throw new PluginException("No module for package" + pkg);
-                }
-            }
-        }
-        return "/" + module + resourceName;
-    }
-
-    private static String toPackage(String path) {
-        if (path.startsWith("/")) {
-            path = path.substring(1);
-        }
-        int i = path.lastIndexOf("/");
-        if (i == -1) {
-            // Default package...
-            return "";
-        }
-        return path.substring(0, i).replaceAll("/", ".");
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,497 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins.asm;
-
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Exports;
-import java.lang.module.ModuleDescriptor.Requires;
-import static java.lang.module.ModuleDescriptor.Requires.Modifier.PUBLIC;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.Sorter;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
-
-/**
- * A container for pools of ClassReader and other resource files. A pool of all
- * the resources or a pool for a given module can be retrieved
- */
-public final class AsmPools {
-
-    /**
-     * Sort the order in which the modules will be stored in the jimage file.
-     */
-    public interface ModuleSorter {
-
-        /**
-         * Sort the list of modules.
-         *
-         * @param modules The list of module names. The module will be stored in
-         * the jimage following this order.
-         * @return A list of module names that expresses the order in which the
-         * modules are stored in the jimage.
-         */
-        public List<String> sort(List<String> modules);
-    }
-
-    private class AsmGlobalPoolImpl implements AsmGlobalPool {
-
-        private Sorter sorter = null;
-
-        private class GlobalWritableClassPool implements WritableClassPool {
-
-            @Override
-            public void addClass(ClassWriter writer) {
-                visitFirstNonFailingPool((AsmModulePool pool) -> {
-                    pool.getTransformedClasses().addClass(writer);
-                });
-            }
-
-            @Override
-            public void forgetClass(String className) {
-                visitFirstNonFailingPool((AsmModulePool pool) -> {
-                    pool.getTransformedClasses().forgetClass(className);
-                });
-            }
-
-            @Override
-            public ClassReader getClassReader(String binaryName) {
-                return visitPools((AsmModulePool pool) -> {
-                    return pool.getTransformedClasses().getClassReader(binaryName);
-                });
-            }
-
-            @Override
-            public Collection<ModuleEntry> getClasses() {
-                List<ModuleEntry> all = new ArrayList<>();
-                visitAllPools((AsmModulePool pool) -> {
-                    for (ModuleEntry rf : pool.getTransformedClasses().getClasses()) {
-                        all.add(rf);
-                    }
-                });
-                return all;
-            }
-
-            @Override
-            public ClassReader getClassReader(ModuleEntry res) {
-                return visitPools((AsmModulePool pool) -> {
-                    return pool.getTransformedClasses().getClassReader(res);
-                });
-            }
-
-        }
-
-        private class GlobalWritableResourcePool implements WritableResourcePool {
-
-            @Override
-            public void addResourceFile(ResourceFile resFile) {
-                visitFirstNonFailingPool((AsmModulePool pool) -> {
-                    pool.getTransformedResourceFiles().addResourceFile(resFile);
-                });
-            }
-
-            @Override
-            public void forgetResourceFile(String resourceName) {
-                visitFirstNonFailingPool((AsmModulePool pool) -> {
-                    pool.getTransformedResourceFiles().forgetResourceFile(resourceName);
-                });
-            }
-
-            @Override
-            public ResourceFile getResourceFile(String name) {
-                return visitPools((AsmModulePool pool) -> {
-                    return pool.getTransformedResourceFiles().getResourceFile(name);
-                });
-            }
-
-            @Override
-            public Collection<ModuleEntry> getResourceFiles() {
-                List<ModuleEntry> all = new ArrayList<>();
-                visitAllPools((AsmModulePool pool) -> {
-                    for (ModuleEntry rf : pool.getTransformedResourceFiles().getResourceFiles()) {
-                        all.add(rf);
-                    }
-                });
-                return all;
-            }
-
-            @Override
-            public ResourceFile getResourceFile(ModuleEntry res) {
-                return visitPools((AsmModulePool pool) -> {
-                    return pool.getTransformedResourceFiles().getResourceFile(res);
-                });
-            }
-
-        }
-
-        @Override
-        public AsmPool.WritableClassPool getTransformedClasses() {
-            return new GlobalWritableClassPool();
-        }
-
-        @Override
-        public AsmPool.WritableResourcePool getTransformedResourceFiles() {
-            return new GlobalWritableResourcePool();
-        }
-
-        @Override
-        public void setSorter(AsmPool.Sorter sorter) {
-            this.sorter = sorter;
-        }
-
-        @Override
-        public Collection<ModuleEntry> getClasses() {
-            List<ModuleEntry> all = new ArrayList<>();
-            visitAllPools((AsmModulePool pool) -> {
-                for (ModuleEntry rf : pool.getClasses()) {
-                    all.add(rf);
-                }
-            });
-            return all;
-        }
-
-        @Override
-        public Collection<ModuleEntry> getResourceFiles() {
-            List<ModuleEntry> all = new ArrayList<>();
-            visitAllPools((AsmModulePool pool) -> {
-                for (ModuleEntry rf : pool.getResourceFiles()) {
-                    all.add(rf);
-                }
-            });
-            return all;
-        }
-
-        @Override
-        public AsmPool.ResourceFile getResourceFile(String binaryName) {
-            return visitPools((AsmModulePool pool) -> {
-                return pool.getResourceFile(binaryName);
-            });
-        }
-
-        @Override
-        public ClassReader getClassReader(String binaryName) {
-            return visitPoolsEx((AsmModulePool pool) -> {
-                return pool.getClassReader(binaryName);
-            });
-        }
-
-        @Override
-        public ResourceFile getResourceFile(ModuleEntry res) {
-            return visitPools((AsmModulePool pool) -> {
-                return pool.getResourceFile(res);
-            });
-        }
-
-        @Override
-        public ClassReader getClassReader(ModuleEntry res) {
-            return visitPoolsEx((AsmModulePool pool) -> {
-                return pool.getClassReader(res);
-            });
-        }
-
-        @Override
-        public void visitClassReaders(AsmPool.ClassReaderVisitor visitor) {
-            visitAllPoolsEx((AsmModulePool pool) -> {
-                pool.visitClassReaders(visitor);
-            });
-        }
-
-        @Override
-        public void visitResourceFiles(AsmPool.ResourceFileVisitor visitor) {
-            visitAllPoolsEx((AsmModulePool pool) -> {
-                pool.visitResourceFiles(visitor);
-            });
-        }
-
-        @Override
-        public void fillOutputResources(ModulePool outputResources) {
-            AsmPools.this.fillOutputResources(outputResources);
-        }
-
-        @Override
-        public void addPackageModuleMapping(String pkg, String module) {
-            AsmModulePool p = pools.get(module);
-            if (p == null) {
-                throw new PluginException("Unknown module " + module);
-            }
-            p.addPackage(pkg);
-        }
-
-        @Override
-        public Set<String> getAccessiblePackages(String module) {
-            AsmModulePool p = pools.get(module);
-            if (p == null) {
-                return null;
-            }
-            ModuleDescriptor desc = p.getDescriptor();
-            Set<String> packages = new HashSet<>();
-            packages.addAll(p.getAllPackages());
-
-            // Retrieve direct dependencies and indirect ones (public)
-            Set<String> modules = new HashSet<>();
-            for (Requires req : desc.requires()) {
-                modules.add(req.name());
-                addAllRequirePublicModules(req.name(), modules);
-            }
-            // Add exported packages of readable modules
-            for (String readable : modules) {
-                AsmModulePool mp = pools.get(readable);
-                if (mp != null) {
-                    for (Exports e : mp.getDescriptor().exports()) {
-                        // exported to all or to the targeted module
-                        if (e.targets().isEmpty() || e.targets().contains(module)) {
-                            packages.add(e.source().replaceAll("\\.", "/"));
-                        }
-                    }
-
-                }
-            }
-            return packages;
-        }
-
-        private void addAllRequirePublicModules(String module, Set<String> modules) {
-            AsmModulePool p = pools.get(module);
-            if (p != null) {
-                for (Requires req : p.getDescriptor().requires()) {
-                    if (req.modifiers().contains(PUBLIC)) {
-                        modules.add(req.name());
-                        addAllRequirePublicModules(req.name(), modules);
-                    }
-                }
-            }
-        }
-
-    }
-
-    private interface VoidPoolVisitor {
-
-        void visit(AsmModulePool pool);
-    }
-
-    private interface VoidPoolVisitorEx {
-
-        void visit(AsmModulePool pool);
-    }
-
-    private interface RetPoolVisitor<P> {
-
-        P visit(AsmModulePool pool);
-    }
-
-    private final Map<String, AsmModulePool> pools = new LinkedHashMap<>();
-    private final AsmModulePool[] poolsArray;
-    private final AsmGlobalPoolImpl global;
-
-    private ModuleSorter moduleSorter;
-
-    /**
-     * A new Asm pools.
-     *
-     * @param inputResources The raw resources to build the pool from.
-     */
-    public AsmPools(ModulePool inputResources) {
-        Objects.requireNonNull(inputResources);
-        Map<String, ModulePool> resPools = new LinkedHashMap<>();
-        Map<String, ModuleDescriptor> descriptors = new HashMap<>();
-        inputResources.entries().forEach(res -> {
-            ModulePool p = resPools.get(res.getModule());
-            if (p == null) {
-                p = new ModulePoolImpl(inputResources.getByteOrder(),
-                        ((ModulePoolImpl)inputResources).getStringTable());
-                resPools.put(res.getModule(), p);
-            }
-            if (res.getPath().endsWith("module-info.class")) {
-                ByteBuffer bb = ByteBuffer.wrap(res.getBytes());
-                ModuleDescriptor descriptor = ModuleDescriptor.read(bb);
-                descriptors.put(res.getModule(), descriptor);
-            }
-            p.add(res);
-        });
-        poolsArray = new AsmModulePool[resPools.size()];
-        int i = 0;
-
-        for (Entry<String, ModulePool> entry : resPools.entrySet()) {
-            ModuleDescriptor descriptor = descriptors.get(entry.getKey());
-            if (descriptor == null) {
-                throw new PluginException("module-info.class not found for " + entry.getKey() + " module");
-            }
-            AsmModulePool p = new AsmPoolImpl(entry.getValue(),
-                    entry.getKey(), this, descriptor);
-            pools.put(entry.getKey(), p);
-            poolsArray[i] = p;
-            i += 1;
-        }
-        global = new AsmGlobalPoolImpl();
-    }
-
-    /**
-     * The pool containing all classes and other resources.
-     *
-     * @return The global pool
-     */
-    public AsmGlobalPool getGlobalPool() {
-        return global;
-    }
-
-    /**
-     * A pool for a given module
-     *
-     * @param name The module name
-     * @return The pool that contains content of the passed module or null if
-     * the module doesn't exist.
-     */
-    public AsmModulePool getModulePool(String name) {
-        Objects.requireNonNull(name);
-        return pools.get(name);
-    }
-
-    /**
-     * The array of module pools.
-     * @return The module pool array.
-     */
-    public AsmModulePool[] getModulePools() {
-        return poolsArray.clone();
-    }
-
-    /**
-     * Set a module sorter. Sorter is used when computing the output resources.
-     *
-     * @param moduleSorter The module sorter
-     */
-    public void setModuleSorter(ModuleSorter moduleSorter) {
-        Objects.requireNonNull(moduleSorter);
-        this.moduleSorter = moduleSorter;
-    }
-
-    /**
-     * Returns the pool of all the resources (transformed and unmodified). The
-     * input resources are replaced by the transformed ones. If a sorter has
-     * been set, it is used to sort in modules.
-     *
-     * @param outputResources The pool used to fill the jimage.
-     */
-    public void fillOutputResources(ModulePool outputResources) {
-        // First sort modules
-        List<String> modules = new ArrayList<>();
-        for (String k : pools.keySet()) {
-            modules.add(k);
-        }
-        if (moduleSorter != null) {
-            modules = moduleSorter.sort(modules);
-        }
-        ModulePool output = new ModulePoolImpl(outputResources.getByteOrder(),
-                ((ModulePoolImpl)outputResources).getStringTable());
-        for (String mn : modules) {
-            AsmPool pool = pools.get(mn);
-            pool.fillOutputResources(output);
-        }
-        sort(outputResources, output, global.sorter);
-    }
-
-    static void sort(ModulePool outputResources,
-            ModulePool transientOutput, Sorter sorter) {
-        if (sorter != null) {
-            List<String> order = sorter.sort(transientOutput);
-            for (String s : order) {
-                outputResources.add(transientOutput.findEntry(s).get());
-            }
-        } else {
-            transientOutput.entries().forEach(res-> {
-                outputResources.add(res);
-            });
-        }
-    }
-
-    private void visitFirstNonFailingPool(VoidPoolVisitorEx pv) {
-        boolean found = false;
-        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
-            try {
-                pv.visit(entry.getValue());
-                found = true;
-                break;
-            } catch (Exception ex) {
-                // XXX OK, try  another one.
-            }
-        }
-        if (!found) {
-            throw new PluginException("No module found");
-        }
-    }
-
-    private void visitAllPools(VoidPoolVisitor pv) {
-        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
-            pv.visit(entry.getValue());
-        }
-    }
-
-    private void visitAllPoolsEx(VoidPoolVisitorEx pv) {
-        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
-            pv.visit(entry.getValue());
-        }
-    }
-
-    private <P> P visitPoolsEx(RetPoolVisitor<P> pv) {
-        P p = null;
-        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
-            try {
-                p = pv.visit(entry.getValue());
-                if (p != null) {
-                    break;
-                }
-            } catch (Exception ex) {
-                // XXX OK, try  another one.
-            }
-        }
-        return p;
-    }
-
-    private <P> P visitPools(RetPoolVisitor<P> pv) {
-        P p = null;
-        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
-            try {
-                p = pv.visit(entry.getValue());
-                if (p != null) {
-                    break;
-                }
-            } catch (Exception ex) {
-                // XXX OK, try  another one.
-            }
-        }
-        return p;
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ControlFlow.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,516 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins.optim;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import java.util.Stack;
-import java.util.TreeSet;
-import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.internal.org.objectweb.asm.tree.analysis.Analyzer;
-import jdk.internal.org.objectweb.asm.tree.analysis.AnalyzerException;
-import jdk.internal.org.objectweb.asm.tree.analysis.BasicInterpreter;
-import jdk.internal.org.objectweb.asm.tree.analysis.BasicValue;
-
-/**
- * Split Java method onto a control flow.
- *
- */
-public final class ControlFlow {
-
-    /**
-     * A block of control
-     */
-    public static final class Block implements Comparable<Block> {
-
-        private final InstructionNode firstInstruction;
-        private final List<InstructionNode> instr = new ArrayList<>();
-        private final List<Block> reachable = new ArrayList<>();
-        private final List<Block> exceptionHandlers = new ArrayList<>();
-        private boolean isExceptionHandler;
-
-        private Block(InstructionNode firstInstruction) {
-            this.firstInstruction = firstInstruction;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof Block)) {
-                return false;
-            }
-            Block b = (Block) other;
-            return firstInstruction.equals(b.firstInstruction);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hashCode(this.firstInstruction);
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder builder = new StringBuilder();
-            for (InstructionNode in : instr) {
-                builder.append(in).append(" ");
-            }
-            builder.append(" reachables: ");
-            for (Block r : reachable) {
-                builder.append(r.getFirstInstruction()).append(" ");
-            }
-            builder.append(" exception handlers: ");
-            for (Block r : exceptionHandlers) {
-                builder.append(r.getFirstInstruction()).append(" ");
-            }
-
-            return "block[" + getFirstInstruction() + "],ex:"
-                    + isExceptionHandler + ",  " + builder.toString();
-        }
-
-        /**
-         * @return the firstInstruction
-         */
-        public InstructionNode getFirstInstruction() {
-            return firstInstruction;
-        }
-
-        /**
-         * @return the instr
-         */
-        public List<InstructionNode> getInstructions() {
-            return Collections.unmodifiableList(instr);
-        }
-
-        /**
-         * @return the reachable
-         */
-        public List<Block> getReachableBlocks() {
-            return Collections.unmodifiableList(reachable);
-        }
-
-        /**
-         * @return the exceptionHandlers
-         */
-        public List<Block> getExceptionHandlerBlocks() {
-            return Collections.unmodifiableList(exceptionHandlers);
-        }
-
-        @Override
-        public int compareTo(Block t) {
-            return this.firstInstruction.index - t.firstInstruction.index;
-        }
-
-        public boolean isExceptionHandler() {
-            return isExceptionHandler;
-        }
-
-    }
-
-    private class ClosureBuilder {
-
-        private final Block root;
-
-        private ClosureBuilder(Block root) {
-            Objects.requireNonNull(root);
-            this.root = root;
-        }
-
-        private Set<Block> build() {
-            Set<Block> allReachable = new TreeSet<>();
-            addAll(root, allReachable);
-            // filter out the reachable from outside this graph
-            Iterator<Block> it = allReachable.iterator();
-            Set<Block> toExclude = new HashSet<>();
-            while (it.hasNext()) {
-                Block b = it.next();
-                for (Block ref : blocks) {
-                    if (!allReachable.contains(ref) && ref.reachable.contains(b)) {
-                        addAll(b, toExclude);
-                        break;
-                    }
-                }
-            }
-            //System.err.println("TO EXCLUDE:\n " + toExclude);
-            allReachable.removeAll(toExclude);
-            //System.err.println("CLOSURE:\n " + allReachable);
-            return Collections.unmodifiableSet(allReachable);
-        }
-
-        // Compute the set of blocks reachable from the current block
-        private void addAll(Block current, Set<Block> closure) {
-            Objects.requireNonNull(current);
-            closure.add(current);
-            for (Block ex : current.exceptionHandlers) {
-                Objects.requireNonNull(ex);
-                if (!closure.contains(ex)) {
-                    addAll(ex, closure);
-                }
-            }
-            for (Block r : current.reachable) {
-                Objects.requireNonNull(r);
-                if (!closure.contains(r)) {
-                    addAll(r, closure);
-                }
-            }
-
-        }
-    }
-
-    /**
-     * An instruction
-     */
-    public static final class InstructionNode {
-
-        private final int index;
-        private final List<InstructionNode> next = new ArrayList<>();
-        private final AbstractInsnNode instr;
-
-        private InstructionNode(int index, AbstractInsnNode instr) {
-            this.index = index;
-            this.instr = instr;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof InstructionNode)) {
-                return false;
-            }
-            final InstructionNode other = (InstructionNode) obj;
-            return this.getIndex() == other.getIndex();
-        }
-
-        @Override
-        public int hashCode() {
-            return this.getIndex();
-        }
-
-        @Override
-        public String toString() {
-            return getIndex() + "(" + (getInstr().getOpcode() == - 1 ? -1
-                    : Integer.toHexString(getInstr().getOpcode())) + ")";
-        }
-
-        /**
-         * @return the index
-         */
-        public int getIndex() {
-            return index;
-        }
-
-        /**
-         * @return the instr
-         */
-        public AbstractInsnNode getInstr() {
-            return instr;
-        }
-
-    }
-
-    private final Map<Integer, Block> allBlocks;
-    private final List<Block> blocks = new ArrayList<>();
-
-    private ControlFlow(Map<Integer, Block> allBlocks) {
-        this.allBlocks = allBlocks;
-        for (Block b : allBlocks.values()) {
-            blocks.add(b);
-        }
-        Collections.sort(blocks);
-    }
-
-    public List<Block> getBlocks() {
-
-        return Collections.unmodifiableList(blocks);
-    }
-
-    public Block getBlock(int firstInstr) {
-        return allBlocks.get(firstInstr);
-    }
-
-    public static ControlFlow createControlFlow(String owner,
-            MethodNode method) throws Exception {
-
-        BlockBuilder bb = new BlockBuilder(owner, method);
-        return bb.build();
-    }
-
-    /**
-     * Return the set of blocks that are only reachable from this block For
-     * example, if b is an Exception handler, returns all the blocks reachable
-     * only from this handler
-     *
-     * @param b
-     * @return
-     */
-    public Set<Block> getClosure(Block b) {
-        return new ClosureBuilder(b).build();
-    }
-
-    private static final class BlockBuilder {
-
-        private InstructionNode root;
-        private final Map<Integer, InstructionNode> instructions = new HashMap<>();
-        private final Map<Integer, List<Integer>> handlers = new HashMap<>();
-        private final Map<Integer, Block> allBlocks = new HashMap<>();
-
-        private final String owner;
-        private final MethodNode method;
-
-        private BlockBuilder(String owner, MethodNode method) {
-            this.owner = owner;
-            this.method = method;
-        }
-
-        private void analyze() throws AnalyzerException {
-            Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(new BasicInterpreter()) {
-
-                @Override
-                protected boolean newControlFlowExceptionEdge(int insn,
-                        int successor) {
-                    List<Integer> lst = handlers.get(successor);
-                    if (lst == null) {
-                        lst = new ArrayList<>();
-                        handlers.put(successor, lst);
-                    }
-                    lst.add(insn);
-                    return true;
-                }
-
-                @Override
-                protected void newControlFlowEdge(int from,
-                        int to) {
-                    if (root == null) {
-                        root = new InstructionNode(from, method.instructions.get(from));
-                        instructions.put(from, root);
-                    }
-                    InstructionNode fromNode = instructions.get(from);
-                    if (fromNode == null) {
-                        fromNode = new InstructionNode(from, method.instructions.get(from));
-                        instructions.put(from, fromNode);
-                    }
-                    InstructionNode toNode = instructions.get(to);
-                    if (toNode == null) {
-                        toNode = new InstructionNode(to, method.instructions.get(to));
-                        instructions.put(to, toNode);
-                    }
-                    if (!fromNode.next.contains(toNode)) {
-                        fromNode.next.add(toNode);
-                    }
-
-                }
-            };
-            analyzer.analyze(owner, method);
-        }
-
-        private Block newBlock(InstructionNode firstInstruction) {
-            Objects.requireNonNull(firstInstruction);
-            Block b = new Block(firstInstruction);
-            allBlocks.put(firstInstruction.getIndex(), b);
-            return b;
-        }
-
-        private ControlFlow build() throws AnalyzerException {
-            analyze();
-            buildBlocks();
-            return new ControlFlow(allBlocks);
-        }
-
-        private void buildBlocks() {
-            List<Block> reachableBlocks = new ArrayList<>();
-            createBlocks(root, reachableBlocks);
-            List<Block> handlersBlocks = new ArrayList<>();
-            for (Entry<Integer, List<Integer>> entry : handlers.entrySet()) {
-                InstructionNode node = instructions.get(entry.getKey());
-                createBlocks(node, handlersBlocks);
-            }
-
-            // attach handler to try blocks
-            for (Entry<Integer, List<Integer>> entry : handlers.entrySet()) {
-                Block handlerBlock = allBlocks.get(entry.getKey());
-                handlerBlock.isExceptionHandler = true;
-                int startTry = entry.getValue().get(0);
-                Block tryBlock = allBlocks.get(startTry);
-                if (tryBlock == null) {
-                    // Need to find the block that contains the instruction and
-                    // make a new block
-                    Block split = null;
-                    for (Block b : allBlocks.values()) {
-                        Iterator<InstructionNode> it = b.instr.iterator();
-                        while (it.hasNext()) {
-                            InstructionNode in = it.next();
-                            if (split == null) {
-                                if (in.index == startTry) {
-                                    split = newBlock(in);
-                                    split.instr.add(in);
-                                    it.remove();
-                                }
-                            } else {
-                                split.instr.add(in);
-                                it.remove();
-                            }
-                        }
-                        if (split != null) {
-                            Iterator<Block> reachables = b.reachable.iterator();
-                            while (reachables.hasNext()) {
-                                Block r = reachables.next();
-                                split.reachable.add(r);
-                                reachables.remove();
-                            }
-                            b.reachable.add(split);
-                            break;
-                        }
-                    }
-                    if (split == null) {
-                        throw new RuntimeException("No try block for handler " + handlerBlock);
-                    }
-                    split.exceptionHandlers.add(handlerBlock);
-                } else {
-                    tryBlock.exceptionHandlers.add(handlerBlock);
-                }
-            }
-
-//            System.err.println("ALL BLOCKS FOUND");
-//            Iterator<Entry<Integer, Block>> blockIt0 = allBlocks.entrySet().iterator();
-//            while (blockIt0.hasNext()) {
-//                Block b = blockIt0.next().getValue();
-//                System.err.println(b);
-//            }
-            //compute real exception blocks, if an instruction is in another block, stop.
-            Iterator<Entry<Integer, Block>> blockIt = allBlocks.entrySet().iterator();
-            while (blockIt.hasNext()) {
-                Block b = blockIt.next().getValue();
-                Iterator<InstructionNode> in = b.instr.iterator();
-                boolean found = false;
-                while (in.hasNext()) {
-                    int i = in.next().getIndex();
-                    if (found) {
-                        in.remove();
-                    } else {
-                        if (startsWith(b, i, allBlocks.values())) {
-                            // Move it to reachable
-                            Block r = allBlocks.get(i);
-                            b.reachable.add(r);
-                            found = true;
-                            in.remove();
-                        } else {
-                        }
-                    }
-                }
-            }
-
-//            System.err.println("Reduced blocks");
-//            Iterator<Entry<Integer, Block>> blockIt1 = allBlocks.entrySet().iterator();
-//            while (blockIt1.hasNext()) {
-//                Block b = blockIt1.next().getValue();
-//                System.err.println(b);
-//            }
-        }
-
-        private boolean startsWith(Block block, int index, Collection<Block> reachableBlocks) {
-            for (Block b : reachableBlocks) {
-                if (b != block && !b.instr.isEmpty() && b.instr.get(0).getIndex() == index) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private static final class StackItem {
-
-            private final InstructionNode instr;
-            private final Block currentBlock;
-
-            private StackItem(InstructionNode instr, Block currentBlock) {
-                Objects.requireNonNull(instr);
-                Objects.requireNonNull(currentBlock);
-                this.instr = instr;
-                this.currentBlock = currentBlock;
-            }
-        }
-
-        /**
-         * This algorithm can't be recursive, possibly too much instructions in
-         * methods.
-         */
-        private void createBlocks(InstructionNode root, List<Block> blocks) {
-            final Stack<StackItem> stack = new Stack<>();
-            stack.push(new StackItem(root, newBlock(root)));
-            while (!stack.isEmpty()) {
-                final StackItem item = stack.pop();
-                final Block currentBlock = item.currentBlock;
-                final InstructionNode current = item.instr;
-                // loop
-                if (currentBlock.instr.contains(current)) {
-                    currentBlock.reachable.add(currentBlock);
-                    continue;
-                }
-                Block existing = allBlocks.get(current.index);
-                if (existing != null && existing != currentBlock) {
-                    currentBlock.reachable.add(existing);
-                    continue;
-                }
-                int previous = currentBlock.instr.size() > 0
-                        ? currentBlock.instr.get(currentBlock.instr.size() - 1).getIndex() : -1;
-                if (previous == -1 || current.getIndex() == previous + 1) {
-                    currentBlock.instr.add(current);
-                    if (current.next.isEmpty()) {
-                        blocks.add(currentBlock);
-                    } else {
-                        if (current.next.size() > 1) {
-                            blocks.add(currentBlock);
-                            for (InstructionNode n : current.next) {
-                                Block loop = allBlocks.get(n.index);
-                                if (loop == null) {
-                                    Block newBlock = newBlock(n);
-                                    currentBlock.reachable.add(newBlock);
-                                    stack.push(new StackItem(n, newBlock));
-                                } else { // loop
-                                    currentBlock.reachable.add(loop);
-                                }
-                            }
-                        } else {
-                            stack.push(new StackItem(current.next.get(0),
-                                    currentBlock));
-                        }
-                    }
-                } else { // to a new block...
-                    // Do nothing...
-                    blocks.add(currentBlock);
-                    Block newBlock = newBlock(current);
-                    currentBlock.reachable.add(newBlock);
-                    stack.push(new StackItem(current, newBlock));
-                }
-            }
-        }
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ForNameFolding.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins.optim;
-
-import java.io.IOException;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.function.Consumer;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.tools.jlink.internal.plugins.OptimizationPlugin.MethodOptimizer;
-import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
-import jdk.tools.jlink.internal.plugins.optim.ControlFlow.Block;
-import jdk.tools.jlink.internal.plugins.optim.ReflectionOptimizer.Data;
-import jdk.tools.jlink.internal.plugins.optim.ReflectionOptimizer.TypeResolver;
-
-
-/**
- * MethodOptimizer that removes Class.forName when possible.
- * WARNING: This code is experimental.
- * TODO: Need to check that the type is accessible prior to replace with a constant.
- */
-public class ForNameFolding implements MethodOptimizer {
-
-    private int numNotReplaced;
-    private int numReplacement;
-    private int numRemovedHandlers;
-    private int instructionsRemoved;
-
-    private Consumer<String> logger;
-
-    @Override
-    public boolean optimize(Consumer<String> logger, AsmPools pools,
-            AsmModulePool modulePool,
-            ClassNode cn, MethodNode m, TypeResolver resolver) throws Exception {
-        this.logger = logger;
-        Data data = ReflectionOptimizer.replaceWithClassConstant(cn, m, createResolver(resolver));
-        instructionsRemoved += data.removedInstructions();
-        numRemovedHandlers += data.removedHandlers().size();
-        for (Entry<String, Set<Block>> entry : data.removedHandlers().entrySet()) {
-            logRemoval(cn.name + "." + m.name + "removed block for " + entry.getKey()
-                    + " : " + entry.getValue());
-        }
-        return data.removedInstructions() > 0;
-    }
-
-    public TypeResolver createResolver(TypeResolver resolver) {
-        return (ClassNode cn, MethodNode mn, String type) -> {
-            ClassReader reader = resolver.resolve(cn, mn, type);
-            if (reader == null) {
-                logNotReplaced(type);
-            } else {
-                logReplaced(type);
-            }
-            return reader;
-        };
-    }
-
-    private void logReplaced(String type) {
-        numReplacement += 1;
-    }
-
-    private void logNotReplaced(String type) {
-        numNotReplaced += 1;
-        if (logger != null) {
-            logger.accept(type + " not resolved");
-        }
-    }
-
-    private void logRemoval(String content) {
-        numRemovedHandlers += 1;
-        if (logger != null) {
-            logger.accept(content);
-        }
-    }
-
-    @Override
-    public void close() throws IOException {
-        if (logger != null) {
-            logger.accept("Class.forName Folding results:\n " + numReplacement
-                    + " removed reflection. " + numRemovedHandlers
-                    + " removed exception handlers."
-                    + numNotReplaced + " types unknown. "
-                    + instructionsRemoved + " instructions removed\n");
-        }
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ReflectionOptimizer.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins.optim;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.Type;
-import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
-import jdk.internal.org.objectweb.asm.tree.LabelNode;
-import jdk.internal.org.objectweb.asm.tree.LdcInsnNode;
-import jdk.internal.org.objectweb.asm.tree.LineNumberNode;
-import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
-import jdk.tools.jlink.internal.plugins.optim.ControlFlow.Block;
-
-/**
- * Implement the reflection optimization.
- */
-public class ReflectionOptimizer {
-
-    public static class Data {
-
-        private int removedInstructions;
-        private final Map<String, Set<Block>> removedHandlers = new HashMap<>();
-
-        private Data() {
-        }
-
-        public int removedInstructions() {
-            return removedInstructions;
-        }
-
-        public Map<String, Set<Block>> removedHandlers() {
-            return Collections.unmodifiableMap(removedHandlers);
-        }
-    }
-
-    public interface TypeResolver {
-
-        public ClassReader resolve(ClassNode cn, MethodNode m, String type);
-    }
-
-    public static Data replaceWithClassConstant(ClassNode cn, MethodNode m,
-            TypeResolver cch)
-            throws Exception {
-        Iterator<AbstractInsnNode> it = m.instructions.iterator();
-        LdcInsnNode insNode = null;
-        Map<LdcInsnNode, LdcInsnNode> replacement = new IdentityHashMap<>();
-        Data data = new Data();
-        while (it.hasNext()) {
-            AbstractInsnNode n = it.next();
-            if (n instanceof LdcInsnNode) {
-                LdcInsnNode ldc = (LdcInsnNode) n;
-                if (ldc.cst instanceof String) {
-                    insNode = ldc;
-                }
-            } else {
-                if (n instanceof MethodInsnNode && insNode != null) {
-                    MethodInsnNode met = (MethodInsnNode) n;
-                    if (met.name.equals("forName")
-                            && met.owner.equals("java/lang/Class")
-                            && met.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
-                        // Can we load the type?
-                        Type type = null;
-                        String binaryName = insNode.cst.toString().replaceAll("\\.", "/");
-                        String unaryClassName = binaryName;
-                        int arrayIndex = binaryName.lastIndexOf("[");
-                        if (arrayIndex >= 0) {
-                            int objIndex = unaryClassName.indexOf("L");
-                            if (objIndex >= 0) {
-                                unaryClassName = unaryClassName.substring(objIndex + 1);
-                                unaryClassName = unaryClassName.substring(0,
-                                        unaryClassName.length() - 1);
-                            } else {
-                                //primitive, this is just fine.
-                                type = Type.getObjectType(binaryName);
-                            }
-                        }
-                        if (type == null) {
-                            if (cch.resolve(cn, m, unaryClassName) != null) {
-                                type = Type.getObjectType(binaryName);
-                            }
-                        }
-                        if (type != null) {
-                            replacement.put(insNode, new LdcInsnNode(type));
-                            it.remove();
-                            data.removedInstructions += 1;
-                        }
-                    } else {
-                        insNode = null;
-                    }
-                    // Virtual node, not taken into account
-                } else if (!(n instanceof LabelNode) && !(n instanceof LineNumberNode)) {
-                    insNode = null;
-                }
-            }
-        }
-        for (Map.Entry<LdcInsnNode, LdcInsnNode> entry : replacement.entrySet()) {
-            m.instructions.set(entry.getKey(), entry.getValue());
-        }
-        if (!replacement.isEmpty()) {
-            String[] types = {"java/lang/ClassNotFoundException"};
-            data.removedInstructions += deleteExceptionHandlers(cch, data, cn, m, types);
-
-        }
-        return data;
-    }
-
-    private static int deleteExceptionHandlers(TypeResolver cch, Data data,
-            ClassNode cn, MethodNode m, String[] exTypes)
-            throws Exception {
-        int instructionsRemoved = 0;
-        for (String ex : exTypes) {
-            ControlFlow f = ControlFlow.createControlFlow(cn.name, m);
-            List<Integer> removed = new ArrayList<>();
-            Set<ControlFlow.Block> blocksToRemove = new TreeSet<>();
-            Iterator<TryCatchBlockNode> it = m.tryCatchBlocks.iterator();
-            List<TryCatchBlockNode> tcbToRemove = new ArrayList<>();
-            while (it.hasNext()) {
-                TryCatchBlockNode bn = it.next();
-                if (bn.type == null
-                        || !bn.type.equals(ex) // An empty block
-                        || tcbToRemove.contains(bn)) {
-                    continue;
-                }
-                // Check that the handler is still required
-                if (!Utils.canThrowCheckedException(cch, cn, m, bn)) {
-                    // try to suppress it.
-                    int block = m.instructions.indexOf(bn.handler);
-                    ControlFlow.Block blockHandler = f.getBlock(block);
-                    if (blockHandler == null) {
-                        if (removed.contains(block)) {
-                            continue;
-                        } else {
-                            throw new Exception(cn.name
-                                    + ", no block for handler " + block);
-                        }
-                    }
-                    tcbToRemove.add(bn);
-                    // Don't delete block if shared (eg: ClassNotFoundException | NoSuchMethodException |
-                    Iterator<TryCatchBlockNode> it2 = m.tryCatchBlocks.iterator();
-                    boolean cont = false;
-                    while (it2.hasNext()) {
-                        TryCatchBlockNode bn2 = it2.next();
-                        if (bn2 != bn) {
-                            if (bn2.start.equals(bn.start)) {
-                                cont = true;
-                            }
-                        }
-                    }
-                    if (cont) {
-                        continue;
-                    }
-                    // An handler is a root, blocks that are only reachable by it
-                    // can be removed.
-                    Set<ControlFlow.Block> blocks = f.getClosure(blockHandler);
-                    StringBuilder sb = new StringBuilder();
-                    for (ControlFlow.Block b : blocks) {
-                        sb.append(b).append("\n");
-                        removed.add(b.getFirstInstruction().getIndex());
-                        // Remove Exception handler if the associated block has been removed
-                        for (TryCatchBlockNode tcb : m.tryCatchBlocks) {
-                            if (tcb != bn) {
-                                // An exception handler removed as a side effect.
-                                if (b.isExceptionHandler()
-                                        && b.getFirstInstruction().getInstr() == tcb.handler) {
-                                    tcbToRemove.add(tcb);
-                                }
-                            }
-                        }
-                    }
-                    blocksToRemove.addAll(blocks);
-
-                    data.removedHandlers.put(ex, blocks);
-
-                }
-            }
-
-            m.tryCatchBlocks.removeAll(tcbToRemove);
-
-            if (!blocksToRemove.isEmpty()) {
-                for (ControlFlow.Block b : blocksToRemove) {
-                    for (ControlFlow.InstructionNode ins : b.getInstructions()) {
-                        if (ins.getInstr().getOpcode() > 0) {
-                            instructionsRemoved += 1;
-                        }
-                    }
-                }
-                Utils.suppressBlocks(m, blocksToRemove);
-            }
-        }
-        return instructionsRemoved;
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/Utils.java	Thu Jul 07 18:21:23 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins.optim;
-
-import java.util.Iterator;
-import java.util.Set;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
-import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
-
-/**
- * Optimization utility methods
- */
-public class Utils {
-
-    public static boolean canThrowCheckedException(ReflectionOptimizer.TypeResolver cch,
-            ClassNode classNode, MethodNode m, TryCatchBlockNode bn) throws Exception {
-        int istart = m.instructions.indexOf(bn.start);
-        int iend = m.instructions.indexOf(bn.end);
-        for (int i = istart; i < iend - 1; i++) {
-            AbstractInsnNode instr = m.instructions.get(i);
-            if (instr instanceof MethodInsnNode) {
-                MethodInsnNode meth = (MethodInsnNode) instr;
-                ClassReader reader = cch.resolve(classNode, m, meth.owner);
-                if (reader != null) {
-                    ClassNode cn = new ClassNode();
-                    reader.accept(cn, ClassReader.EXPAND_FRAMES);
-                    for (MethodNode method : cn.methods) {
-                        if (method.name.equals(meth.name)) {
-                            for (String e : method.exceptions) {
-                                if (e.equals(bn.type)) {
-                                    return true;
-                                }
-                            }
-                        }
-                    }
-                } else {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public static void suppressBlocks(MethodNode m, Set<ControlFlow.Block> toRemove) throws Exception {
-        m.instructions.resetLabels();
-        Iterator<AbstractInsnNode> it = m.instructions.iterator();
-        while (it.hasNext()) {
-            AbstractInsnNode n = it.next();
-            Iterator<TryCatchBlockNode> handlers = m.tryCatchBlocks.iterator();
-            boolean cont = false;
-            // Do not delete instructions that are end of other try block.
-            while (handlers.hasNext()) {
-                TryCatchBlockNode handler = handlers.next();
-                if (handler.end == n) {
-                    cont = true;
-                }
-            }
-            if (cont) {
-                continue;
-            }
-
-            for (ControlFlow.Block b : toRemove) {
-                for (ControlFlow.InstructionNode ins : b.getInstructions()) {
-                    if (ins.getInstr() == n) {
-                        it.remove();
-                    }
-                }
-            }
-        }
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties	Thu Jul 07 18:35:29 2016 +0000
@@ -31,11 +31,10 @@
 Any number of <key>=<value> pairs can be passed.\n\
 del: is to delete the list of keys in release file.
 
-class-optim.argument=<all|forName-folding>[:log=<log file>]
+class-for-name.argument=
 
-class-optim.description=\
-Class optimization. Warning: This plugin is experimental.\n\
-An optional <log file> can be specified to log applied optimizations.
+class-for-name.description=\
+Class optimization: convert Class.forName calls to constant loads.
 
 compress.argument=<0|1|2>[:filter=<pattern-list>]
 
@@ -47,7 +46,6 @@
 An optional <pattern-list> filter can be specified to list the pattern of\n\
 files to be included.
 
-
 compact-cp.argument=<resource paths>
 
 compact-cp.description=Constant Pool strings sharing.\n\
--- a/src/jdk.jlink/share/classes/module-info.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/src/jdk.jlink/share/classes/module-info.java	Thu Jul 07 18:35:29 2016 +0000
@@ -39,9 +39,9 @@
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.StripNativeCommandsPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.OrderResourcesPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.OptimizationPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.IncludeLocalesPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin;
-}
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ClassForNamePlugin;
+ }
--- a/test/ProblemList.txt	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/ProblemList.txt	Thu Jul 07 18:35:29 2016 +0000
@@ -124,6 +124,10 @@
 # jdk_lang
 
 java/lang/StringCoding/CheckEncodings.sh                        7008363 generic-all
+java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java	8160690 generic-all
+java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java	8160690 generic-all
+java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java	8160690 generic-all
+java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java	8160690 generic-all
 
 ############################################################################
 
@@ -136,6 +140,9 @@
 
 java/lang/management/MemoryMXBean/LowMemoryTest.java            8130339 generic-all
 
+java/lang/management/MemoryMXBean/Pending.java                  8158837 generic-all
+java/lang/management/MemoryMXBean/PendingAllGC.sh               8158760 generic-all
+
 ############################################################################
 
 # jdk_io
@@ -278,8 +285,6 @@
 
 sun/security/tools/keytool/autotest.sh                          8130302 generic-all
 
-sun/security/x509/URICertStore/ExtensionsWithLDAP.java          8134577 generic-all
-
 ############################################################################
 
 # jdk_sound
@@ -344,8 +349,6 @@
 
 java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.java 8062512 generic-all
 
-java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java 8130337 generic-all
-
 java/util/Arrays/ParallelPrefix.java                            8080165,8085982 generic-all
 
 java/util/BitSet/BitSetStreamTest.java                          8079538 generic-all
--- a/test/TEST.groups	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/TEST.groups	Thu Jul 07 18:35:29 2016 +0000
@@ -27,6 +27,7 @@
 
 tier1 = \
     :jdk_lang \
+    -java/lang/ProcessBuilder/Zombies.java \
     :jdk_util \
     -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
     -java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
@@ -37,6 +38,7 @@
     tools/pack200
 
 tier2 = \
+    java/lang/ProcessBuilder/Zombies.java \
     java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
     java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
     :jdk_io \
--- a/test/com/sun/crypto/provider/KeyAgreement/SupportedDHParamGens.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/com/sun/crypto/provider/KeyAgreement/SupportedDHParamGens.java	Thu Jul 07 18:35:29 2016 +0000
@@ -29,8 +29,8 @@
  * @run main/timeout=300 SupportedDHParamGens 768
  * @run main/timeout=300 SupportedDHParamGens 832
  * @run main/timeout=300 SupportedDHParamGens 1024
- * @run main/timeout=300 SupportedDHParamGens 2048
- * @run main/timeout=450 SupportedDHParamGens 3072
+ * @run main/timeout=600 SupportedDHParamGens 2048
+ * @run main/timeout=700 SupportedDHParamGens 3072
  */
 
 import java.math.BigInteger;
--- a/test/java/io/Serializable/failureAtomicity/FailureAtomicity.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/java/io/Serializable/failureAtomicity/FailureAtomicity.java	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
  * @test
  * @bug 8071474
  * @summary Better failure atomicity for default read object.
+ * @modules jdk.compiler
  * @library /lib/testlibrary
  * @build jdk.testlibrary.FileUtils
  * @compile FailureAtomicity.java SerialRef.java
--- a/test/java/lang/ProcessBuilder/Zombies.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/java/lang/ProcessBuilder/Zombies.java	Thu Jul 07 18:35:29 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,9 @@
             ! new File("/bin/ps").canExecute())
             return;
         System.out.println("Looks like a Unix system.");
+        long mypid = ProcessHandle.current().getPid();
+        System.out.printf("mypid: %d%n", mypid);
+
         final Runtime rt = Runtime.getRuntime();
 
         try {
@@ -59,7 +62,10 @@
             throw new Error("expected IOException not thrown");
         } catch (IOException expected) {/* OK */}
 
-        rt.exec(TrueCommand).waitFor();
+        Process p = rt.exec(TrueCommand);
+        ProcessHandle pp = p.toHandle().parent().orElse(null);
+        System.out.printf("pid: %d, parent: %s%n", p.getPid(), pp);
+        p.waitFor();
 
         // Count all the zombies that are children of this Java process
         final String[] zombieCounter = {
@@ -68,6 +74,13 @@
         };
 
         int zombies = rt.exec(zombieCounter).waitFor();
-        if (zombies != 0) throw new Error(zombies + " zombies!");
+        if (zombies != 0) {
+            // Log remaining processes
+            ProcessBuilder pb = new ProcessBuilder("/bin/ps", "-ef");
+            pb.inheritIO();
+            Process p2 = pb.start();
+            p2.waitFor();
+            throw new Error(zombies + " zombies!");
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/annotation/AnnotationVerifier.java	Thu Jul 07 18:35:29 2016 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Create class file using ASM, slightly modified the ASMifier output
+ */
+
+import sun.reflect.annotation.AnnotationType;
+import java.lang.annotation.AnnotationFormatError;
+import org.testng.annotations.*;
+
+/*
+ * @test
+ * @bug 8158510
+ * @summary Verify valid annotation
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @modules java.base/sun.reflect.annotation
+ * @clean AnnotationWithVoidReturn.class AnnotationWithParameter.class
+ * @compile -XDignore.symbol.file ClassFileGenerator.java
+ * @run main ClassFileGenerator
+ * @run testng AnnotationVerifier
+ */
+
+public class AnnotationVerifier {
+
+    @AnnotationWithParameter
+    @AnnotationWithVoidReturn
+    static class BadAnnotation {
+    }
+
+    @Test
+    @ExpectedExceptions(IllegalArgumentException.class)
+    public void annotationValidationIAE() {
+        AnnotationType.getInstance(AnnotationWithParameter.class);
+    }
+
+    @Test(expectedExceptions = AnnotationFormatError.class)
+    public void annotationValidationAFE() {
+        BadAnnotation.class.getAnnotation(AnnotationWithVoidReturn.class);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/annotation/ClassFileGenerator.java	Thu Jul 07 18:35:29 2016 +0000
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Create class file using ASM, slightly modified the ASMifier output
+ */
+
+
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import jdk.internal.org.objectweb.asm.*;
+
+
+public class ClassFileGenerator {
+
+    public static void main(String... args) throws Exception {
+        classFileWriter("AnnotationWithVoidReturn.class", AnnoationWithVoidReturnDump.dump());
+        classFileWriter("AnnotationWithParameter.class", AnnoationWithParameterDump.dump());
+    }
+
+    private static void classFileWriter(String name, byte[] contents) throws IOException {
+        try (FileOutputStream fos = new FileOutputStream(new File(System.getProperty("test.classes"),
+                name))) {
+            fos.write(contents);
+        }
+    }
+
+    /*
+    Following code create equivalent classfile,
+    which is not allowed by javac.
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface AnnotationWithVoidReturn {
+    void m() default 1;
+    }
+    */
+
+    private static class AnnoationWithVoidReturnDump implements Opcodes {
+        public static byte[] dump() throws Exception {
+            ClassWriter cw = new ClassWriter(0);
+            MethodVisitor mv;
+            AnnotationVisitor av0;
+
+            cw.visit(52, ACC_PUBLIC + ACC_ANNOTATION + ACC_ABSTRACT + +ACC_INTERFACE,
+                    "AnnotationWithVoidReturn", null,
+                    "java/lang/Object", new String[]{"java/lang/annotation/Annotation"});
+
+            {
+                av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
+                av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;",
+                        "RUNTIME");
+                av0.visitEnd();
+            }
+            {
+                mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "m", "()V", null, null);
+                mv.visitEnd();
+            }
+            {
+                av0 = mv.visitAnnotationDefault();
+                av0.visit(null, new Integer(1));
+                av0.visitEnd();
+            }
+            cw.visitEnd();
+
+            return cw.toByteArray();
+
+        }
+    }
+
+    /*
+    Following code create equivalent classfile,
+    which is not allowed by javac.
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface AnnotationWithParameter {
+       int m(int x);
+    }
+    */
+
+    private static class AnnoationWithParameterDump implements Opcodes {
+        public static byte[] dump() throws Exception {
+
+            ClassWriter cw = new ClassWriter(0);
+            MethodVisitor mv;
+            AnnotationVisitor av0;
+
+            cw.visit(52, ACC_PUBLIC + ACC_ANNOTATION + ACC_ABSTRACT + ACC_INTERFACE,
+                    "AnnotationWithParameter", null,
+                    "java/lang/Object", new String[]{"java/lang/annotation/Annotation"});
+
+            {
+                av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
+                av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;",
+                        "RUNTIME");
+                av0.visitEnd();
+            }
+            {
+                mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT,
+                        "badValue",
+                        "(I)I", // Bad method with a parameter
+                        null, null);
+                mv.visitEnd();
+            }
+            {
+                av0 = mv.visitAnnotationDefault();
+                av0.visit(null, new Integer(-1));
+                av0.visitEnd();
+            }
+            cw.visitEnd();
+
+            return cw.toByteArray();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/annotation/typeAnnotations/MissingAnnotation.java	Thu Jul 07 18:35:29 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE_USE)
+public @interface MissingAnnotation { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/annotation/typeAnnotations/NoNpeOnMissingAnnotation.java	Thu Jul 07 18:35:29 2016 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8152174
+ * @summary Verify that a missing class file for a type use annotation doesn't cause a NPE when attempting to read the annotation.
+ * @compile NoNpeOnMissingAnnotation.java MissingAnnotation.java
+ * @run main NoNpeOnMissingAnnotation
+ * @clean MissingAnnotation
+ * @run main NoNpeOnMissingAnnotation
+ */
+
+import java.lang.annotation.*;
+
+public class NoNpeOnMissingAnnotation {
+    public static void main(String... args) throws Exception {
+        System.out.println(NoNpeOnMissingAnnotation.class.
+                           getDeclaredMethod("foo").
+                           getAnnotatedReturnType());
+    }
+
+    @MissingAnnotation Object foo() { return null; }
+}
--- a/test/java/lang/invoke/DropArgumentsTest.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/java/lang/invoke/DropArgumentsTest.java	Thu Jul 07 18:35:29 2016 +0000
@@ -24,6 +24,7 @@
  */
 
 /* @test
+ * @bug  8158169
  * @summary unit tests for java.lang.invoke.MethodHandles
  * @run testng test.java.lang.invoke.DropArgumentsTest
  */
@@ -32,6 +33,7 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.util.Collections;
 import java.util.List;
 import static java.lang.invoke.MethodHandles.*;
 import static java.lang.invoke.MethodType.*;
@@ -78,6 +80,7 @@
             {cat, -1, bigType.parameterList(), 0},
             {cat, 0, bigType.parameterList(), -1},
             {cat, 3, bigType.parameterList(), 0},
+            {cat, 0, bigType.parameterList(), 6},
             {cat, 0, bigType.parameterList(), 2}
         };
     }
@@ -96,4 +99,30 @@
         MethodType bigTypewithVoid = cat.type().insertParameterTypes(0, void.class, String.class, int.class);
         MethodHandle handle2 = MethodHandles.dropArgumentsToMatch(cat, 0, bigTypewithVoid.parameterList(), 1);
     }
+
+    public static class MethodSet {
+
+        static void mVoid() {
+
+        }
+
+        static void mVoid(int t) {
+
+        }
+    }
+
+    @Test
+    public void dropArgumentsToMatchPosSkipRange() throws Throwable {
+        // newTypes.size() == 1, pos == 1   &&   target.paramSize() == 0, skip == 0
+        MethodHandle mh1 = MethodHandles.lookup().findStatic(MethodSet.class, "mVoid",
+                                                             MethodType.methodType(void.class));
+        MethodHandle handle1 = dropArgumentsToMatch(mh1, 0, Collections.singletonList(int.class), 1);
+        assertEquals(1, handle1.type().parameterList().size());
+
+        // newTypes.size() == 1, pos == 0   &&   target.paramSize() == 1, skip == 1
+        MethodHandle mh2 = MethodHandles.lookup().findStatic(MethodSet.class, "mVoid",
+                                                             MethodType.methodType(void.class, int.class));
+        MethodHandle handle2 = dropArgumentsToMatch(mh2, 1, Collections.singletonList(int.class), 0);
+        assertEquals(2, handle2.type().parameterList().size());
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/LoopCombinatorLongSignatureTest.java	Thu Jul 07 18:35:29 2016 +0000
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+/* @test
+ * @bug 8160717
+ * @run main/othervm -ea -esa -Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=-1 test.java.lang.invoke.LoopCombinatorLongSignatureTest
+ * @run main/othervm -ea -esa test.java.lang.invoke.LoopCombinatorLongSignatureTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
+
+/**
+ * If a loop with an excessive amount of clauses is created, so that the number of parameters to the resulting loop
+ * handle exceeds the allowed maximum, an IAE must be signalled. The test is run first in LambdaForm interpretation mode
+ * and then in default mode, wherein bytecode generation falls back to LFI mode due to excessively long methods.
+ */
+public class LoopCombinatorLongSignatureTest {
+
+    static final MethodHandle INIT = MethodHandles.constant(int.class, 0);
+    static final MethodHandle STEP = MethodHandles.identity(int.class);
+    static final MethodHandle PRED_F = MethodHandles.constant(boolean.class, false);
+    static final MethodHandle PRED_T = MethodHandles.constant(boolean.class, true);
+    static final MethodHandle FINI = MethodHandles.identity(int.class);
+
+    static final int ARG_LIMIT = 254; // for internal reasons, this is the maximum allowed number of arguments
+
+    public static void main(String[] args) {
+        for (int loopArgs = 0; loopArgs < 2; ++loopArgs) {
+            testLongSignature(loopArgs, false);
+            testLongSignature(loopArgs, true);
+        }
+    }
+
+    static void testLongSignature(int loopArgs, boolean excessive) {
+        int nClauses = ARG_LIMIT - loopArgs + (excessive ? 1 : 0);
+
+        System.out.print((excessive ? "(EXCESSIVE)" : "(LONG     )") + " arguments: " + loopArgs + ", clauses: " + nClauses + " -> ");
+
+        // extend init to denote what arguments the loop should accept
+        Class<?>[] argTypes = new Class<?>[loopArgs];
+        Arrays.fill(argTypes, int.class);
+        MethodHandle init = MethodHandles.dropArguments(INIT, 0, argTypes);
+
+        // build clauses
+        MethodHandle[][] clauses = new MethodHandle[nClauses][];
+        MethodHandle[] clause = {init, STEP, PRED_T, FINI};
+        MethodHandle[] fclause = {init, STEP, PRED_F, FINI};
+        Arrays.fill(clauses, clause);
+        clauses[nClauses - 1] = fclause; // make the last clause terminate the loop
+
+        try {
+            MethodHandle loop = MethodHandles.loop(clauses);
+            if (excessive) {
+                throw new AssertionError("loop construction should have failed");
+            } else {
+                int r;
+                if (loopArgs == 0) {
+                    r = (int) loop.invoke();
+                } else {
+                    Object[] args = new Object[loopArgs];
+                    Arrays.fill(args, 0);
+                    r = (int) loop.invokeWithArguments(args);
+                }
+                System.out.println("SUCCEEDED (OK) -> " + r);
+            }
+        } catch (IllegalArgumentException iae) {
+            if (excessive) {
+                System.out.println("FAILED    (OK)");
+            } else {
+                iae.printStackTrace(System.out);
+                throw new AssertionError("loop construction should not have failed (see above)");
+            }
+        } catch (Throwable t) {
+            t.printStackTrace(System.out);
+            throw new AssertionError("unexpected failure (see above)");
+        }
+    }
+
+}
--- a/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java	Thu Jul 07 18:35:29 2016 +0000
@@ -145,7 +145,7 @@
         GET_OPAQUE(TestAccessType.GET),
         SET_OPAQUE(TestAccessType.SET),
         COMPARE_AND_SET(TestAccessType.COMPARE_AND_SET),
-        COMPARE_AND_EXCHANGE_VOLATILE(TestAccessType.COMPARE_AND_EXCHANGE),
+        COMPARE_AND_EXCHANGE(TestAccessType.COMPARE_AND_EXCHANGE),
         COMPARE_AND_EXCHANGE_ACQUIRE(TestAccessType.COMPARE_AND_EXCHANGE),
         COMPARE_AND_EXCHANGE_RELEASE(TestAccessType.COMPARE_AND_EXCHANGE),
         WEAK_COMPARE_AND_SET(TestAccessType.COMPARE_AND_SET),
--- a/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java	Thu Jul 07 18:35:29 2016 +0000
@@ -99,15 +99,15 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
 
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET));
@@ -260,41 +260,6 @@
             vh.setOpaque(recv, false);
         });
 
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeVolatile(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeRelease(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.getAndSet(recv, true);
-        });
 
         checkUOE(() -> {
             boolean o = (boolean) vh.getAndAdd(recv, true);
@@ -350,41 +315,6 @@
             vh.setOpaque(false);
         });
 
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeVolatile(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeRelease(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.getAndSet(true);
-        });
 
         checkUOE(() -> {
             boolean o = (boolean) vh.getAndAdd(true);
@@ -426,45 +356,116 @@
             assertEquals(x, false, "setOpaque boolean value");
         }
 
+        vh.set(recv, true);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, true, false);
+            assertEquals(r, true, "success compareAndSet boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "success compareAndSet boolean value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, true, false);
+            assertEquals(r, false, "failing compareAndSet boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "failing compareAndSet boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchange(recv, false, true);
+            assertEquals(r, false, "success compareAndExchange boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "success compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchange(recv, false, false);
+            assertEquals(r, true, "failing compareAndExchange boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "failing compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
+            assertEquals(r, true, "success compareAndExchangeAcquire boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "success compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
+            assertEquals(r, false, "failing compareAndExchangeAcquire boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "failing compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeRelease(recv, false, true);
+            assertEquals(r, false, "success compareAndExchangeRelease boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "success compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeRelease(recv, false, false);
+            assertEquals(r, true, "failing compareAndExchangeRelease boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "failing compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSet boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "weakCompareAndSet boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "weakCompareAndSetAcquire boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "weakCompareAndSetRelease boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetVolatile(recv, false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "weakCompareAndSetVolatile boolean value");
+        }
+
+        // Compare set and get
+        {
+            boolean o = (boolean) vh.getAndSet(recv, false);
+            assertEquals(o, true, "getAndSet boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "getAndSet boolean value");
+        }
 
     }
 
     static void testInstanceFieldUnsupported(VarHandleTestAccessBoolean recv, VarHandle vh) {
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeVolatile(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeRelease(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(recv, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.getAndSet(recv, true);
-        });
 
         checkUOE(() -> {
             boolean o = (boolean) vh.getAndAdd(recv, true);
@@ -506,45 +507,116 @@
             assertEquals(x, false, "setOpaque boolean value");
         }
 
+        vh.set(true);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(true, false);
+            assertEquals(r, true, "success compareAndSet boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "success compareAndSet boolean value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(true, false);
+            assertEquals(r, false, "failing compareAndSet boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "failing compareAndSet boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchange(false, true);
+            assertEquals(r, false, "success compareAndExchange boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "success compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchange(false, false);
+            assertEquals(r, true, "failing compareAndExchange boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "failing compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
+            assertEquals(r, true, "success compareAndExchangeAcquire boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "success compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
+            assertEquals(r, false, "failing compareAndExchangeAcquire boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "failing compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeRelease(false, true);
+            assertEquals(r, false, "success compareAndExchangeRelease boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "success compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeRelease(false, false);
+            assertEquals(r, true, "failing compareAndExchangeRelease boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "failing compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSet boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "weakCompareAndSet boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "weakCompareAndSetAcquire boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "weakCompareAndSetRelease boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "weakCompareAndSetVolatile boolean");
+        }
+
+        // Compare set and get
+        {
+            boolean o = (boolean) vh.getAndSet(false);
+            assertEquals(o, true, "getAndSet boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "getAndSet boolean value");
+        }
 
     }
 
     static void testStaticFieldUnsupported(VarHandle vh) {
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeVolatile(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeRelease(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.getAndSet(true);
-        });
 
         checkUOE(() -> {
             boolean o = (boolean) vh.getAndAdd(true);
@@ -589,6 +661,112 @@
                 assertEquals(x, false, "setOpaque boolean value");
             }
 
+            vh.set(array, i, true);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, true, false);
+                assertEquals(r, true, "success compareAndSet boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "success compareAndSet boolean value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, true, false);
+                assertEquals(r, false, "failing compareAndSet boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "failing compareAndSet boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchange(array, i, false, true);
+                assertEquals(r, false, "success compareAndExchange boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "success compareAndExchange boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchange(array, i, false, false);
+                assertEquals(r, true, "failing compareAndExchange boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "failing compareAndExchange boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchangeAcquire(array, i, true, false);
+                assertEquals(r, true, "success compareAndExchangeAcquire boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "success compareAndExchangeAcquire boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchangeAcquire(array, i, true, false);
+                assertEquals(r, false, "failing compareAndExchangeAcquire boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "failing compareAndExchangeAcquire boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchangeRelease(array, i, false, true);
+                assertEquals(r, false, "success compareAndExchangeRelease boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "success compareAndExchangeRelease boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchangeRelease(array, i, false, false);
+                assertEquals(r, true, "failing compareAndExchangeRelease boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "failing compareAndExchangeRelease boolean value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, true, false);
+                }
+                assertEquals(success, true, "weakCompareAndSet boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "weakCompareAndSet boolean value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, false, true);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "weakCompareAndSetAcquire boolean");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, true, false);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "weakCompareAndSetRelease boolean");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetVolatile(array, i, false, true);
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "weakCompareAndSetVolatile boolean");
+            }
+
+            // Compare set and get
+            {
+                boolean o = (boolean) vh.getAndSet(array, i, false);
+                assertEquals(o, true, "getAndSet boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "getAndSet boolean value");
+            }
 
         }
     }
@@ -597,41 +775,6 @@
         boolean[] array = new boolean[10];
 
         int i = 0;
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(array, i, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeVolatile(array, i, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeAcquire(array, i, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.compareAndExchangeRelease(array, i, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(array, i, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(array, i, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(array, i, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(array, i, true, false);
-        });
-
-        checkUOE(() -> {
-            boolean r = (boolean) vh.getAndSet(array, i, true);
-        });
 
         checkUOE(() -> {
             boolean o = (boolean) vh.getAndAdd(array, i, true);
@@ -680,6 +823,41 @@
                 vh.setOpaque(array, ci, true);
             });
 
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, true, false);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = (boolean) vh.compareAndExchange(array, ci, false, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = (boolean) vh.compareAndExchangeAcquire(array, ci, false, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = (boolean) vh.compareAndExchangeRelease(array, ci, false, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, true, false);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, true, false);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, true, false);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, true, false);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndSet(array, ci, true);
+            });
 
         }
     }
--- a/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java	Thu Jul 07 18:35:29 2016 +0000
@@ -42,11 +42,11 @@
 import static org.testng.Assert.*;
 
 public class VarHandleTestAccessByte extends VarHandleBaseTest {
-    static final byte static_final_v = (byte)1;
+    static final byte static_final_v = (byte)0x01;
 
     static byte static_v;
 
-    final byte final_v = (byte)1;
+    final byte final_v = (byte)0x01;
 
     byte v;
 
@@ -99,18 +99,18 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
 
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET));
     }
 
 
@@ -220,89 +220,47 @@
         // Plain
         {
             byte x = (byte) vh.get(recv);
-            assertEquals(x, (byte)1, "get byte value");
+            assertEquals(x, (byte)0x01, "get byte value");
         }
 
 
         // Volatile
         {
             byte x = (byte) vh.getVolatile(recv);
-            assertEquals(x, (byte)1, "getVolatile byte value");
+            assertEquals(x, (byte)0x01, "getVolatile byte value");
         }
 
         // Lazy
         {
             byte x = (byte) vh.getAcquire(recv);
-            assertEquals(x, (byte)1, "getRelease byte value");
+            assertEquals(x, (byte)0x01, "getRelease byte value");
         }
 
         // Opaque
         {
             byte x = (byte) vh.getOpaque(recv);
-            assertEquals(x, (byte)1, "getOpaque byte value");
+            assertEquals(x, (byte)0x01, "getOpaque byte value");
         }
     }
 
     static void testInstanceFinalFieldUnsupported(VarHandleTestAccessByte recv, VarHandle vh) {
         checkUOE(() -> {
-            vh.set(recv, (byte)2);
+            vh.set(recv, (byte)0x23);
         });
 
         checkUOE(() -> {
-            vh.setVolatile(recv, (byte)2);
+            vh.setVolatile(recv, (byte)0x23);
         });
 
         checkUOE(() -> {
-            vh.setRelease(recv, (byte)2);
+            vh.setRelease(recv, (byte)0x23);
         });
 
         checkUOE(() -> {
-            vh.setOpaque(recv, (byte)2);
+            vh.setOpaque(recv, (byte)0x23);
         });
 
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(recv, (byte)1, (byte)2);
-        });
 
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeVolatile(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.getAndSet(recv, (byte)1);
-        });
-
-        checkUOE(() -> {
-            byte o = (byte) vh.getAndAdd(recv, (byte)1);
-        });
-
-        checkUOE(() -> {
-            byte o = (byte) vh.addAndGet(recv, (byte)1);
-        });
     }
 
 
@@ -310,249 +268,353 @@
         // Plain
         {
             byte x = (byte) vh.get();
-            assertEquals(x, (byte)1, "get byte value");
+            assertEquals(x, (byte)0x01, "get byte value");
         }
 
 
         // Volatile
         {
             byte x = (byte) vh.getVolatile();
-            assertEquals(x, (byte)1, "getVolatile byte value");
+            assertEquals(x, (byte)0x01, "getVolatile byte value");
         }
 
         // Lazy
         {
             byte x = (byte) vh.getAcquire();
-            assertEquals(x, (byte)1, "getRelease byte value");
+            assertEquals(x, (byte)0x01, "getRelease byte value");
         }
 
         // Opaque
         {
             byte x = (byte) vh.getOpaque();
-            assertEquals(x, (byte)1, "getOpaque byte value");
+            assertEquals(x, (byte)0x01, "getOpaque byte value");
         }
     }
 
     static void testStaticFinalFieldUnsupported(VarHandle vh) {
         checkUOE(() -> {
-            vh.set((byte)2);
+            vh.set((byte)0x23);
         });
 
         checkUOE(() -> {
-            vh.setVolatile((byte)2);
+            vh.setVolatile((byte)0x23);
         });
 
         checkUOE(() -> {
-            vh.setRelease((byte)2);
+            vh.setRelease((byte)0x23);
         });
 
         checkUOE(() -> {
-            vh.setOpaque((byte)2);
+            vh.setOpaque((byte)0x23);
         });
 
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet((byte)1, (byte)2);
-        });
 
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeVolatile((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeAcquire((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeRelease((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.getAndSet((byte)1);
-        });
-
-        checkUOE(() -> {
-            byte o = (byte) vh.getAndAdd((byte)1);
-        });
-
-        checkUOE(() -> {
-            byte o = (byte) vh.addAndGet((byte)1);
-        });
     }
 
 
     static void testInstanceField(VarHandleTestAccessByte recv, VarHandle vh) {
         // Plain
         {
-            vh.set(recv, (byte)1);
+            vh.set(recv, (byte)0x01);
             byte x = (byte) vh.get(recv);
-            assertEquals(x, (byte)1, "set byte value");
+            assertEquals(x, (byte)0x01, "set byte value");
         }
 
 
         // Volatile
         {
-            vh.setVolatile(recv, (byte)2);
+            vh.setVolatile(recv, (byte)0x23);
             byte x = (byte) vh.getVolatile(recv);
-            assertEquals(x, (byte)2, "setVolatile byte value");
+            assertEquals(x, (byte)0x23, "setVolatile byte value");
         }
 
         // Lazy
         {
-            vh.setRelease(recv, (byte)1);
+            vh.setRelease(recv, (byte)0x01);
             byte x = (byte) vh.getAcquire(recv);
-            assertEquals(x, (byte)1, "setRelease byte value");
+            assertEquals(x, (byte)0x01, "setRelease byte value");
         }
 
         // Opaque
         {
-            vh.setOpaque(recv, (byte)2);
+            vh.setOpaque(recv, (byte)0x23);
             byte x = (byte) vh.getOpaque(recv);
-            assertEquals(x, (byte)2, "setOpaque byte value");
+            assertEquals(x, (byte)0x23, "setOpaque byte value");
         }
 
+        vh.set(recv, (byte)0x01);
 
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, (byte)0x01, (byte)0x23);
+            assertEquals(r, true, "success compareAndSet byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "success compareAndSet byte value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, (byte)0x01, (byte)0x45);
+            assertEquals(r, false, "failing compareAndSet byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "failing compareAndSet byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchange(recv, (byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchange byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "success compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchange(recv, (byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchange byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "failing compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)0x01, (byte)0x23);
+            assertEquals(r, (byte)0x01, "success compareAndExchangeAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "success compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)0x01, (byte)0x45);
+            assertEquals(r, (byte)0x23, "failing compareAndExchangeAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "failing compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchangeRelease byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "success compareAndExchangeRelease byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchangeRelease byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "failing compareAndExchangeRelease byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, (byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSet byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "weakCompareAndSet byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, (byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, (byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetVolatile(recv, (byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "weakCompareAndSetVolatile byte value");
+        }
+
+        // Compare set and get
+        {
+            byte o = (byte) vh.getAndSet(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSet byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "getAndSet byte value");
+        }
+
+        vh.set(recv, (byte)0x01);
+
+        // get and add, add and get
+        {
+            byte o = (byte) vh.getAndAdd(recv, (byte)0x45);
+            assertEquals(o, (byte)0x01, "getAndAdd byte");
+            byte c = (byte) vh.addAndGet(recv, (byte)0x45);
+            assertEquals(c, (byte)((byte)0x01 + (byte)0x45 + (byte)0x45), "getAndAdd byte value");
+        }
     }
 
     static void testInstanceFieldUnsupported(VarHandleTestAccessByte recv, VarHandle vh) {
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(recv, (byte)1, (byte)2);
-        });
 
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeVolatile(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(recv, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.getAndSet(recv, (byte)1);
-        });
-
-        checkUOE(() -> {
-            byte o = (byte) vh.getAndAdd(recv, (byte)1);
-        });
-
-        checkUOE(() -> {
-            byte o = (byte) vh.addAndGet(recv, (byte)1);
-        });
     }
 
 
     static void testStaticField(VarHandle vh) {
         // Plain
         {
-            vh.set((byte)1);
+            vh.set((byte)0x01);
             byte x = (byte) vh.get();
-            assertEquals(x, (byte)1, "set byte value");
+            assertEquals(x, (byte)0x01, "set byte value");
         }
 
 
         // Volatile
         {
-            vh.setVolatile((byte)2);
+            vh.setVolatile((byte)0x23);
             byte x = (byte) vh.getVolatile();
-            assertEquals(x, (byte)2, "setVolatile byte value");
+            assertEquals(x, (byte)0x23, "setVolatile byte value");
         }
 
         // Lazy
         {
-            vh.setRelease((byte)1);
+            vh.setRelease((byte)0x01);
             byte x = (byte) vh.getAcquire();
-            assertEquals(x, (byte)1, "setRelease byte value");
+            assertEquals(x, (byte)0x01, "setRelease byte value");
         }
 
         // Opaque
         {
-            vh.setOpaque((byte)2);
+            vh.setOpaque((byte)0x23);
             byte x = (byte) vh.getOpaque();
-            assertEquals(x, (byte)2, "setOpaque byte value");
+            assertEquals(x, (byte)0x23, "setOpaque byte value");
         }
 
+        vh.set((byte)0x01);
 
+        // Compare
+        {
+            boolean r = vh.compareAndSet((byte)0x01, (byte)0x23);
+            assertEquals(r, true, "success compareAndSet byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "success compareAndSet byte value");
+        }
+
+        {
+            boolean r = vh.compareAndSet((byte)0x01, (byte)0x45);
+            assertEquals(r, false, "failing compareAndSet byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "failing compareAndSet byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchange((byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchange byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "success compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchange((byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchange byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "failing compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeAcquire((byte)0x01, (byte)0x23);
+            assertEquals(r, (byte)0x01, "success compareAndExchangeAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "success compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeAcquire((byte)0x01, (byte)0x45);
+            assertEquals(r, (byte)0x23, "failing compareAndExchangeAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "failing compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeRelease((byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchangeRelease byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "success compareAndExchangeRelease byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeRelease((byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchangeRelease byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "failing compareAndExchangeRelease byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet((byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSet byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "weakCompareAndSet byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire((byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease((byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease((byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "weakCompareAndSetVolatile byte");
+        }
+
+        // Compare set and get
+        {
+            byte o = (byte) vh.getAndSet((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSet byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "getAndSet byte value");
+        }
+
+        vh.set((byte)0x01);
+
+        // get and add, add and get
+        {
+            byte o = (byte) vh.getAndAdd( (byte)0x45);
+            assertEquals(o, (byte)0x01, "getAndAdd byte");
+            byte c = (byte) vh.addAndGet((byte)0x45);
+            assertEquals(c, (byte)((byte)0x01 + (byte)0x45 + (byte)0x45), "getAndAdd byte value");
+        }
     }
 
     static void testStaticFieldUnsupported(VarHandle vh) {
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet((byte)1, (byte)2);
-        });
 
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeVolatile((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeAcquire((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeRelease((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.getAndSet((byte)1);
-        });
-
-        checkUOE(() -> {
-            byte o = (byte) vh.getAndAdd((byte)1);
-        });
-
-        checkUOE(() -> {
-            byte o = (byte) vh.addAndGet((byte)1);
-        });
     }
 
 
@@ -562,34 +624,149 @@
         for (int i = 0; i < array.length; i++) {
             // Plain
             {
-                vh.set(array, i, (byte)1);
+                vh.set(array, i, (byte)0x01);
                 byte x = (byte) vh.get(array, i);
-                assertEquals(x, (byte)1, "get byte value");
+                assertEquals(x, (byte)0x01, "get byte value");
             }
 
 
             // Volatile
             {
-                vh.setVolatile(array, i, (byte)2);
+                vh.setVolatile(array, i, (byte)0x23);
                 byte x = (byte) vh.getVolatile(array, i);
-                assertEquals(x, (byte)2, "setVolatile byte value");
+                assertEquals(x, (byte)0x23, "setVolatile byte value");
             }
 
             // Lazy
             {
-                vh.setRelease(array, i, (byte)1);
+                vh.setRelease(array, i, (byte)0x01);
                 byte x = (byte) vh.getAcquire(array, i);
-                assertEquals(x, (byte)1, "setRelease byte value");
+                assertEquals(x, (byte)0x01, "setRelease byte value");
             }
 
             // Opaque
             {
-                vh.setOpaque(array, i, (byte)2);
+                vh.setOpaque(array, i, (byte)0x23);
                 byte x = (byte) vh.getOpaque(array, i);
-                assertEquals(x, (byte)2, "setOpaque byte value");
+                assertEquals(x, (byte)0x23, "setOpaque byte value");
             }
 
+            vh.set(array, i, (byte)0x01);
 
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, (byte)0x01, (byte)0x23);
+                assertEquals(r, true, "success compareAndSet byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "success compareAndSet byte value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, (byte)0x01, (byte)0x45);
+                assertEquals(r, false, "failing compareAndSet byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "failing compareAndSet byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchange(array, i, (byte)0x23, (byte)0x01);
+                assertEquals(r, (byte)0x23, "success compareAndExchange byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "success compareAndExchange byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchange(array, i, (byte)0x23, (byte)0x45);
+                assertEquals(r, (byte)0x01, "failing compareAndExchange byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "failing compareAndExchange byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchangeAcquire(array, i, (byte)0x01, (byte)0x23);
+                assertEquals(r, (byte)0x01, "success compareAndExchangeAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "success compareAndExchangeAcquire byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchangeAcquire(array, i, (byte)0x01, (byte)0x45);
+                assertEquals(r, (byte)0x23, "failing compareAndExchangeAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "failing compareAndExchangeAcquire byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchangeRelease(array, i, (byte)0x23, (byte)0x01);
+                assertEquals(r, (byte)0x23, "success compareAndExchangeRelease byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "success compareAndExchangeRelease byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchangeRelease(array, i, (byte)0x23, (byte)0x45);
+                assertEquals(r, (byte)0x01, "failing compareAndExchangeRelease byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "failing compareAndExchangeRelease byte value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, (byte)0x01, (byte)0x23);
+                }
+                assertEquals(success, true, "weakCompareAndSet byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "weakCompareAndSet byte value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, (byte)0x23, (byte)0x01);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, (byte)0x01, (byte)0x23);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetVolatile(array, i, (byte)0x23, (byte)0x01);
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "weakCompareAndSetVolatile byte");
+            }
+
+            // Compare set and get
+            {
+                byte o = (byte) vh.getAndSet(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndSet byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "getAndSet byte value");
+            }
+
+            vh.set(array, i, (byte)0x01);
+
+            // get and add, add and get
+            {
+                byte o = (byte) vh.getAndAdd(array, i, (byte)0x45);
+                assertEquals(o, (byte)0x01, "getAndAdd byte");
+                byte c = (byte) vh.addAndGet(array, i, (byte)0x45);
+                assertEquals(c, (byte)((byte)0x01 + (byte)0x45 + (byte)0x45), "getAndAdd byte value");
+            }
         }
     }
 
@@ -597,49 +774,7 @@
         byte[] array = new byte[10];
 
         int i = 0;
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(array, i, (byte)1, (byte)2);
-        });
 
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeVolatile(array, i, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeAcquire(array, i, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.compareAndExchangeRelease(array, i, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(array, i, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(array, i, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(array, i, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(array, i, (byte)1, (byte)2);
-        });
-
-        checkUOE(() -> {
-            byte r = (byte) vh.getAndSet(array, i, (byte)1);
-        });
-
-        checkUOE(() -> {
-            byte o = (byte) vh.getAndAdd(array, i, (byte)1);
-        });
-
-        checkUOE(() -> {
-            byte o = (byte) vh.addAndGet(array, i, (byte)1);
-        });
     }
 
     static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
@@ -653,7 +788,7 @@
             });
 
             checkIOOBE(() -> {
-                vh.set(array, ci, (byte)1);
+                vh.set(array, ci, (byte)0x01);
             });
 
             checkIOOBE(() -> {
@@ -661,7 +796,7 @@
             });
 
             checkIOOBE(() -> {
-                vh.setVolatile(array, ci, (byte)1);
+                vh.setVolatile(array, ci, (byte)0x01);
             });
 
             checkIOOBE(() -> {
@@ -669,7 +804,7 @@
             });
 
             checkIOOBE(() -> {
-                vh.setRelease(array, ci, (byte)1);
+                vh.setRelease(array, ci, (byte)0x01);
             });
 
             checkIOOBE(() -> {
@@ -677,10 +812,52 @@
             });
 
             checkIOOBE(() -> {
-                vh.setOpaque(array, ci, (byte)1);
+                vh.setOpaque(array, ci, (byte)0x01);
             });
 
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, (byte)0x01, (byte)0x23);
+            });
 
+            checkIOOBE(() -> {
+                byte r = (byte) vh.compareAndExchange(array, ci, (byte)0x23, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte r = (byte) vh.compareAndExchangeAcquire(array, ci, (byte)0x23, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte r = (byte) vh.compareAndExchangeRelease(array, ci, (byte)0x23, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, (byte)0x01, (byte)0x23);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, (byte)0x01, (byte)0x23);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, (byte)0x01, (byte)0x23);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, (byte)0x01, (byte)0x23);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndSet(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndAdd(array, ci, (byte)0x45);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.addAndGet(array, ci, (byte)0x45);
+            });
         }
     }
 }
--- a/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java	Thu Jul 07 18:35:29 2016 +0000
@@ -42,11 +42,11 @@
 import static org.testng.Assert.*;
 
 public class VarHandleTestAccessChar extends VarHandleBaseTest {
-    static final char static_final_v = 'a';
+    static final char static_final_v = '\u0123';
 
     static char static_v;
 
-    final char final_v = 'a';
+    final char final_v = '\u0123';
 
     char v;
 
@@ -99,18 +99,18 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
 
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET));
     }
 
 
@@ -220,89 +220,47 @@
         // Plain
         {
             char x = (char) vh.get(recv);
-            assertEquals(x, 'a', "get char value");
+            assertEquals(x, '\u0123', "get char value");
         }
 
 
         // Volatile
         {
             char x = (char) vh.getVolatile(recv);
-            assertEquals(x, 'a', "getVolatile char value");
+            assertEquals(x, '\u0123', "getVolatile char value");
         }
 
         // Lazy
         {
             char x = (char) vh.getAcquire(recv);
-            assertEquals(x, 'a', "getRelease char value");
+            assertEquals(x, '\u0123', "getRelease char value");
         }
 
         // Opaque
         {
             char x = (char) vh.getOpaque(recv);
-            assertEquals(x, 'a', "getOpaque char value");
+            assertEquals(x, '\u0123', "getOpaque char value");
         }
     }
 
     static void testInstanceFinalFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) {
         checkUOE(() -> {
-            vh.set(recv, 'b');
+            vh.set(recv, '\u4567');
         });
 
         checkUOE(() -> {
-            vh.setVolatile(recv, 'b');
+            vh.setVolatile(recv, '\u4567');
         });
 
         checkUOE(() -> {
-            vh.setRelease(recv, 'b');
+            vh.setRelease(recv, '\u4567');
         });
 
         checkUOE(() -> {
-            vh.setOpaque(recv, 'b');
+            vh.setOpaque(recv, '\u4567');
         });
 
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(recv, 'a', 'b');
-        });
 
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeVolatile(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeAcquire(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeRelease(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.getAndSet(recv, 'a');
-        });
-
-        checkUOE(() -> {
-            char o = (char) vh.getAndAdd(recv, 'a');
-        });
-
-        checkUOE(() -> {
-            char o = (char) vh.addAndGet(recv, 'a');
-        });
     }
 
 
@@ -310,249 +268,353 @@
         // Plain
         {
             char x = (char) vh.get();
-            assertEquals(x, 'a', "get char value");
+            assertEquals(x, '\u0123', "get char value");
         }
 
 
         // Volatile
         {
             char x = (char) vh.getVolatile();
-            assertEquals(x, 'a', "getVolatile char value");
+            assertEquals(x, '\u0123', "getVolatile char value");
         }
 
         // Lazy
         {
             char x = (char) vh.getAcquire();
-            assertEquals(x, 'a', "getRelease char value");
+            assertEquals(x, '\u0123', "getRelease char value");
         }
 
         // Opaque
         {
             char x = (char) vh.getOpaque();
-            assertEquals(x, 'a', "getOpaque char value");
+            assertEquals(x, '\u0123', "getOpaque char value");
         }
     }
 
     static void testStaticFinalFieldUnsupported(VarHandle vh) {
         checkUOE(() -> {
-            vh.set('b');
+            vh.set('\u4567');
         });
 
         checkUOE(() -> {
-            vh.setVolatile('b');
+            vh.setVolatile('\u4567');
         });
 
         checkUOE(() -> {
-            vh.setRelease('b');
+            vh.setRelease('\u4567');
         });
 
         checkUOE(() -> {
-            vh.setOpaque('b');
+            vh.setOpaque('\u4567');
         });
 
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet('a', 'b');
-        });
 
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeVolatile('a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeAcquire('a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeRelease('a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet('a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile('a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire('a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease('a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.getAndSet('a');
-        });
-
-        checkUOE(() -> {
-            char o = (char) vh.getAndAdd('a');
-        });
-
-        checkUOE(() -> {
-            char o = (char) vh.addAndGet('a');
-        });
     }
 
 
     static void testInstanceField(VarHandleTestAccessChar recv, VarHandle vh) {
         // Plain
         {
-            vh.set(recv, 'a');
+            vh.set(recv, '\u0123');
             char x = (char) vh.get(recv);
-            assertEquals(x, 'a', "set char value");
+            assertEquals(x, '\u0123', "set char value");
         }
 
 
         // Volatile
         {
-            vh.setVolatile(recv, 'b');
+            vh.setVolatile(recv, '\u4567');
             char x = (char) vh.getVolatile(recv);
-            assertEquals(x, 'b', "setVolatile char value");
+            assertEquals(x, '\u4567', "setVolatile char value");
         }
 
         // Lazy
         {
-            vh.setRelease(recv, 'a');
+            vh.setRelease(recv, '\u0123');
             char x = (char) vh.getAcquire(recv);
-            assertEquals(x, 'a', "setRelease char value");
+            assertEquals(x, '\u0123', "setRelease char value");
         }
 
         // Opaque
         {
-            vh.setOpaque(recv, 'b');
+            vh.setOpaque(recv, '\u4567');
             char x = (char) vh.getOpaque(recv);
-            assertEquals(x, 'b', "setOpaque char value");
+            assertEquals(x, '\u4567', "setOpaque char value");
         }
 
+        vh.set(recv, '\u0123');
 
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, '\u0123', '\u4567');
+            assertEquals(r, true, "success compareAndSet char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "success compareAndSet char value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, '\u0123', '\u89AB');
+            assertEquals(r, false, "failing compareAndSet char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "failing compareAndSet char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchange(recv, '\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchange char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "success compareAndExchange char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchange(recv, '\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchange char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "failing compareAndExchange char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeAcquire(recv, '\u0123', '\u4567');
+            assertEquals(r, '\u0123', "success compareAndExchangeAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "success compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeAcquire(recv, '\u0123', '\u89AB');
+            assertEquals(r, '\u4567', "failing compareAndExchangeAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "failing compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeRelease(recv, '\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchangeRelease char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "success compareAndExchangeRelease char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeRelease(recv, '\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchangeRelease char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "failing compareAndExchangeRelease char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, '\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSet char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "weakCompareAndSet char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, '\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "weakCompareAndSetAcquire char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, '\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "weakCompareAndSetRelease char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetVolatile(recv, '\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "weakCompareAndSetVolatile char value");
+        }
+
+        // Compare set and get
+        {
+            char o = (char) vh.getAndSet(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndSet char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "getAndSet char value");
+        }
+
+        vh.set(recv, '\u0123');
+
+        // get and add, add and get
+        {
+            char o = (char) vh.getAndAdd(recv, '\u89AB');
+            assertEquals(o, '\u0123', "getAndAdd char");
+            char c = (char) vh.addAndGet(recv, '\u89AB');
+            assertEquals(c, (char)('\u0123' + '\u89AB' + '\u89AB'), "getAndAdd char value");
+        }
     }
 
     static void testInstanceFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) {
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(recv, 'a', 'b');
-        });
 
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeVolatile(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeAcquire(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeRelease(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.getAndSet(recv, 'a');
-        });
-
-        checkUOE(() -> {
-            char o = (char) vh.getAndAdd(recv, 'a');
-        });
-
-        checkUOE(() -> {
-            char o = (char) vh.addAndGet(recv, 'a');
-        });
     }
 
 
     static void testStaticField(VarHandle vh) {
         // Plain
         {
-            vh.set('a');
+            vh.set('\u0123');
             char x = (char) vh.get();
-            assertEquals(x, 'a', "set char value");
+            assertEquals(x, '\u0123', "set char value");
         }
 
 
         // Volatile
         {
-            vh.setVolatile('b');
+            vh.setVolatile('\u4567');
             char x = (char) vh.getVolatile();
-            assertEquals(x, 'b', "setVolatile char value");
+            assertEquals(x, '\u4567', "setVolatile char value");
         }
 
         // Lazy
         {
-            vh.setRelease('a');
+            vh.setRelease('\u0123');
             char x = (char) vh.getAcquire();
-            assertEquals(x, 'a', "setRelease char value");
+            assertEquals(x, '\u0123', "setRelease char value");
         }
 
         // Opaque
         {
-            vh.setOpaque('b');
+            vh.setOpaque('\u4567');
             char x = (char) vh.getOpaque();
-            assertEquals(x, 'b', "setOpaque char value");
+            assertEquals(x, '\u4567', "setOpaque char value");
         }
 
+        vh.set('\u0123');
 
+        // Compare
+        {
+            boolean r = vh.compareAndSet('\u0123', '\u4567');
+            assertEquals(r, true, "success compareAndSet char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "success compareAndSet char value");
+        }
+
+        {
+            boolean r = vh.compareAndSet('\u0123', '\u89AB');
+            assertEquals(r, false, "failing compareAndSet char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "failing compareAndSet char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchange('\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchange char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "success compareAndExchange char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchange('\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchange char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "failing compareAndExchange char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeAcquire('\u0123', '\u4567');
+            assertEquals(r, '\u0123', "success compareAndExchangeAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "success compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeAcquire('\u0123', '\u89AB');
+            assertEquals(r, '\u4567', "failing compareAndExchangeAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "failing compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeRelease('\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchangeRelease char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "success compareAndExchangeRelease char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeRelease('\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchangeRelease char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "failing compareAndExchangeRelease char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet('\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSet char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "weakCompareAndSet char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire('\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "weakCompareAndSetAcquire char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease('\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "weakCompareAndSetRelease char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease('\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "weakCompareAndSetVolatile char");
+        }
+
+        // Compare set and get
+        {
+            char o = (char) vh.getAndSet('\u4567');
+            assertEquals(o, '\u0123', "getAndSet char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "getAndSet char value");
+        }
+
+        vh.set('\u0123');
+
+        // get and add, add and get
+        {
+            char o = (char) vh.getAndAdd( '\u89AB');
+            assertEquals(o, '\u0123', "getAndAdd char");
+            char c = (char) vh.addAndGet('\u89AB');
+            assertEquals(c, (char)('\u0123' + '\u89AB' + '\u89AB'), "getAndAdd char value");
+        }
     }
 
     static void testStaticFieldUnsupported(VarHandle vh) {
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet('a', 'b');
-        });
 
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeVolatile('a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeAcquire('a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeRelease('a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet('a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile('a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire('a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease('a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.getAndSet('a');
-        });
-
-        checkUOE(() -> {
-            char o = (char) vh.getAndAdd('a');
-        });
-
-        checkUOE(() -> {
-            char o = (char) vh.addAndGet('a');
-        });
     }
 
 
@@ -562,34 +624,149 @@
         for (int i = 0; i < array.length; i++) {
             // Plain
             {
-                vh.set(array, i, 'a');
+                vh.set(array, i, '\u0123');
                 char x = (char) vh.get(array, i);
-                assertEquals(x, 'a', "get char value");
+                assertEquals(x, '\u0123', "get char value");
             }
 
 
             // Volatile
             {
-                vh.setVolatile(array, i, 'b');
+                vh.setVolatile(array, i, '\u4567');
                 char x = (char) vh.getVolatile(array, i);
-                assertEquals(x, 'b', "setVolatile char value");
+                assertEquals(x, '\u4567', "setVolatile char value");
             }
 
             // Lazy
             {
-                vh.setRelease(array, i, 'a');
+                vh.setRelease(array, i, '\u0123');
                 char x = (char) vh.getAcquire(array, i);
-                assertEquals(x, 'a', "setRelease char value");
+                assertEquals(x, '\u0123', "setRelease char value");
             }
 
             // Opaque
             {
-                vh.setOpaque(array, i, 'b');
+                vh.setOpaque(array, i, '\u4567');
                 char x = (char) vh.getOpaque(array, i);
-                assertEquals(x, 'b', "setOpaque char value");
+                assertEquals(x, '\u4567', "setOpaque char value");
             }
 
+            vh.set(array, i, '\u0123');
 
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, '\u0123', '\u4567');
+                assertEquals(r, true, "success compareAndSet char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "success compareAndSet char value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, '\u0123', '\u89AB');
+                assertEquals(r, false, "failing compareAndSet char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "failing compareAndSet char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchange(array, i, '\u4567', '\u0123');
+                assertEquals(r, '\u4567', "success compareAndExchange char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "success compareAndExchange char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchange(array, i, '\u4567', '\u89AB');
+                assertEquals(r, '\u0123', "failing compareAndExchange char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "failing compareAndExchange char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchangeAcquire(array, i, '\u0123', '\u4567');
+                assertEquals(r, '\u0123', "success compareAndExchangeAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "success compareAndExchangeAcquire char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchangeAcquire(array, i, '\u0123', '\u89AB');
+                assertEquals(r, '\u4567', "failing compareAndExchangeAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "failing compareAndExchangeAcquire char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchangeRelease(array, i, '\u4567', '\u0123');
+                assertEquals(r, '\u4567', "success compareAndExchangeRelease char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "success compareAndExchangeRelease char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchangeRelease(array, i, '\u4567', '\u89AB');
+                assertEquals(r, '\u0123', "failing compareAndExchangeRelease char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "failing compareAndExchangeRelease char value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, '\u0123', '\u4567');
+                }
+                assertEquals(success, true, "weakCompareAndSet char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "weakCompareAndSet char value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, '\u4567', '\u0123');
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "weakCompareAndSetAcquire char");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, '\u0123', '\u4567');
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "weakCompareAndSetRelease char");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetVolatile(array, i, '\u4567', '\u0123');
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "weakCompareAndSetVolatile char");
+            }
+
+            // Compare set and get
+            {
+                char o = (char) vh.getAndSet(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndSet char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "getAndSet char value");
+            }
+
+            vh.set(array, i, '\u0123');
+
+            // get and add, add and get
+            {
+                char o = (char) vh.getAndAdd(array, i, '\u89AB');
+                assertEquals(o, '\u0123', "getAndAdd char");
+                char c = (char) vh.addAndGet(array, i, '\u89AB');
+                assertEquals(c, (char)('\u0123' + '\u89AB' + '\u89AB'), "getAndAdd char value");
+            }
         }
     }
 
@@ -597,49 +774,7 @@
         char[] array = new char[10];
 
         int i = 0;
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(array, i, 'a', 'b');
-        });
 
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeVolatile(array, i, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeAcquire(array, i, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.compareAndExchangeRelease(array, i, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(array, i, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(array, i, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(array, i, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(array, i, 'a', 'b');
-        });
-
-        checkUOE(() -> {
-            char r = (char) vh.getAndSet(array, i, 'a');
-        });
-
-        checkUOE(() -> {
-            char o = (char) vh.getAndAdd(array, i, 'a');
-        });
-
-        checkUOE(() -> {
-            char o = (char) vh.addAndGet(array, i, 'a');
-        });
     }
 
     static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
@@ -653,7 +788,7 @@
             });
 
             checkIOOBE(() -> {
-                vh.set(array, ci, 'a');
+                vh.set(array, ci, '\u0123');
             });
 
             checkIOOBE(() -> {
@@ -661,7 +796,7 @@
             });
 
             checkIOOBE(() -> {
-                vh.setVolatile(array, ci, 'a');
+                vh.setVolatile(array, ci, '\u0123');
             });
 
             checkIOOBE(() -> {
@@ -669,7 +804,7 @@
             });
 
             checkIOOBE(() -> {
-                vh.setRelease(array, ci, 'a');
+                vh.setRelease(array, ci, '\u0123');
             });
 
             checkIOOBE(() -> {
@@ -677,10 +812,52 @@
             });
 
             checkIOOBE(() -> {
-                vh.setOpaque(array, ci, 'a');
+                vh.setOpaque(array, ci, '\u0123');
             });
 
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, '\u0123', '\u4567');
+            });
 
+            checkIOOBE(() -> {
+                char r = (char) vh.compareAndExchange(array, ci, '\u4567', '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char r = (char) vh.compareAndExchangeAcquire(array, ci, '\u4567', '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char r = (char) vh.compareAndExchangeRelease(array, ci, '\u4567', '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, '\u0123', '\u4567');
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, '\u0123', '\u4567');
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, '\u0123', '\u4567');
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, '\u0123', '\u4567');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndSet(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndAdd(array, ci, '\u89AB');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.addAndGet(array, ci, '\u89AB');
+            });
         }
     }
 }
--- a/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java	Thu Jul 07 18:21:23 2016 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java	Thu Jul 07 18:35:29 2016 +0000
@@ -99,18 +99,18 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
 
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET));
     }
 
 
@@ -260,49 +260,7 @@
             vh.setOpaque(recv, 2.0d);
         });
 
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(recv, 1.0d, 2.0d);
-        });
 
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeVolatile(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeRelease(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.getAndSet(recv, 1.0d);
-        });
-
-        checkUOE(() -> {
-            double o = (double) vh.getAndAdd(recv, 1.0d);
-        });
-
-        checkUOE(() -> {
-            double o = (double) vh.addAndGet(recv, 1.0d);
-        });
     }
 
 
@@ -350,49 +308,7 @@
             vh.setOpaque(2.0d);
         });
 
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(1.0d, 2.0d);
-        });
 
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeVolatile(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeAcquire(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeRelease(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.getAndSet(1.0d);
-        });
-
-        checkUOE(() -> {
-            double o = (double) vh.getAndAdd(1.0d);
-        });
-
-        checkUOE(() -> {
-            double o = (double) vh.addAndGet(1.0d);
-        });
     }
 
 
@@ -426,53 +342,126 @@
             assertEquals(x, 2.0d, "setOpaque double value");
         }
 
+        vh.set(recv, 1.0d);
 
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, 1.0d, 2.0d);
+            assertEquals(r, true, "success compareAndSet double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "success compareAndSet double value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, 1.0d, 3.0d);
+            assertEquals(r, false, "failing compareAndSet double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "failing compareAndSet double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchange(recv, 2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchange double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "success compareAndExchange double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchange(recv, 2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchange double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "failing compareAndExchange double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 2.0d);
+            assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "success compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 3.0d);
+            assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "failing compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeRelease(recv, 2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "success compareAndExchangeRelease double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeRelease(recv, 2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "failing compareAndExchangeRelease double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, 1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSet double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "weakCompareAndSet double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, 2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "weakCompareAndSetAcquire double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "weakCompareAndSetRelease double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetVolatile(recv, 2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "weakCompareAndSetVolatile double value");
+        }
+
+        // Compare set and get
+        {
+            double o = (double) vh.getAndSet(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndSet double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "getAndSet double value");
+        }
+
+        vh.set(recv, 1.0d);
+
+        // get and add, add and get
+        {
+            double o = (double) vh.getAndAdd(recv, 3.0d);
+            assertEquals(o, 1.0d, "getAndAdd double");
+            double c = (double) vh.addAndGet(recv, 3.0d);
+            assertEquals(c, (double)(1.0d + 3.0d + 3.0d), "getAndAdd double value");
+        }
     }
 
     static void testInstanceFieldUnsupported(VarHandleTestAccessDouble recv, VarHandle vh) {
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(recv, 1.0d, 2.0d);
-        });
 
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeVolatile(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeRelease(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.getAndSet(recv, 1.0d);
-        });
-
-        checkUOE(() -> {
-            double o = (double) vh.getAndAdd(recv, 1.0d);
-        });
-
-        checkUOE(() -> {
-            double o = (double) vh.addAndGet(recv, 1.0d);
-        });
     }
 
 
@@ -506,53 +495,126 @@
             assertEquals(x, 2.0d, "setOpaque double value");
         }
 
+        vh.set(1.0d);
 
+        // Compare
+        {
+            boolean r = vh.compareAndSet(1.0d, 2.0d);
+            assertEquals(r, true, "success compareAndSet double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "success compareAndSet double value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(1.0d, 3.0d);
+            assertEquals(r, false, "failing compareAndSet double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "failing compareAndSet double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchange(2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchange double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "success compareAndExchange double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchange(2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchange double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "failing compareAndExchange double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeAcquire(1.0d, 2.0d);
+            assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "success compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeAcquire(1.0d, 3.0d);
+            assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "failing compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeRelease(2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "success compareAndExchangeRelease double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeRelease(2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "failing compareAndExchangeRelease double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSet double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "weakCompareAndSet double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "weakCompareAndSetAcquire double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "weakCompareAndSetRelease double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "weakCompareAndSetVolatile double");
+        }
+
+        // Compare set and get
+        {
+            double o = (double) vh.getAndSet(2.0d);
+            assertEquals(o, 1.0d, "getAndSet double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "getAndSet double value");
+        }
+
+        vh.set(1.0d);
+
+        // get and add, add and get
+        {
+            double o = (double) vh.getAndAdd( 3.0d);
+            assertEquals(o, 1.0d, "getAndAdd double");
+            double c = (double) vh.addAndGet(3.0d);
+            assertEquals(c, (double)(1.0d + 3.0d + 3.0d), "getAndAdd double value");
+        }
     }
 
     static void testStaticFieldUnsupported(VarHandle vh) {
-        checkUOE(() -> {
-            boolean r = vh.compareAndSet(1.0d, 2.0d);
-        });
 
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeVolatile(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeAcquire(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.compareAndExchangeRelease(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSet(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetVolatile(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            boolean r = vh.weakCompareAndSetRelease(1.0d, 2.0d);
-        });
-
-        checkUOE(() -> {
-            double r = (double) vh.getAndSet(1.0d);
-        });
-
-        checkUOE(() -> {
-            double o = (double) vh.getAndAdd(1.0d);
-        });
-
-        checkUOE(() -> {
-            double o = (double) vh.addAndGet(1.0d);
-        });
     }
 
 
@@ -589,7 +651,122 @@
                 assertEquals(x, 2.0d, "setOpaque double value");
             }
 
+            vh.set(array, i, 1.0d);
 
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, 1.0d, 2.0d);
+                assertEquals(r, true, "success compareAndSet double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "success compareAndSet double value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, 1.0d, 3.0d);
+                assertEquals(r, false, "failing compareAndSet double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "failing compareAndSet double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchange(array, i, 2.0d, 1.0d);
+                assertEquals(r, 2.0d, "success compareAndExchange double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "success compareAndExchange double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchange(array, i, 2.0d, 3.0d);
+                assertEquals(r, 1.0d, "failing compareAndExchange double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "failing compareAndExchange double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchangeAcquire(array, i, 1.0d, 2.0d);
+                assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "success compareAndExchangeAcquire double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchangeAcquire(array, i, 1.0d, 3.0d);
+                assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "failing compareAndExchangeAcquire double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchangeRelease(array, i, 2.0d, 1.0d);
+                assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "success compareAndExchangeRelease double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchangeRelease(array, i, 2.0d, 3.0d);
+                assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "failing compareAndExchangeRelease double value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, 1.0d, 2.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSet double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "weakCompareAndSet double value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, 2.0d, 1.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "weakCompareAndSetAcquire double");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, 1.0d, 2.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "weakCompareAndSetRelease double");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetVolatile(array, i, 2.0d, 1.0d);
+                }
+                assertEquals(su