diff --git a/.hgignore b/.hgignore
index aec0e31d131..9aab81ce35d 100644
--- a/.hgignore
+++ b/.hgignore
@@ -1,5 +1,6 @@
 ^build/
 ^dist/
+^.idea/
 nbproject/private/
 ^webrev
 ^.hgtip
diff --git a/.hgtags b/.hgtags
index 7f711e51df0..5618d206183 100644
--- a/.hgtags
+++ b/.hgtags
@@ -360,3 +360,4 @@ c84d0cce090e161d736de69e941830adf8c2f87a jdk-9+114
 8d78fb40648dd221ce4ef19f9d5aa41ee1a3a884 jdk-9+115
 84aba7335005a3a47751dcf1f37935f97df9f99a jdk-9+116
 82b8d12a553f5617737c238cec060281d52e351c jdk-9+117
+7c04fcb12bd4a31570a238e663fa846dfa5ec3b8 jdk-9+118
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index bd47c1a0596..08fd371176c 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -360,3 +360,4 @@ f900d5afd9c83a0df8f36161c27c5e4c86a66f4c jdk-9+111
 09617ce980b99d49abfd54dacfed353c47e2a115 jdk-9+115
 6743a8e0cab7b5f6f4a0575f6664892f0ab740af jdk-9+116
 e882bcdbdac436523f3d5681611d3118a3804ea7 jdk-9+117
+047f95de8f918d8ff5e8cd2636a2abb5c3c8adb8 jdk-9+118
diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4
index 7789f01450e..bdcec6208f3 100644
--- a/common/autoconf/flags.m4
+++ b/common/autoconf/flags.m4
@@ -768,7 +768,7 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER],
         $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing"
         ;;
     esac
-    TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: 6, IF_AT_LEAST: FLAGS_SETUP_GCC6_COMPILER_FLAGS)
+    TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: 6, PREFIX: $2, IF_AT_LEAST: FLAGS_SETUP_GCC6_COMPILER_FLAGS)
   elif test "x$TOOLCHAIN_TYPE" = xclang; then
     $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_GNU_SOURCE"
 
@@ -964,7 +964,7 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER],
         -Wunused-value -Woverloaded-virtual"
 
     if test "x$TOOLCHAIN_TYPE" = xgcc; then
-      TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: [4.8],
+      TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: [4.8], PREFIX: $2,
           IF_AT_LEAST: [
             # These flags either do not work or give spurious warnings prior to gcc 4.8.
             $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-format-zero-length -Wtype-limits -Wuninitialized"
@@ -1411,9 +1411,15 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_MISC],
         DISABLE_WARNING_PREFIX=
       fi
       CFLAGS_WARNINGS_ARE_ERRORS="-Werror"
-      # Repeate the check for the BUILD_CC
+      # Repeate the check for the BUILD_CC and BUILD_CXX. Need to also reset
+      # CFLAGS since any target specific flags will likely not work with the
+      # build compiler
       CC_OLD="$CC"
+      CXX_OLD="$CXX"
       CC="$BUILD_CC"
+      CXX="$BUILD_CXX"
+      CFLAGS_OLD="$CFLAGS"
+      CFLAGS=""
       FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [-Wno-this-is-a-warning-that-do-not-exist],
           IF_TRUE: [BUILD_CC_CAN_DISABLE_WARNINGS=true],
           IF_FALSE: [BUILD_CC_CAN_DISABLE_WARNINGS=false]
@@ -1424,6 +1430,8 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_MISC],
         BUILD_CC_DISABLE_WARNING_PREFIX=
       fi
       CC="$CC_OLD"
+      CXX="$CXX_OLD"
+      CFLAGS="$CFLAGS_OLD"
       ;;
     clang)
       DISABLE_WARNING_PREFIX="-Wno-"
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index 548ab680d2a..f40198f8da3 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -4900,6 +4900,8 @@ TOOLCHAIN_MINIMUM_VERSION_xlc=""
 
 # Prepare the system so that TOOLCHAIN_CHECK_COMPILER_VERSION can be called.
 # Must have CC_VERSION_NUMBER and CXX_VERSION_NUMBER.
+# $1 - optional variable prefix for compiler and version variables (BUILD_)
+# $2 - optional variable prefix for comparable variable (OPENJDK_BUILD_)
 
 
 # Check if the configured compiler (C and C++) is of a specific version or
@@ -4909,6 +4911,7 @@ TOOLCHAIN_MINIMUM_VERSION_xlc=""
 #   VERSION:   The version string to check against the found version
 #   IF_AT_LEAST:   block to run if the compiler is at least this version (>=)
 #   IF_OLDER_THAN:   block to run if the compiler is older than this version (<)
+#   PREFIX:   Optional variable prefix for compiler to compare version for (OPENJDK_BUILD_)
 
 
 
@@ -5073,7 +5076,7 @@ VS_SDK_PLATFORM_NAME_2013=
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1462806878
+DATE_WHEN_GENERATED=1462970869
 
 ###############################################################################
 #
@@ -34795,19 +34798,19 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
 
 
   if test "x$CC_VERSION_NUMBER" != "x$CXX_VERSION_NUMBER"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C and C++ compiler has different version numbers, $CC_VERSION_NUMBER vs $CXX_VERSION_NUMBER." >&5
-$as_echo "$as_me: WARNING: C and C++ compiler has different version numbers, $CC_VERSION_NUMBER vs $CXX_VERSION_NUMBER." >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C and C++ compiler have different version numbers, $CC_VERSION_NUMBER vs $CXX_VERSION_NUMBER." >&5
+$as_echo "$as_me: WARNING: C and C++ compiler have different version numbers, $CC_VERSION_NUMBER vs $CXX_VERSION_NUMBER." >&2;}
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: This typically indicates a broken setup, and is not supported" >&5
 $as_echo "$as_me: WARNING: This typically indicates a broken setup, and is not supported" >&2;}
   fi
 
   # We only check CC_VERSION_NUMBER since we assume CXX_VERSION_NUMBER is equal.
-  if  [[ "$CC_VERSION_NUMBER" =~ (.*\.){3} ]] ; then
+  if  [[ "[$]CC_VERSION_NUMBER" =~ (.*\.){3} ]] ; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C compiler version number has more than three parts (X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong." >&5
 $as_echo "$as_me: WARNING: C compiler version number has more than three parts (X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
   fi
 
-  if  [[  "$CC_VERSION_NUMBER" =~ [0-9]{6} ]] ; then
+  if  [[  "[$]CC_VERSION_NUMBER" =~ [0-9]{6} ]] ; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C compiler version number has a part larger than 99999: $CC_VERSION_NUMBER. Comparisons might be wrong." >&5
 $as_echo "$as_me: WARNING: C compiler version number has a part larger than 99999: $CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
   fi
@@ -34850,6 +34853,13 @@ $as_echo "$as_me: WARNING: C compiler version number has a part larger than 9999
 
 
 
+
+
+
+
+
+
+
 
 
 
@@ -34897,6 +34907,8 @@ $as_echo "$as_me: WARNING: You are using $TOOLCHAIN_TYPE older than $TOOLCHAIN_M
 
 
 
+
+
   fi
 
   #
@@ -46475,6 +46487,268 @@ $as_echo "$as_me: Rewriting BUILD_STRIP to \"$new_complete\"" >&6;}
     BUILD_LDCXX="$BUILD_CXX"
 
     PATH="$OLDPATH"
+
+
+  COMPILER=$BUILD_CC
+  COMPILER_NAME=BuildC
+
+  if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
+    # cc -V output typically looks like
+    #     cc: Sun C 5.12 Linux_i386 2011/11/16
+    COMPILER_VERSION_OUTPUT=`$COMPILER -V 2>&1`
+    # Check that this is likely to be the Solaris Studio cc.
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null
+    if test $? -ne 0; then
+      ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1`
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
+$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with -V was: \"$COMPILER_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running with -V was: \"$COMPILER_VERSION_OUTPUT\"" >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&6;}
+      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
+    fi
+    # Remove usage instructions (if present), and
+    # collapse compiler output into a single line
+    COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/ *[Uu]sage:.*//'`
+    COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e "s/^.*[ ,\t]$COMPILER_NAME[ ,\t]\([1-9]\.[0-9][0-9]*\).*/\1/"`
+  elif test  "x$TOOLCHAIN_TYPE" = xxlc; then
+    # xlc -qversion output typically looks like
+    #     IBM XL C/C++ for AIX, V11.1 (5724-X13)
+    #     Version: 11.01.0000.0015
+    COMPILER_VERSION_OUTPUT=`$COMPILER -qversion 2>&1`
+    # Check that this is likely to be the IBM XL C compiler.
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "IBM XL C" > /dev/null
+    if test $? -ne 0; then
+      ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1`
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
+$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with -qversion was: \"$COMPILER_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running with -qversion was: \"$COMPILER_VERSION_OUTPUT\"" >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&6;}
+      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
+    fi
+    # Collapse compiler output into a single line
+    COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT`
+    COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/^.*, V\([1-9][0-9.]*\).*$/\1/'`
+  elif test  "x$TOOLCHAIN_TYPE" = xmicrosoft; then
+    # There is no specific version flag, but all output starts with a version string.
+    # First line typically looks something like:
+    # Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
+    COMPILER_VERSION_OUTPUT=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'`
+    # Check that this is likely to be Microsoft CL.EXE.
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "Microsoft.*Compiler" > /dev/null
+    if test $? -ne 0; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
+$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running it was: \"$COMPILER_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running it was: \"$COMPILER_VERSION_OUTPUT\"" >&6;}
+      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
+    fi
+    # Collapse compiler output into a single line
+    COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT`
+    COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/^.*ersion.\([1-9][0-9.]*\) .*$/\1/'`
+  elif test  "x$TOOLCHAIN_TYPE" = xgcc; then
+    # gcc --version output typically looks like
+    #     gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+    #     Copyright (C) 2013 Free Software Foundation, Inc.
+    #     This is free software; see the source for copying conditions.  There is NO
+    #     warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    COMPILER_VERSION_OUTPUT=`$COMPILER --version 2>&1`
+    # Check that this is likely to be GCC.
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "Free Software Foundation" > /dev/null
+    if test $? -ne 0; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
+$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$COMPILER_VERSION\"" >&5
+$as_echo "$as_me: The result from running with --version was: \"$COMPILER_VERSION\"" >&6;}
+      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
+    fi
+    # Remove Copyright and legalese from version string, and
+    # collapse into a single line
+    COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/ *Copyright .*//'`
+    COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/^.* \([1-9]\.[0-9.]*\)[^0-9.].*$/\1/'`
+  elif test  "x$TOOLCHAIN_TYPE" = xclang; then
+    # clang --version output typically looks like
+    #    Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
+    #    clang version 3.3 (tags/RELEASE_33/final)
+    # or
+    #    Debian clang version 3.2-7ubuntu1 (tags/RELEASE_32/final) (based on LLVM 3.2)
+    #    Target: x86_64-pc-linux-gnu
+    #    Thread model: posix
+    COMPILER_VERSION_OUTPUT=`$COMPILER --version 2>&1`
+    # Check that this is likely to be clang
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "clang" > /dev/null
+    if test $? -ne 0; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
+$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$COMPILER_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running with --version was: \"$COMPILER_VERSION_OUTPUT\"" >&6;}
+      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
+    fi
+    # Collapse compiler output into a single line
+    COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT`
+    COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/^.* version \([1-9][0-9.]*\).*$/\1/'`
+  else
+      as_fn_error $? "Unknown toolchain type $TOOLCHAIN_TYPE." "$LINENO" 5
+  fi
+  # This sets CC_VERSION_NUMBER or CXX_VERSION_NUMBER. (This comment is a grep marker)
+  BUILD_CC_VERSION_NUMBER="$COMPILER_VERSION_NUMBER"
+  # This sets CC_VERSION_STRING or CXX_VERSION_STRING. (This comment is a grep marker)
+  BUILD_CC_VERSION_STRING="$COMPILER_VERSION_STRING"
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Using $TOOLCHAIN_TYPE $COMPILER_NAME compiler version $COMPILER_VERSION_NUMBER [$COMPILER_VERSION_STRING]" >&5
+$as_echo "$as_me: Using $TOOLCHAIN_TYPE $COMPILER_NAME compiler version $COMPILER_VERSION_NUMBER [$COMPILER_VERSION_STRING]" >&6;}
+
+
+  COMPILER=$BUILD_CXX
+  COMPILER_NAME=BuildC++
+
+  if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
+    # cc -V output typically looks like
+    #     cc: Sun C 5.12 Linux_i386 2011/11/16
+    COMPILER_VERSION_OUTPUT=`$COMPILER -V 2>&1`
+    # Check that this is likely to be the Solaris Studio cc.
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null
+    if test $? -ne 0; then
+      ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1`
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
+$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with -V was: \"$COMPILER_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running with -V was: \"$COMPILER_VERSION_OUTPUT\"" >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&6;}
+      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
+    fi
+    # Remove usage instructions (if present), and
+    # collapse compiler output into a single line
+    COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/ *[Uu]sage:.*//'`
+    COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e "s/^.*[ ,\t]$COMPILER_NAME[ ,\t]\([1-9]\.[0-9][0-9]*\).*/\1/"`
+  elif test  "x$TOOLCHAIN_TYPE" = xxlc; then
+    # xlc -qversion output typically looks like
+    #     IBM XL C/C++ for AIX, V11.1 (5724-X13)
+    #     Version: 11.01.0000.0015
+    COMPILER_VERSION_OUTPUT=`$COMPILER -qversion 2>&1`
+    # Check that this is likely to be the IBM XL C compiler.
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "IBM XL C" > /dev/null
+    if test $? -ne 0; then
+      ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1`
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
+$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with -qversion was: \"$COMPILER_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running with -qversion was: \"$COMPILER_VERSION_OUTPUT\"" >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&6;}
+      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
+    fi
+    # Collapse compiler output into a single line
+    COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT`
+    COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/^.*, V\([1-9][0-9.]*\).*$/\1/'`
+  elif test  "x$TOOLCHAIN_TYPE" = xmicrosoft; then
+    # There is no specific version flag, but all output starts with a version string.
+    # First line typically looks something like:
+    # Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
+    COMPILER_VERSION_OUTPUT=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'`
+    # Check that this is likely to be Microsoft CL.EXE.
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "Microsoft.*Compiler" > /dev/null
+    if test $? -ne 0; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
+$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running it was: \"$COMPILER_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running it was: \"$COMPILER_VERSION_OUTPUT\"" >&6;}
+      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
+    fi
+    # Collapse compiler output into a single line
+    COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT`
+    COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/^.*ersion.\([1-9][0-9.]*\) .*$/\1/'`
+  elif test  "x$TOOLCHAIN_TYPE" = xgcc; then
+    # gcc --version output typically looks like
+    #     gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+    #     Copyright (C) 2013 Free Software Foundation, Inc.
+    #     This is free software; see the source for copying conditions.  There is NO
+    #     warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    COMPILER_VERSION_OUTPUT=`$COMPILER --version 2>&1`
+    # Check that this is likely to be GCC.
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "Free Software Foundation" > /dev/null
+    if test $? -ne 0; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
+$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$COMPILER_VERSION\"" >&5
+$as_echo "$as_me: The result from running with --version was: \"$COMPILER_VERSION\"" >&6;}
+      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
+    fi
+    # Remove Copyright and legalese from version string, and
+    # collapse into a single line
+    COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/ *Copyright .*//'`
+    COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/^.* \([1-9]\.[0-9.]*\)[^0-9.].*$/\1/'`
+  elif test  "x$TOOLCHAIN_TYPE" = xclang; then
+    # clang --version output typically looks like
+    #    Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
+    #    clang version 3.3 (tags/RELEASE_33/final)
+    # or
+    #    Debian clang version 3.2-7ubuntu1 (tags/RELEASE_32/final) (based on LLVM 3.2)
+    #    Target: x86_64-pc-linux-gnu
+    #    Thread model: posix
+    COMPILER_VERSION_OUTPUT=`$COMPILER --version 2>&1`
+    # Check that this is likely to be clang
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "clang" > /dev/null
+    if test $? -ne 0; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
+$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$COMPILER_VERSION_OUTPUT\"" >&5
+$as_echo "$as_me: The result from running with --version was: \"$COMPILER_VERSION_OUTPUT\"" >&6;}
+      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
+    fi
+    # Collapse compiler output into a single line
+    COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT`
+    COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \
+        $SED -e 's/^.* version \([1-9][0-9.]*\).*$/\1/'`
+  else
+      as_fn_error $? "Unknown toolchain type $TOOLCHAIN_TYPE." "$LINENO" 5
+  fi
+  # This sets CC_VERSION_NUMBER or CXX_VERSION_NUMBER. (This comment is a grep marker)
+  BUILD_CXX_VERSION_NUMBER="$COMPILER_VERSION_NUMBER"
+  # This sets CC_VERSION_STRING or CXX_VERSION_STRING. (This comment is a grep marker)
+  BUILD_CXX_VERSION_STRING="$COMPILER_VERSION_STRING"
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Using $TOOLCHAIN_TYPE $COMPILER_NAME compiler version $COMPILER_VERSION_NUMBER [$COMPILER_VERSION_STRING]" >&5
+$as_echo "$as_me: Using $TOOLCHAIN_TYPE $COMPILER_NAME compiler version $COMPILER_VERSION_NUMBER [$COMPILER_VERSION_STRING]" >&6;}
+
+
+  if test "x$BUILD_CC_VERSION_NUMBER" != "x$BUILD_CXX_VERSION_NUMBER"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C and C++ compiler have different version numbers, $BUILD_CC_VERSION_NUMBER vs $BUILD_CXX_VERSION_NUMBER." >&5
+$as_echo "$as_me: WARNING: C and C++ compiler have different version numbers, $BUILD_CC_VERSION_NUMBER vs $BUILD_CXX_VERSION_NUMBER." >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: This typically indicates a broken setup, and is not supported" >&5
+$as_echo "$as_me: WARNING: This typically indicates a broken setup, and is not supported" >&2;}
+  fi
+
+  # We only check CC_VERSION_NUMBER since we assume CXX_VERSION_NUMBER is equal.
+  if  [[ "[$]BUILD_CC_VERSION_NUMBER" =~ (.*\.){3} ]] ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C compiler version number has more than three parts (X.Y.Z): $BUILD_CC_VERSION_NUMBER. Comparisons might be wrong." >&5
+$as_echo "$as_me: WARNING: C compiler version number has more than three parts (X.Y.Z): $BUILD_CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
+  fi
+
+  if  [[  "[$]BUILD_CC_VERSION_NUMBER" =~ [0-9]{6} ]] ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C compiler version number has a part larger than 99999: $BUILD_CC_VERSION_NUMBER. Comparisons might be wrong." >&5
+$as_echo "$as_me: WARNING: C compiler version number has a part larger than 99999: $BUILD_CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
+  fi
+
+  OPENJDK_BUILD_COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$BUILD_CC_VERSION_NUMBER"`
+
   else
     # If we are not cross compiling, use the normal target compilers for
     # building the build platform executables.
@@ -49122,6 +49396,18 @@ $as_echo "$supports" >&6; }
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -49711,6 +49997,8 @@ $as_echo "$supports" >&6; }
 
 
 
+
+
   elif test "x$TOOLCHAIN_TYPE" = xclang; then
     JVM_CFLAGS="$JVM_CFLAGS -D_GNU_SOURCE"
 
@@ -49935,6 +50223,18 @@ $as_echo "$supports" >&6; }
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -49987,6 +50287,8 @@ $as_echo "$supports" >&6; }
 
 
 
+
+
     fi
     if !   [[ " $JVM_VARIANTS " =~ " zero " ]]   && !   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
       # Non-zero builds have stricter warnings
@@ -50440,6 +50742,18 @@ $as_echo "$supports" >&6; }
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -50469,7 +50783,7 @@ $as_echo "$supports" >&6; }
   # Version comparison method inspired by http://stackoverflow.com/a/24067243
   COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"`
 
-  if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then
+  if test $OPENJDK_BUILD_COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then
     :
 
   else
@@ -50488,6 +50802,8 @@ $as_echo "$supports" >&6; }
 
 
 
+
+
   elif test "x$TOOLCHAIN_TYPE" = xclang; then
     OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_GNU_SOURCE"
 
@@ -50712,6 +51028,18 @@ $as_echo "$supports" >&6; }
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -50741,7 +51069,7 @@ $as_echo "$supports" >&6; }
   # Version comparison method inspired by http://stackoverflow.com/a/24067243
   COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"`
 
-  if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then
+  if test $OPENJDK_BUILD_COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then
     :
 
             # These flags either do not work or give spurious warnings prior to gcc 4.8.
@@ -50764,6 +51092,8 @@ $as_echo "$supports" >&6; }
 
 
 
+
+
     fi
     if !   [[ " $JVM_VARIANTS " =~ " zero " ]]   && !   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
       # Non-zero builds have stricter warnings
@@ -51918,9 +52248,15 @@ $as_echo "$supports" >&6; }
         DISABLE_WARNING_PREFIX=
       fi
       CFLAGS_WARNINGS_ARE_ERRORS="-Werror"
-      # Repeate the check for the BUILD_CC
+      # Repeate the check for the BUILD_CC and BUILD_CXX. Need to also reset
+      # CFLAGS since any target specific flags will likely not work with the
+      # build compiler
       CC_OLD="$CC"
+      CXX_OLD="$CXX"
       CC="$BUILD_CC"
+      CXX="$BUILD_CXX"
+      CFLAGS_OLD="$CFLAGS"
+      CFLAGS=""
 
 
 
@@ -52198,6 +52534,8 @@ $as_echo "$supports" >&6; }
         BUILD_CC_DISABLE_WARNING_PREFIX=
       fi
       CC="$CC_OLD"
+      CXX="$CXX_OLD"
+      CFLAGS="$CFLAGS_OLD"
       ;;
     clang)
       DISABLE_WARNING_PREFIX="-Wno-"
diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4
index 7e7a07c5d8b..c93d487a870 100644
--- a/common/autoconf/toolchain.m4
+++ b/common/autoconf/toolchain.m4
@@ -59,23 +59,25 @@ TOOLCHAIN_MINIMUM_VERSION_xlc=""
 
 # Prepare the system so that TOOLCHAIN_CHECK_COMPILER_VERSION can be called.
 # Must have CC_VERSION_NUMBER and CXX_VERSION_NUMBER.
+# $1 - optional variable prefix for compiler and version variables (BUILD_)
+# $2 - optional variable prefix for comparable variable (OPENJDK_BUILD_)
 AC_DEFUN([TOOLCHAIN_PREPARE_FOR_VERSION_COMPARISONS],
 [
-  if test "x$CC_VERSION_NUMBER" != "x$CXX_VERSION_NUMBER"; then
-    AC_MSG_WARN([C and C++ compiler has different version numbers, $CC_VERSION_NUMBER vs $CXX_VERSION_NUMBER.])
+  if test "x[$]$1CC_VERSION_NUMBER" != "x[$]$1CXX_VERSION_NUMBER"; then
+    AC_MSG_WARN([C and C++ compiler have different version numbers, [$]$1CC_VERSION_NUMBER vs [$]$1CXX_VERSION_NUMBER.])
     AC_MSG_WARN([This typically indicates a broken setup, and is not supported])
   fi
 
   # We only check CC_VERSION_NUMBER since we assume CXX_VERSION_NUMBER is equal.
-  if [ [[ "$CC_VERSION_NUMBER" =~ (.*\.){3} ]] ]; then
-    AC_MSG_WARN([C compiler version number has more than three parts (X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong.])
+  if [ [[ "[$]$1CC_VERSION_NUMBER" =~ (.*\.){3} ]] ]; then
+    AC_MSG_WARN([C compiler version number has more than three parts (X.Y.Z): [$]$1CC_VERSION_NUMBER. Comparisons might be wrong.])
   fi
 
-  if [ [[  "$CC_VERSION_NUMBER" =~ [0-9]{6} ]] ]; then
-    AC_MSG_WARN([C compiler version number has a part larger than 99999: $CC_VERSION_NUMBER. Comparisons might be wrong.])
+  if [ [[  "[$]$1CC_VERSION_NUMBER" =~ [0-9]{6} ]] ]; then
+    AC_MSG_WARN([C compiler version number has a part larger than 99999: [$]$1CC_VERSION_NUMBER. Comparisons might be wrong.])
   fi
 
-  COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", [$]1, [$]2, [$]3) }' <<< "$CC_VERSION_NUMBER"`
+  $2COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", [$]1, [$]2, [$]3) }' <<< "[$]$1CC_VERSION_NUMBER"`
 ])
 
 # Check if the configured compiler (C and C++) is of a specific version or
@@ -85,8 +87,9 @@ AC_DEFUN([TOOLCHAIN_PREPARE_FOR_VERSION_COMPARISONS],
 #   VERSION:   The version string to check against the found version
 #   IF_AT_LEAST:   block to run if the compiler is at least this version (>=)
 #   IF_OLDER_THAN:   block to run if the compiler is older than this version (<)
+#   PREFIX:   Optional variable prefix for compiler to compare version for (OPENJDK_BUILD_)
 BASIC_DEFUN_NAMED([TOOLCHAIN_CHECK_COMPILER_VERSION],
-    [*VERSION IF_AT_LEAST IF_OLDER_THAN], [$@],
+    [*VERSION PREFIX IF_AT_LEAST IF_OLDER_THAN], [$@],
 [
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
   REFERENCE_VERSION=ARG_VERSION
@@ -102,7 +105,7 @@ BASIC_DEFUN_NAMED([TOOLCHAIN_CHECK_COMPILER_VERSION],
   # Version comparison method inspired by http://stackoverflow.com/a/24067243
   COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", [$]1, [$]2, [$]3) }' <<< "$REFERENCE_VERSION"`
 
-  if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then
+  if test [$]ARG_PREFIX[COMPARABLE_ACTUAL_VERSION] -ge $COMPARABLE_REFERENCE_VERSION ; then
     :
     ARG_IF_AT_LEAST
   else
@@ -808,6 +811,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS],
     BUILD_LDCXX="$BUILD_CXX"
 
     PATH="$OLDPATH"
+
+    TOOLCHAIN_EXTRACT_COMPILER_VERSION(BUILD_CC, [BuildC])
+    TOOLCHAIN_EXTRACT_COMPILER_VERSION(BUILD_CXX, [BuildC++])
+    TOOLCHAIN_PREPARE_FOR_VERSION_COMPARISONS([BUILD_], [OPENJDK_BUILD_])
   else
     # If we are not cross compiling, use the normal target compilers for
     # building the build platform executables.
diff --git a/common/bin/idea.sh b/common/bin/idea.sh
new file mode 100644
index 00000000000..911d309c070
--- /dev/null
+++ b/common/bin/idea.sh
@@ -0,0 +1,199 @@
+#!/bin/sh
+#
+# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+
+# Shell script for generating an IDEA project from a given list of modules
+
+usage() {
+      echo "usage: $0 [-h|--help] [-v|--verbose] [-o|--output <path>] [modules]+" 
+      exit 1
+}
+
+SCRIPT_DIR=`dirname $0`
+PWD=`pwd`
+cd $SCRIPT_DIR; SCRIPT_DIR=`pwd`
+cd ../../; TOP=`pwd`; cd $PWD
+
+IDEA_OUTPUT=$TOP/.idea
+VERBOSE="false"
+while [ $# -gt 0 ]
+do
+  case $1 in
+    -h | --help )
+      usage
+      ;;
+
+    -v | --vebose )
+      VERBOSE="true"
+      ;;
+
+    -o | --output )
+      IDEA_OUTPUT=$2
+      shift
+      ;;
+
+    -*)  # bad option
+      usage
+      ;;
+
+     * )  # non option
+      break
+      ;;
+  esac
+  shift
+done
+
+mkdir $IDEA_OUTPUT || exit 1
+cd $IDEA_OUTPUT; IDEA_OUTPUT=`pwd`
+
+IDEA_MAKE="$TOP/make/idea"
+IDEA_TEMPLATE="$IDEA_MAKE/template"
+IML_TEMPLATE="$IDEA_TEMPLATE/jdk.iml"
+ANT_TEMPLATE="$IDEA_TEMPLATE/ant.xml"
+IDEA_IML="$IDEA_OUTPUT/jdk.iml"
+IDEA_ANT="$IDEA_OUTPUT/ant.xml"
+
+if [ "$VERBOSE" = "true" ] ; then
+  echo "output dir: $IDEA_OUTPUT"
+  echo "idea template dir: $IDEA_TEMPLATE"
+fi
+
+if [ ! -f "$IML_TEMPLATE" ] ; then
+  echo "FATAL: cannot find $IML_TEMPLATE" >&2; exit 1
+fi
+
+if [ ! -f "$ANT_TEMPLATE" ] ; then
+  echo "FATAL: cannot find $ANT_TEMPLATE" >&2; exit 1
+fi
+
+cp -r "$IDEA_TEMPLATE"/* "$IDEA_OUTPUT"
+cd $TOP ; make -f "$IDEA_MAKE/idea.gmk" -I make/common idea MAKEOVERRIDES= OUT=$IDEA_OUTPUT/env.cfg MODULES="$*" || exit 1
+cd $SCRIPT_DIR
+
+. $IDEA_OUTPUT/env.cfg
+
+# Expect MODULE_ROOTS, MODULE_NAMES, BOOT_JDK & SPEC to be set
+if [ "x$MODULE_ROOTS" = "x" ] ; then
+  echo "FATAL: MODULE_ROOTS is empty" >&2; exit 1
+fi
+
+if [ "x$MODULE_NAMES" = "x" ] ; then
+  echo "FATAL: MODULE_NAMES is empty" >&2; exit 1
+fi
+
+if [ "x$BOOT_JDK" = "x" ] ; then
+  echo "FATAL: BOOT_JDK is empty" >&2; exit 1
+fi
+
+if [ "x$SPEC" = "x" ] ; then
+  echo "FATAL: SPEC is empty" >&2; exit 1
+fi
+
+SOURCE_FOLDER="      <sourceFolder url=\"file://\$MODULE_DIR\$/####\" isTestSource=\"false\" />"
+SOURCE_FOLDERS_DONE="false"
+
+addSourceFolder() {
+  root=$@
+  relativePath="`echo "$root" | sed -e s@"$TOP/\(.*$\)"@"\1"@`"
+  folder="`echo "$SOURCE_FOLDER" | sed -e s@"\(.*/\)####\(.*\)"@"\1$relativePath\2"@`"
+  printf "%s\n" "$folder" >> $IDEA_IML
+}
+
+### Generate project iml
+RELATIVE_BUILD_DIR="`dirname $SPEC | sed -e s@"$TOP/\(.*$\)"@"\1"@`"
+rm -f $IDEA_IML
+while IFS= read -r line
+do
+  if echo "$line" | egrep "^ .* <sourceFolder.*####" > /dev/null ; then
+    if [ "$SOURCE_FOLDERS_DONE" = "false" ] ; then 
+      SOURCE_FOLDERS_DONE="true"
+      for root in $MODULE_ROOTS; do
+         addSourceFolder $root
+      done
+    fi
+  elif echo "$line" | egrep "^ .* <excludeFolder.*####" > /dev/null ; then
+    ul="`echo "$line" | sed -e s@"\(.*/\)####\(.*\)"@"\1$RELATIVE_BUILD_DIR\2"@`"
+    printf "%s\n" "$ul" >> $IDEA_IML 
+  else
+    printf "%s\n" "$line" >> $IDEA_IML
+  fi
+done < "$IML_TEMPLATE"
+
+
+MODULE_NAME="        <property name=\"module.name\" value=\"####\" />"
+
+addModuleName() {
+  mn="`echo "$MODULE_NAME" | sed -e s@"\(.*\)####\(.*\)"@"\1$MODULE_NAMES\2"@`"
+  printf "%s\n" "$mn" >> $IDEA_ANT
+}
+
+BUILD_DIR="        <property name=\"build.target.dir\" value=\"####\" />"
+
+addBuildDir() {
+  DIR=`dirname $SPEC`
+  mn="`echo "$BUILD_DIR" | sed -e s@"\(.*\)####\(.*\)"@"\1$DIR\2"@`"
+  printf "%s\n" "$mn" >> $IDEA_ANT
+}
+
+### Generate ant.xml
+
+rm -f $IDEA_ANT
+while IFS= read -r line
+do
+  if echo "$line" | egrep "^ .* <property name=\"module.name\"" > /dev/null ; then
+    addModuleName
+  elif echo "$line" | egrep "^ .* <property name=\"build.target.dir\"" > /dev/null ; then
+    addBuildDir
+  else
+    printf "%s\n" "$line" >> $IDEA_ANT
+  fi
+done < "$ANT_TEMPLATE"
+
+### Compile the custom Logger
+
+CLASSES=$IDEA_OUTPUT/classes
+
+if [ "x$ANT_HOME" = "x" ] ; then
+   # try some common locations, before giving up
+   if [ -f "/usr/share/ant/lib/ant.jar" ] ; then
+     ANT_HOME="/usr/share/ant"
+   elif [ -f "/usr/local/Cellar/ant/1.9.4/libexec/lib/ant.jar" ] ; then
+     ANT_HOME="/usr/local/Cellar/ant/1.9.4/libexec"
+   else
+     echo "FATAL: cannot find ant. Try setting ANT_HOME." >&2; exit 1
+   fi
+fi
+CP=$ANT_HOME/lib/ant.jar
+rm -rf $CLASSES; mkdir $CLASSES
+
+if [ "x$CYGPATH" = "x" ] ; then ## CYGPATH may be set in env.cfg
+  JAVAC_SOURCE_FILE=$IDEA_OUTPUT/src/idea/JdkIdeaAntLogger.java
+  JAVAC_CLASSES=$CLASSES
+  JAVAC_CP=$CP
+else
+  JAVAC_SOURCE_FILE=`cygpath -am $IDEA_OUTPUT/src/idea/JdkIdeaAntLogger.java`
+  JAVAC_CLASSES=`cygpath -am $CLASSES`
+  JAVAC_CP=`cygpath -am $CP`
+fi
+
+$BOOT_JDK/bin/javac -d $JAVAC_CLASSES -cp $JAVAC_CP $JAVAC_SOURCE_FILE
diff --git a/common/bin/jib.sh b/common/bin/jib.sh
index 454d78ce1d7..ea52385537b 100644
--- a/common/bin/jib.sh
+++ b/common/bin/jib.sh
@@ -89,7 +89,7 @@ install_jib() {
     fi
 
     if command -v curl > /dev/null; then
-        getcmd="curl -s"
+        getcmd="curl -s -L --retry 3 --retry-delay 5"
     elif command -v wget > /dev/null; then
         getcmd="wget --quiet -O -"
     else
diff --git a/corba/.hgtags b/corba/.hgtags
index 7a705d44659..feea5f070eb 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -360,3 +360,4 @@ cc30faa2da498c478e89ab062ff160653ca1b170 jdk-9+113
 7bab1b1b36824924b1c657a8419369ba93d198d3 jdk-9+115
 7dfa7377a5e601b8f740741a9a80e04c72dd04d6 jdk-9+116
 7a1b36bf2fe55a9a7732489ccdd326c910329a7e jdk-9+117
+8c2c2d17f7ce92a31c9ccb44a122ec62f5a85ace jdk-9+118
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index d308ce9a4c0..c2bf9fb792d 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -520,3 +520,4 @@ b64432bae5271735fd53300b2005b713e98ef411 jdk-9+114
 88dd08d7be0fe7fb9f1914b1628f0aae9bf56e25 jdk-9+115
 61a214186dae6811dd989e9165e42f7dbf02acde jdk-9+116
 88170d3642905b9e6cac03e8efcc976885a7e6da jdk-9+117
+9b1075cac08dc836ec32e7b368415cbe3aceaf8c jdk-9+118
diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp
index 5166478e5e7..834e1ae88fc 100644
--- a/hotspot/src/share/vm/prims/jvm.cpp
+++ b/hotspot/src/share/vm/prims/jvm.cpp
@@ -3387,14 +3387,14 @@ bool force_verify_field_access(Klass* current_class, Klass* field_class, AccessF
   return (!access.is_private() && InstanceKlass::cast(current_class)->is_same_class_package(field_class));
 }
 
-// Return the first non-null class loader up the execution stack, or null
-// if only code from the null class loader is on the stack.
+// Return the first user-defined class loader up the execution stack, or null
+// if only code from the bootstrap or platform class loader is on the stack.
 
 JVM_ENTRY(jobject, JVM_LatestUserDefinedLoader(JNIEnv *env))
   for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
     vfst.skip_reflection_related_frames(); // Only needed for 1.4 reflection
     oop loader = vfst.method()->method_holder()->class_loader();
-    if (loader != NULL) {
+    if (loader != NULL && !SystemDictionary::is_platform_class_loader(loader)) {
       return JNIHandles::make_local(env, loader);
     }
   }
diff --git a/hotspot/test/Makefile b/hotspot/test/Makefile
index 3468e65bcac..1dfecd6bce1 100644
--- a/hotspot/test/Makefile
+++ b/hotspot/test/Makefile
@@ -120,24 +120,33 @@ endif
 TEST_ROOT := $(shell pwd)
 
 # Root of all test results
-ifdef ALT_OUTPUTDIR
-  ABS_BUILD_ROOT = $(ALT_OUTPUTDIR)
+ifdef TEST_OUTPUT_DIR
+  $(shell $(MKDIR) -p $(TEST_OUTPUT_DIR)/jtreg)
+  ABS_TEST_OUTPUT_DIR := \
+    $(shell $(CD) $(TEST_OUTPUT_DIR)/jtreg && $(PWD))
 else
-  ABS_BUILD_ROOT = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)
+  ifdef ALT_OUTPUTDIR
+    ABS_OUTPUTDIR = $(shell $(CD) $(ALT_OUTPUTDIR) && $(PWD))
+  else
+    ABS_OUTPUTDIR = $(shell $(CD) $(TEST_ROOT)/.. && $(PWD))
+  endif
+
+  ABS_PLATFORM_BUILD_ROOT = $(ABS_OUTPUTDIR)
+  ABS_TEST_OUTPUT_DIR := $(ABS_PLATFORM_BUILD_ROOT)/testoutput/$(UNIQUE_DIR)
 endif
-ABS_TEST_OUTPUT_DIR = $(ABS_BUILD_ROOT)/testoutput/$(UNIQUE_DIR)
 
 # Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
 ifndef PRODUCT_HOME
-  # Try to use j2sdk-image if it exists
-  ABS_JDK_IMAGE = $(ABS_BUILD_ROOT)/j2sdk-image
-  PRODUCT_HOME :=                       \
-    $(shell                             \
-      if [ -d $(ABS_JDK_IMAGE) ] ; then \
-         $(ECHO) "$(ABS_JDK_IMAGE)";    \
-       else                             \
-         $(ECHO) "$(ABS_BUILD_ROOT)" ;  \
+  # Try to use images/jdk if it exists
+  ABS_JDK_IMAGE = $(ABS_PLATFORM_BUILD_ROOT)/images/jdk
+  PRODUCT_HOME :=                       		\
+    $(shell                             		\
+      if [ -d $(ABS_JDK_IMAGE) ] ; then 		\
+         $(ECHO) "$(ABS_JDK_IMAGE)";    		\
+       else                             		\
+         $(ECHO) "$(ABS_PLATFORM_BUILD_ROOT)";		\
        fi)
+  PRODUCT_HOME := $(PRODUCT_HOME)
 endif
 
 # Expect JPRT to set JAVA_ARGS (e.g. -server etc.)
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index f36d86837fa..3bef243c570 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -360,3 +360,4 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103
 1902a5bda18e794b31fc5f520f5e7d827714b50d jdk-9+115
 9d71d20e614777cd23c1a43b38b5c08a9094d27a jdk-9+116
 46b57560cd06ebcdd21489250628ff5f9d9d8916 jdk-9+117
+a8aa25fc6c5fda0ed7a93b8ffee62da326a752fc jdk-9+118
diff --git a/jaxp/THIRD_PARTY_README b/jaxp/THIRD_PARTY_README
index a93b35b994c..4d3007051ce 100644
--- a/jaxp/THIRD_PARTY_README
+++ b/jaxp/THIRD_PARTY_README
@@ -3387,7 +3387,6 @@ included with JRE 8, JDK 8, and OpenJDK 8, except where noted:
   Apache Commons Math 2.2
   Apache Derby 10.10.1.2        [included with JDK 8]
   Apache Jakarta BCEL 5.2 
-  Apache Jakarta Regexp 1.4 
   Apache Santuario XML Security for Java 1.5.4
   Apache Xalan-Java 2.7.1 
   Apache Xerces Java 2.10.0 
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java
index 162afd1e0dd..f755549b902 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java
@@ -4,64 +4,29 @@
  */
 package com.sun.org.apache.bcel.internal.util;
 
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
- * Copyright (c) 2001 The Apache Software Foundation.  All rights
- * reserved.
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
  *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" and
- *    "Apache BCEL" must not be used to endorse or promote products
- *    derived from this software without prior written permission. For
- *    written permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    "Apache BCEL", nor may "Apache" appear in their name, without
- *    prior written permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
  */
 
-import java.util.*;
 import com.sun.org.apache.bcel.internal.Constants;
 import com.sun.org.apache.bcel.internal.generic.*;
-import com.sun.org.apache.regexp.internal.*;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * InstructionFinder is a tool to search for given instructions patterns,
@@ -231,28 +196,22 @@ public class InstructionFinder {
     if(start == -1)
       throw new ClassGenException("Instruction handle " + from +
                                   " not found in instruction list.");
-    try {
-      RE regex = new RE(search);
-      ArrayList matches = new ArrayList();
 
-      while(start < il_string.length() && regex.match(il_string, start)) {
-        int startExpr = regex.getParenStart(0);
-        int endExpr   = regex.getParenEnd(0);
-        int lenExpr   = regex.getParenLength(0);
+    Pattern regex = Pattern.compile(search);
+    List<InstructionHandle[]> matches = new ArrayList<>();
+    Matcher matcher = regex.matcher(il_string);
+    while(start < il_string.length() && matcher.find(start)) {
+      int startExpr = matcher.start();
+      int endExpr   = matcher.end();
+      int lenExpr   = endExpr - startExpr;
+      InstructionHandle[] match = getMatch(startExpr, lenExpr);
 
-        InstructionHandle[] match = getMatch(startExpr, lenExpr);
-
-        if((constraint == null) || constraint.checkCode(match))
-          matches.add(match);
-        start = endExpr;
-      }
-
-      return matches.iterator();
-    } catch(RESyntaxException e) {
-      System.err.println(e);
+      if((constraint == null) || constraint.checkCode(match))
+        matches.add(match);
+      start = endExpr;
     }
 
-    return null;
+    return matches.iterator();
   }
 
   /**
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/CharacterArrayCharacterIterator.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/CharacterArrayCharacterIterator.java
deleted file mode 100644
index 6382d478d96..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/CharacterArrayCharacterIterator.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-/**
- * Encapsulates char[] as CharacterIterator
- *
- * @author <a href="mailto:ales.novak@netbeans.com">Ales Novak</a>
- */
-public final class CharacterArrayCharacterIterator implements CharacterIterator
-{
-    /** encapsulated */
-    private final char[] src;
-    /** offset in the char array */
-    private final int off;
-    /** used portion of the array */
-    private final int len;
-
-    /** @param src - encapsulated String */
-    public CharacterArrayCharacterIterator(char[] src, int off, int len)
-    {
-        this.src = src;
-        this.off = off;
-        this.len = len;
-    }
-
-    /** @return a substring */
-    public String substring(int beginIndex, int endIndex)
-    {
-        if (endIndex > len) {
-            throw new IndexOutOfBoundsException("endIndex=" + endIndex
-                                                + "; sequence size=" + len);
-        }
-        if (beginIndex < 0 || beginIndex > endIndex) {
-            throw new IndexOutOfBoundsException("beginIndex=" + beginIndex
-                                                + "; endIndex=" + endIndex);
-        }
-        return new String(src, off + beginIndex, endIndex - beginIndex);
-    }
-
-    /** @return a substring */
-    public String substring(int beginIndex)
-    {
-        return substring(beginIndex, len);
-    }
-
-    /** @return a character at the specified position. */
-    public char charAt(int pos)
-    {
-        return src[off + pos];
-    }
-
-    /** @return <tt>true</tt> iff if the specified index is after the end of the character stream */
-    public boolean isEnd(int pos)
-    {
-        return (pos >= len);
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/CharacterIterator.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/CharacterIterator.java
deleted file mode 100644
index 69db536aaa2..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/CharacterIterator.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-/**
- * Encapsulates different types of character sources - String, InputStream, ...
- * Defines a set of common methods
- *
- * @author <a href="mailto:ales.novak@netbeans.com">Ales Novak</a>
- */
-public interface CharacterIterator
-{
-    /** @return a substring */
-    String substring(int beginIndex, int endIndex);
-
-    /** @return a substring */
-    String substring(int beginIndex);
-
-    /** @return a character at the specified position. */
-    char charAt(int pos);
-
-    /** @return <tt>true</tt> iff if the specified index is after the end of the character stream */
-    boolean isEnd(int pos);
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RE.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RE.java
deleted file mode 100644
index 0cdc012dbb7..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RE.java
+++ /dev/null
@@ -1,1760 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-import java.io.Serializable;
-import java.util.Vector;
-
-/**
- * RE is an efficient, lightweight regular expression evaluator/matcher
- * class. Regular expressions are pattern descriptions which enable
- * sophisticated matching of strings.  In addition to being able to
- * match a string against a pattern, you can also extract parts of the
- * match.  This is especially useful in text parsing! Details on the
- * syntax of regular expression patterns are given below.
- *
- * <p>
- * To compile a regular expression (RE), you can simply construct an RE
- * matcher object from the string specification of the pattern, like this:
- *
- * <pre>
- *  RE r = new RE("a*b");
- * </pre>
- *
- * <p>
- * Once you have done this, you can call either of the RE.match methods to
- * perform matching on a String.  For example:
- *
- * <pre>
- *  boolean matched = r.match("aaaab");
- * </pre>
- *
- * will cause the boolean matched to be set to true because the
- * pattern "a*b" matches the string "aaaab".
- *
- * <p>
- * If you were interested in the <i>number</i> of a's which matched the
- * first part of our example expression, you could change the expression to
- * "(a*)b".  Then when you compiled the expression and matched it against
- * something like "xaaaab", you would get results like this:
- *
- * <pre>
- *  RE r = new RE("(a*)b");                  // Compile expression
- *  boolean matched = r.match("xaaaab");     // Match against "xaaaab"
- *
- *  String wholeExpr = r.getParen(0);        // wholeExpr will be 'aaaab'
- *  String insideParens = r.getParen(1);     // insideParens will be 'aaaa'
- *
- *  int startWholeExpr = r.getParenStart(0); // startWholeExpr will be index 1
- *  int endWholeExpr = r.getParenEnd(0);     // endWholeExpr will be index 6
- *  int lenWholeExpr = r.getParenLength(0);  // lenWholeExpr will be 5
- *
- *  int startInside = r.getParenStart(1);    // startInside will be index 1
- *  int endInside = r.getParenEnd(1);        // endInside will be index 5
- *  int lenInside = r.getParenLength(1);     // lenInside will be 4
- * </pre>
- *
- * You can also refer to the contents of a parenthesized expression
- * within a regular expression itself.  This is called a
- * 'backreference'.  The first backreference in a regular expression is
- * denoted by \1, the second by \2 and so on.  So the expression:
- *
- * <pre>
- *  ([0-9]+)=\1
- * </pre>
- *
- * will match any string of the form n=n (like 0=0 or 2=2).
- *
- * <p>
- * The full regular expression syntax accepted by RE is described here:
- *
- * <pre>
- *
- *  <b><font face=times roman>Characters</font></b>
- *
- *    <i>unicodeChar</i>   Matches any identical unicode character
- *    \                    Used to quote a meta-character (like '*')
- *    \\                   Matches a single '\' character
- *    \0nnn                Matches a given octal character
- *    \xhh                 Matches a given 8-bit hexadecimal character
- *    \\uhhhh              Matches a given 16-bit hexadecimal character
- *    \t                   Matches an ASCII tab character
- *    \n                   Matches an ASCII newline character
- *    \r                   Matches an ASCII return character
- *    \f                   Matches an ASCII form feed character
- *
- *
- *  <b><font face=times roman>Character Classes</font></b>
- *
- *    [abc]                Simple character class
- *    [a-zA-Z]             Character class with ranges
- *    [^abc]               Negated character class
- * </pre>
- *
- * <b>NOTE:</b> Incomplete ranges will be interpreted as &quot;starts
- * from zero&quot; or &quot;ends with last character&quot;.
- * <br>
- * I.e. [-a] is the same as [\\u0000-a], and [a-] is the same as [a-\\uFFFF],
- * [-] means &quot;all characters&quot;.
- *
- * <pre>
- *
- *  <b><font face=times roman>Standard POSIX Character Classes</font></b>
- *
- *    [:alnum:]            Alphanumeric characters.
- *    [:alpha:]            Alphabetic characters.
- *    [:blank:]            Space and tab characters.
- *    [:cntrl:]            Control characters.
- *    [:digit:]            Numeric characters.
- *    [:graph:]            Characters that are printable and are also visible.
- *                         (A space is printable, but not visible, while an
- *                         `a' is both.)
- *    [:lower:]            Lower-case alphabetic characters.
- *    [:print:]            Printable characters (characters that are not
- *                         control characters.)
- *    [:punct:]            Punctuation characters (characters that are not letter,
- *                         digits, control characters, or space characters).
- *    [:space:]            Space characters (such as space, tab, and formfeed,
- *                         to name a few).
- *    [:upper:]            Upper-case alphabetic characters.
- *    [:xdigit:]           Characters that are hexadecimal digits.
- *
- *
- *  <b><font face=times roman>Non-standard POSIX-style Character Classes</font></b>
- *
- *    [:javastart:]        Start of a Java identifier
- *    [:javapart:]         Part of a Java identifier
- *
- *
- *  <b><font face=times roman>Predefined Classes</font></b>
- *
- *    .         Matches any character other than newline
- *    \w        Matches a "word" character (alphanumeric plus "_")
- *    \W        Matches a non-word character
- *    \s        Matches a whitespace character
- *    \S        Matches a non-whitespace character
- *    \d        Matches a digit character
- *    \D        Matches a non-digit character
- *
- *
- *  <b><font face=times roman>Boundary Matchers</font></b>
- *
- *    ^         Matches only at the beginning of a line
- *    $         Matches only at the end of a line
- *    \b        Matches only at a word boundary
- *    \B        Matches only at a non-word boundary
- *
- *
- *  <b><font face=times roman>Greedy Closures</font></b>
- *
- *    A*        Matches A 0 or more times (greedy)
- *    A+        Matches A 1 or more times (greedy)
- *    A?        Matches A 1 or 0 times (greedy)
- *    A{n}      Matches A exactly n times (greedy)
- *    A{n,}     Matches A at least n times (greedy)
- *    A{n,m}    Matches A at least n but not more than m times (greedy)
- *
- *
- *  <b><font face=times roman>Reluctant Closures</font></b>
- *
- *    A*?       Matches A 0 or more times (reluctant)
- *    A+?       Matches A 1 or more times (reluctant)
- *    A??       Matches A 0 or 1 times (reluctant)
- *
- *
- *  <b><font face=times roman>Logical Operators</font></b>
- *
- *    AB        Matches A followed by B
- *    A|B       Matches either A or B
- *    (A)       Used for subexpression grouping
- *   (?:A)      Used for subexpression clustering (just like grouping but
- *              no backrefs)
- *
- *
- *  <b><font face=times roman>Backreferences</font></b>
- *
- *    \1    Backreference to 1st parenthesized subexpression
- *    \2    Backreference to 2nd parenthesized subexpression
- *    \3    Backreference to 3rd parenthesized subexpression
- *    \4    Backreference to 4th parenthesized subexpression
- *    \5    Backreference to 5th parenthesized subexpression
- *    \6    Backreference to 6th parenthesized subexpression
- *    \7    Backreference to 7th parenthesized subexpression
- *    \8    Backreference to 8th parenthesized subexpression
- *    \9    Backreference to 9th parenthesized subexpression
- * </pre>
- *
- * <p>
- * All closure operators (+, *, ?, {m,n}) are greedy by default, meaning
- * that they match as many elements of the string as possible without
- * causing the overall match to fail.  If you want a closure to be
- * reluctant (non-greedy), you can simply follow it with a '?'.  A
- * reluctant closure will match as few elements of the string as
- * possible when finding matches.  {m,n} closures don't currently
- * support reluctancy.
- *
- * <p>
- * <b><font face="times roman">Line terminators</font></b>
- * <br>
- * A line terminator is a one- or two-character sequence that marks
- * the end of a line of the input character sequence. The following
- * are recognized as line terminators:
- * <ul>
- * <li>A newline (line feed) character ('\n'),</li>
- * <li>A carriage-return character followed immediately by a newline character ("\r\n"),</li>
- * <li>A standalone carriage-return character ('\r'),</li>
- * <li>A next-line character ('\u0085'),</li>
- * <li>A line-separator character ('\u2028'), or</li>
- * <li>A paragraph-separator character ('\u2029).</li>
- * </ul>
- *
- * <p>
- * RE runs programs compiled by the RECompiler class.  But the RE
- * matcher class does not include the actual regular expression compiler
- * for reasons of efficiency.  In fact, if you want to pre-compile one
- * or more regular expressions, the 'recompile' class can be invoked
- * from the command line to produce compiled output like this:
- *
- * <pre>
- *    // Pre-compiled regular expression "a*b"
- *    char[] re1Instructions =
- *    {
- *        0x007c, 0x0000, 0x001a, 0x007c, 0x0000, 0x000d, 0x0041,
- *        0x0001, 0x0004, 0x0061, 0x007c, 0x0000, 0x0003, 0x0047,
- *        0x0000, 0xfff6, 0x007c, 0x0000, 0x0003, 0x004e, 0x0000,
- *        0x0003, 0x0041, 0x0001, 0x0004, 0x0062, 0x0045, 0x0000,
- *        0x0000,
- *    };
- *
- *
- *    REProgram re1 = new REProgram(re1Instructions);
- * </pre>
- *
- * You can then construct a regular expression matcher (RE) object from
- * the pre-compiled expression re1 and thus avoid the overhead of
- * compiling the expression at runtime. If you require more dynamic
- * regular expressions, you can construct a single RECompiler object and
- * re-use it to compile each expression. Similarly, you can change the
- * program run by a given matcher object at any time. However, RE and
- * RECompiler are not threadsafe (for efficiency reasons, and because
- * requiring thread safety in this class is deemed to be a rare
- * requirement), so you will need to construct a separate compiler or
- * matcher object for each thread (unless you do thread synchronization
- * yourself). Once expression compiled into the REProgram object, REProgram
- * can be safely shared across multiple threads and RE objects.
- *
- * <br><p><br>
- *
- * <font color="red">
- * <i>ISSUES:</i>
- *
- * <ul>
- *  <li>com.weusours.util.re is not currently compatible with all
- *      standard POSIX regcomp flags</li>
- *  <li>com.weusours.util.re does not support POSIX equivalence classes
- *      ([=foo=] syntax) (I18N/locale issue)</li>
- *  <li>com.weusours.util.re does not support nested POSIX character
- *      classes (definitely should, but not completely trivial)</li>
- *  <li>com.weusours.util.re Does not support POSIX character collation
- *      concepts ([.foo.] syntax) (I18N/locale issue)</li>
- *  <li>Should there be different matching styles (simple, POSIX, Perl etc?)</li>
- *  <li>Should RE support character iterators (for backwards RE matching!)?</li>
- *  <li>Should RE support reluctant {m,n} closures (does anyone care)?</li>
- *  <li>Not *all* possibilities are considered for greediness when backreferences
- *      are involved (as POSIX suggests should be the case).  The POSIX RE
- *      "(ac*)c*d[ac]*\1", when matched against "acdacaa" should yield a match
- *      of acdacaa where \1 is "a".  This is not the case in this RE package,
- *      and actually Perl doesn't go to this extent either!  Until someone
- *      actually complains about this, I'm not sure it's worth "fixing".
- *      If it ever is fixed, test #137 in RETest.txt should be updated.</li>
- * </ul>
- *
- * </font>
- *
- * @see recompile
- * @see RECompiler
- *
- * @author <a href="mailto:jonl@muppetlabs.com">Jonathan Locke</a>
- * @author <a href="mailto:ts@sch-fer.de">Tobias Sch&auml;fer</a>
- */
-public class RE implements Serializable
-{
-    /**
-     * Specifies normal, case-sensitive matching behaviour.
-     */
-    public static final int MATCH_NORMAL          = 0x0000;
-
-    /**
-     * Flag to indicate that matching should be case-independent (folded)
-     */
-    public static final int MATCH_CASEINDEPENDENT = 0x0001;
-
-    /**
-     * Newlines should match as BOL/EOL (^ and $)
-     */
-    public static final int MATCH_MULTILINE       = 0x0002;
-
-    /**
-     * Consider all input a single body of text - newlines are matched by .
-     */
-    public static final int MATCH_SINGLELINE      = 0x0004;
-
-    /************************************************
-     *                                              *
-     * The format of a node in a program is:        *
-     *                                              *
-     * [ OPCODE ] [ OPDATA ] [ OPNEXT ] [ OPERAND ] *
-     *                                              *
-     * char OPCODE - instruction                    *
-     * char OPDATA - modifying data                 *
-     * char OPNEXT - next node (relative offset)    *
-     *                                              *
-     ************************************************/
-
-                 //   Opcode              Char       Opdata/Operand  Meaning
-                 //   ----------          ---------- --------------- --------------------------------------------------
-    static final char OP_END              = 'E';  //                 end of program
-    static final char OP_BOL              = '^';  //                 match only if at beginning of line
-    static final char OP_EOL              = '$';  //                 match only if at end of line
-    static final char OP_ANY              = '.';  //                 match any single character except newline
-    static final char OP_ANYOF            = '[';  // count/ranges    match any char in the list of ranges
-    static final char OP_BRANCH           = '|';  // node            match this alternative or the next one
-    static final char OP_ATOM             = 'A';  // length/string   length of string followed by string itself
-    static final char OP_STAR             = '*';  // node            kleene closure
-    static final char OP_PLUS             = '+';  // node            positive closure
-    static final char OP_MAYBE            = '?';  // node            optional closure
-    static final char OP_ESCAPE           = '\\'; // escape          special escape code char class (escape is E_* code)
-    static final char OP_OPEN             = '(';  // number          nth opening paren
-    static final char OP_OPEN_CLUSTER     = '<';  //                 opening cluster
-    static final char OP_CLOSE            = ')';  // number          nth closing paren
-    static final char OP_CLOSE_CLUSTER    = '>';  //                 closing cluster
-    static final char OP_BACKREF          = '#';  // number          reference nth already matched parenthesized string
-    static final char OP_GOTO             = 'G';  //                 nothing but a (back-)pointer
-    static final char OP_NOTHING          = 'N';  //                 match null string such as in '(a|)'
-    static final char OP_RELUCTANTSTAR    = '8';  // none/expr       reluctant '*' (mnemonic for char is unshifted '*')
-    static final char OP_RELUCTANTPLUS    = '=';  // none/expr       reluctant '+' (mnemonic for char is unshifted '+')
-    static final char OP_RELUCTANTMAYBE   = '/';  // none/expr       reluctant '?' (mnemonic for char is unshifted '?')
-    static final char OP_POSIXCLASS       = 'P';  // classid         one of the posix character classes
-
-    // Escape codes
-    static final char E_ALNUM             = 'w';  // Alphanumeric
-    static final char E_NALNUM            = 'W';  // Non-alphanumeric
-    static final char E_BOUND             = 'b';  // Word boundary
-    static final char E_NBOUND            = 'B';  // Non-word boundary
-    static final char E_SPACE             = 's';  // Whitespace
-    static final char E_NSPACE            = 'S';  // Non-whitespace
-    static final char E_DIGIT             = 'd';  // Digit
-    static final char E_NDIGIT            = 'D';  // Non-digit
-
-    // Posix character classes
-    static final char POSIX_CLASS_ALNUM   = 'w';  // Alphanumerics
-    static final char POSIX_CLASS_ALPHA   = 'a';  // Alphabetics
-    static final char POSIX_CLASS_BLANK   = 'b';  // Blanks
-    static final char POSIX_CLASS_CNTRL   = 'c';  // Control characters
-    static final char POSIX_CLASS_DIGIT   = 'd';  // Digits
-    static final char POSIX_CLASS_GRAPH   = 'g';  // Graphic characters
-    static final char POSIX_CLASS_LOWER   = 'l';  // Lowercase characters
-    static final char POSIX_CLASS_PRINT   = 'p';  // Printable characters
-    static final char POSIX_CLASS_PUNCT   = '!';  // Punctuation
-    static final char POSIX_CLASS_SPACE   = 's';  // Spaces
-    static final char POSIX_CLASS_UPPER   = 'u';  // Uppercase characters
-    static final char POSIX_CLASS_XDIGIT  = 'x';  // Hexadecimal digits
-    static final char POSIX_CLASS_JSTART  = 'j';  // Java identifier start
-    static final char POSIX_CLASS_JPART   = 'k';  // Java identifier part
-
-    // Limits
-    static final int maxNode  = 65536;            // Maximum number of nodes in a program
-    static final int MAX_PAREN = 16;              // Number of paren pairs (only 9 can be backrefs)
-
-    // Node layout constants
-    static final int offsetOpcode = 0;            // Opcode offset (first character)
-    static final int offsetOpdata = 1;            // Opdata offset (second char)
-    static final int offsetNext   = 2;            // Next index offset (third char)
-    static final int nodeSize     = 3;            // Node size (in chars)
-
-    // State of current program
-    REProgram program;                            // Compiled regular expression 'program'
-    transient CharacterIterator search;           // The string being matched against
-    int matchFlags;                               // Match behaviour flags
-    int maxParen = MAX_PAREN;
-
-    // Parenthesized subexpressions
-    transient int parenCount;                     // Number of subexpressions matched (num open parens + 1)
-    transient int start0;                         // Cache of start[0]
-    transient int end0;                           // Cache of start[0]
-    transient int start1;                         // Cache of start[1]
-    transient int end1;                           // Cache of start[1]
-    transient int start2;                         // Cache of start[2]
-    transient int end2;                           // Cache of start[2]
-    transient int[] startn;                       // Lazy-alloced array of sub-expression starts
-    transient int[] endn;                         // Lazy-alloced array of sub-expression ends
-
-    // Backreferences
-    transient int[] startBackref;                 // Lazy-alloced array of backref starts
-    transient int[] endBackref;                   // Lazy-alloced array of backref ends
-
-    /**
-     * Constructs a regular expression matcher from a String by compiling it
-     * using a new instance of RECompiler.  If you will be compiling many
-     * expressions, you may prefer to use a single RECompiler object instead.
-     *
-     * @param pattern The regular expression pattern to compile.
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     * @see RECompiler
-     * @see recompile
-     */
-    public RE(String pattern) throws RESyntaxException
-    {
-        this(pattern, MATCH_NORMAL);
-    }
-
-    /**
-     * Constructs a regular expression matcher from a String by compiling it
-     * using a new instance of RECompiler.  If you will be compiling many
-     * expressions, you may prefer to use a single RECompiler object instead.
-     *
-     * @param pattern The regular expression pattern to compile.
-     * @param matchFlags The matching style
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     * @see RECompiler
-     * @see recompile
-     */
-    public RE(String pattern, int matchFlags) throws RESyntaxException
-    {
-        this(new RECompiler().compile(pattern));
-        setMatchFlags(matchFlags);
-    }
-
-    /**
-     * Construct a matcher for a pre-compiled regular expression from program
-     * (bytecode) data.  Permits special flags to be passed in to modify matching
-     * behaviour.
-     *
-     * @param program Compiled regular expression program (see RECompiler and/or recompile)
-     * @param matchFlags One or more of the RE match behaviour flags (RE.MATCH_*):
-     *
-     * <pre>
-     *   MATCH_NORMAL              // Normal (case-sensitive) matching
-     *   MATCH_CASEINDEPENDENT     // Case folded comparisons
-     *   MATCH_MULTILINE           // Newline matches as BOL/EOL
-     * </pre>
-     *
-     * @see RECompiler
-     * @see REProgram
-     * @see recompile
-     */
-    public RE(REProgram program, int matchFlags)
-    {
-        setProgram(program);
-        setMatchFlags(matchFlags);
-    }
-
-    /**
-     * Construct a matcher for a pre-compiled regular expression from program
-     * (bytecode) data.
-     *
-     * @param program Compiled regular expression program
-     * @see RECompiler
-     * @see recompile
-     */
-    public RE(REProgram program)
-    {
-        this(program, MATCH_NORMAL);
-    }
-
-    /**
-     * Constructs a regular expression matcher with no initial program.
-     * This is likely to be an uncommon practice, but is still supported.
-     */
-    public RE()
-    {
-        this((REProgram)null, MATCH_NORMAL);
-    }
-
-    /**
-     * Converts a 'simplified' regular expression to a full regular expression
-     *
-     * @param pattern The pattern to convert
-     * @return The full regular expression
-     */
-    public static String simplePatternToFullRegularExpression(String pattern)
-    {
-        StringBuffer buf = new StringBuffer();
-        for (int i = 0; i < pattern.length(); i++)
-        {
-            char c = pattern.charAt(i);
-            switch (c)
-            {
-                case '*':
-                    buf.append(".*");
-                    break;
-
-                case '.':
-                case '[':
-                case ']':
-                case '\\':
-                case '+':
-                case '?':
-                case '{':
-                case '}':
-                case '$':
-                case '^':
-                case '|':
-                case '(':
-                case ')':
-                    buf.append('\\');
-                default:
-                    buf.append(c);
-                    break;
-            }
-        }
-        return buf.toString();
-    }
-
-    /**
-     * Sets match behaviour flags which alter the way RE does matching.
-     * @param matchFlags One or more of the RE match behaviour flags (RE.MATCH_*):
-     *
-     * <pre>
-     *   MATCH_NORMAL              // Normal (case-sensitive) matching
-     *   MATCH_CASEINDEPENDENT     // Case folded comparisons
-     *   MATCH_MULTILINE           // Newline matches as BOL/EOL
-     * </pre>
-     */
-    public void setMatchFlags(int matchFlags)
-    {
-        this.matchFlags = matchFlags;
-    }
-
-    /**
-     * Returns the current match behaviour flags.
-     * @return Current match behaviour flags (RE.MATCH_*).
-     *
-     * <pre>
-     *   MATCH_NORMAL              // Normal (case-sensitive) matching
-     *   MATCH_CASEINDEPENDENT     // Case folded comparisons
-     *   MATCH_MULTILINE           // Newline matches as BOL/EOL
-     * </pre>
-     *
-     * @see #setMatchFlags
-     */
-    public int getMatchFlags()
-    {
-        return matchFlags;
-    }
-
-    /**
-     * Sets the current regular expression program used by this matcher object.
-     *
-     * @param program Regular expression program compiled by RECompiler.
-     * @see RECompiler
-     * @see REProgram
-     * @see recompile
-     */
-    public void setProgram(REProgram program)
-    {
-        this.program = program;
-        if (program != null && program.maxParens != -1) {
-            this.maxParen = program.maxParens;
-        } else {
-            this.maxParen = MAX_PAREN;
-        }
-    }
-
-    /**
-     * Returns the current regular expression program in use by this matcher object.
-     *
-     * @return Regular expression program
-     * @see #setProgram
-     */
-    public REProgram getProgram()
-    {
-        return program;
-    }
-
-    /**
-     * Returns the number of parenthesized subexpressions available after a successful match.
-     *
-     * @return Number of available parenthesized subexpressions
-     */
-    public int getParenCount()
-    {
-        return parenCount;
-    }
-
-    /**
-     * Gets the contents of a parenthesized subexpression after a successful match.
-     *
-     * @param which Nesting level of subexpression
-     * @return String
-     */
-    public String getParen(int which)
-    {
-        int start;
-        if (which < parenCount && (start = getParenStart(which)) >= 0)
-        {
-            return search.substring(start, getParenEnd(which));
-        }
-        return null;
-    }
-
-    /**
-     * Returns the start index of a given paren level.
-     *
-     * @param which Nesting level of subexpression
-     * @return String index
-     */
-    public final int getParenStart(int which)
-    {
-        if (which < parenCount)
-        {
-            switch (which)
-            {
-                case 0:
-                    return start0;
-
-                case 1:
-                    return start1;
-
-                case 2:
-                    return start2;
-
-                default:
-                    if (startn == null)
-                    {
-                        allocParens();
-                    }
-                    return startn[which];
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Returns the end index of a given paren level.
-     *
-     * @param which Nesting level of subexpression
-     * @return String index
-     */
-    public final int getParenEnd(int which)
-    {
-        if (which < parenCount)
-        {
-            switch (which)
-            {
-                case 0:
-                    return end0;
-
-                case 1:
-                    return end1;
-
-                case 2:
-                    return end2;
-
-                default:
-                    if (endn == null)
-                    {
-                        allocParens();
-                    }
-                    return endn[which];
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Returns the length of a given paren level.
-     *
-     * @param which Nesting level of subexpression
-     * @return Number of characters in the parenthesized subexpression
-     */
-    public final int getParenLength(int which)
-    {
-        if (which < parenCount)
-        {
-            return getParenEnd(which) - getParenStart(which);
-        }
-        return -1;
-    }
-
-    /**
-     * Sets the start of a paren level
-     *
-     * @param which Which paren level
-     * @param i Index in input array
-     */
-    protected final void setParenStart(int which, int i)
-    {
-        if (which < parenCount)
-        {
-            switch (which)
-            {
-                case 0:
-                    start0 = i;
-                    break;
-
-                case 1:
-                    start1 = i;
-                    break;
-
-                case 2:
-                    start2 = i;
-                    break;
-
-                default:
-                    if (startn == null)
-                    {
-                        allocParens();
-                    }
-                    startn[which] = i;
-                    break;
-            }
-        }
-    }
-
-    /**
-     * Sets the end of a paren level
-     *
-     * @param which Which paren level
-     * @param i Index in input array
-     */
-    protected final void setParenEnd(int which, int i)
-    {
-        if (which < parenCount)
-        {
-            switch (which)
-            {
-                case 0:
-                    end0 = i;
-                    break;
-
-                case 1:
-                    end1 = i;
-                    break;
-
-                case 2:
-                    end2 = i;
-                    break;
-
-                default:
-                    if (endn == null)
-                    {
-                        allocParens();
-                    }
-                    endn[which] = i;
-                    break;
-            }
-        }
-    }
-
-    /**
-     * Throws an Error representing an internal error condition probably resulting
-     * from a bug in the regular expression compiler (or possibly data corruption).
-     * In practice, this should be very rare.
-     *
-     * @param s Error description
-     */
-    protected void internalError(String s) throws Error
-    {
-        throw new Error("RE internal error: " + s);
-    }
-
-    /**
-     * Performs lazy allocation of subexpression arrays
-     */
-    private final void allocParens()
-    {
-        // Allocate arrays for subexpressions
-        startn = new int[maxParen];
-        endn = new int[maxParen];
-
-        // Set sub-expression pointers to invalid values
-        for (int i = 0; i < maxParen; i++)
-        {
-            startn[i] = -1;
-            endn[i] = -1;
-        }
-    }
-
-    /**
-     * Try to match a string against a subset of nodes in the program
-     *
-     * @param firstNode Node to start at in program
-     * @param lastNode  Last valid node (used for matching a subexpression without
-     *                  matching the rest of the program as well).
-     * @param idxStart  Starting position in character array
-     * @return Final input array index if match succeeded.  -1 if not.
-     */
-    protected int matchNodes(int firstNode, int lastNode, int idxStart)
-    {
-        // Our current place in the string
-        int idx = idxStart;
-
-        // Loop while node is valid
-        int next, opcode, opdata;
-        int idxNew;
-        char[] instruction = program.instruction;
-        for (int node = firstNode; node < lastNode; )
-        {
-            opcode = instruction[node + offsetOpcode];
-            next   = node + (short)instruction[node + offsetNext];
-            opdata = instruction[node + offsetOpdata];
-
-            switch (opcode)
-            {
-                case OP_RELUCTANTMAYBE:
-                    {
-                        int once = 0;
-                        do
-                        {
-                            // Try to match the rest without using the reluctant subexpr
-                            if ((idxNew = matchNodes(next, maxNode, idx)) != -1)
-                            {
-                                return idxNew;
-                            }
-                        }
-                        while ((once++ == 0) && (idx = matchNodes(node + nodeSize, next, idx)) != -1);
-                        return -1;
-                    }
-
-                case OP_RELUCTANTPLUS:
-                    while ((idx = matchNodes(node + nodeSize, next, idx)) != -1)
-                    {
-                        // Try to match the rest without using the reluctant subexpr
-                        if ((idxNew = matchNodes(next, maxNode, idx)) != -1)
-                        {
-                            return idxNew;
-                        }
-                    }
-                    return -1;
-
-                case OP_RELUCTANTSTAR:
-                    do
-                    {
-                        // Try to match the rest without using the reluctant subexpr
-                        if ((idxNew = matchNodes(next, maxNode, idx)) != -1)
-                        {
-                            return idxNew;
-                        }
-                    }
-                    while ((idx = matchNodes(node + nodeSize, next, idx)) != -1);
-                    return -1;
-
-                case OP_OPEN:
-
-                    // Match subexpression
-                    if ((program.flags & REProgram.OPT_HASBACKREFS) != 0)
-                    {
-                        startBackref[opdata] = idx;
-                    }
-                    if ((idxNew = matchNodes(next, maxNode, idx)) != -1)
-                    {
-                        // Increase valid paren count
-                        if ((opdata + 1) > parenCount)
-                        {
-                            parenCount = opdata + 1;
-                        }
-
-                        // Don't set paren if already set later on
-                        if (getParenStart(opdata) == -1)
-                        {
-                            setParenStart(opdata, idx);
-                        }
-                    }
-                    return idxNew;
-
-                case OP_CLOSE:
-
-                    // Done matching subexpression
-                    if ((program.flags & REProgram.OPT_HASBACKREFS) != 0)
-                    {
-                        endBackref[opdata] = idx;
-                    }
-                    if ((idxNew = matchNodes(next, maxNode, idx)) != -1)
-                    {
-                        // Increase valid paren count
-                        if ((opdata + 1) > parenCount)
-                        {
-                            parenCount = opdata + 1;
-                        }
-
-                        // Don't set paren if already set later on
-                        if (getParenEnd(opdata) == -1)
-                        {
-                            setParenEnd(opdata, idx);
-                        }
-                    }
-                    return idxNew;
-
-                case OP_OPEN_CLUSTER:
-                case OP_CLOSE_CLUSTER:
-                    // starting or ending the matching of a subexpression which has no backref.
-                    return matchNodes( next, maxNode, idx );
-
-                case OP_BACKREF:
-                    {
-                        // Get the start and end of the backref
-                        int s = startBackref[opdata];
-                        int e = endBackref[opdata];
-
-                        // We don't know the backref yet
-                        if (s == -1 || e == -1)
-                        {
-                            return -1;
-                        }
-
-                        // The backref is empty size
-                        if (s == e)
-                        {
-                            break;
-                        }
-
-                        // Get the length of the backref
-                        int l = e - s;
-
-                        // If there's not enough input left, give up.
-                        if (search.isEnd(idx + l - 1))
-                        {
-                            return -1;
-                        }
-
-                        // Case fold the backref?
-                        final boolean caseFold =
-                            ((matchFlags & MATCH_CASEINDEPENDENT) != 0);
-                        // Compare backref to input
-                        for (int i = 0; i < l; i++)
-                        {
-                            if (compareChars(search.charAt(idx++), search.charAt(s + i), caseFold) != 0)
-                            {
-                                return -1;
-                            }
-                        }
-                    }
-                    break;
-
-                case OP_BOL:
-
-                    // Fail if we're not at the start of the string
-                    if (idx != 0)
-                    {
-                        // If we're multiline matching, we could still be at the start of a line
-                        if ((matchFlags & MATCH_MULTILINE) == MATCH_MULTILINE)
-                        {
-                            // If not at start of line, give up
-                            if (idx <= 0 || !isNewline(idx - 1)) {
-                                return -1;
-                            } else {
-                                break;
-                            }
-                        }
-                        return -1;
-                    }
-                    break;
-
-                case OP_EOL:
-
-                    // If we're not at the end of string
-                    if (!search.isEnd(0) && !search.isEnd(idx))
-                    {
-                        // If we're multi-line matching
-                        if ((matchFlags & MATCH_MULTILINE) == MATCH_MULTILINE)
-                        {
-                            // Give up if we're not at the end of a line
-                            if (!isNewline(idx)) {
-                                return -1;
-                            } else {
-                                break;
-                            }
-                        }
-                        return -1;
-                    }
-                    break;
-
-                case OP_ESCAPE:
-
-                    // Which escape?
-                    switch (opdata)
-                    {
-                        // Word boundary match
-                        case E_NBOUND:
-                        case E_BOUND:
-                            {
-                                char cLast = ((idx == 0) ? '\n' : search.charAt(idx - 1));
-                                char cNext = ((search.isEnd(idx)) ? '\n' : search.charAt(idx));
-                                if ((Character.isLetterOrDigit(cLast) == Character.isLetterOrDigit(cNext)) == (opdata == E_BOUND))
-                                {
-                                    return -1;
-                                }
-                            }
-                            break;
-
-                        // Alpha-numeric, digit, space, javaLetter, javaLetterOrDigit
-                        case E_ALNUM:
-                        case E_NALNUM:
-                        case E_DIGIT:
-                        case E_NDIGIT:
-                        case E_SPACE:
-                        case E_NSPACE:
-
-                            // Give up if out of input
-                            if (search.isEnd(idx))
-                            {
-                                return -1;
-                            }
-
-                            char c = search.charAt(idx);
-
-                            // Switch on escape
-                            switch (opdata)
-                            {
-                                case E_ALNUM:
-                                case E_NALNUM:
-                                    if (!((Character.isLetterOrDigit(c) || c == '_') == (opdata == E_ALNUM)))
-                                    {
-                                        return -1;
-                                    }
-                                    break;
-
-                                case E_DIGIT:
-                                case E_NDIGIT:
-                                    if (!(Character.isDigit(c) == (opdata == E_DIGIT)))
-                                    {
-                                        return -1;
-                                    }
-                                    break;
-
-                                case E_SPACE:
-                                case E_NSPACE:
-                                    if (!(Character.isWhitespace(c) == (opdata == E_SPACE)))
-                                    {
-                                        return -1;
-                                    }
-                                    break;
-                            }
-                            idx++;
-                            break;
-
-                        default:
-                            internalError("Unrecognized escape '" + opdata + "'");
-                    }
-                    break;
-
-                case OP_ANY:
-
-                    if ((matchFlags & MATCH_SINGLELINE) == MATCH_SINGLELINE) {
-                        // Match anything
-                        if (search.isEnd(idx))
-                        {
-                            return -1;
-                        }
-                    }
-                    else
-                    {
-                        // Match anything but a newline
-                        if (search.isEnd(idx) || isNewline(idx))
-                        {
-                            return -1;
-                        }
-                    }
-                    idx++;
-                    break;
-
-                case OP_ATOM:
-                    {
-                        // Match an atom value
-                        if (search.isEnd(idx))
-                        {
-                            return -1;
-                        }
-
-                        // Get length of atom and starting index
-                        int lenAtom = opdata;
-                        int startAtom = node + nodeSize;
-
-                        // Give up if not enough input remains to have a match
-                        if (search.isEnd(lenAtom + idx - 1))
-                        {
-                            return -1;
-                        }
-
-                        // Match atom differently depending on casefolding flag
-                        final boolean caseFold =
-                            ((matchFlags & MATCH_CASEINDEPENDENT) != 0);
-
-                        for (int i = 0; i < lenAtom; i++)
-                        {
-                            if (compareChars(search.charAt(idx++), instruction[startAtom + i], caseFold) != 0)
-                            {
-                                return -1;
-                            }
-                        }
-                    }
-                    break;
-
-                case OP_POSIXCLASS:
-                    {
-                        // Out of input?
-                        if (search.isEnd(idx))
-                        {
-                            return -1;
-                        }
-
-                        switch (opdata)
-                        {
-                            case POSIX_CLASS_ALNUM:
-                                if (!Character.isLetterOrDigit(search.charAt(idx)))
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_ALPHA:
-                                if (!Character.isLetter(search.charAt(idx)))
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_DIGIT:
-                                if (!Character.isDigit(search.charAt(idx)))
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_BLANK: // JWL - bugbug: is this right??
-                                if (!Character.isSpaceChar(search.charAt(idx)))
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_SPACE:
-                                if (!Character.isWhitespace(search.charAt(idx)))
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_CNTRL:
-                                if (Character.getType(search.charAt(idx)) != Character.CONTROL)
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_GRAPH: // JWL - bugbug???
-                                switch (Character.getType(search.charAt(idx)))
-                                {
-                                    case Character.MATH_SYMBOL:
-                                    case Character.CURRENCY_SYMBOL:
-                                    case Character.MODIFIER_SYMBOL:
-                                    case Character.OTHER_SYMBOL:
-                                        break;
-
-                                    default:
-                                        return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_LOWER:
-                                if (Character.getType(search.charAt(idx)) != Character.LOWERCASE_LETTER)
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_UPPER:
-                                if (Character.getType(search.charAt(idx)) != Character.UPPERCASE_LETTER)
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_PRINT:
-                                if (Character.getType(search.charAt(idx)) == Character.CONTROL)
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_PUNCT:
-                            {
-                                int type = Character.getType(search.charAt(idx));
-                                switch(type)
-                                {
-                                    case Character.DASH_PUNCTUATION:
-                                    case Character.START_PUNCTUATION:
-                                    case Character.END_PUNCTUATION:
-                                    case Character.CONNECTOR_PUNCTUATION:
-                                    case Character.OTHER_PUNCTUATION:
-                                        break;
-
-                                    default:
-                                        return -1;
-                                }
-                            }
-                            break;
-
-                            case POSIX_CLASS_XDIGIT: // JWL - bugbug??
-                            {
-                                boolean isXDigit = ((search.charAt(idx) >= '0' && search.charAt(idx) <= '9') ||
-                                                    (search.charAt(idx) >= 'a' && search.charAt(idx) <= 'f') ||
-                                                    (search.charAt(idx) >= 'A' && search.charAt(idx) <= 'F'));
-                                if (!isXDigit)
-                                {
-                                    return -1;
-                                }
-                            }
-                            break;
-
-                            case POSIX_CLASS_JSTART:
-                                if (!Character.isJavaIdentifierStart(search.charAt(idx)))
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            case POSIX_CLASS_JPART:
-                                if (!Character.isJavaIdentifierPart(search.charAt(idx)))
-                                {
-                                    return -1;
-                                }
-                                break;
-
-                            default:
-                                internalError("Bad posix class");
-                                break;
-                        }
-
-                        // Matched.
-                        idx++;
-                    }
-                    break;
-
-                case OP_ANYOF:
-                    {
-                        // Out of input?
-                        if (search.isEnd(idx))
-                        {
-                            return -1;
-                        }
-
-                        // Get character to match against character class and maybe casefold
-                        char c = search.charAt(idx);
-                        boolean caseFold = (matchFlags & MATCH_CASEINDEPENDENT) != 0;
-                        // Loop through character class checking our match character
-                        int idxRange = node + nodeSize;
-                        int idxEnd = idxRange + (opdata * 2);
-                        boolean match = false;
-                        for (int i = idxRange; !match && i < idxEnd; )
-                        {
-                            // Get start, end and match characters
-                            char s = instruction[i++];
-                            char e = instruction[i++];
-
-                            match = ((compareChars(c, s, caseFold) >= 0)
-                                     && (compareChars(c, e, caseFold) <= 0));
-                        }
-
-                        // Fail if we didn't match the character class
-                        if (!match)
-                        {
-                            return -1;
-                        }
-                        idx++;
-                    }
-                    break;
-
-                case OP_BRANCH:
-                {
-                    // Check for choices
-                    if (instruction[next + offsetOpcode] != OP_BRANCH)
-                    {
-                        // If there aren't any other choices, just evaluate this branch.
-                        node += nodeSize;
-                        continue;
-                    }
-
-                    // Try all available branches
-                    short nextBranch;
-                    do
-                    {
-                        // Try matching the branch against the string
-                        if ((idxNew = matchNodes(node + nodeSize, maxNode, idx)) != -1)
-                        {
-                            return idxNew;
-                        }
-
-                        // Go to next branch (if any)
-                        nextBranch = (short)instruction[node + offsetNext];
-                        node += nextBranch;
-                    }
-                    while (nextBranch != 0 && (instruction[node + offsetOpcode] == OP_BRANCH));
-
-                    // Failed to match any branch!
-                    return -1;
-                }
-
-                case OP_NOTHING:
-                case OP_GOTO:
-
-                    // Just advance to the next node without doing anything
-                    break;
-
-                case OP_END:
-
-                    // Match has succeeded!
-                    setParenEnd(0, idx);
-                    return idx;
-
-                default:
-
-                    // Corrupt program
-                    internalError("Invalid opcode '" + opcode + "'");
-            }
-
-            // Advance to the next node in the program
-            node = next;
-        }
-
-        // We "should" never end up here
-        internalError("Corrupt program");
-        return -1;
-    }
-
-    /**
-     * Match the current regular expression program against the current
-     * input string, starting at index i of the input string.  This method
-     * is only meant for internal use.
-     *
-     * @param i The input string index to start matching at
-     * @return True if the input matched the expression
-     */
-    protected boolean matchAt(int i)
-    {
-        // Initialize start pointer, paren cache and paren count
-        start0 = -1;
-        end0   = -1;
-        start1 = -1;
-        end1   = -1;
-        start2 = -1;
-        end2   = -1;
-        startn = null;
-        endn   = null;
-        parenCount = 1;
-        setParenStart(0, i);
-
-        // Allocate backref arrays (unless optimizations indicate otherwise)
-        if ((program.flags & REProgram.OPT_HASBACKREFS) != 0)
-        {
-            startBackref = new int[maxParen];
-            endBackref = new int[maxParen];
-        }
-
-        // Match against string
-        int idx;
-        if ((idx = matchNodes(0, maxNode, i)) != -1)
-        {
-            setParenEnd(0, idx);
-            return true;
-        }
-
-        // Didn't match
-        parenCount = 0;
-        return false;
-    }
-
-    /**
-     * Matches the current regular expression program against a character array,
-     * starting at a given index.
-     *
-     * @param search String to match against
-     * @param i Index to start searching at
-     * @return True if string matched
-     */
-    public boolean match(String search, int i)
-    {
-        return match(new StringCharacterIterator(search), i);
-    }
-
-    /**
-     * Matches the current regular expression program against a character array,
-     * starting at a given index.
-     *
-     * @param search String to match against
-     * @param i Index to start searching at
-     * @return True if string matched
-     */
-    public boolean match(CharacterIterator search, int i)
-    {
-        // There is no compiled program to search with!
-        if (program == null)
-        {
-            // This should be uncommon enough to be an error case rather
-            // than an exception (which would have to be handled everywhere)
-            internalError("No RE program to run!");
-        }
-
-        // Save string to search
-        this.search = search;
-
-        // Can we optimize the search by looking for a prefix string?
-        if (program.prefix == null)
-        {
-            // Unprefixed matching must try for a match at each character
-            for ( ;! search.isEnd(i - 1); i++)
-            {
-                // Try a match at index i
-                if (matchAt(i))
-                {
-                    return true;
-                }
-            }
-            return false;
-        }
-        else
-        {
-            // Prefix-anchored matching is possible
-            boolean caseIndependent = (matchFlags & MATCH_CASEINDEPENDENT) != 0;
-            char[] prefix = program.prefix;
-            for ( ; !search.isEnd(i + prefix.length - 1); i++)
-            {
-                int j = i;
-                int k = 0;
-
-                boolean match;
-                do {
-                    // If there's a mismatch of any character in the prefix, give up
-                    match = (compareChars(search.charAt(j++), prefix[k++], caseIndependent) == 0);
-                } while (match && k < prefix.length);
-
-                // See if the whole prefix string matched
-                if (k == prefix.length)
-                {
-                    // We matched the full prefix at firstChar, so try it
-                    if (matchAt(i))
-                    {
-                        return true;
-                    }
-                }
-            }
-            return false;
-        }
-    }
-
-    /**
-     * Matches the current regular expression program against a String.
-     *
-     * @param search String to match against
-     * @return True if string matched
-     */
-    public boolean match(String search)
-    {
-        return match(search, 0);
-    }
-
-    /**
-     * Splits a string into an array of strings on regular expression boundaries.
-     * This function works the same way as the Perl function of the same name.
-     * Given a regular expression of "[ab]+" and a string to split of
-     * "xyzzyababbayyzabbbab123", the result would be the array of Strings
-     * "[xyzzy, yyz, 123]".
-     *
-     * <p>Please note that the first string in the resulting array may be an empty
-     * string. This happens when the very first character of input string is
-     * matched by the pattern.
-     *
-     * @param s String to split on this regular exression
-     * @return Array of strings
-     */
-    public String[] split(String s)
-    {
-        // Create new vector
-        Vector v = new Vector();
-
-        // Start at position 0 and search the whole string
-        int pos = 0;
-        int len = s.length();
-
-        // Try a match at each position
-        while (pos < len && match(s, pos))
-        {
-            // Get start of match
-            int start = getParenStart(0);
-
-            // Get end of match
-            int newpos = getParenEnd(0);
-
-            // Check if no progress was made
-            if (newpos == pos)
-            {
-                v.addElement(s.substring(pos, start + 1));
-                newpos++;
-            }
-            else
-            {
-                v.addElement(s.substring(pos, start));
-            }
-
-            // Move to new position
-            pos = newpos;
-        }
-
-        // Push remainder if it's not empty
-        String remainder = s.substring(pos);
-        if (remainder.length() != 0)
-        {
-            v.addElement(remainder);
-        }
-
-        // Return vector as an array of strings
-        String[] ret = new String[v.size()];
-        v.copyInto(ret);
-        return ret;
-    }
-
-    /**
-     * Flag bit that indicates that subst should replace all occurrences of this
-     * regular expression.
-     */
-    public static final int REPLACE_ALL            = 0x0000;
-
-    /**
-     * Flag bit that indicates that subst should only replace the first occurrence
-     * of this regular expression.
-     */
-    public static final int REPLACE_FIRSTONLY      = 0x0001;
-
-    /**
-     * Flag bit that indicates that subst should replace backreferences
-     */
-    public static final int REPLACE_BACKREFERENCES = 0x0002;
-
-    /**
-     * Substitutes a string for this regular expression in another string.
-     * This method works like the Perl function of the same name.
-     * Given a regular expression of "a*b", a String to substituteIn of
-     * "aaaabfooaaabgarplyaaabwackyb" and the substitution String "-", the
-     * resulting String returned by subst would be "-foo-garply-wacky-".
-     *
-     * @param substituteIn String to substitute within
-     * @param substitution String to substitute for all matches of this regular expression.
-     * @return The string substituteIn with zero or more occurrences of the current
-     * regular expression replaced with the substitution String (if this regular
-     * expression object doesn't match at any position, the original String is returned
-     * unchanged).
-     */
-    public String subst(String substituteIn, String substitution)
-    {
-        return subst(substituteIn, substitution, REPLACE_ALL);
-    }
-
-    /**
-     * Substitutes a string for this regular expression in another string.
-     * This method works like the Perl function of the same name.
-     * Given a regular expression of "a*b", a String to substituteIn of
-     * "aaaabfooaaabgarplyaaabwackyb" and the substitution String "-", the
-     * resulting String returned by subst would be "-foo-garply-wacky-".
-     * <p>
-     * It is also possible to reference the contents of a parenthesized expression
-     * with $0, $1, ... $9. A regular expression of "http://[\\.\\w\\-\\?/~_@&=%]+",
-     * a String to substituteIn of "visit us: http://www.apache.org!" and the
-     * substitution String "&lt;a href=\"$0\"&gt;$0&lt;/a&gt;", the resulting String
-     * returned by subst would be
-     * "visit us: &lt;a href=\"http://www.apache.org\"&gt;http://www.apache.org&lt;/a&gt;!".
-     * <p>
-     * <i>Note:</i> $0 represents the whole match.
-     *
-     * @param substituteIn String to substitute within
-     * @param substitution String to substitute for matches of this regular expression
-     * @param flags One or more bitwise flags from REPLACE_*.  If the REPLACE_FIRSTONLY
-     * flag bit is set, only the first occurrence of this regular expression is replaced.
-     * If the bit is not set (REPLACE_ALL), all occurrences of this pattern will be
-     * replaced. If the flag REPLACE_BACKREFERENCES is set, all backreferences will
-     * be processed.
-     * @return The string substituteIn with zero or more occurrences of the current
-     * regular expression replaced with the substitution String (if this regular
-     * expression object doesn't match at any position, the original String is returned
-     * unchanged).
-     */
-    public String subst(String substituteIn, String substitution, int flags)
-    {
-        // String to return
-        StringBuffer ret = new StringBuffer();
-
-        // Start at position 0 and search the whole string
-        int pos = 0;
-        int len = substituteIn.length();
-
-        // Try a match at each position
-        while (pos < len && match(substituteIn, pos))
-        {
-            // Append string before match
-            ret.append(substituteIn.substring(pos, getParenStart(0)));
-
-            if ((flags & REPLACE_BACKREFERENCES) != 0)
-            {
-                // Process backreferences
-                int lCurrentPosition = 0;
-                int lLastPosition = -2;
-                int lLength = substitution.length();
-                boolean bAddedPrefix = false;
-
-                while ((lCurrentPosition = substitution.indexOf("$", lCurrentPosition)) >= 0)
-                {
-                    if ((lCurrentPosition == 0 || substitution.charAt(lCurrentPosition - 1) != '\\')
-                        && lCurrentPosition+1 < lLength)
-                    {
-                        char c = substitution.charAt(lCurrentPosition + 1);
-                        if (c >= '0' && c <= '9')
-                        {
-                            if (bAddedPrefix == false)
-                            {
-                                // Append everything between the beginning of the
-                                // substitution string and the current $ sign
-                                ret.append(substitution.substring(0, lCurrentPosition));
-                                bAddedPrefix = true;
-                            }
-                            else
-                            {
-                                // Append everything between the last and the current $ sign
-                                ret.append(substitution.substring(lLastPosition + 2, lCurrentPosition));
-                            }
-
-                            // Append the parenthesized expression
-                            // Note: if a parenthesized expression of the requested
-                            // index is not available "null" is added to the string
-                            ret.append(getParen(c - '0'));
-                            lLastPosition = lCurrentPosition;
-                        }
-                    }
-
-                    // Move forward, skipping past match
-                    lCurrentPosition++;
-                }
-
-                // Append everything after the last $ sign
-                ret.append(substitution.substring(lLastPosition + 2, lLength));
-            }
-            else
-            {
-                // Append substitution without processing backreferences
-                ret.append(substitution);
-            }
-
-            // Move forward, skipping past match
-            int newpos = getParenEnd(0);
-
-            // We always want to make progress!
-            if (newpos == pos)
-            {
-                newpos++;
-            }
-
-            // Try new position
-            pos = newpos;
-
-            // Break out if we're only supposed to replace one occurrence
-            if ((flags & REPLACE_FIRSTONLY) != 0)
-            {
-                break;
-            }
-        }
-
-        // If there's remaining input, append it
-        if (pos < len)
-        {
-            ret.append(substituteIn.substring(pos));
-        }
-
-        // Return string buffer as string
-        return ret.toString();
-    }
-
-    /**
-     * Returns an array of Strings, whose toString representation matches a regular
-     * expression. This method works like the Perl function of the same name.  Given
-     * a regular expression of "a*b" and an array of String objects of [foo, aab, zzz,
-     * aaaab], the array of Strings returned by grep would be [aab, aaaab].
-     *
-     * @param search Array of Objects to search
-     * @return Array of Strings whose toString() value matches this regular expression.
-     */
-    public String[] grep(Object[] search)
-    {
-        // Create new vector to hold return items
-        Vector v = new Vector();
-
-        // Traverse array of objects
-        for (int i = 0; i < search.length; i++)
-        {
-            // Get next object as a string
-            String s = search[i].toString();
-
-            // If it matches this regexp, add it to the list
-            if (match(s))
-            {
-                v.addElement(s);
-            }
-        }
-
-        // Return vector as an array of strings
-        String[] ret = new String[v.size()];
-        v.copyInto(ret);
-        return ret;
-    }
-
-    /**
-     * @return true if character at i-th position in the <code>search</code> string is a newline
-     */
-    private boolean isNewline(int i)
-    {
-        char nextChar = search.charAt(i);
-
-        if (nextChar == '\n' || nextChar == '\r' || nextChar == '\u0085'
-            || nextChar == '\u2028' || nextChar == '\u2029')
-        {
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Compares two characters.
-     *
-     * @param c1 first character to compare.
-     * @param c2 second character to compare.
-     * @param caseIndependent whether comparision is case insensitive or not.
-     * @return negative, 0, or positive integer as the first character
-     *         less than, equal to, or greater then the second.
-     */
-    private int compareChars(char c1, char c2, boolean caseIndependent)
-    {
-        if (caseIndependent)
-        {
-            c1 = Character.toLowerCase(c1);
-            c2 = Character.toLowerCase(c2);
-        }
-        return ((int)c1 - (int)c2);
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RECompiler.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RECompiler.java
deleted file mode 100644
index 23874ee8da0..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RECompiler.java
+++ /dev/null
@@ -1,1520 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-import com.sun.org.apache.regexp.internal.RE;
-import java.util.Hashtable;
-
-/**
- * A regular expression compiler class.  This class compiles a pattern string into a
- * regular expression program interpretable by the RE evaluator class.  The 'recompile'
- * command line tool uses this compiler to pre-compile regular expressions for use
- * with RE.  For a description of the syntax accepted by RECompiler and what you can
- * do with regular expressions, see the documentation for the RE matcher class.
- *
- * @see RE
- * @see recompile
- *
- * @author <a href="mailto:jonl@muppetlabs.com">Jonathan Locke</a>
- * @author <a href="mailto:gholam@xtra.co.nz">Michael McCallum</a>
- */
-public class RECompiler
-{
-    // The compiled program
-    char[] instruction;                                 // The compiled RE 'program' instruction buffer
-    int lenInstruction;                                 // The amount of the program buffer currently in use
-
-    // Input state for compiling regular expression
-    String pattern;                                     // Input string
-    int len;                                            // Length of the pattern string
-    int idx;                                            // Current input index into ac
-    int parens;                                         // Total number of paren pairs
-
-    // Node flags
-    static final int NODE_NORMAL   = 0;                 // No flags (nothing special)
-    static final int NODE_NULLABLE = 1;                 // True if node is potentially null
-    static final int NODE_TOPLEVEL = 2;                 // True if top level expr
-
-    // Special types of 'escapes'
-    static final int ESC_MASK      = 0xffff0;           // Escape complexity mask
-    static final int ESC_BACKREF   = 0xfffff;           // Escape is really a backreference
-    static final int ESC_COMPLEX   = 0xffffe;           // Escape isn't really a true character
-    static final int ESC_CLASS     = 0xffffd;           // Escape represents a whole class of characters
-
-    // {m,n} stacks
-    int maxBrackets = 10;                               // Maximum number of bracket pairs
-    static final int bracketUnbounded = -1;             // Unbounded value
-    int brackets = 0;                                   // Number of bracket sets
-    int[] bracketStart = null;                          // Starting point
-    int[] bracketEnd = null;                            // Ending point
-    int[] bracketMin = null;                            // Minimum number of matches
-    int[] bracketOpt = null;                            // Additional optional matches
-
-    // Lookup table for POSIX character class names
-    static Hashtable hashPOSIX = new Hashtable();
-    static
-    {
-        hashPOSIX.put("alnum",     new Character(RE.POSIX_CLASS_ALNUM));
-        hashPOSIX.put("alpha",     new Character(RE.POSIX_CLASS_ALPHA));
-        hashPOSIX.put("blank",     new Character(RE.POSIX_CLASS_BLANK));
-        hashPOSIX.put("cntrl",     new Character(RE.POSIX_CLASS_CNTRL));
-        hashPOSIX.put("digit",     new Character(RE.POSIX_CLASS_DIGIT));
-        hashPOSIX.put("graph",     new Character(RE.POSIX_CLASS_GRAPH));
-        hashPOSIX.put("lower",     new Character(RE.POSIX_CLASS_LOWER));
-        hashPOSIX.put("print",     new Character(RE.POSIX_CLASS_PRINT));
-        hashPOSIX.put("punct",     new Character(RE.POSIX_CLASS_PUNCT));
-        hashPOSIX.put("space",     new Character(RE.POSIX_CLASS_SPACE));
-        hashPOSIX.put("upper",     new Character(RE.POSIX_CLASS_UPPER));
-        hashPOSIX.put("xdigit",    new Character(RE.POSIX_CLASS_XDIGIT));
-        hashPOSIX.put("javastart", new Character(RE.POSIX_CLASS_JSTART));
-        hashPOSIX.put("javapart",  new Character(RE.POSIX_CLASS_JPART));
-    }
-
-    /**
-     * Constructor.  Creates (initially empty) storage for a regular expression program.
-     */
-    public RECompiler()
-    {
-        // Start off with a generous, yet reasonable, initial size
-        instruction = new char[128];
-        lenInstruction = 0;
-    }
-
-    /**
-     * Ensures that n more characters can fit in the program buffer.
-     * If n more can't fit, then the size is doubled until it can.
-     * @param n Number of additional characters to ensure will fit.
-     */
-    void ensure(int n)
-    {
-        // Get current program length
-        int curlen = instruction.length;
-
-        // If the current length + n more is too much
-        if (lenInstruction + n >= curlen)
-        {
-            // Double the size of the program array until n more will fit
-            while (lenInstruction + n >= curlen)
-            {
-                curlen *= 2;
-            }
-
-            // Allocate new program array and move data into it
-            char[] newInstruction = new char[curlen];
-            System.arraycopy(instruction, 0, newInstruction, 0, lenInstruction);
-            instruction = newInstruction;
-        }
-    }
-
-    /**
-     * Emit a single character into the program stream.
-     * @param c Character to add
-     */
-    void emit(char c)
-    {
-        // Make room for character
-        ensure(1);
-
-        // Add character
-        instruction[lenInstruction++] = c;
-    }
-
-    /**
-     * Inserts a node with a given opcode and opdata at insertAt.  The node relative next
-     * pointer is initialized to 0.
-     * @param opcode Opcode for new node
-     * @param opdata Opdata for new node (only the low 16 bits are currently used)
-     * @param insertAt Index at which to insert the new node in the program
-     */
-    void nodeInsert(char opcode, int opdata, int insertAt)
-    {
-        // Make room for a new node
-        ensure(RE.nodeSize);
-
-        // Move everything from insertAt to the end down nodeSize elements
-        System.arraycopy(instruction, insertAt, instruction, insertAt + RE.nodeSize, lenInstruction - insertAt);
-        instruction[insertAt + RE.offsetOpcode] = opcode;
-        instruction[insertAt + RE.offsetOpdata] = (char)opdata;
-        instruction[insertAt + RE.offsetNext] = 0;
-        lenInstruction += RE.nodeSize;
-    }
-
-    /**
-     * Appends a node to the end of a node chain
-     * @param node Start of node chain to traverse
-     * @param pointTo Node to have the tail of the chain point to
-     */
-    void setNextOfEnd(int node, int pointTo)
-    {
-        // Traverse the chain until the next offset is 0
-        int next = instruction[node + RE.offsetNext];
-        // while the 'node' is not the last in the chain
-        // and the 'node' is not the last in the program.
-        while ( next != 0 && node < lenInstruction )
-        {
-            // if the node we are supposed to point to is in the chain then
-            // point to the end of the program instead.
-            // Michael McCallum <gholam@xtra.co.nz>
-            // FIXME: // This is a _hack_ to stop infinite programs.
-            // I believe that the implementation of the reluctant matches is wrong but
-            // have not worked out a better way yet.
-            if ( node == pointTo ) {
-              pointTo = lenInstruction;
-            }
-            node += next;
-            next = instruction[node + RE.offsetNext];
-        }
-        // if we have reached the end of the program then dont set the pointTo.
-        // im not sure if this will break any thing but passes all the tests.
-        if ( node < lenInstruction ) {
-            // Point the last node in the chain to pointTo.
-            instruction[node + RE.offsetNext] = (char)(short)(pointTo - node);
-        }
-    }
-
-    /**
-     * Adds a new node
-     * @param opcode Opcode for node
-     * @param opdata Opdata for node (only the low 16 bits are currently used)
-     * @return Index of new node in program
-     */
-    int node(char opcode, int opdata)
-    {
-        // Make room for a new node
-        ensure(RE.nodeSize);
-
-        // Add new node at end
-        instruction[lenInstruction + RE.offsetOpcode] = opcode;
-        instruction[lenInstruction + RE.offsetOpdata] = (char)opdata;
-        instruction[lenInstruction + RE.offsetNext] = 0;
-        lenInstruction += RE.nodeSize;
-
-        // Return index of new node
-        return lenInstruction - RE.nodeSize;
-    }
-
-
-    /**
-     * Throws a new internal error exception
-     * @exception Error Thrown in the event of an internal error.
-     */
-    void internalError() throws Error
-    {
-        throw new Error("Internal error!");
-    }
-
-    /**
-     * Throws a new syntax error exception
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     */
-    void syntaxError(String s) throws RESyntaxException
-    {
-        throw new RESyntaxException(s);
-    }
-
-    /**
-     * Allocate storage for brackets only as needed
-     */
-    void allocBrackets()
-    {
-        // Allocate bracket stacks if not already done
-        if (bracketStart == null)
-        {
-            // Allocate storage
-            bracketStart = new int[maxBrackets];
-            bracketEnd   = new int[maxBrackets];
-            bracketMin   = new int[maxBrackets];
-            bracketOpt   = new int[maxBrackets];
-
-            // Initialize to invalid values
-            for (int i = 0; i < maxBrackets; i++)
-            {
-                bracketStart[i] = bracketEnd[i] = bracketMin[i] = bracketOpt[i] = -1;
-            }
-        }
-    }
-
-    /** Enlarge storage for brackets only as needed. */
-    synchronized void reallocBrackets() {
-        // trick the tricky
-        if (bracketStart == null) {
-            allocBrackets();
-        }
-
-        int new_size = maxBrackets * 2;
-        int[] new_bS = new int[new_size];
-        int[] new_bE = new int[new_size];
-        int[] new_bM = new int[new_size];
-        int[] new_bO = new int[new_size];
-        // Initialize to invalid values
-        for (int i=brackets; i<new_size; i++) {
-            new_bS[i] = new_bE[i] = new_bM[i] = new_bO[i] = -1;
-        }
-        System.arraycopy(bracketStart,0, new_bS,0, brackets);
-        System.arraycopy(bracketEnd,0,   new_bE,0, brackets);
-        System.arraycopy(bracketMin,0,   new_bM,0, brackets);
-        System.arraycopy(bracketOpt,0,   new_bO,0, brackets);
-        bracketStart = new_bS;
-        bracketEnd   = new_bE;
-        bracketMin   = new_bM;
-        bracketOpt   = new_bO;
-        maxBrackets  = new_size;
-    }
-
-    /**
-     * Match bracket {m,n} expression put results in bracket member variables
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     */
-    void bracket() throws RESyntaxException
-    {
-        // Current character must be a '{'
-        if (idx >= len || pattern.charAt(idx++) != '{')
-        {
-            internalError();
-        }
-
-        // Next char must be a digit
-        if (idx >= len || !Character.isDigit(pattern.charAt(idx)))
-        {
-            syntaxError("Expected digit");
-        }
-
-        // Get min ('m' of {m,n}) number
-        StringBuffer number = new StringBuffer();
-        while (idx < len && Character.isDigit(pattern.charAt(idx)))
-        {
-            number.append(pattern.charAt(idx++));
-        }
-        try
-        {
-            bracketMin[brackets] = Integer.parseInt(number.toString());
-        }
-        catch (NumberFormatException e)
-        {
-            syntaxError("Expected valid number");
-        }
-
-        // If out of input, fail
-        if (idx >= len)
-        {
-            syntaxError("Expected comma or right bracket");
-        }
-
-        // If end of expr, optional limit is 0
-        if (pattern.charAt(idx) == '}')
-        {
-            idx++;
-            bracketOpt[brackets] = 0;
-            return;
-        }
-
-        // Must have at least {m,} and maybe {m,n}.
-        if (idx >= len || pattern.charAt(idx++) != ',')
-        {
-            syntaxError("Expected comma");
-        }
-
-        // If out of input, fail
-        if (idx >= len)
-        {
-            syntaxError("Expected comma or right bracket");
-        }
-
-        // If {m,} max is unlimited
-        if (pattern.charAt(idx) == '}')
-        {
-            idx++;
-            bracketOpt[brackets] = bracketUnbounded;
-            return;
-        }
-
-        // Next char must be a digit
-        if (idx >= len || !Character.isDigit(pattern.charAt(idx)))
-        {
-            syntaxError("Expected digit");
-        }
-
-        // Get max number
-        number.setLength(0);
-        while (idx < len && Character.isDigit(pattern.charAt(idx)))
-        {
-            number.append(pattern.charAt(idx++));
-        }
-        try
-        {
-            bracketOpt[brackets] = Integer.parseInt(number.toString()) - bracketMin[brackets];
-        }
-        catch (NumberFormatException e)
-        {
-            syntaxError("Expected valid number");
-        }
-
-        // Optional repetitions must be >= 0
-        if (bracketOpt[brackets] < 0)
-        {
-            syntaxError("Bad range");
-        }
-
-        // Must have close brace
-        if (idx >= len || pattern.charAt(idx++) != '}')
-        {
-            syntaxError("Missing close brace");
-        }
-    }
-
-    /**
-     * Match an escape sequence.  Handles quoted chars and octal escapes as well
-     * as normal escape characters.  Always advances the input stream by the
-     * right amount. This code "understands" the subtle difference between an
-     * octal escape and a backref.  You can access the type of ESC_CLASS or
-     * ESC_COMPLEX or ESC_BACKREF by looking at pattern[idx - 1].
-     * @return ESC_* code or character if simple escape
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     */
-    int escape() throws RESyntaxException
-    {
-        // "Shouldn't" happen
-        if (pattern.charAt(idx) != '\\')
-        {
-            internalError();
-        }
-
-        // Escape shouldn't occur as last character in string!
-        if (idx + 1 == len)
-        {
-            syntaxError("Escape terminates string");
-        }
-
-        // Switch on character after backslash
-        idx += 2;
-        char escapeChar = pattern.charAt(idx - 1);
-        switch (escapeChar)
-        {
-            case RE.E_BOUND:
-            case RE.E_NBOUND:
-                return ESC_COMPLEX;
-
-            case RE.E_ALNUM:
-            case RE.E_NALNUM:
-            case RE.E_SPACE:
-            case RE.E_NSPACE:
-            case RE.E_DIGIT:
-            case RE.E_NDIGIT:
-                return ESC_CLASS;
-
-            case 'u':
-            case 'x':
-                {
-                    // Exact required hex digits for escape type
-                    int hexDigits = (escapeChar == 'u' ? 4 : 2);
-
-                    // Parse up to hexDigits characters from input
-                    int val = 0;
-                    for ( ; idx < len && hexDigits-- > 0; idx++)
-                    {
-                        // Get char
-                        char c = pattern.charAt(idx);
-
-                        // If it's a hexadecimal digit (0-9)
-                        if (c >= '0' && c <= '9')
-                        {
-                            // Compute new value
-                            val = (val << 4) + c - '0';
-                        }
-                        else
-                        {
-                            // If it's a hexadecimal letter (a-f)
-                            c = Character.toLowerCase(c);
-                            if (c >= 'a' && c <= 'f')
-                            {
-                                // Compute new value
-                                val = (val << 4) + (c - 'a') + 10;
-                            }
-                            else
-                            {
-                                // If it's not a valid digit or hex letter, the escape must be invalid
-                                // because hexDigits of input have not been absorbed yet.
-                                syntaxError("Expected " + hexDigits + " hexadecimal digits after \\" + escapeChar);
-                            }
-                        }
-                    }
-                    return val;
-                }
-
-            case 't':
-                return '\t';
-
-            case 'n':
-                return '\n';
-
-            case 'r':
-                return '\r';
-
-            case 'f':
-                return '\f';
-
-            case '0':
-            case '1':
-            case '2':
-            case '3':
-            case '4':
-            case '5':
-            case '6':
-            case '7':
-            case '8':
-            case '9':
-
-                // An octal escape starts with a 0 or has two digits in a row
-                if ((idx < len && Character.isDigit(pattern.charAt(idx))) || escapeChar == '0')
-                {
-                    // Handle \nnn octal escapes
-                    int val = escapeChar - '0';
-                    if (idx < len && Character.isDigit(pattern.charAt(idx)))
-                    {
-                        val = ((val << 3) + (pattern.charAt(idx++) - '0'));
-                        if (idx < len && Character.isDigit(pattern.charAt(idx)))
-                        {
-                            val = ((val << 3) + (pattern.charAt(idx++) - '0'));
-                        }
-                    }
-                    return val;
-                }
-
-                // It's actually a backreference (\[1-9]), not an escape
-                return ESC_BACKREF;
-
-            default:
-
-                // Simple quoting of a character
-                return escapeChar;
-        }
-    }
-
-    /**
-     * Compile a character class
-     * @return Index of class node
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     */
-    int characterClass() throws RESyntaxException
-    {
-        // Check for bad calling or empty class
-        if (pattern.charAt(idx) != '[')
-        {
-            internalError();
-        }
-
-        // Check for unterminated or empty class
-        if ((idx + 1) >= len || pattern.charAt(++idx) == ']')
-        {
-            syntaxError("Empty or unterminated class");
-        }
-
-        // Check for POSIX character class
-        if (idx < len && pattern.charAt(idx) == ':')
-        {
-            // Skip colon
-            idx++;
-
-            // POSIX character classes are denoted with lowercase ASCII strings
-            int idxStart = idx;
-            while (idx < len && pattern.charAt(idx) >= 'a' && pattern.charAt(idx) <= 'z')
-            {
-                idx++;
-            }
-
-            // Should be a ":]" to terminate the POSIX character class
-            if ((idx + 1) < len && pattern.charAt(idx) == ':' && pattern.charAt(idx + 1) == ']')
-            {
-                // Get character class
-                String charClass = pattern.substring(idxStart, idx);
-
-                // Select the POSIX class id
-                Character i = (Character)hashPOSIX.get(charClass);
-                if (i != null)
-                {
-                    // Move past colon and right bracket
-                    idx += 2;
-
-                    // Return new POSIX character class node
-                    return node(RE.OP_POSIXCLASS, i.charValue());
-                }
-                syntaxError("Invalid POSIX character class '" + charClass + "'");
-            }
-            syntaxError("Invalid POSIX character class syntax");
-        }
-
-        // Try to build a class.  Create OP_ANYOF node
-        int ret = node(RE.OP_ANYOF, 0);
-
-        // Parse class declaration
-        char CHAR_INVALID = Character.MAX_VALUE;
-        char last = CHAR_INVALID;
-        char simpleChar = 0;
-        boolean include = true;
-        boolean definingRange = false;
-        int idxFirst = idx;
-        char rangeStart = Character.MIN_VALUE;
-        char rangeEnd;
-        RERange range = new RERange();
-        while (idx < len && pattern.charAt(idx) != ']')
-        {
-
-            switchOnCharacter:
-
-            // Switch on character
-            switch (pattern.charAt(idx))
-            {
-                case '^':
-                    include = !include;
-                    if (idx == idxFirst)
-                    {
-                        range.include(Character.MIN_VALUE, Character.MAX_VALUE, true);
-                    }
-                    idx++;
-                    continue;
-
-                case '\\':
-                {
-                    // Escape always advances the stream
-                    int c;
-                    switch (c = escape ())
-                    {
-                        case ESC_COMPLEX:
-                        case ESC_BACKREF:
-
-                            // Word boundaries and backrefs not allowed in a character class!
-                            syntaxError("Bad character class");
-
-                        case ESC_CLASS:
-
-                            // Classes can't be an endpoint of a range
-                            if (definingRange)
-                            {
-                                syntaxError("Bad character class");
-                            }
-
-                            // Handle specific type of class (some are ok)
-                            switch (pattern.charAt(idx - 1))
-                            {
-                                case RE.E_NSPACE:
-                                case RE.E_NDIGIT:
-                                case RE.E_NALNUM:
-                                    syntaxError("Bad character class");
-
-                                case RE.E_SPACE:
-                                    range.include('\t', include);
-                                    range.include('\r', include);
-                                    range.include('\f', include);
-                                    range.include('\n', include);
-                                    range.include('\b', include);
-                                    range.include(' ', include);
-                                    break;
-
-                                case RE.E_ALNUM:
-                                    range.include('a', 'z', include);
-                                    range.include('A', 'Z', include);
-                                    range.include('_', include);
-
-                                    // Fall through!
-
-                                case RE.E_DIGIT:
-                                    range.include('0', '9', include);
-                                    break;
-                            }
-
-                            // Make last char invalid (can't be a range start)
-                            last = CHAR_INVALID;
-                            break;
-
-                        default:
-
-                            // Escape is simple so treat as a simple char
-                            simpleChar = (char) c;
-                            break switchOnCharacter;
-                    }
-                }
-                continue;
-
-                case '-':
-
-                    // Start a range if one isn't already started
-                    if (definingRange)
-                    {
-                        syntaxError("Bad class range");
-                    }
-                    definingRange = true;
-
-                    // If no last character, start of range is 0
-                    rangeStart = (last == CHAR_INVALID ? 0 : last);
-
-                    // Premature end of range. define up to Character.MAX_VALUE
-                    if ((idx + 1) < len && pattern.charAt(++idx) == ']')
-                    {
-                        simpleChar = Character.MAX_VALUE;
-                        break;
-                    }
-                    continue;
-
-                default:
-                    simpleChar = pattern.charAt(idx++);
-                    break;
-            }
-
-            // Handle simple character simpleChar
-            if (definingRange)
-            {
-                // if we are defining a range make it now
-                rangeEnd = simpleChar;
-
-                // Actually create a range if the range is ok
-                if (rangeStart >= rangeEnd)
-                {
-                    syntaxError("Bad character class");
-                }
-                range.include(rangeStart, rangeEnd, include);
-
-                // We are done defining the range
-                last = CHAR_INVALID;
-                definingRange = false;
-            }
-            else
-            {
-                // If simple character and not start of range, include it
-                if (idx >= len || pattern.charAt(idx) != '-')
-                {
-                    range.include(simpleChar, include);
-                }
-                last = simpleChar;
-            }
-        }
-
-        // Shouldn't be out of input
-        if (idx == len)
-        {
-            syntaxError("Unterminated character class");
-        }
-
-        // Absorb the ']' end of class marker
-        idx++;
-
-        // Emit character class definition
-        instruction[ret + RE.offsetOpdata] = (char)range.num;
-        for (int i = 0; i < range.num; i++)
-        {
-            emit((char)range.minRange[i]);
-            emit((char)range.maxRange[i]);
-        }
-        return ret;
-    }
-
-    /**
-     * Absorb an atomic character string.  This method is a little tricky because
-     * it can un-include the last character of string if a closure operator follows.
-     * This is correct because *+? have higher precedence than concatentation (thus
-     * ABC* means AB(C*) and NOT (ABC)*).
-     * @return Index of new atom node
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     */
-    int atom() throws RESyntaxException
-    {
-        // Create a string node
-        int ret = node(RE.OP_ATOM, 0);
-
-        // Length of atom
-        int lenAtom = 0;
-
-        // Loop while we've got input
-
-        atomLoop:
-
-        while (idx < len)
-        {
-            // Is there a next char?
-            if ((idx + 1) < len)
-            {
-                char c = pattern.charAt(idx + 1);
-
-                // If the next 'char' is an escape, look past the whole escape
-                if (pattern.charAt(idx) == '\\')
-                {
-                    int idxEscape = idx;
-                    escape();
-                    if (idx < len)
-                    {
-                        c = pattern.charAt(idx);
-                    }
-                    idx = idxEscape;
-                }
-
-                // Switch on next char
-                switch (c)
-                {
-                    case '{':
-                    case '?':
-                    case '*':
-                    case '+':
-
-                        // If the next character is a closure operator and our atom is non-empty, the
-                        // current character should bind to the closure operator rather than the atom
-                        if (lenAtom != 0)
-                        {
-                            break atomLoop;
-                        }
-                }
-            }
-
-            // Switch on current char
-            switch (pattern.charAt(idx))
-            {
-                case ']':
-                case '^':
-                case '$':
-                case '.':
-                case '[':
-                case '(':
-                case ')':
-                case '|':
-                    break atomLoop;
-
-                case '{':
-                case '?':
-                case '*':
-                case '+':
-
-                    // We should have an atom by now
-                    if (lenAtom == 0)
-                    {
-                        // No atom before closure
-                        syntaxError("Missing operand to closure");
-                    }
-                    break atomLoop;
-
-                case '\\':
-
-                    {
-                        // Get the escaped character (advances input automatically)
-                        int idxBeforeEscape = idx;
-                        int c = escape();
-
-                        // Check if it's a simple escape (as opposed to, say, a backreference)
-                        if ((c & ESC_MASK) == ESC_MASK)
-                        {
-                            // Not a simple escape, so backup to where we were before the escape.
-                            idx = idxBeforeEscape;
-                            break atomLoop;
-                        }
-
-                        // Add escaped char to atom
-                        emit((char) c);
-                        lenAtom++;
-                    }
-                    break;
-
-                default:
-
-                    // Add normal character to atom
-                    emit(pattern.charAt(idx++));
-                    lenAtom++;
-                    break;
-            }
-        }
-
-        // This "shouldn't" happen
-        if (lenAtom == 0)
-        {
-            internalError();
-        }
-
-        // Emit the atom length into the program
-        instruction[ret + RE.offsetOpdata] = (char)lenAtom;
-        return ret;
-    }
-
-    /**
-     * Match a terminal node.
-     * @param flags Flags
-     * @return Index of terminal node (closeable)
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     */
-    int terminal(int[] flags) throws RESyntaxException
-    {
-        switch (pattern.charAt(idx))
-        {
-        case RE.OP_EOL:
-        case RE.OP_BOL:
-        case RE.OP_ANY:
-            return node(pattern.charAt(idx++), 0);
-
-        case '[':
-            return characterClass();
-
-        case '(':
-            return expr(flags);
-
-        case ')':
-            syntaxError("Unexpected close paren");
-
-        case '|':
-            internalError();
-
-        case ']':
-            syntaxError("Mismatched class");
-
-        case 0:
-            syntaxError("Unexpected end of input");
-
-        case '?':
-        case '+':
-        case '{':
-        case '*':
-            syntaxError("Missing operand to closure");
-
-        case '\\':
-            {
-                // Don't forget, escape() advances the input stream!
-                int idxBeforeEscape = idx;
-
-                // Switch on escaped character
-                switch (escape())
-                {
-                    case ESC_CLASS:
-                    case ESC_COMPLEX:
-                        flags[0] &= ~NODE_NULLABLE;
-                        return node(RE.OP_ESCAPE, pattern.charAt(idx - 1));
-
-                    case ESC_BACKREF:
-                        {
-                            char backreference = (char)(pattern.charAt(idx - 1) - '0');
-                            if (parens <= backreference)
-                            {
-                                syntaxError("Bad backreference");
-                            }
-                            flags[0] |= NODE_NULLABLE;
-                            return node(RE.OP_BACKREF, backreference);
-                        }
-
-                    default:
-
-                        // We had a simple escape and we want to have it end up in
-                        // an atom, so we back up and fall though to the default handling
-                        idx = idxBeforeEscape;
-                        flags[0] &= ~NODE_NULLABLE;
-                        break;
-                }
-            }
-        }
-
-        // Everything above either fails or returns.
-        // If it wasn't one of the above, it must be the start of an atom.
-        flags[0] &= ~NODE_NULLABLE;
-        return atom();
-    }
-
-    /**
-     * Compile a possibly closured terminal
-     * @param flags Flags passed by reference
-     * @return Index of closured node
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     */
-    int closure(int[] flags) throws RESyntaxException
-    {
-        // Before terminal
-        int idxBeforeTerminal = idx;
-
-        // Values to pass by reference to terminal()
-        int[] terminalFlags = { NODE_NORMAL };
-
-        // Get terminal symbol
-        int ret = terminal(terminalFlags);
-
-        // Or in flags from terminal symbol
-        flags[0] |= terminalFlags[0];
-
-        // Advance input, set NODE_NULLABLE flag and do sanity checks
-        if (idx >= len)
-        {
-            return ret;
-        }
-        boolean greedy = true;
-        char closureType = pattern.charAt(idx);
-        switch (closureType)
-        {
-            case '?':
-            case '*':
-
-                // The current node can be null
-                flags[0] |= NODE_NULLABLE;
-
-            case '+':
-
-                // Eat closure character
-                idx++;
-
-            case '{':
-
-                // Don't allow blantant stupidity
-                int opcode = instruction[ret + RE.offsetOpcode];
-                if (opcode == RE.OP_BOL || opcode == RE.OP_EOL)
-                {
-                    syntaxError("Bad closure operand");
-                }
-                if ((terminalFlags[0] & NODE_NULLABLE) != 0)
-                {
-                    syntaxError("Closure operand can't be nullable");
-                }
-                break;
-        }
-
-        // If the next character is a '?', make the closure non-greedy (reluctant)
-        if (idx < len && pattern.charAt(idx) == '?')
-        {
-            idx++;
-            greedy = false;
-        }
-
-        if (greedy)
-        {
-            // Actually do the closure now
-            switch (closureType)
-            {
-                case '{':
-                {
-                    // We look for our bracket in the list
-                    boolean found = false;
-                    int i;
-                    allocBrackets();
-                    for (i = 0; i < brackets; i++)
-                    {
-                        if (bracketStart[i] == idx)
-                        {
-                            found = true;
-                            break;
-                        }
-                    }
-
-                    // If its not in the list we parse the {m,n}
-                    if (!found)
-                    {
-                        if (brackets >= maxBrackets)
-                        {
-                            reallocBrackets();
-                        }
-                        bracketStart[brackets] = idx;
-                        bracket();
-                        bracketEnd[brackets] = idx;
-                        i = brackets++;
-                    }
-
-                    // Process min first
-                    if (bracketMin[i]-- > 0)
-                    {
-                        if (bracketMin[i] > 0 || bracketOpt[i] != 0) {
-                            // Rewind stream and run it through again - more matchers coming
-                            for (int j = 0; j < brackets; j++) {
-                                if (j != i && bracketStart[j] < idx
-                                    && bracketStart[j] >= idxBeforeTerminal)
-                                {
-                                    brackets--;
-                                    bracketStart[j] = bracketStart[brackets];
-                                    bracketEnd[j] = bracketEnd[brackets];
-                                    bracketMin[j] = bracketMin[brackets];
-                                    bracketOpt[j] = bracketOpt[brackets];
-                                }
-                            }
-
-                            idx = idxBeforeTerminal;
-                        } else {
-                            // Bug #1030: No optinal matches - no need to rewind
-                            idx = bracketEnd[i];
-                        }
-                        break;
-                    }
-
-                    // Do the right thing for maximum ({m,})
-                    if (bracketOpt[i] == bracketUnbounded)
-                    {
-                        // Drop through now and closure expression.
-                        // We are done with the {m,} expr, so skip rest
-                        closureType = '*';
-                        bracketOpt[i] = 0;
-                        idx = bracketEnd[i];
-                    }
-                    else
-                        if (bracketOpt[i]-- > 0)
-                        {
-                            if (bracketOpt[i] > 0)
-                            {
-                                // More optional matchers - 'play it again sam!'
-                                idx = idxBeforeTerminal;
-                            } else {
-                                // Bug #1030: We are done - this one is last and optional
-                                idx = bracketEnd[i];
-                            }
-                            // Drop through to optionally close
-                            closureType = '?';
-                        }
-                        else
-                        {
-                            // Rollback terminal - neither min nor opt matchers present
-                            lenInstruction = ret;
-                            node(RE.OP_NOTHING, 0);
-
-                            // We are done. skip the rest of {m,n} expr
-                            idx = bracketEnd[i];
-                            break;
-                        }
-                }
-
-                // Fall through!
-
-                case '?':
-                case '*':
-
-                    if (!greedy)
-                    {
-                        break;
-                    }
-
-                    if (closureType == '?')
-                    {
-                        // X? is compiled as (X|)
-                        nodeInsert(RE.OP_BRANCH, 0, ret);                 // branch before X
-                        setNextOfEnd(ret, node (RE.OP_BRANCH, 0));        // inserted branch to option
-                        int nothing = node (RE.OP_NOTHING, 0);            // which is OP_NOTHING
-                        setNextOfEnd(ret, nothing);                       // point (second) branch to OP_NOTHING
-                        setNextOfEnd(ret + RE.nodeSize, nothing);         // point the end of X to OP_NOTHING node
-                    }
-
-                    if (closureType == '*')
-                    {
-                        // X* is compiled as (X{gotoX}|)
-                        nodeInsert(RE.OP_BRANCH, 0, ret);                         // branch before X
-                        setNextOfEnd(ret + RE.nodeSize, node(RE.OP_BRANCH, 0));   // end of X points to an option
-                        setNextOfEnd(ret + RE.nodeSize, node(RE.OP_GOTO, 0));     // to goto
-                        setNextOfEnd(ret + RE.nodeSize, ret);                     // the start again
-                        setNextOfEnd(ret, node(RE.OP_BRANCH, 0));                 // the other option is
-                        setNextOfEnd(ret, node(RE.OP_NOTHING, 0));                // OP_NOTHING
-                    }
-                    break;
-
-                case '+':
-                {
-                    // X+ is compiled as X({gotoX}|)
-                    int branch;
-                    branch = node(RE.OP_BRANCH, 0);                   // a new branch
-                    setNextOfEnd(ret, branch);                        // is added to the end of X
-                    setNextOfEnd(node(RE.OP_GOTO, 0), ret);           // one option is to go back to the start
-                    setNextOfEnd(branch, node(RE.OP_BRANCH, 0));      // the other option
-                    setNextOfEnd(ret, node(RE.OP_NOTHING, 0));        // is OP_NOTHING
-                }
-                break;
-            }
-        }
-        else
-        {
-            // Add end after closured subexpr
-            setNextOfEnd(ret, node(RE.OP_END, 0));
-
-            // Actually do the closure now
-            switch (closureType)
-            {
-                case '?':
-                    nodeInsert(RE.OP_RELUCTANTMAYBE, 0, ret);
-                    break;
-
-                case '*':
-                    nodeInsert(RE.OP_RELUCTANTSTAR, 0, ret);
-                    break;
-
-                case '+':
-                    nodeInsert(RE.OP_RELUCTANTPLUS, 0, ret);
-                    break;
-            }
-
-            // Point to the expr after the closure
-            setNextOfEnd(ret, lenInstruction);
-        }
-        return ret;
-    }
-
-    /**
-     * Compile one branch of an or operator (implements concatenation)
-     * @param flags Flags passed by reference
-     * @return Pointer to branch node
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     */
-    int branch(int[] flags) throws RESyntaxException
-    {
-        // Get each possibly closured piece and concat
-        int node;
-        int ret = node(RE.OP_BRANCH, 0);
-        int chain = -1;
-        int[] closureFlags = new int[1];
-        boolean nullable = true;
-        while (idx < len && pattern.charAt(idx) != '|' && pattern.charAt(idx) != ')')
-        {
-            // Get new node
-            closureFlags[0] = NODE_NORMAL;
-            node = closure(closureFlags);
-            if (closureFlags[0] == NODE_NORMAL)
-            {
-                nullable = false;
-            }
-
-            // If there's a chain, append to the end
-            if (chain != -1)
-            {
-                setNextOfEnd(chain, node);
-            }
-
-            // Chain starts at current
-            chain = node;
-        }
-
-        // If we don't run loop, make a nothing node
-        if (chain == -1)
-        {
-            node(RE.OP_NOTHING, 0);
-        }
-
-        // Set nullable flag for this branch
-        if (nullable)
-        {
-            flags[0] |= NODE_NULLABLE;
-        }
-        return ret;
-    }
-
-    /**
-     * Compile an expression with possible parens around it.  Paren matching
-     * is done at this level so we can tie the branch tails together.
-     * @param flags Flag value passed by reference
-     * @return Node index of expression in instruction array
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     */
-    int expr(int[] flags) throws RESyntaxException
-    {
-        // Create open paren node unless we were called from the top level (which has no parens)
-        int paren = -1;
-        int ret = -1;
-        int closeParens = parens;
-        if ((flags[0] & NODE_TOPLEVEL) == 0 && pattern.charAt(idx) == '(')
-        {
-            // if its a cluster ( rather than a proper subexpression ie with backrefs )
-            if ( idx + 2 < len && pattern.charAt( idx + 1 ) == '?' && pattern.charAt( idx + 2 ) == ':' )
-            {
-                paren = 2;
-                idx += 3;
-                ret = node( RE.OP_OPEN_CLUSTER, 0 );
-            }
-            else
-            {
-                paren = 1;
-                idx++;
-                ret = node(RE.OP_OPEN, parens++);
-            }
-        }
-        flags[0] &= ~NODE_TOPLEVEL;
-
-        // Create a branch node
-        int branch = branch(flags);
-        if (ret == -1)
-        {
-            ret = branch;
-        }
-        else
-        {
-            setNextOfEnd(ret, branch);
-        }
-
-        // Loop through branches
-        while (idx < len && pattern.charAt(idx) == '|')
-        {
-            idx++;
-            branch = branch(flags);
-            setNextOfEnd(ret, branch);
-        }
-
-        // Create an ending node (either a close paren or an OP_END)
-        int end;
-        if ( paren > 0 )
-        {
-            if (idx < len && pattern.charAt(idx) == ')')
-            {
-                idx++;
-            }
-            else
-            {
-                syntaxError("Missing close paren");
-            }
-            if ( paren == 1 )
-            {
-                end = node(RE.OP_CLOSE, closeParens);
-            }
-            else
-            {
-                end = node( RE.OP_CLOSE_CLUSTER, 0 );
-            }
-        }
-        else
-        {
-            end = node(RE.OP_END, 0);
-        }
-
-        // Append the ending node to the ret nodelist
-        setNextOfEnd(ret, end);
-
-        // Hook the ends of each branch to the end node
-        int currentNode = ret;
-        int nextNodeOffset = instruction[ currentNode + RE.offsetNext ];
-        // while the next node o
-        while ( nextNodeOffset != 0 && currentNode < lenInstruction )
-        {
-            // If branch, make the end of the branch's operand chain point to the end node.
-            if ( instruction[ currentNode + RE.offsetOpcode ] == RE.OP_BRANCH )
-            {
-                setNextOfEnd( currentNode + RE.nodeSize, end );
-            }
-            nextNodeOffset = instruction[ currentNode + RE.offsetNext ];
-            currentNode += nextNodeOffset;
-        }
-
-        // Return the node list
-        return ret;
-    }
-
-    /**
-     * Compiles a regular expression pattern into a program runnable by the pattern
-     * matcher class 'RE'.
-     * @param pattern Regular expression pattern to compile (see RECompiler class
-     * for details).
-     * @return A compiled regular expression program.
-     * @exception RESyntaxException Thrown if the regular expression has invalid syntax.
-     * @see RECompiler
-     * @see RE
-     */
-    public REProgram compile(String pattern) throws RESyntaxException
-    {
-        // Initialize variables for compilation
-        this.pattern = pattern;                         // Save pattern in instance variable
-        len = pattern.length();                         // Precompute pattern length for speed
-        idx = 0;                                        // Set parsing index to the first character
-        lenInstruction = 0;                             // Set emitted instruction count to zero
-        parens = 1;                                     // Set paren level to 1 (the implicit outer parens)
-        brackets = 0;                                   // No bracketed closures yet
-
-        // Initialize pass by reference flags value
-        int[] flags = { NODE_TOPLEVEL };
-
-        // Parse expression
-        expr(flags);
-
-        // Should be at end of input
-        if (idx != len)
-        {
-            if (pattern.charAt(idx) == ')')
-            {
-                syntaxError("Unmatched close paren");
-            }
-            syntaxError("Unexpected input remains");
-        }
-
-        // Return the result
-        char[] ins = new char[lenInstruction];
-        System.arraycopy(instruction, 0, ins, 0, lenInstruction);
-        return new REProgram(parens, ins);
-    }
-
-    /**
-     * Local, nested class for maintaining character ranges for character classes.
-     */
-    class RERange
-    {
-        int size = 16;                      // Capacity of current range arrays
-        int[] minRange = new int[size];     // Range minima
-        int[] maxRange = new int[size];     // Range maxima
-        int num = 0;                        // Number of range array elements in use
-
-        /**
-         * Deletes the range at a given index from the range lists
-         * @param index Index of range to delete from minRange and maxRange arrays.
-         */
-        void delete(int index)
-        {
-            // Return if no elements left or index is out of range
-            if (num == 0 || index >= num)
-            {
-                return;
-            }
-
-            // Move elements down
-            while (++index < num)
-            {
-                if (index - 1 >= 0)
-                {
-                    minRange[index-1] = minRange[index];
-                    maxRange[index-1] = maxRange[index];
-                }
-            }
-
-            // One less element now
-            num--;
-        }
-
-        /**
-         * Merges a range into the range list, coalescing ranges if possible.
-         * @param min Minimum end of range
-         * @param max Maximum end of range
-         */
-        void merge(int min, int max)
-        {
-            // Loop through ranges
-            for (int i = 0; i < num; i++)
-            {
-                // Min-max is subsumed by minRange[i]-maxRange[i]
-                if (min >= minRange[i] && max <= maxRange[i])
-                {
-                    return;
-                }
-
-                // Min-max subsumes minRange[i]-maxRange[i]
-                else if (min <= minRange[i] && max >= maxRange[i])
-                {
-                    delete(i);
-                    merge(min, max);
-                    return;
-                }
-
-                // Min is in the range, but max is outside
-                else if (min >= minRange[i] && min <= maxRange[i])
-                {
-                    delete(i);
-                    min = minRange[i];
-                    merge(min, max);
-                    return;
-                }
-
-                // Max is in the range, but min is outside
-                else if (max >= minRange[i] && max <= maxRange[i])
-                {
-                    delete(i);
-                    max = maxRange[i];
-                    merge(min, max);
-                    return;
-                }
-            }
-
-            // Must not overlap any other ranges
-            if (num >= size)
-            {
-                size *= 2;
-                int[] newMin = new int[size];
-                int[] newMax = new int[size];
-                System.arraycopy(minRange, 0, newMin, 0, num);
-                System.arraycopy(maxRange, 0, newMax, 0, num);
-                minRange = newMin;
-                maxRange = newMax;
-            }
-            minRange[num] = min;
-            maxRange[num] = max;
-            num++;
-        }
-
-        /**
-         * Removes a range by deleting or shrinking all other ranges
-         * @param min Minimum end of range
-         * @param max Maximum end of range
-         */
-        void remove(int min, int max)
-        {
-            // Loop through ranges
-            for (int i = 0; i < num; i++)
-            {
-                // minRange[i]-maxRange[i] is subsumed by min-max
-                if (minRange[i] >= min && maxRange[i] <= max)
-                {
-                    delete(i);
-                    i--;
-                    return;
-                }
-
-                // min-max is subsumed by minRange[i]-maxRange[i]
-                else if (min >= minRange[i] && max <= maxRange[i])
-                {
-                    int minr = minRange[i];
-                    int maxr = maxRange[i];
-                    delete(i);
-                    if (minr < min)
-                    {
-                        merge(minr, min - 1);
-                    }
-                    if (max < maxr)
-                    {
-                        merge(max + 1, maxr);
-                    }
-                    return;
-                }
-
-                // minRange is in the range, but maxRange is outside
-                else if (minRange[i] >= min && minRange[i] <= max)
-                {
-                    minRange[i] = max + 1;
-                    return;
-                }
-
-                // maxRange is in the range, but minRange is outside
-                else if (maxRange[i] >= min && maxRange[i] <= max)
-                {
-                    maxRange[i] = min - 1;
-                    return;
-                }
-            }
-        }
-
-        /**
-         * Includes (or excludes) the range from min to max, inclusive.
-         * @param min Minimum end of range
-         * @param max Maximum end of range
-         * @param include True if range should be included.  False otherwise.
-         */
-        void include(int min, int max, boolean include)
-        {
-            if (include)
-            {
-                merge(min, max);
-            }
-            else
-            {
-                remove(min, max);
-            }
-        }
-
-        /**
-         * Includes a range with the same min and max
-         * @param minmax Minimum and maximum end of range (inclusive)
-         * @param include True if range should be included.  False otherwise.
-         */
-        void include(char minmax, boolean include)
-        {
-            include(minmax, minmax, include);
-        }
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REDebugCompiler.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REDebugCompiler.java
deleted file mode 100644
index 815d4fdfa81..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REDebugCompiler.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-import java.io.PrintWriter;
-import java.util.Hashtable;
-
-/**
- * A subclass of RECompiler which can dump a regular expression program
- * for debugging purposes.
- *
- * @author <a href="mailto:jonl@muppetlabs.com">Jonathan Locke</a>
- */
-public class REDebugCompiler extends RECompiler
-{
-    /**
-     * Mapping from opcodes to descriptive strings
-     */
-    static Hashtable hashOpcode = new Hashtable();
-    static
-    {
-        hashOpcode.put(new Integer(RE.OP_RELUCTANTSTAR),    "OP_RELUCTANTSTAR");
-        hashOpcode.put(new Integer(RE.OP_RELUCTANTPLUS),    "OP_RELUCTANTPLUS");
-        hashOpcode.put(new Integer(RE.OP_RELUCTANTMAYBE),   "OP_RELUCTANTMAYBE");
-        hashOpcode.put(new Integer(RE.OP_END),              "OP_END");
-        hashOpcode.put(new Integer(RE.OP_BOL),              "OP_BOL");
-        hashOpcode.put(new Integer(RE.OP_EOL),              "OP_EOL");
-        hashOpcode.put(new Integer(RE.OP_ANY),              "OP_ANY");
-        hashOpcode.put(new Integer(RE.OP_ANYOF),            "OP_ANYOF");
-        hashOpcode.put(new Integer(RE.OP_BRANCH),           "OP_BRANCH");
-        hashOpcode.put(new Integer(RE.OP_ATOM),             "OP_ATOM");
-        hashOpcode.put(new Integer(RE.OP_STAR),             "OP_STAR");
-        hashOpcode.put(new Integer(RE.OP_PLUS),             "OP_PLUS");
-        hashOpcode.put(new Integer(RE.OP_MAYBE),            "OP_MAYBE");
-        hashOpcode.put(new Integer(RE.OP_NOTHING),          "OP_NOTHING");
-        hashOpcode.put(new Integer(RE.OP_GOTO),             "OP_GOTO");
-        hashOpcode.put(new Integer(RE.OP_ESCAPE),           "OP_ESCAPE");
-        hashOpcode.put(new Integer(RE.OP_OPEN),             "OP_OPEN");
-        hashOpcode.put(new Integer(RE.OP_CLOSE),            "OP_CLOSE");
-        hashOpcode.put(new Integer(RE.OP_BACKREF),          "OP_BACKREF");
-        hashOpcode.put(new Integer(RE.OP_POSIXCLASS),       "OP_POSIXCLASS");
-        hashOpcode.put(new Integer(RE.OP_OPEN_CLUSTER),      "OP_OPEN_CLUSTER");
-        hashOpcode.put(new Integer(RE.OP_CLOSE_CLUSTER),      "OP_CLOSE_CLUSTER");
-    }
-
-    /**
-     * Returns a descriptive string for an opcode.
-     * @param opcode Opcode to convert to a string
-     * @return Description of opcode
-     */
-    String opcodeToString(char opcode)
-    {
-        // Get string for opcode
-        String ret =(String)hashOpcode.get(new Integer(opcode));
-
-        // Just in case we have a corrupt program
-        if (ret == null)
-        {
-            ret = "OP_????";
-        }
-        return ret;
-    }
-
-    /**
-     * Return a string describing a (possibly unprintable) character.
-     * @param c Character to convert to a printable representation
-     * @return String representation of character
-     */
-    String charToString(char c)
-    {
-        // If it's unprintable, convert to '\###'
-        if (c < ' ' || c > 127)
-        {
-            return "\\" + (int)c;
-        }
-
-        // Return the character as a string
-        return String.valueOf(c);
-    }
-
-    /**
-     * Returns a descriptive string for a node in a regular expression program.
-     * @param node Node to describe
-     * @return Description of node
-     */
-    String nodeToString(int node)
-    {
-        // Get opcode and opdata for node
-        char opcode =      instruction[node + RE.offsetOpcode];
-        int opdata  = (int)instruction[node + RE.offsetOpdata];
-
-        // Return opcode as a string and opdata value
-        return opcodeToString(opcode) + ", opdata = " + opdata;
-    }
-
-    /**
-     * Inserts a node with a given opcode and opdata at insertAt.  The node relative next
-     * pointer is initialized to 0.
-     * @param opcode Opcode for new node
-     * @param opdata Opdata for new node (only the low 16 bits are currently used)
-     * @param insertAt Index at which to insert the new node in the program * /
-    void nodeInsert(char opcode, int opdata, int insertAt) {
-        System.out.println( "====> " + opcode + " " + opdata + " " + insertAt );
-        PrintWriter writer = new PrintWriter( System.out );
-        dumpProgram( writer );
-        super.nodeInsert( opcode, opdata, insertAt );
-        System.out.println( "====< " );
-        dumpProgram( writer );
-        writer.flush();
-    }/**/
-
-
-    /**
-    * Appends a node to the end of a node chain
-    * @param node Start of node chain to traverse
-    * @param pointTo Node to have the tail of the chain point to * /
-    void setNextOfEnd(int node, int pointTo) {
-        System.out.println( "====> " + node + " " + pointTo );
-        PrintWriter writer = new PrintWriter( System.out );
-        dumpProgram( writer );
-        super.setNextOfEnd( node, pointTo );
-        System.out.println( "====< " );
-        dumpProgram( writer );
-        writer.flush();
-    }/**/
-
-
-    /**
-     * Dumps the current program to a PrintWriter
-     * @param p PrintWriter for program dump output
-     */
-    public void dumpProgram(PrintWriter p)
-    {
-        // Loop through the whole program
-        for (int i = 0; i < lenInstruction; )
-        {
-            // Get opcode, opdata and next fields of current program node
-            char opcode =        instruction[i + RE.offsetOpcode];
-            char opdata =        instruction[i + RE.offsetOpdata];
-            short next  = (short)instruction[i + RE.offsetNext];
-
-            // Display the current program node
-            p.print(i + ". " + nodeToString(i) + ", next = ");
-
-            // If there's no next, say 'none', otherwise give absolute index of next node
-            if (next == 0)
-            {
-                p.print("none");
-            }
-            else
-            {
-                p.print(i + next);
-            }
-
-            // Move past node
-            i += RE.nodeSize;
-
-            // If character class
-            if (opcode == RE.OP_ANYOF)
-            {
-                // Opening bracket for start of char class
-                p.print(", [");
-
-                // Show each range in the char class
-                int rangeCount = opdata;
-                for (int r = 0; r < rangeCount; r++)
-                {
-                    // Get first and last chars in range
-                    char charFirst = instruction[i++];
-                    char charLast  = instruction[i++];
-
-                    // Print range as X-Y, unless range encompasses only one char
-                    if (charFirst == charLast)
-                    {
-                        p.print(charToString(charFirst));
-                    }
-                    else
-                    {
-                        p.print(charToString(charFirst) + "-" + charToString(charLast));
-                    }
-                }
-
-                // Annotate the end of the char class
-                p.print("]");
-            }
-
-            // If atom
-            if (opcode == RE.OP_ATOM)
-            {
-                // Open quote
-                p.print(", \"");
-
-                // Print each character in the atom
-                for (int len = opdata; len-- != 0; )
-                {
-                    p.print(charToString(instruction[i++]));
-                }
-
-                // Close quote
-                p.print("\"");
-            }
-
-            // Print a newline
-            p.println("");
-        }
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REProgram.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REProgram.java
deleted file mode 100644
index f7a39ce3fe1..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REProgram.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-import java.io.Serializable;
-
-/**
- * A class that holds compiled regular expressions.  This is exposed mainly
- * for use by the recompile utility (which helps you produce precompiled
- * REProgram objects). You should not otherwise need to work directly with
- * this class.
-*
- * @see RE
- * @see RECompiler
- *
- * @author <a href="mailto:jonl@muppetlabs.com">Jonathan Locke</a>
- */
-public class REProgram implements Serializable
-{
-    static final int OPT_HASBACKREFS = 1;
-
-    char[] instruction;         // The compiled regular expression 'program'
-    int lenInstruction;         // The amount of the instruction buffer in use
-    char[] prefix;              // Prefix string optimization
-    int flags;                  // Optimization flags (REProgram.OPT_*)
-    int maxParens = -1;
-
-    /**
-     * Constructs a program object from a character array
-     * @param instruction Character array with RE opcode instructions in it
-     */
-    public REProgram(char[] instruction)
-    {
-        this(instruction, instruction.length);
-    }
-
-    /**
-     * Constructs a program object from a character array
-     * @param parens Count of parens in the program
-     * @param instruction Character array with RE opcode instructions in it
-     */
-    public REProgram(int parens, char[] instruction)
-    {
-        this(instruction, instruction.length);
-        this.maxParens = parens;
-    }
-
-    /**
-     * Constructs a program object from a character array
-     * @param instruction Character array with RE opcode instructions in it
-     * @param lenInstruction Amount of instruction array in use
-     */
-    public REProgram(char[] instruction, int lenInstruction)
-    {
-        setInstructions(instruction, lenInstruction);
-    }
-
-    /**
-     * Returns a copy of the current regular expression program in a character
-     * array that is exactly the right length to hold the program.  If there is
-     * no program compiled yet, getInstructions() will return null.
-     * @return A copy of the current compiled RE program
-     */
-    public char[] getInstructions()
-    {
-        // Ensure program has been compiled!
-        if (lenInstruction != 0)
-        {
-            // Return copy of program
-            char[] ret = new char[lenInstruction];
-            System.arraycopy(instruction, 0, ret, 0, lenInstruction);
-            return ret;
-        }
-        return null;
-    }
-
-    /**
-     * Sets a new regular expression program to run.  It is this method which
-     * performs any special compile-time search optimizations.  Currently only
-     * two optimizations are in place - one which checks for backreferences
-     * (so that they can be lazily allocated) and another which attempts to
-     * find an prefix anchor string so that substantial amounts of input can
-     * potentially be skipped without running the actual program.
-     * @param instruction Program instruction buffer
-     * @param lenInstruction Length of instruction buffer in use
-     */
-    public void setInstructions(char[] instruction, int lenInstruction)
-    {
-        // Save reference to instruction array
-        this.instruction = instruction;
-        this.lenInstruction = lenInstruction;
-
-        // Initialize other program-related variables
-        flags = 0;
-        prefix = null;
-
-        // Try various compile-time optimizations if there's a program
-        if (instruction != null && lenInstruction != 0)
-        {
-            // If the first node is a branch
-            if (lenInstruction >= RE.nodeSize && instruction[0 + RE.offsetOpcode] == RE.OP_BRANCH)
-            {
-                // to the end node
-                int next = instruction[0 + RE.offsetNext];
-                if (instruction[next + RE.offsetOpcode] == RE.OP_END)
-                {
-                    // and the branch starts with an atom
-                    if (lenInstruction >= (RE.nodeSize * 2) && instruction[RE.nodeSize + RE.offsetOpcode] == RE.OP_ATOM)
-                    {
-                        // then get that atom as an prefix because there's no other choice
-                        int lenAtom = instruction[RE.nodeSize + RE.offsetOpdata];
-                        prefix = new char[lenAtom];
-                        System.arraycopy(instruction, RE.nodeSize * 2, prefix, 0, lenAtom);
-                    }
-                }
-            }
-
-            BackrefScanLoop:
-
-            // Check for backreferences
-            for (int i = 0; i < lenInstruction; i += RE.nodeSize)
-            {
-                switch (instruction[i + RE.offsetOpcode])
-                {
-                    case RE.OP_ANYOF:
-                        i += (instruction[i + RE.offsetOpdata] * 2);
-                        break;
-
-                    case RE.OP_ATOM:
-                        i += instruction[i + RE.offsetOpdata];
-                        break;
-
-                    case RE.OP_BACKREF:
-                        flags |= OPT_HASBACKREFS;
-                        break BackrefScanLoop;
-                }
-            }
-        }
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RESyntaxException.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RESyntaxException.java
deleted file mode 100644
index a13f901ece4..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RESyntaxException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-/**
- * Exception thrown to indicate a syntax error in a regular expression.
- * This is a non-checked exception because you should only have problems compiling
- * a regular expression during development.
- * If you are making regular expresion programs dynamically then you can catch it
- * if you wish. But should not be forced to.
- *
- * @author <a href="mailto:jonl@muppetlabs.com">Jonathan Locke</a>
- * @author <a href="mailto:gholam@xtra.co.nz>Michael McCallum</a>
- */
-public class RESyntaxException extends RuntimeException
-{
-    /**
-     * Constructor.
-     * @param s Further description of the syntax error
-     */
-    public RESyntaxException(String s)
-    {
-        super("Syntax error: " + s);
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RETest.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RETest.java
deleted file mode 100644
index 463776d5140..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RETest.java
+++ /dev/null
@@ -1,883 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.io.File;
-import java.io.ByteArrayOutputStream;
-import java.io.ObjectOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ObjectInputStream;
-import java.io.StringBufferInputStream;
-import java.io.StringReader;
-import java.io.IOException;
-
-/**
- * Data driven (and optionally interactive) testing harness to exercise regular
- * expression compiler and matching engine.
- *
- * @author <a href="mailto:jonl@muppetlabs.com">Jonathan Locke</a>
- * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
- * @author <a href="mailto:gholam@xtra.co.nz">Michael McCallum</a>
- */
-public class RETest
-{
-    // True if we want to see output from success cases
-    static final boolean showSuccesses = false;
-
-    // A new line character.
-    static final String NEW_LINE = System.getProperty( "line.separator" );
-
-    // Construct a debug compiler
-    REDebugCompiler compiler = new REDebugCompiler();
-
-    /**
-     * Main program entrypoint.  If an argument is given, it will be compiled
-     * and interactive matching will ensue.  If no argument is given, the
-     * file RETest.txt will be used as automated testing input.
-     * @param args Command line arguments (optional regular expression)
-     */
-    public static void main(String[] args)
-    {
-        try
-        {
-            if (!test( args )) {
-                System.exit(1);
-            }
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-            System.exit(1);
-        }
-    }
-
-    /**
-     * Testing entrypoint.
-     * @param args Command line arguments
-     * @exception Exception thrown in case of error
-     */
-    public static boolean test( String[] args ) throws Exception
-    {
-        RETest test = new RETest();
-        // Run interactive tests against a single regexp
-        if (args.length == 2)
-        {
-            test.runInteractiveTests(args[1]);
-        }
-        else if (args.length == 1)
-        {
-            // Run automated tests
-            test.runAutomatedTests(args[0]);
-        }
-        else
-        {
-            System.out.println( "Usage: RETest ([-i] [regex]) ([/path/to/testfile.txt])" );
-            System.out.println( "By Default will run automated tests from file 'docs/RETest.txt' ..." );
-            System.out.println();
-            test.runAutomatedTests("docs/RETest.txt");
-        }
-        return test.failures == 0;
-    }
-
-    /**
-     * Constructor
-     */
-    public RETest()
-    {
-    }
-
-    /**
-     * Compile and test matching against a single expression
-     * @param expr Expression to compile and test
-     */
-    void runInteractiveTests(String expr)
-    {
-        RE r = new RE();
-        try
-        {
-            // Compile expression
-            r.setProgram(compiler.compile(expr));
-
-            // Show expression
-            say("" + NEW_LINE + "" + expr + "" + NEW_LINE + "");
-
-            // Show program for compiled expression
-            PrintWriter writer = new PrintWriter( System.out );
-            compiler.dumpProgram( writer );
-            writer.flush();
-
-            boolean running = true;
-            // Test matching against compiled expression
-            while ( running )
-            {
-                // Read from keyboard
-                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
-                System.out.print("> ");
-                System.out.flush();
-                String match = br.readLine();
-
-                if ( match != null )
-                {
-                    // Try a match against the keyboard input
-                    if (r.match(match))
-                    {
-                        say("Match successful.");
-                    }
-                    else
-                    {
-                        say("Match failed.");
-                    }
-
-                    // Show subparen registers
-                    showParens(r);
-                }
-                else
-                {
-                    running = false;
-                    System.out.println();
-                }
-            }
-        }
-        catch (Exception e)
-        {
-            say("Error: " + e.toString());
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * Exit with a fatal error.
-     * @param s Last famous words before exiting
-     */
-    void die(String s)
-    {
-        say("FATAL ERROR: " + s);
-        System.exit(-1);
-    }
-
-    /**
-     * Fail with an error. Will print a big failure message to System.out.
-     *
-     * @param log Output before failure
-     * @param s Failure description
-     */
-    void fail(StringBuffer log, String s)
-    {
-        System.out.print(log.toString());
-        fail(s);
-    }
-
-    /**
-     * Fail with an error. Will print a big failure message to System.out.
-     *
-     * @param s Failure description
-     */
-    void fail(String s)
-    {
-        failures++;
-        say("" + NEW_LINE + "");
-        say("*******************************************************");
-        say("*********************  FAILURE!  **********************");
-        say("*******************************************************");
-        say("" + NEW_LINE + "");
-        say(s);
-        say("");
-        // make sure the writer gets flushed.
-        if (compiler != null) {
-            PrintWriter writer = new PrintWriter( System.out );
-            compiler.dumpProgram( writer );
-            writer.flush();
-            say("" + NEW_LINE + "");
-        }
-    }
-
-    /**
-     * Say something to standard out
-     * @param s What to say
-     */
-    void say(String s)
-    {
-        System.out.println(s);
-    }
-
-    /**
-     * Dump parenthesized subexpressions found by a regular expression matcher object
-     * @param r Matcher object with results to show
-     */
-    void showParens(RE r)
-    {
-        // Loop through each paren
-        for (int i = 0; i < r.getParenCount(); i++)
-        {
-            // Show paren register
-            say("$" + i + " = " + r.getParen(i));
-        }
-    }
-
-    /*
-     * number in automated test
-     */
-    int testCount = 0;
-
-    /*
-     * Count of failures in automated test
-     */
-    int failures = 0;
-
-    /**
-     * Run automated tests in RETest.txt file (from Perl 4.0 test battery)
-     * @exception Exception thrown in case of error
-     */
-    void runAutomatedTests(String testDocument) throws Exception
-    {
-        long ms = System.currentTimeMillis();
-
-        // Some unit tests
-        testPrecompiledRE();
-        testSplitAndGrep();
-        testSubst();
-        testOther();
-
-        // Test from script file
-        File testInput = new File(testDocument);
-        if (! testInput.exists()) {
-            throw new Exception ("Could not find: " + testDocument);
-        }
-
-        BufferedReader br = new BufferedReader(new FileReader(testInput));
-        try
-        {
-            // While input is available, parse lines
-            while (br.ready())
-            {
-                RETestCase testcase = getNextTestCase(br);
-                if (testcase != null) {
-                    testcase.runTest();
-                }
-            }
-        }
-        finally
-        {
-            br.close();
-        }
-
-        // Show match time
-        say(NEW_LINE + NEW_LINE + "Match time = " + (System.currentTimeMillis() - ms) + " ms.");
-
-        // Print final results
-        if (failures > 0) {
-            say("*************** THERE ARE FAILURES! *******************");
-        }
-        say("Tests complete.  " + testCount + " tests, " + failures + " failure(s).");
-    }
-
-    /**
-     * Run automated unit test
-     * @exception Exception thrown in case of error
-     */
-    void testOther() throws Exception
-    {
-        // Serialization test 1: Compile regexp and serialize/deserialize it
-        RE r = new RE("(a*)b");
-        say("Serialized/deserialized (a*)b");
-        ByteArrayOutputStream out = new ByteArrayOutputStream(128);
-        new ObjectOutputStream(out).writeObject(r);
-        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
-        r = (RE)new ObjectInputStream(in).readObject();
-        if (!r.match("aaab"))
-        {
-            fail("Did not match 'aaab' with deserialized RE.");
-        } else {
-            say("aaaab = true");
-            showParens(r);
-        }
-
-        // Serialization test 2: serialize/deserialize used regexp
-        out.reset();
-        say("Deserialized (a*)b");
-        new ObjectOutputStream(out).writeObject(r);
-        in = new ByteArrayInputStream(out.toByteArray());
-        r = (RE)new ObjectInputStream(in).readObject();
-        if (r.getParenCount() != 0)
-        {
-            fail("Has parens after deserialization.");
-        }
-        if (!r.match("aaab"))
-        {
-            fail("Did not match 'aaab' with deserialized RE.");
-        } else {
-            say("aaaab = true");
-            showParens(r);
-        }
-
-        // Test MATCH_CASEINDEPENDENT
-        r = new RE("abc(\\w*)");
-        say("MATCH_CASEINDEPENDENT abc(\\w*)");
-        r.setMatchFlags(RE.MATCH_CASEINDEPENDENT);
-        say("abc(d*)");
-        if (!r.match("abcddd"))
-        {
-            fail("Did not match 'abcddd'.");
-        } else {
-            say("abcddd = true");
-            showParens(r);
-        }
-
-        if (!r.match("aBcDDdd"))
-        {
-            fail("Did not match 'aBcDDdd'.");
-        } else {
-            say("aBcDDdd = true");
-            showParens(r);
-        }
-
-        if (!r.match("ABCDDDDD"))
-        {
-            fail("Did not match 'ABCDDDDD'.");
-        } else {
-            say("ABCDDDDD = true");
-            showParens(r);
-        }
-
-        r = new RE("(A*)b\\1");
-        r.setMatchFlags(RE.MATCH_CASEINDEPENDENT);
-        if (!r.match("AaAaaaBAAAAAA"))
-        {
-            fail("Did not match 'AaAaaaBAAAAAA'.");
-        } else {
-            say("AaAaaaBAAAAAA = true");
-            showParens(r);
-        }
-
-        r = new RE("[A-Z]*");
-        r.setMatchFlags(RE.MATCH_CASEINDEPENDENT);
-        if (!r.match("CaBgDe12"))
-        {
-            fail("Did not match 'CaBgDe12'.");
-        } else {
-            say("CaBgDe12 = true");
-            showParens(r);
-        }
-
-        // Test MATCH_MULTILINE. Test for eol/bol symbols.
-        r = new RE("^abc$", RE.MATCH_MULTILINE);
-        if (!r.match("\nabc")) {
-            fail("\"\\nabc\" doesn't match \"^abc$\"");
-        }
-        if (!r.match("\rabc")) {
-            fail("\"\\rabc\" doesn't match \"^abc$\"");
-        }
-        if (!r.match("\r\nabc")) {
-            fail("\"\\r\\nabc\" doesn't match \"^abc$\"");
-        }
-        if (!r.match("\u0085abc")) {
-            fail("\"\\u0085abc\" doesn't match \"^abc$\"");
-        }
-        if (!r.match("\u2028abc")) {
-            fail("\"\\u2028abc\" doesn't match \"^abc$\"");
-        }
-        if (!r.match("\u2029abc")) {
-            fail("\"\\u2029abc\" doesn't match \"^abc$\"");
-        }
-
-        // Test MATCH_MULTILINE. Test that '.' does not matches new line.
-        r = new RE("^a.*b$", RE.MATCH_MULTILINE);
-        if (r.match("a\nb")) {
-            fail("\"a\\nb\" matches \"^a.*b$\"");
-        }
-        if (r.match("a\rb")) {
-            fail("\"a\\rb\" matches \"^a.*b$\"");
-        }
-        if (r.match("a\r\nb")) {
-            fail("\"a\\r\\nb\" matches \"^a.*b$\"");
-        }
-        if (r.match("a\u0085b")) {
-            fail("\"a\\u0085b\" matches \"^a.*b$\"");
-        }
-        if (r.match("a\u2028b")) {
-            fail("\"a\\u2028b\" matches \"^a.*b$\"");
-        }
-        if (r.match("a\u2029b")) {
-            fail("\"a\\u2029b\" matches \"^a.*b$\"");
-        }
-    }
-
-    private void testPrecompiledRE()
-    {
-        // Pre-compiled regular expression "a*b"
-        char[] re1Instructions =
-        {
-            0x007c, 0x0000, 0x001a, 0x007c, 0x0000, 0x000d, 0x0041,
-            0x0001, 0x0004, 0x0061, 0x007c, 0x0000, 0x0003, 0x0047,
-            0x0000, 0xfff6, 0x007c, 0x0000, 0x0003, 0x004e, 0x0000,
-            0x0003, 0x0041, 0x0001, 0x0004, 0x0062, 0x0045, 0x0000,
-            0x0000,
-        };
-
-        REProgram re1 = new REProgram(re1Instructions);
-
-        // Simple test of pre-compiled regular expressions
-        RE r = new RE(re1);
-        say("a*b");
-        boolean result = r.match("aaab");
-        say("aaab = " + result);
-        showParens(r);
-        if (!result) {
-            fail("\"aaab\" doesn't match to precompiled \"a*b\"");
-        }
-
-        result = r.match("b");
-        say("b = " + result);
-        showParens(r);
-        if (!result) {
-            fail("\"b\" doesn't match to precompiled \"a*b\"");
-        }
-
-        result = r.match("c");
-        say("c = " + result);
-        showParens(r);
-        if (result) {
-            fail("\"c\" matches to precompiled \"a*b\"");
-        }
-
-        result = r.match("ccccaaaaab");
-        say("ccccaaaaab = " + result);
-        showParens(r);
-        if (!result) {
-            fail("\"ccccaaaaab\" doesn't match to precompiled \"a*b\"");
-        }
-    }
-
-    private void testSplitAndGrep()
-    {
-        String[] expected = {"xxxx", "xxxx", "yyyy", "zzz"};
-        RE r = new RE("a*b");
-        String[] s = r.split("xxxxaabxxxxbyyyyaaabzzz");
-        for (int i = 0; i < expected.length && i < s.length; i++) {
-            assertEquals("Wrong splitted part", expected[i], s[i]);
-        }
-        assertEquals("Wrong number of splitted parts", expected.length,
-                     s.length);
-
-        r = new RE("x+");
-        expected = new String[] {"xxxx", "xxxx"};
-        s = r.grep(s);
-        for (int i = 0; i < s.length; i++)
-        {
-            say("s[" + i + "] = " + s[i]);
-            assertEquals("Grep fails", expected[i], s[i]);
-        }
-        assertEquals("Wrong number of string found by grep", expected.length,
-                     s.length);
-    }
-
-    private void testSubst()
-    {
-        RE r = new RE("a*b");
-        String expected = "-foo-garply-wacky-";
-        String actual = r.subst("aaaabfooaaabgarplyaaabwackyb", "-");
-        assertEquals("Wrong result of substitution in \"a*b\"", expected, actual);
-
-        // Test subst() with backreferences
-        r = new RE("http://[\\.\\w\\-\\?/~_@&=%]+");
-        actual = r.subst("visit us: http://www.apache.org!",
-                         "1234<a href=\"$0\">$0</a>", RE.REPLACE_BACKREFERENCES);
-        assertEquals("Wrong subst() result", "visit us: 1234<a href=\"http://www.apache.org\">http://www.apache.org</a>!", actual);
-
-        // Test subst() with backreferences without leading characters
-        // before first backreference
-        r = new RE("(.*?)=(.*)");
-        actual = r.subst("variable=value",
-                         "$1_test_$212", RE.REPLACE_BACKREFERENCES);
-        assertEquals("Wrong subst() result", "variable_test_value12", actual);
-
-        // Test subst() with NO backreferences
-        r = new RE("^a$");
-        actual = r.subst("a",
-                         "b", RE.REPLACE_BACKREFERENCES);
-        assertEquals("Wrong subst() result", "b", actual);
-
-        // Test subst() with NO backreferences
-        r = new RE("^a$", RE.MATCH_MULTILINE);
-        actual = r.subst("\r\na\r\n",
-                         "b", RE.REPLACE_BACKREFERENCES);
-        assertEquals("Wrong subst() result", "\r\nb\r\n", actual);
-    }
-
-    public void assertEquals(String message, String expected, String actual)
-    {
-        if (expected != null && !expected.equals(actual)
-            || actual != null && !actual.equals(expected))
-        {
-            fail(message + " (expected \"" + expected
-                 + "\", actual \"" + actual + "\")");
-        }
-    }
-
-    public void assertEquals(String message, int expected, int actual)
-    {
-        if (expected != actual) {
-            fail(message + " (expected \"" + expected
-                 + "\", actual \"" + actual + "\")");
-        }
-    }
-
-    /**
-     * Converts yesno string to boolean.
-     * @param yesno string representation of expected result
-     * @return true if yesno is "YES", false if yesno is "NO"
-     *         stops program otherwise.
-     */
-    private boolean getExpectedResult(String yesno)
-    {
-        if ("NO".equals(yesno))
-        {
-            return false;
-        }
-        else if ("YES".equals(yesno))
-        {
-            return true;
-        }
-        else
-        {
-            // Bad test script
-            die("Test script error!");
-            return false; //to please javac
-        }
-    }
-
-    /**
-     * Finds next test description in a given script.
-     * @param br <code>BufferedReader</code> for a script file
-     * @return strign tag for next test description
-     * @exception IOException if some io problems occured
-     */
-    private String findNextTest(BufferedReader br) throws IOException
-    {
-        String number = "";
-
-        while (br.ready())
-        {
-            number = br.readLine();
-            if (number == null)
-            {
-                break;
-            }
-            number = number.trim();
-            if (number.startsWith("#"))
-            {
-                break;
-            }
-            if (!number.equals(""))
-            {
-                say("Script error.  Line = " + number);
-                System.exit(-1);
-            }
-        }
-        return number;
-    }
-
-    /**
-     * Creates testcase for the next test description in the script file.
-     * @param br <code>BufferedReader</code> for script file.
-     * @return a new tescase or null.
-     * @exception IOException if some io problems occured
-     */
-    private RETestCase getNextTestCase(BufferedReader br) throws IOException
-    {
-        // Find next re test case
-        final String tag = findNextTest(br);
-
-        // Are we done?
-        if (!br.ready())
-        {
-            return null;
-        }
-
-        // Get expression
-        final String expr = br.readLine();
-
-        // Get test information
-        final String matchAgainst = br.readLine();
-        final boolean badPattern = "ERR".equals(matchAgainst);
-        boolean shouldMatch = false;
-        int expectedParenCount = 0;
-        String[] expectedParens = null;
-
-        if (!badPattern) {
-            shouldMatch = getExpectedResult(br.readLine().trim());
-            if (shouldMatch) {
-                expectedParenCount = Integer.parseInt(br.readLine().trim());
-                expectedParens = new String[expectedParenCount];
-                for (int i = 0; i < expectedParenCount; i++) {
-                    expectedParens[i] = br.readLine();
-                }
-            }
-        }
-
-        return new RETestCase(this, tag, expr, matchAgainst, badPattern,
-                              shouldMatch, expectedParens);
-    }
-}
-
-final class RETestCase
-{
-    final private StringBuffer log = new StringBuffer();
-    final private int number;
-    final private String tag; // number from script file
-    final private String pattern;
-    final private String toMatch;
-    final private boolean badPattern;
-    final private boolean shouldMatch;
-    final private String[] parens;
-    final private RETest test;
-    private RE regexp;
-
-    public RETestCase(RETest test, String tag, String pattern,
-                      String toMatch, boolean badPattern,
-                      boolean shouldMatch, String[] parens)
-    {
-        this.number = ++test.testCount;
-        this.test = test;
-        this.tag = tag;
-        this.pattern = pattern;
-        this.toMatch = toMatch;
-        this.badPattern = badPattern;
-        this.shouldMatch = shouldMatch;
-        if (parens != null) {
-            this.parens = new String[parens.length];
-            for (int i = 0; i < parens.length; i++) {
-                this.parens[i] = parens[i];
-            }
-        } else {
-            this.parens = null;
-        }
-    }
-
-    public void runTest()
-    {
-        test.say(tag + "(" + number + "): " + pattern);
-        if (testCreation()) {
-            testMatch();
-        }
-    }
-
-    boolean testCreation()
-    {
-        try
-        {
-            // Compile it
-            regexp = new RE();
-            regexp.setProgram(test.compiler.compile(pattern));
-            // Expression didn't cause an expected error
-            if (badPattern)
-            {
-                test.fail(log, "Was expected to be an error, but wasn't.");
-                return false;
-            }
-
-            return true;
-        }
-        // Some expressions *should* cause exceptions to be thrown
-        catch (Exception e)
-        {
-            // If it was supposed to be an error, report success and continue
-            if (badPattern)
-            {
-                log.append("   Match: ERR\n");
-                success("Produces an error (" + e.toString() + "), as expected.");
-                return false;
-            }
-
-            // Wasn't supposed to be an error
-            String message = (e.getMessage() == null) ? e.toString() : e.getMessage();
-            test.fail(log, "Produces an unexpected exception \"" + message + "\"");
-            e.printStackTrace();
-        }
-        catch (Error e)
-        {
-            // Internal error happened
-            test.fail(log, "Compiler threw fatal error \"" + e.getMessage() + "\"");
-            e.printStackTrace();
-        }
-
-        return false;
-    }
-
-    private void testMatch()
-    {
-        log.append("   Match against: '" + toMatch + "'\n");
-        // Try regular matching
-        try
-        {
-            // Match against the string
-            boolean result = regexp.match(toMatch);
-            log.append("   Matched: " + (result ? "YES" : "NO") + "\n");
-
-            // Check result, parens, and iterators
-            if (checkResult(result) && (!shouldMatch || checkParens()))
-            {
-                // test match(CharacterIterator, int)
-                // for every CharacterIterator implementation.
-                log.append("   Match using StringCharacterIterator\n");
-                if (!tryMatchUsingCI(new StringCharacterIterator(toMatch)))
-                    return;
-
-                log.append("   Match using CharacterArrayCharacterIterator\n");
-                if (!tryMatchUsingCI(new CharacterArrayCharacterIterator(toMatch.toCharArray(), 0, toMatch.length())))
-                    return;
-
-                log.append("   Match using StreamCharacterIterator\n");
-                if (!tryMatchUsingCI(new StreamCharacterIterator(new StringBufferInputStream(toMatch))))
-                    return;
-
-                log.append("   Match using ReaderCharacterIterator\n");
-                if (!tryMatchUsingCI(new ReaderCharacterIterator(new StringReader(toMatch))))
-                    return;
-            }
-        }
-        // Matcher blew it
-        catch(Exception e)
-        {
-            test.fail(log, "Matcher threw exception: " + e.toString());
-            e.printStackTrace();
-        }
-        // Internal error
-        catch(Error e)
-        {
-            test.fail(log, "Matcher threw fatal error \"" + e.getMessage() + "\"");
-            e.printStackTrace();
-        }
-    }
-
-    private boolean checkResult(boolean result)
-    {
-        // Write status
-        if (result == shouldMatch) {
-            success((shouldMatch ? "Matched" : "Did not match")
-                    + " \"" + toMatch + "\", as expected:");
-            return true;
-        } else {
-            if (shouldMatch) {
-                test.fail(log, "Did not match \"" + toMatch + "\", when expected to.");
-            } else {
-                test.fail(log, "Matched \"" + toMatch + "\", when not expected to.");
-            }
-            return false;
-        }
-    }
-
-    private boolean checkParens()
-    {
-        // Show subexpression registers
-        if (RETest.showSuccesses)
-        {
-            test.showParens(regexp);
-        }
-
-        log.append("   Paren count: " + regexp.getParenCount() + "\n");
-        if (!assertEquals(log, "Wrong number of parens", parens.length, regexp.getParenCount()))
-        {
-            return false;
-        }
-
-        // Check registers against expected contents
-        for (int p = 0; p < regexp.getParenCount(); p++)
-        {
-            log.append("   Paren " + p + ": " + regexp.getParen(p) + "\n");
-
-            // Compare expected result with actual
-            if ("null".equals(parens[p]) && regexp.getParen(p) == null)
-            {
-                // Consider "null" in test file equal to null
-                continue;
-            }
-            if (!assertEquals(log, "Wrong register " + p, parens[p], regexp.getParen(p)))
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    boolean tryMatchUsingCI(CharacterIterator matchAgainst)
-    {
-        try {
-            boolean result = regexp.match(matchAgainst, 0);
-            log.append("   Match: " + (result ? "YES" : "NO") + "\n");
-            return checkResult(result) && (!shouldMatch || checkParens());
-        }
-        // Matcher blew it
-        catch(Exception e)
-        {
-            test.fail(log, "Matcher threw exception: " + e.toString());
-            e.printStackTrace();
-        }
-        // Internal error
-        catch(Error e)
-        {
-            test.fail(log, "Matcher threw fatal error \"" + e.getMessage() + "\"");
-            e.printStackTrace();
-        }
-        return false;
-    }
-
-    public boolean assertEquals(StringBuffer log, String message, String expected, String actual)
-    {
-        if (expected != null && !expected.equals(actual)
-            || actual != null && !actual.equals(expected))
-        {
-            test.fail(log, message + " (expected \"" + expected
-                      + "\", actual \"" + actual + "\")");
-            return false;
-        }
-        return true;
-    }
-
-    public boolean assertEquals(StringBuffer log, String message, int expected, int actual)
-    {
-        if (expected != actual) {
-            test.fail(log, message + " (expected \"" + expected
-                      + "\", actual \"" + actual + "\")");
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Show a success
-     * @param s Success story
-     */
-    void success(String s)
-    {
-        if (RETest.showSuccesses)
-        {
-            test.say("" + RETest.NEW_LINE + "-----------------------" + RETest.NEW_LINE + "");
-            test.say("Expression #" + (number) + " \"" + pattern + "\" ");
-            test.say("Success: " + s);
-        }
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REUtil.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REUtil.java
deleted file mode 100644
index 10907ece8d6..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REUtil.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-/**
- * This is a class that contains utility helper methods for this package.
- *
- * @author <a href="mailto:jonl@muppetlabs.com">Jonathan Locke</a>
- */
-public class REUtil
-{
-    /** complex: */
-    private static final String complexPrefix = "complex:";
-
-    /**
-     * Creates a regular expression, permitting simple or complex syntax
-     * @param expression The expression, beginning with a prefix if it's complex or
-     * having no prefix if it's simple
-     * @param matchFlags Matching style flags
-     * @return The regular expression object
-     * @exception RESyntaxException thrown in case of error
-     */
-    public static RE createRE(String expression, int matchFlags) throws RESyntaxException
-    {
-        if (expression.startsWith(complexPrefix))
-        {
-            return new RE(expression.substring(complexPrefix.length()), matchFlags);
-        }
-        return new RE(RE.simplePatternToFullRegularExpression(expression), matchFlags);
-    }
-
-    /**
-     * Creates a regular expression, permitting simple or complex syntax
-     * @param expression The expression, beginning with a prefix if it's complex or
-     * having no prefix if it's simple
-     * @return The regular expression object
-     * @exception RESyntaxException thrown in case of error
-     */
-    public static RE createRE(String expression) throws RESyntaxException
-    {
-        return createRE(expression, RE.MATCH_NORMAL);
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/ReaderCharacterIterator.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/ReaderCharacterIterator.java
deleted file mode 100644
index 7eafff44121..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/ReaderCharacterIterator.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-import java.io.Reader;
-import java.io.IOException;
-
-/**
- * Encapsulates java.io.Reader as CharacterIterator
- *
- * @author <a href="mailto:ales.novak@netbeans.com">Ales Novak</a>
- */
-public final class ReaderCharacterIterator implements CharacterIterator
-{
-    /** Underlying reader */
-    private final Reader reader;
-
-    /** Buffer of read chars */
-    private final StringBuffer buff;
-
-    /** read end? */
-    private boolean closed;
-
-    /** @param reader a Reader, which is parsed */
-    public ReaderCharacterIterator(Reader reader)
-    {
-        this.reader = reader;
-        this.buff = new StringBuffer(512);
-        this.closed = false;
-    }
-
-    /** @return a substring */
-    public String substring(int beginIndex, int endIndex)
-    {
-        try
-        {
-            ensure(endIndex);
-            return buff.toString().substring(beginIndex, endIndex);
-        }
-        catch (IOException e)
-        {
-            throw new StringIndexOutOfBoundsException(e.getMessage());
-        }
-    }
-
-    /** @return a substring */
-    public String substring(int beginIndex)
-    {
-        try
-        {
-            readAll();
-            return buff.toString().substring(beginIndex);
-        }
-        catch (IOException e)
-        {
-            throw new StringIndexOutOfBoundsException(e.getMessage());
-        }
-    }
-
-    /** @return a character at the specified position. */
-    public char charAt(int pos)
-    {
-        try
-        {
-            ensure(pos);
-            return buff.charAt(pos);
-        }
-        catch (IOException e)
-        {
-            throw new StringIndexOutOfBoundsException(e.getMessage());
-        }
-    }
-
-    /** @return <tt>true</tt> iff if the specified index is after the end of the character stream */
-    public boolean isEnd(int pos)
-    {
-        if (buff.length() > pos)
-        {
-            return false;
-        }
-        else
-        {
-            try
-            {
-                ensure(pos);
-                return (buff.length() <= pos);
-            }
-            catch (IOException e)
-            {
-                throw new StringIndexOutOfBoundsException(e.getMessage());
-            }
-        }
-    }
-
-    /** Reads n characters from the stream and appends them to the buffer */
-    private int read(int n) throws IOException
-    {
-        if (closed)
-        {
-            return 0;
-        }
-
-        char[] c = new char[n];
-        int count = 0;
-        int read = 0;
-
-        do
-        {
-            read = reader.read(c);
-            if (read < 0) // EOF
-            {
-                closed = true;
-                break;
-            }
-            count += read;
-            buff.append(c, 0, read);
-        }
-        while (count < n);
-
-        return count;
-    }
-
-    /** Reads rest of the stream. */
-    private void readAll() throws IOException
-    {
-        while(! closed)
-        {
-            read(1000);
-        }
-    }
-
-    /** Reads chars up to the idx */
-    private void ensure(int idx) throws IOException
-    {
-        if (closed)
-        {
-            return;
-        }
-
-        if (idx < buff.length())
-        {
-            return;
-        }
-        read(idx + 1 - buff.length());
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/StreamCharacterIterator.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/StreamCharacterIterator.java
deleted file mode 100644
index e489065b79b..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/StreamCharacterIterator.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-/**
- * Encapsulates java.io.InputStream as CharacterIterator.
- *
- * @author <a href="mailto:ales.novak@netbeans.com">Ales Novak</a>
- */
-public final class StreamCharacterIterator implements CharacterIterator
-{
-    /** Underlying is */
-    private final InputStream is;
-
-    /** Buffer of read chars */
-    private final StringBuffer buff;
-
-    /** read end? */
-    private boolean closed;
-
-    /** @param is an InputStream, which is parsed */
-    public StreamCharacterIterator(InputStream is)
-    {
-        this.is = is;
-        this.buff = new StringBuffer(512);
-        this.closed = false;
-    }
-
-    /** @return a substring */
-    public String substring(int beginIndex, int endIndex)
-    {
-        try
-        {
-            ensure(endIndex);
-            return buff.toString().substring(beginIndex, endIndex);
-        }
-        catch (IOException e)
-        {
-            throw new StringIndexOutOfBoundsException(e.getMessage());
-        }
-    }
-
-    /** @return a substring */
-    public String substring(int beginIndex)
-    {
-        try
-        {
-            readAll();
-            return buff.toString().substring(beginIndex);
-        }
-        catch (IOException e)
-        {
-            throw new StringIndexOutOfBoundsException(e.getMessage());
-        }
-    }
-
-
-    /** @return a character at the specified position. */
-    public char charAt(int pos)
-    {
-        try
-        {
-            ensure(pos);
-            return buff.charAt(pos);
-        }
-        catch (IOException e)
-        {
-            throw new StringIndexOutOfBoundsException(e.getMessage());
-        }
-    }
-
-    /** @return <tt>true</tt> iff if the specified index is after the end of the character stream */
-    public boolean isEnd(int pos)
-    {
-        if (buff.length() > pos)
-        {
-            return false;
-        }
-        else
-        {
-            try
-            {
-                ensure(pos);
-                return (buff.length() <= pos);
-            }
-            catch (IOException e)
-            {
-                throw new StringIndexOutOfBoundsException(e.getMessage());
-            }
-        }
-    }
-
-    /** Reads n characters from the stream and appends them to the buffer */
-    private int read(int n) throws IOException
-    {
-        if (closed)
-        {
-            return 0;
-        }
-
-        int c;
-        int i = n;
-        while (--i >= 0)
-        {
-            c = is.read();
-            if (c < 0) // EOF
-            {
-                closed = true;
-                break;
-            }
-            buff.append((char) c);
-        }
-        return n - i;
-    }
-
-    /** Reads rest of the stream. */
-    private void readAll() throws IOException
-    {
-        while(! closed)
-        {
-            read(1000);
-        }
-    }
-
-    /** Reads chars up to the idx */
-    private void ensure(int idx) throws IOException
-    {
-        if (closed)
-        {
-            return;
-        }
-
-        if (idx < buff.length())
-        {
-            return;
-        }
-
-        read(idx + 1 - buff.length());
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/StringCharacterIterator.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/StringCharacterIterator.java
deleted file mode 100644
index bc6c859973c..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/StringCharacterIterator.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-/**
- * Encapsulates String as CharacterIterator.
- *
- * @author <a href="mailto:ales.novak@netbeans.com">Ales Novak</a>
- */
-public final class StringCharacterIterator implements CharacterIterator
-{
-    /** encapsulated */
-    private final String src;
-
-    /** @param src - encapsulated String */
-    public StringCharacterIterator(String src)
-    {
-        this.src = src;
-    }
-
-    /** @return a substring */
-    public String substring(int beginIndex, int endIndex)
-    {
-        return src.substring(beginIndex, endIndex);
-    }
-
-    /** @return a substring */
-    public String substring(int beginIndex)
-    {
-        return src.substring(beginIndex);
-    }
-
-    /** @return a character at the specified position. */
-    public char charAt(int pos)
-    {
-        return src.charAt(pos);
-    }
-
-    /** @return <tt>true</tt> iff if the specified index is after the end of the character stream */
-    public boolean isEnd(int pos)
-    {
-        return (pos >= src.length());
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/recompile.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/recompile.java
deleted file mode 100644
index fc0cbb3b977..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/recompile.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.regexp.internal;
-
-import com.sun.org.apache.regexp.internal.RECompiler;
-import com.sun.org.apache.regexp.internal.RESyntaxException;
-
-/**
- * 'recompile' is a command line tool that pre-compiles one or more regular expressions
- * for use with the regular expression matcher class 'RE'.  For example, the command
- * "java recompile a*b" produces output like this:
- *
- * <pre>
- *
- *    // Pre-compiled regular expression "a*b"
- *    char[] re1Instructions =
- *    {
- *        0x007c, 0x0000, 0x001a, 0x007c, 0x0000, 0x000d, 0x0041,
- *        0x0001, 0x0004, 0x0061, 0x007c, 0x0000, 0x0003, 0x0047,
- *        0x0000, 0xfff6, 0x007c, 0x0000, 0x0003, 0x004e, 0x0000,
- *        0x0003, 0x0041, 0x0001, 0x0004, 0x0062, 0x0045, 0x0000,
- *        0x0000,
- *    };
- *
- *    REProgram re1 = new REProgram(re1Instructions);
- *
- * </pre>
- *
- * By pasting this output into your code, you can construct a regular expression matcher
- * (RE) object directly from the pre-compiled data (the character array re1), thus avoiding
- * the overhead of compiling the expression at runtime.  For example:
- *
- * <pre>
- *
- *    RE r = new RE(re1);
- *
- * </pre>
- *
- * @see RE
- * @see RECompiler
- *
- * @author <a href="mailto:jonl@muppetlabs.com">Jonathan Locke</a>
- */
-public class recompile
-{
-    /**
-     * Main application entrypoint.
-     * @param arg Command line arguments
-     */
-    static public void main(String[] arg)
-    {
-        // Create a compiler object
-        RECompiler r = new RECompiler();
-
-        // Print usage if arguments are incorrect
-        if (arg.length <= 0 || arg.length % 2 != 0)
-        {
-            System.out.println("Usage: recompile <patternname> <pattern>");
-            System.exit(0);
-        }
-
-        // Loop through arguments, compiling each
-        for (int i = 0; i < arg.length; i += 2)
-        {
-            try
-            {
-                // Compile regular expression
-                String name         = arg[i];
-                String pattern      = arg[i+1];
-                String instructions = name + "PatternInstructions";
-
-                // Output program as a nice, formatted character array
-                System.out.print("\n    // Pre-compiled regular expression '" + pattern + "'\n"
-                                 + "    private static char[] " + instructions + " = \n    {");
-
-                // Compile program for pattern
-                REProgram program = r.compile(pattern);
-
-                // Number of columns in output
-                int numColumns = 7;
-
-                // Loop through program
-                char[] p = program.getInstructions();
-                for (int j = 0; j < p.length; j++)
-                {
-                    // End of column?
-                    if ((j % numColumns) == 0)
-                    {
-                        System.out.print("\n        ");
-                    }
-
-                    // Print character as padded hex number
-                    String hex = Integer.toHexString(p[j]);
-                    while (hex.length() < 4)
-                    {
-                        hex = "0" + hex;
-                    }
-                    System.out.print("0x" + hex + ", ");
-                }
-
-                // End of program block
-                System.out.println("\n    };");
-                System.out.println("\n    private static RE " + name + "Pattern = new RE(new REProgram(" + instructions + "));");
-            }
-            catch (RESyntaxException e)
-            {
-                System.out.println("Syntax error in expression \"" + arg[i] + "\": " + e.toString());
-            }
-            catch (Exception e)
-            {
-                System.out.println("Unexpected exception: " + e.toString());
-            }
-            catch (Error e)
-            {
-                System.out.println("Internal error: " + e.toString());
-            }
-        }
-    }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java
index 8262111f444..f3b9b50397a 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1345,6 +1345,15 @@ public final class XMLStreamWriterImpl extends AbstractMap implements XMLStreamW
         }
     }
 
+    /**
+     * Writes character reference in hex format.
+     */
+    private void writeCharRef(int codePoint) throws IOException {
+        fWriter.write( "&#x" );
+        fWriter.write( Integer.toHexString(codePoint) );
+        fWriter.write( ';' );
+    }
+
     /**
      * Writes XML content to underlying writer. Escapes characters unless
      * escaping character feature is turned off.
@@ -1368,10 +1377,14 @@ public final class XMLStreamWriterImpl extends AbstractMap implements XMLStreamW
             if (fEncoder != null && !fEncoder.canEncode(ch)){
                 fWriter.write(content, startWritePos, index - startWritePos );
 
-                // Escape this char as underlying encoder cannot handle it
-                fWriter.write( "&#x" );
-                fWriter.write(Integer.toHexString(ch));
-                fWriter.write( ';' );
+                // Check if current and next characters forms a surrogate pair
+                // and escape it to avoid generation of invalid xml content
+                if ( index != end - 1 && Character.isSurrogatePair(ch, content[index+1])) {
+                    writeCharRef(Character.toCodePoint(ch, content[index+1]));
+                    index++;
+                } else {
+                    writeCharRef(ch);
+                }
                 startWritePos = index + 1;
                 continue;
             }
@@ -1439,10 +1452,15 @@ public final class XMLStreamWriterImpl extends AbstractMap implements XMLStreamW
             if (fEncoder != null && !fEncoder.canEncode(ch)){
                 fWriter.write(content, startWritePos, index - startWritePos );
 
-                // Escape this char as underlying encoder cannot handle it
-                fWriter.write( "&#x" );
-                fWriter.write(Integer.toHexString(ch));
-                fWriter.write( ';' );
+                // Check if current and next characters forms a surrogate pair
+                // and escape it to avoid generation of invalid xml content
+                if ( index != end - 1 && Character.isSurrogatePair(ch, content.charAt(index+1))) {
+                    writeCharRef(Character.toCodePoint(ch, content.charAt(index+1)));
+                    index++;
+                } else {
+                    writeCharRef(ch);
+                }
+
                 startWritePos = index + 1;
                 continue;
             }
diff --git a/jaxp/src/java.xml/share/classes/module-info.java b/jaxp/src/java.xml/share/classes/module-info.java
index 3bd3fa340e7..ed48672adfc 100644
--- a/jaxp/src/java.xml/share/classes/module-info.java
+++ b/jaxp/src/java.xml/share/classes/module-info.java
@@ -86,5 +86,6 @@ module java.xml {
     uses javax.xml.transform.TransformerFactory;
     uses javax.xml.validation.SchemaFactory;
     uses javax.xml.xpath.XPathFactory;
+    uses org.xml.sax.XMLReader;
 }
 
diff --git a/jaxp/src/java.xml/share/classes/org/xml/sax/AttributeList.java b/jaxp/src/java.xml/share/classes/org/xml/sax/AttributeList.java
index 3b9f0f0f376..f79d5067c31 100644
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/AttributeList.java
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/AttributeList.java
@@ -93,6 +93,7 @@ package org.xml.sax;
  * @see org.xml.sax.DocumentHandler#startElement startElement
  * @see org.xml.sax.helpers.AttributeListImpl AttributeListImpl
  */
+@Deprecated(since="5")
 public interface AttributeList {
 
 
diff --git a/jaxp/src/java.xml/share/classes/org/xml/sax/DocumentHandler.java b/jaxp/src/java.xml/share/classes/org/xml/sax/DocumentHandler.java
index 0c8b93b85b2..91cdac156ca 100644
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/DocumentHandler.java
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/DocumentHandler.java
@@ -68,6 +68,7 @@ package org.xml.sax;
  * @see org.xml.sax.Locator
  * @see org.xml.sax.HandlerBase
  */
+@Deprecated(since="5")
 public interface DocumentHandler {
 
 
diff --git a/jaxp/src/java.xml/share/classes/org/xml/sax/Parser.java b/jaxp/src/java.xml/share/classes/org/xml/sax/Parser.java
index 099df32951b..fef6e44843b 100644
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/Parser.java
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/Parser.java
@@ -73,6 +73,7 @@ import java.util.Locale;
  * @see org.xml.sax.HandlerBase
  * @see org.xml.sax.InputSource
  */
+@Deprecated(since="5")
 public interface Parser
 {
 
diff --git a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/NewInstance.java b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/NewInstance.java
index c3516b17b5a..acd3996d014 100644
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/NewInstance.java
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/NewInstance.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,8 +32,7 @@
 
 package org.xml.sax.helpers;
 
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
+import java.util.Objects;
 
 /**
  * Create a new instance of a class by name.
@@ -57,31 +56,26 @@ import java.lang.reflect.InvocationTargetException;
  * @version 2.0.1 (sax2r2)
  */
 class NewInstance {
+
     private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xerces.internal";
     /**
      * Creates a new instance of the specified class name
      *
      * Package private so this code is not exposed at the API level.
      */
-    static Object newInstance (ClassLoader classLoader, String className)
+    static <T> T newInstance (Class<T> type, ClassLoader loader, String clsName)
         throws ClassNotFoundException, IllegalAccessException,
             InstantiationException
     {
-        // make sure we have access to restricted packages
-        boolean internal = false;
-        if (System.getSecurityManager() != null) {
-            if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
-                internal = true;
-            }
+        ClassLoader classLoader = Objects.requireNonNull(loader);
+        String className = Objects.requireNonNull(clsName);
+
+        if (className.startsWith(DEFAULT_PACKAGE)) {
+            return type.cast(new com.sun.org.apache.xerces.internal.parsers.SAXParser());
         }
 
-        Class driverClass;
-        if (classLoader == null || internal) {
-            driverClass = Class.forName(className);
-        } else {
-            driverClass = classLoader.loadClass(className);
-        }
-        return driverClass.newInstance();
+        Class<?> driverClass = classLoader.loadClass(className);
+        return type.cast(driverClass.newInstance());
     }
 
 }
diff --git a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/ParserFactory.java b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/ParserFactory.java
index efbefe01509..6e658867220 100644
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/ParserFactory.java
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/ParserFactory.java
@@ -30,8 +30,6 @@
 
 package org.xml.sax.helpers;
 
-import org.xml.sax.Parser;
-
 
 /**
  * Java-specific class for dynamically loading SAX parsers.
@@ -65,6 +63,8 @@ import org.xml.sax.Parser;
  * @author David Megginson
  * @version 2.0.1 (sax2r2)
  */
+@SuppressWarnings( "deprecation" )
+@Deprecated(since="5")
 public class ParserFactory {
     private static SecuritySupport ss = new SecuritySupport();
 
@@ -97,7 +97,7 @@ public class ParserFactory {
      * @see #makeParser(java.lang.String)
      * @see org.xml.sax.Parser
      */
-    public static Parser makeParser ()
+    public static org.xml.sax.Parser makeParser ()
         throws ClassNotFoundException,
         IllegalAccessException,
         InstantiationException,
@@ -134,14 +134,13 @@ public class ParserFactory {
      * @see #makeParser()
      * @see org.xml.sax.Parser
      */
-    public static Parser makeParser (String className)
+    public static org.xml.sax.Parser makeParser (String className)
         throws ClassNotFoundException,
         IllegalAccessException,
         InstantiationException,
         ClassCastException
     {
-        return (Parser) NewInstance.newInstance (
-                ss.getContextClassLoader(), className);
+        return NewInstance.newInstance (org.xml.sax.Parser.class, ss.getClassLoader(), className);
     }
 
 }
diff --git a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/SecuritySupport.java b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/SecuritySupport.java
index ecd5696942d..3d753b1dcd3 100644
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/SecuritySupport.java
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/SecuritySupport.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -37,72 +37,56 @@ import java.security.*;
  */
 class SecuritySupport  {
 
-
-    ClassLoader getContextClassLoader() throws SecurityException{
-        return (ClassLoader)
-                AccessController.doPrivileged(new PrivilegedAction() {
-            public Object run() {
-                ClassLoader cl = null;
-                //try {
-                cl = Thread.currentThread().getContextClassLoader();
-                //} catch (SecurityException ex) { }
-
-                if (cl == null)
-                    cl = ClassLoader.getSystemClassLoader();
-
-                return cl;
+    /**
+     * Returns the current thread's context class loader, or the system class loader
+     * if the context class loader is null.
+     * @return the current thread's context class loader, or the system class loader
+     * @throws SecurityException
+     */
+    ClassLoader getClassLoader() throws SecurityException{
+        return AccessController.doPrivileged((PrivilegedAction<ClassLoader>)() -> {
+            ClassLoader cl = Thread.currentThread().getContextClassLoader();
+            if (cl == null) {
+                cl = ClassLoader.getSystemClassLoader();
             }
+
+            return cl;
         });
     }
 
     String getSystemProperty(final String propName) {
-        return (String)
-            AccessController.doPrivileged(new PrivilegedAction() {
-                public Object run() {
-                    return System.getProperty(propName);
-                }
-            });
+        return AccessController.doPrivileged((PrivilegedAction<String>)()
+                -> System.getProperty(propName));
     }
 
     FileInputStream getFileInputStream(final File file)
         throws FileNotFoundException
     {
         try {
-            return (FileInputStream)
-                AccessController.doPrivileged(new PrivilegedExceptionAction() {
-                    public Object run() throws FileNotFoundException {
-                        return new FileInputStream(file);
-                    }
-                });
+            return AccessController.doPrivileged((PrivilegedExceptionAction<FileInputStream>)() ->
+                    new FileInputStream(file));
         } catch (PrivilegedActionException e) {
             throw (FileNotFoundException)e.getException();
         }
     }
 
-    InputStream getResourceAsStream(final ClassLoader cl,
-                                           final String name)
+
+    InputStream getResourceAsStream(final ClassLoader cl, final String name)
     {
-        return (InputStream)
-            AccessController.doPrivileged(new PrivilegedAction() {
-                public Object run() {
-                    InputStream ris;
-                    if (cl == null) {
-                        ris = SecuritySupport.class.getResourceAsStream(name);
-                    } else {
-                        ris = cl.getResourceAsStream(name);
-                    }
-                    return ris;
-                }
-            });
+        return AccessController.doPrivileged((PrivilegedAction<InputStream>) () -> {
+            InputStream ris;
+            if (cl == null) {
+                ris = SecuritySupport.class.getResourceAsStream(name);
+            } else {
+                ris = cl.getResourceAsStream(name);
+            }
+            return ris;
+        });
     }
 
     boolean doesFileExist(final File f) {
-    return ((Boolean)
-            AccessController.doPrivileged(new PrivilegedAction() {
-                public Object run() {
-                    return new Boolean(f.exists());
-                }
-            })).booleanValue();
+        return (AccessController.doPrivileged((PrivilegedAction<Boolean>)() ->
+                new Boolean(f.exists())));
     }
 
 }
diff --git a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/XMLReaderFactory.java b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/XMLReaderFactory.java
index 9635e4cf777..6b183ff7350 100644
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/XMLReaderFactory.java
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/XMLReaderFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,10 +32,17 @@
 
 package org.xml.sax.helpers;
 import java.io.BufferedReader;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import org.xml.sax.XMLReader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
 
 
 /**
@@ -70,7 +77,11 @@ import org.xml.sax.SAXException;
  * @since 1.4, SAX 2.0
  * @author David Megginson, David Brownell
  * @version 2.0.1 (sax2r2)
+ *
+ * @deprecated It is recommended to use {@link javax.xml.parsers.SAXParserFactory}
+ * instead.
  */
+@Deprecated(since="9")
 final public class XMLReaderFactory
 {
     /**
@@ -83,47 +94,43 @@ final public class XMLReaderFactory
     }
 
     private static final String property = "org.xml.sax.driver";
-    private static SecuritySupport ss = new SecuritySupport();
+    private static final SecuritySupport ss = new SecuritySupport();
 
-    private static String _clsFromJar = null;
-    private static boolean _jarread = false;
     /**
-     * Attempt to create an XMLReader from system defaults.
-     * In environments which can support it, the name of the XMLReader
-     * class is determined by trying each these options in order, and
-     * using the first one which succeeds:
-     * <ul>
-     *
+     * Obtains a new instance of a {@link org.xml.sax.XMLReader}.
+     * This method uses the following ordered lookup procedure to find and load
+     * the {@link org.xml.sax.XMLReader} implementation class:
+     * <p>
+     * <ol>
      * <li>If the system property {@code org.xml.sax.driver}
      * has a value, that is used as an XMLReader class name. </li>
+     * <li>
+     * Use the service-provider loading facility, defined by the
+     * {@link java.util.ServiceLoader} class, to attempt to locate and load an
+     * implementation of the service {@link org.xml.sax.XMLReader} by using the
+     * {@linkplain java.lang.Thread#getContextClassLoader() current thread's context class loader}.
+     * If the context class loader is null, the
+     * {@linkplain ClassLoader#getSystemClassLoader() system class loader} will
+     * be used.
+     * </li>
+     * <li>
+     * Deprecated. Look for a class name in the {@code META-INF/services/org.xml.sax.driver}
+     * file in a jar file available to the runtime.</li>
+     * <li>
+     * <p>
+     * Otherwise, the system-default implementation is returned.
+     * </li>
+     * </ol>
      *
-     * <li>The JAR "Services API" is used to look for a class name
-     * in the <em>META-INF/services/org.xml.sax.driver</em> file in
-     * jarfiles available to the runtime.</li>
+     * @apiNote
+     * The process that looks for a class name in the
+     * {@code META-INF/services/org.xml.sax.driver} file in a jar file does not
+     * conform to the specification of the service-provider loading facility
+     * as defined in {@link java.util.ServiceLoader} and therefore does not
+     * support modularization. It is deprecated as of Java SE 9 and subject to
+     * removal in a future release.
      *
-     * <li> SAX parser distributions are strongly encouraged to provide
-     * a default XMLReader class name that will take effect only when
-     * previous options (on this list) are not successful.</li>
-     *
-     * <li>Finally, if {@link ParserFactory#makeParser()} can
-     * return a system default SAX1 parser, that parser is wrapped in
-     * a {@link ParserAdapter}.  (This is a migration aid for SAX1
-     * environments, where the {@code org.xml.sax.parser} system
-     * property will often be usable.) </li>
-     * </ul>
-     *
-     * <p> In environments such as small embedded systems, which can not
-     * support that flexibility, other mechanisms to determine the default
-     * may be used.
-     *
-     * <p>Note that many Java environments allow system properties to be
-     * initialized on a command line.  This means that <em>in most cases</em>
-     * setting a good value for that property ensures that calls to this
-     * method will succeed, except when security policies intervene.
-     * This will also maximize application portability to older SAX
-     * environments, with less robust implementations of this method.
-     *
-     * @return A new XMLReader.
+     * @return a new XMLReader.
      * @exception org.xml.sax.SAXException If no default XMLReader class
      *            can be identified and instantiated.
      * @see #createXMLReader(java.lang.String)
@@ -132,7 +139,7 @@ final public class XMLReaderFactory
         throws SAXException
     {
         String          className = null;
-        ClassLoader     cl = ss.getContextClassLoader();
+        ClassLoader     cl = ss.getClassLoader();
 
         // 1. try the JVM-instance-wide system property
         try {
@@ -140,62 +147,26 @@ final public class XMLReaderFactory
         }
         catch (RuntimeException e) { /* continue searching */ }
 
-        // 2. if that fails, try META-INF/services/
+        // 2. try the ServiceLoader
         if (className == null) {
-            if (!_jarread) {
-                _jarread = true;
-                String      service = "META-INF/services/" + property;
-                InputStream in;
-                BufferedReader      reader;
-
-                try {
-                    if (cl != null) {
-                        in = ss.getResourceAsStream(cl, service);
-
-                        // If no provider found then try the current ClassLoader
-                        if (in == null) {
-                            cl = null;
-                            in = ss.getResourceAsStream(cl, service);
-                        }
-                    } else {
-                        // No Context ClassLoader, try the current ClassLoader
-                        in = ss.getResourceAsStream(cl, service);
-                    }
-
-                    if (in != null) {
-                        reader = new BufferedReader (new InputStreamReader (in, "UTF8"));
-                        _clsFromJar = reader.readLine ();
-                        in.close ();
-                    }
-                } catch (Exception e) {
-                }
+            final XMLReader provider = findServiceProvider(XMLReader.class, cl);
+            if (provider != null) {
+                return provider;
             }
-            className = _clsFromJar;
         }
 
-        // 3. Distro-specific fallback
+        // 3. try META-INF/services/org.xml.sax.driver. This old process allows
+        // legacy providers to be found
         if (className == null) {
-// BEGIN DISTRIBUTION-SPECIFIC
-
-            // EXAMPLE:
-            // className = "com.example.sax.XmlReader";
-            // or a $JAVA_HOME/jre/lib/*properties setting...
-            className = "com.sun.org.apache.xerces.internal.parsers.SAXParser";
-
-// END DISTRIBUTION-SPECIFIC
+            className = jarLookup(cl);
         }
 
-        // do we know the XMLReader implementation class yet?
-        if (className != null)
-            return loadClass (cl, className);
-
-        // 4. panic -- adapt any SAX1 parser
-        try {
-            return new ParserAdapter (ParserFactory.makeParser ());
-        } catch (Exception e) {
-            throw new SAXException ("Can't create default XMLReader; "
-                    + "is system property org.xml.sax.driver set?");
+        // 4. Distro-specific fallback
+        if (className == null) {
+            return new com.sun.org.apache.xerces.internal.parsers.SAXParser();
         }
+
+        return loadClass (cl, className);
     }
 
 
@@ -217,14 +188,14 @@ final public class XMLReaderFactory
     public static XMLReader createXMLReader (String className)
         throws SAXException
     {
-        return loadClass (ss.getContextClassLoader(), className);
+        return loadClass (ss.getClassLoader(), className);
     }
 
     private static XMLReader loadClass (ClassLoader loader, String className)
     throws SAXException
     {
         try {
-            return (XMLReader) NewInstance.newInstance (loader, className);
+            return NewInstance.newInstance (XMLReader.class, loader, className);
         } catch (ClassNotFoundException e1) {
             throw new SAXException("SAX2 driver class " + className +
                                    " not found", e1);
@@ -240,4 +211,64 @@ final public class XMLReaderFactory
                                    " does not implement XMLReader", e4);
         }
     }
+
+    /**
+     * Locates a provider by directly reading the jar service file.
+     * @param loader the ClassLoader to be used to read the service file
+     * @return the name of the provider, or null if nothing is found
+     */
+    private static String jarLookup(final ClassLoader loader) {
+        final ClassLoader cl = Objects.requireNonNull(loader);
+        String clsFromJar = null;
+        String service = "META-INF/services/" + property;
+        InputStream in;
+        BufferedReader      reader;
+
+        try {
+            in = ss.getResourceAsStream(cl, service);
+
+            // If no provider found then try the current ClassLoader
+            if (in == null) {
+                in = ss.getResourceAsStream(null, service);
+            }
+
+            if (in != null) {
+                reader = new BufferedReader (new InputStreamReader (in, "UTF8"));
+                clsFromJar = reader.readLine ();
+                in.close ();
+            }
+        } catch (IOException e) {
+        }
+        return clsFromJar;
+    }
+
+    /*
+     * Try to find provider using the ServiceLoader API
+     *
+     * @param type Base class / Service interface of the factory to find.
+     *
+     * @return instance of provider class if found or null
+     */
+    private static <T> T findServiceProvider(final Class<T> type, final ClassLoader loader)
+            throws SAXException {
+        ClassLoader cl = Objects.requireNonNull(loader);
+        try {
+            return AccessController.doPrivileged((PrivilegedAction<T>) () -> {
+                final ServiceLoader<T> serviceLoader;
+                serviceLoader = ServiceLoader.load(type, cl);
+                final Iterator<T> iterator = serviceLoader.iterator();
+                if (iterator.hasNext()) {
+                    return iterator.next();
+                } else {
+                    return null;
+                }
+            });
+        } catch(ServiceConfigurationError e) {
+            final RuntimeException x = new RuntimeException(
+                    "Provider for " + type + " cannot be created", e);
+            throw new SAXException("Provider for " + type + " cannot be created", x);
+
+          }
+      }
+
 }
diff --git a/jaxp/test/Makefile b/jaxp/test/Makefile
index 912f2b98406..bf94d252889 100644
--- a/jaxp/test/Makefile
+++ b/jaxp/test/Makefile
@@ -76,14 +76,20 @@ endif
 TEST_ROOT := $(shell $(PWD))
 
 # Root of all test results
-ifdef ALT_OUTPUTDIR
-  ABS_OUTPUTDIR = $(shell $(CD) $(ALT_OUTPUTDIR) && $(PWD))
+ifdef TEST_OUTPUT_DIR
+  $(shell $(MKDIR) -p $(TEST_OUTPUT_DIR)/jtreg)
+  ABS_TEST_OUTPUT_DIR := \
+    $(shell $(CD) $(TEST_OUTPUT_DIR)/jtreg && $(PWD))
 else
-  ABS_OUTPUTDIR = $(shell $(CD) $(TEST_ROOT)/.. && $(PWD))
-endif
+  ifdef ALT_OUTPUTDIR
+    ABS_OUTPUTDIR = $(shell $(CD) $(ALT_OUTPUTDIR) && $(PWD))
+  else
+    ABS_OUTPUTDIR = $(shell $(CD) $(TEST_ROOT)/.. && $(PWD))
+  endif
 
-ABS_PLATFORM_BUILD_ROOT = $(ABS_OUTPUTDIR)
-ABS_TEST_OUTPUT_DIR := $(ABS_PLATFORM_BUILD_ROOT)/testoutput/$(UNIQUE_DIR)
+  ABS_PLATFORM_BUILD_ROOT = $(ABS_OUTPUTDIR)
+  ABS_TEST_OUTPUT_DIR := $(ABS_PLATFORM_BUILD_ROOT)/testoutput/$(UNIQUE_DIR)
+endif
 
 # Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
 ifndef PRODUCT_HOME
diff --git a/jaxp/test/ProblemList.txt b/jaxp/test/ProblemList.txt
index c9aaf13d1fb..b6b8b41ba4f 100644
--- a/jaxp/test/ProblemList.txt
+++ b/jaxp/test/ProblemList.txt
@@ -29,3 +29,5 @@ javax/xml/jaxp/isolatedjdk/catalog/PropertiesTest.sh            generic-all
 # 8150145
 javax/xml/jaxp/unittest/common/TransformationWarningsTest.java	generic-all
 
+# 8156508
+javax/xml/jaxp/unittest/stream/FactoryFindTest.java             generic-all
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java
index c3403f9d1d0..c2bf928ba1f 100644
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java
@@ -38,7 +38,7 @@ import org.testng.annotations.Test;
  * @library /javax/xml/jaxp/libs
  * @build jdk.testlibrary.*
  * @run testng BasicModularXMLParserTest
- * @bug 8078820
+ * @bug 8078820 8156119
  * @summary Tests JAXP lib can instantiate the following interfaces
  *          with customized provider module on boot layer
  *
@@ -51,6 +51,7 @@ import org.testng.annotations.Test;
  *          javax.xml.transform.TransformerFactory
  *          javax.xml.validation.SchemaFactory
  *          javax.xml.xpath.XPathFactory
+ *          org.xml.sax.XMLReader
  */
 
 @Test
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java
index 45f24001278..3e157679b9e 100644
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java
@@ -50,7 +50,7 @@ import jdk.testlibrary.CompilerUtils;
  * @library /javax/xml/jaxp/libs
  * @build jdk.testlibrary.*
  * @run testng LayerModularXMLParserTest
- * @bug 8078820
+ * @bug 8078820 8156119
  * @summary Tests JAXP lib works with layer and TCCL
  */
 
@@ -75,7 +75,7 @@ public class LayerModularXMLParserTest {
      * services provided by provider2
      */
     private static final String[] services2 = { "javax.xml.datatype.DatatypeFactory",
-            "javax.xml.stream.XMLEventFactory" };
+            "javax.xml.stream.XMLEventFactory", "org.xml.sax.XMLReader" };
 
     /*
      * Compiles all modules used by the test
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/XMLReaderFactoryTest.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/XMLReaderFactoryTest.java
new file mode 100644
index 00000000000..ef3507fe9d1
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/XMLReaderFactoryTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.testlibrary.CompilerUtils;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/*
+ * @test
+ * @library /javax/xml/jaxp/libs
+ * @build jdk.testlibrary.*
+ * @run testng XMLReaderFactoryTest
+ * @bug 8152912 8015099 8156119
+ * @summary Tests XMLReaderFactory can work as ServiceLoader compliant, as well as backward compatible
+ */
+
+@Test
+public class XMLReaderFactoryTest {
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src").resolve("xmlprovider3");
+    private static final Path CLASSES_DIR = Paths.get("classes");
+    private static final Path LEGACY_DIR = CLASSES_DIR.resolve("legacy");
+    private static final Path SERVICE_DIR = CLASSES_DIR.resolve("service");
+
+    // resources to copy to the class path
+    private static final String LEGACY_SERVICE_FILE = "legacy/META-INF/services/org.xml.sax.driver";
+    private static final String SERVICE_FILE = "service/META-INF/services/org.xml.sax.XMLReader";
+
+    /*
+     * Compile class and copy service files
+     */
+    @BeforeTest
+    public void setup() throws Exception {
+        setup(LEGACY_DIR, LEGACY_SERVICE_FILE);
+        setup(SERVICE_DIR, SERVICE_FILE);
+    }
+
+    private void setup(Path dest, String serviceFile) throws Exception {
+        Files.createDirectories(dest);
+        assertTrue(CompilerUtils.compile(SRC_DIR, dest));
+
+        Path file = Paths.get(serviceFile.replace('/', File.separatorChar));
+        Path source = SRC_DIR.resolve(file);
+        Path target = CLASSES_DIR.resolve(file);
+        Files.createDirectories(target.getParent());
+        Files.copy(source, target);
+
+    }
+
+    public void testService() throws Exception {
+        ClassLoader clBackup = Thread.currentThread().getContextClassLoader();
+        try {
+            URL[] classUrls = { SERVICE_DIR.toUri().toURL() };
+            URLClassLoader loader = new URLClassLoader(classUrls, ClassLoader.getSystemClassLoader().getParent());
+
+            // set TCCL and try locating the provider
+            Thread.currentThread().setContextClassLoader(loader);
+            XMLReader reader = XMLReaderFactory.createXMLReader();
+            assertEquals(reader.getClass().getName(), "xp3.XMLReaderImpl");
+        } finally {
+            Thread.currentThread().setContextClassLoader(clBackup);
+        }
+    }
+
+    public void testLegacy() throws Exception {
+        ClassLoader clBackup = Thread.currentThread().getContextClassLoader();
+        try {
+            URL[] classUrls = { LEGACY_DIR.toUri().toURL() };
+            URLClassLoader loader = new URLClassLoader(classUrls, ClassLoader.getSystemClassLoader().getParent());
+
+            // set TCCL and try locating the provider
+            Thread.currentThread().setContextClassLoader(loader);
+            XMLReader reader1 = XMLReaderFactory.createXMLReader();
+            assertEquals(reader1.getClass().getName(), "xp3.XMLReaderImpl");
+
+            // now point to a random URL
+            Thread.currentThread().setContextClassLoader(
+                    new URLClassLoader(new URL[0], ClassLoader.getSystemClassLoader().getParent()));
+            // ClassNotFoundException if also trying to load class of reader1, which
+            // would be the case before 8152912
+            XMLReader reader2 = XMLReaderFactory.createXMLReader();
+            assertEquals(reader2.getClass().getName(), "com.sun.org.apache.xerces.internal.parsers.SAXParser");
+        } finally {
+            Thread.currentThread().setContextClassLoader(clBackup);
+        }
+    }
+}
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java
index 6dfaec5cedf..4f4a530a288 100644
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java
@@ -31,6 +31,8 @@ import java.lang.System;
 import java.util.Iterator;
 import java.util.ServiceLoader;
 
+import org.xml.sax.helpers.XMLReaderFactory;
+
 public class XMLFactoryHelper {
     /*
      * instantiate a xml factory by reflection e.g.
@@ -41,7 +43,9 @@ public class XMLFactoryHelper {
         try {
             // set thread context class loader to module class loader
             Thread.currentThread().setContextClassLoader(XMLFactoryHelper.class.getClassLoader());
-            if (serviceName.equals("javax.xml.validation.SchemaFactory"))
+            if (serviceName.equals("org.xml.sax.XMLReader"))
+                return XMLReaderFactory.createXMLReader();
+            else if (serviceName.equals("javax.xml.validation.SchemaFactory"))
                 return Class.forName(serviceName).getMethod("newInstance", String.class)
                         .invoke(null, W3C_XML_SCHEMA_NS_URI);
             else
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java
index cb0a37e916b..ee3e3e004d5 100644
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java
@@ -30,6 +30,8 @@ import java.util.HashSet;
 import java.util.Set;
 import java.util.stream.Stream;
 
+import org.xml.sax.helpers.XMLReaderFactory;
+
 public class Main {
     /*
      * @param args, the names of provider modules, which have been loaded
@@ -69,7 +71,9 @@ public class Main {
      */
     private static Object instantiateXMLService(String serviceName) {
         try {
-            if (serviceName.equals("javax.xml.validation.SchemaFactory"))
+            if (serviceName.equals("org.xml.sax.XMLReader"))
+                return XMLReaderFactory.createXMLReader();
+            else if (serviceName.equals("javax.xml.validation.SchemaFactory"))
                 return Class.forName(serviceName).getMethod("newInstance", String.class)
                         .invoke(null, W3C_XML_SCHEMA_NS_URI);
             else
@@ -102,6 +106,7 @@ public class Main {
             "javax.xml.parsers.DocumentBuilderFactory", "javax.xml.parsers.SAXParserFactory",
             "javax.xml.stream.XMLEventFactory", "javax.xml.stream.XMLInputFactory",
             "javax.xml.stream.XMLOutputFactory", "javax.xml.transform.TransformerFactory",
-            "javax.xml.validation.SchemaFactory", "javax.xml.xpath.XPathFactory" };
+            "javax.xml.validation.SchemaFactory", "javax.xml.xpath.XPathFactory",
+            "org.xml.sax.XMLReader"};
 
 }
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java
index d55645e58e9..c8bc623aa7a 100644
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java
@@ -26,4 +26,5 @@ module xmlprovider2 {
 
     provides javax.xml.datatype.DatatypeFactory with xp2.DatatypeFactoryImpl;
     provides javax.xml.stream.XMLEventFactory with xp2.XMLEventFactoryImpl;
+    provides org.xml.sax.XMLReader with xp2.XMLReaderImpl;
 }
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLReaderImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLReaderImpl.java
new file mode 100644
index 00000000000..0b6276f818e
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLReaderImpl.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package xp2;
+
+import java.io.IOException;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+
+public class XMLReaderImpl implements XMLReader {
+
+    @Override
+    public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
+        return false;
+    }
+
+    @Override
+    public void setFeature(String name, boolean value) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+    }
+
+    @Override
+    public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
+        return null;
+    }
+
+    @Override
+    public void setProperty(String name, Object value) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+    }
+
+    @Override
+    public void setEntityResolver(EntityResolver resolver) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public EntityResolver getEntityResolver() {
+        return null;
+    }
+
+    @Override
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    @Override
+    public DTDHandler getDTDHandler() {
+        return null;
+    }
+
+    @Override
+    public void setContentHandler(ContentHandler handler) {
+    }
+
+    @Override
+    public ContentHandler getContentHandler() {
+        return null;
+    }
+
+    @Override
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    @Override
+    public ErrorHandler getErrorHandler() {
+        return null;
+    }
+
+    @Override
+    public void parse(InputSource input) throws IOException, SAXException {
+    }
+
+    @Override
+    public void parse(String systemId) throws IOException, SAXException {
+    }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/legacy/META-INF/services/org.xml.sax.driver b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/legacy/META-INF/services/org.xml.sax.driver
new file mode 100644
index 00000000000..ef9ddc888ef
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/legacy/META-INF/services/org.xml.sax.driver
@@ -0,0 +1 @@
+xp3.XMLReaderImpl
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/service/META-INF/services/org.xml.sax.XMLReader b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/service/META-INF/services/org.xml.sax.XMLReader
new file mode 100644
index 00000000000..ef9ddc888ef
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/service/META-INF/services/org.xml.sax.XMLReader
@@ -0,0 +1 @@
+xp3.XMLReaderImpl
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/xp3/XMLReaderImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/xp3/XMLReaderImpl.java
new file mode 100644
index 00000000000..80738a961c1
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/xp3/XMLReaderImpl.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package xp3;
+
+import java.io.IOException;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+
+public class XMLReaderImpl implements XMLReader {
+
+    @Override
+    public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
+        return false;
+    }
+
+    @Override
+    public void setFeature(String name, boolean value) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+    }
+
+    @Override
+    public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
+        return null;
+    }
+
+    @Override
+    public void setProperty(String name, Object value) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+    }
+
+    @Override
+    public void setEntityResolver(EntityResolver resolver) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public EntityResolver getEntityResolver() {
+        return null;
+    }
+
+    @Override
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    @Override
+    public DTDHandler getDTDHandler() {
+        return null;
+    }
+
+    @Override
+    public void setContentHandler(ContentHandler handler) {
+    }
+
+    @Override
+    public ContentHandler getContentHandler() {
+        return null;
+    }
+
+    @Override
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    @Override
+    public ErrorHandler getErrorHandler() {
+        return null;
+    }
+
+    @Override
+    public void parse(InputSource input) throws IOException, SAXException {
+    }
+
+    @Override
+    public void parse(String systemId) throws IOException, SAXException {
+    }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/SurrogatesTest.java b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/SurrogatesTest.java
new file mode 100644
index 00000000000..a24c6b8b54f
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/SurrogatesTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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 stream.XMLStreamWriterTest;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+
+/*
+ * @test
+ * @bug 8145974
+ * @modules javax.xml
+ * @summary Check that XMLStreamWriter generates valid xml with surrogate pair
+ *  used within element text
+ */
+
+public class SurrogatesTest {
+
+    // Test that valid surrogate characters can be written/readen by xml stream
+    // reader/writer
+    @Test(dataProvider = "validData")
+    public void xmlWithValidSurrogatesTest(String content)
+            throws Exception {
+        generateAndReadXml(content);
+    }
+
+    // Test that unbalanced surrogate character will
+    @Test(dataProvider = "invalidData",
+            expectedExceptions = XMLStreamException.class)
+    public void xmlWithUnbalancedSurrogatesTest(String content)
+            throws Exception {
+        generateAndReadXml(content);
+    }
+
+    // Generates xml content with XMLStreamWriter and read it to check
+    // for correctness of xml and generated data
+    void generateAndReadXml(String content) throws Exception {
+        ByteArrayOutputStream stream = new ByteArrayOutputStream();
+        XMLOutputFactory factory = XMLOutputFactory.newInstance();
+        OutputStreamWriter streamWriter = new OutputStreamWriter(stream);
+        XMLStreamWriter writer = factory.createXMLStreamWriter(streamWriter);
+
+        // Generate xml with selected stream writer type
+        generateXML(writer, content);
+        String output = stream.toString();
+        System.out.println("Generated xml: " + output);
+        // Read generated xml with StAX parser
+        readXML(output.getBytes(), content);
+    }
+
+    // Generates XML with provided xml stream writer. Provided string
+    // is inserted into xml twice: with usage of writeCharacters( String )
+    // and writeCharacters( char [], int , int )
+    private void generateXML(XMLStreamWriter writer, String sequence)
+            throws XMLStreamException {
+        char[] seqArr = sequence.toCharArray();
+        writer.writeStartDocument();
+        writer.writeStartElement("root");
+
+        // Use writeCharacters( String ) to write characters
+        writer.writeStartElement("writeCharactersWithString");
+        writer.writeCharacters(sequence);
+        writer.writeEndElement();
+
+        // Use writeCharacters( char [], int , int ) to write characters
+        writer.writeStartElement("writeCharactersWithArray");
+        writer.writeCharacters(seqArr, 0, seqArr.length);
+        writer.writeEndElement();
+
+        // Close root element and document
+        writer.writeEndElement();
+        writer.writeEndDocument();
+        writer.flush();
+        writer.close();
+    }
+
+    // Reads generated XML data and check if it contains expected
+    // text in writeCharactersWithString and writeCharactersWithArray
+    // elements
+    private void readXML(byte[] xmlData, String expectedContent)
+            throws Exception {
+        InputStream stream = new ByteArrayInputStream(xmlData);
+        XMLInputFactory factory = XMLInputFactory.newInstance();
+        XMLStreamReader xmlReader
+                = factory.createXMLStreamReader(stream);
+        boolean inTestElement = false;
+        StringBuilder sb = new StringBuilder();
+        while (xmlReader.hasNext()) {
+            String ename;
+            switch (xmlReader.getEventType()) {
+                case XMLStreamConstants.START_ELEMENT:
+                    ename = xmlReader.getLocalName();
+                    if (ename.equals("writeCharactersWithString")
+                            || ename.equals("writeCharactersWithArray")) {
+                        inTestElement = true;
+                    }
+                    break;
+                case XMLStreamConstants.END_ELEMENT:
+                    ename = xmlReader.getLocalName();
+                    if (ename.equals("writeCharactersWithString")
+                            || ename.equals("writeCharactersWithArray")) {
+                        inTestElement = false;
+                        String content = sb.toString();
+                        System.out.println(ename + " text:'" + content + "' expected:'" + expectedContent+"'");
+                        Assert.assertEquals(content, expectedContent);
+                        sb.setLength(0);
+                    }
+                    break;
+                case XMLStreamConstants.CHARACTERS:
+                    if (inTestElement) {
+                        sb.append(xmlReader.getText());
+                    }
+                    break;
+            }
+            xmlReader.next();
+        }
+    }
+
+    @DataProvider(name = "validData")
+    Object[][] getValidData() {
+        return new Object[][] {
+            {"Don't Worry Be \uD83D\uDE0A"},
+            {"BMP characters \uE000\uFFFD"},
+            {"Simple text"},
+        };
+    }
+
+    @DataProvider(name = "invalidData")
+    Object[][] getInvalidData() {
+        return new Object[][] {
+            {"Unbalanced surrogate \uD83D"},
+            {"Unbalanced surrogate \uD83Dis here"},
+            {"Surrogate with followup BMP\uD83D\uFFF9"},
+        };
+    }
+}
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 514c6a8ced9..4d92200f4dc 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -363,3 +363,4 @@ b314bb02182b9ca94708a91f312c377f5435f740 jdk-9+114
 4ff86e5489e4c0513dadfa69def8601c110ca5cd jdk-9+115
 529f0bf896e58525614d863e283ad155531941cb jdk-9+116
 58265b39fc74b932bda4d4f4649c530a89f55c4e jdk-9+117
+6ba73d04589ccc0705a5d8ae5111b63632b6ad20 jdk-9+118
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 59c7f91c625..2b6d80debed 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -360,3 +360,4 @@ bb8379287f3736f38c52b2d1418784e2592461d1 jdk-9+114
 35225b837d66582037eeadeb471c13235dfd793d jdk-9+115
 baeb5edb38939cdb78ae0ac6f4fd368465cbf188 jdk-9+116
 4da0f73ce03aaf245b92cc040cc0ab0e3fa54dc2 jdk-9+117
+e1eba5cfa5cc8c66d524396a05323dc93568730a jdk-9+118
diff --git a/jdk/make/Import.gmk b/jdk/make/Import.gmk
index d479b095514..29e4ce0f19e 100644
--- a/jdk/make/Import.gmk
+++ b/jdk/make/Import.gmk
@@ -112,7 +112,7 @@ $(BASE_INSTALL_LIBRARIES_HERE)/server/%$(SHARED_LIBRARY_SUFFIX): $(BASE_INSTALL_
 	$(LN) -s ../$(@F) $@
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
-  $(BASE_INSTALL_LIBRARIES_HERE)/server/%.dSYM : $(BASE_INSTALL_LIBRARIES_HERE)/%.dSYM
+  $(BASE_INSTALL_LIBRARIES_HERE)/server/%.dSYM:
 	$(MKDIR) -p $(@D)
 	$(RM) $@
 	$(LN) -s ../$(@F) $@
diff --git a/jdk/make/launcher/Launcher-java.base.gmk b/jdk/make/launcher/Launcher-java.base.gmk
index 77d241405c3..d5ded27b9ea 100644
--- a/jdk/make/launcher/Launcher-java.base.gmk
+++ b/jdk/make/launcher/Launcher-java.base.gmk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,11 @@
 
 include LauncherCommon.gmk
 
-JAVA_RC_FLAGS += -i $(JDK_TOPDIR)/src/java.base/windows/native/common
+JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/java.base/windows/native/common
 ifdef OPENJDK
-  JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons"
+  JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons
 else
-  JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons"
+  JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons
 endif
 
 ################################################################################
diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk
index 57067da008d..b4c6f5e20a3 100644
--- a/jdk/make/lib/Awt2dLibraries.gmk
+++ b/jdk/make/lib/Awt2dLibraries.gmk
@@ -213,9 +213,9 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
   endif
 
   ifdef OPENJDK
-    LIBAWT_RC_FLAGS := -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons"
+    LIBAWT_RC_FLAGS := -I $(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons
   else
-    LIBAWT_RC_FLAGS := -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons"
+    LIBAWT_RC_FLAGS := -I $(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons
   endif
   LIBAWT_VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/java.desktop/windows/native/libawt/windows/awt.rc
 endif
diff --git a/jdk/make/mapfiles/libj2ucrypto/mapfile-vers b/jdk/make/mapfiles/libj2ucrypto/mapfile-vers
index 833da53297e..2f2b8d6a4dd 100644
--- a/jdk/make/mapfiles/libj2ucrypto/mapfile-vers
+++ b/jdk/make/mapfiles/libj2ucrypto/mapfile-vers
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -30,28 +30,35 @@ SUNWprivate_1.1 {
                 JNI_OnLoad;
                 Java_com_oracle_security_ucrypto_UcryptoProvider_loadLibraries;
                 Java_com_oracle_security_ucrypto_UcryptoProvider_getMechList;
-		Java_com_oracle_security_ucrypto_NativeDigest_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree;
+                Java_com_oracle_security_ucrypto_NativeDigest_nativeInit;
                 Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate;
                 Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest;
-                Java_com_oracle_security_ucrypto_NativeDigest_nativeClone;
                 Java_com_oracle_security_ucrypto_NativeDigest_nativeFree;
-		Java_com_oracle_security_ucrypto_NativeCipher_nativeInit;
-		Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
-		Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
+                Java_com_oracle_security_ucrypto_NativeCipher_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
+                Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
                 Java_com_oracle_security_ucrypto_NativeKey_nativeFree;
                 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit;
                 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
                 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
-		Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
-
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
+                Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest;
-                JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree;
                 JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
@@ -60,10 +67,10 @@ SUNWprivate_1.1 {
                 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
                 JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
 
 	local:
diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers
index 118b0fd3ddf..693f5a87fb8 100644
--- a/jdk/make/mapfiles/libjava/mapfile-vers
+++ b/jdk/make/mapfiles/libjava/mapfile-vers
@@ -262,7 +262,7 @@ SUNWprivate_1.1 {
 		Java_jdk_internal_reflect_Reflection_getCallerClass__;
 		Java_jdk_internal_reflect_Reflection_getCallerClass__I;
 		Java_jdk_internal_reflect_Reflection_getClassAccessFlags;
-		Java_jdk_internal_misc_VM_latestUserDefinedLoader;
+		Java_jdk_internal_misc_VM_latestUserDefinedLoader0;
                 Java_jdk_internal_misc_VM_getuid;
                 Java_jdk_internal_misc_VM_geteuid;
                 Java_jdk_internal_misc_VM_getgid;
diff --git a/jdk/src/java.base/share/classes/java/io/BufferedWriter.java b/jdk/src/java.base/share/classes/java/io/BufferedWriter.java
index 28e170fe800..3d8e1ee1b19 100644
--- a/jdk/src/java.base/share/classes/java/io/BufferedWriter.java
+++ b/jdk/src/java.base/share/classes/java/io/BufferedWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -153,13 +153,18 @@ public class BufferedWriter extends Writer {
      * needed.  If the requested length is at least as large as the buffer,
      * however, then this method will flush the buffer and write the characters
      * directly to the underlying stream.  Thus redundant
-     * <code>BufferedWriter</code>s will not copy data unnecessarily.
+     * {@code BufferedWriter}s will not copy data unnecessarily.
      *
      * @param  cbuf  A character array
      * @param  off   Offset from which to start reading characters
      * @param  len   Number of characters to write
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(char cbuf[], int off, int len) throws IOException {
         synchronized (lock) {
@@ -195,17 +200,24 @@ public class BufferedWriter extends Writer {
     /**
      * Writes a portion of a String.
      *
-     * <p> If the value of the {@code len} parameter is negative then no
-     * characters are written.  This is contrary to the specification of this
-     * method in the {@linkplain java.io.Writer#write(java.lang.String,int,int)
-     * superclass}, which requires that an {@link IndexOutOfBoundsException} be
-     * thrown.
+     * @implSpec
+     * While the specification of this method in the
+     * {@linkplain java.io.Writer#write(java.lang.String,int,int) superclass}
+     * recommends that an {@link IndexOutOfBoundsException} be thrown
+     * if {@code len} is negative or {@code off + len} is negative,
+     * the implementation in this class does not throw such an exception in
+     * these cases but instead simply writes no characters.
      *
      * @param  s     String to be written
      * @param  off   Offset from which to start reading characters
      * @param  len   Number of characters to be written
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative,
+     *          or {@code off + len} is greater than the length
+     *          of the given string
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(String s, int off, int len) throws IOException {
         synchronized (lock) {
diff --git a/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java b/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java
index ed27bbae314..773b59614d9 100644
--- a/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java
+++ b/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,6 +91,11 @@ class CharArrayWriter extends Writer {
      * @param c the data to be written
      * @param off       the start offset in the data
      * @param len       the number of chars that are written
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
      */
     public void write(char c[], int off, int len) {
         if ((off < 0) || (off > c.length) || (len < 0) ||
@@ -114,6 +119,11 @@ class CharArrayWriter extends Writer {
      * @param  str  String to be written from
      * @param  off  Offset from which to start reading characters
      * @param  len  Number of characters to be written
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given string
      */
     public void write(String str, int off, int len) {
         synchronized (lock) {
diff --git a/jdk/src/java.base/share/classes/java/io/FilterWriter.java b/jdk/src/java.base/share/classes/java/io/FilterWriter.java
index 303c674e0c0..8272b3cc8bf 100644
--- a/jdk/src/java.base/share/classes/java/io/FilterWriter.java
+++ b/jdk/src/java.base/share/classes/java/io/FilterWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -72,7 +72,12 @@ public abstract class FilterWriter extends Writer {
      * @param  off   Offset from which to start reading characters
      * @param  len   Number of characters to be written
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(char cbuf[], int off, int len) throws IOException {
         out.write(cbuf, off, len);
@@ -85,7 +90,12 @@ public abstract class FilterWriter extends Writer {
      * @param  off  Offset from which to start reading characters
      * @param  len  Number of characters to be written
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(String str, int off, int len) throws IOException {
         out.write(str, off, len);
diff --git a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java
index a591136419d..9f13c9216a3 100644
--- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java
+++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java
@@ -603,12 +603,12 @@ public class ObjectInputStream
      *     Class.forName(desc.getName(), false, loader)
      * </pre>
      * where <code>loader</code> is determined as follows: if there is a
-     * method on the current thread's stack whose declaring class was
-     * defined by a user-defined class loader (and was not a generated to
-     * implement reflective invocations), then <code>loader</code> is class
-     * loader corresponding to the closest such method to the currently
-     * executing frame; otherwise, <code>loader</code> is
-     * <code>null</code>. If this call results in a
+     * method on the current thread's stack whose declaring class is not a
+     * <a href="../lang/ClassLoader.html#builtinLoaders">
+     * <em>platform class</em></a>, then <code>loader</code> is
+     * the class loader of such class; otherwise, <code>loader</code>
+     * is the {@linkplain ClassLoader#getPlatformClassLoader()
+     * platform class loader}.  If this call results in a
      * <code>ClassNotFoundException</code> and the name of the passed
      * <code>ObjectStreamClass</code> instance is the Java language keyword
      * for a primitive type or void, then the <code>Class</code> object
@@ -666,12 +666,15 @@ public class ObjectInputStream
      * <pre>
      *     Class.forName(i, false, loader)
      * </pre>
-     * where <code>loader</code> is that of the first non-<code>null</code>
-     * class loader up the execution stack, or <code>null</code> if no
-     * non-<code>null</code> class loaders are on the stack (the same class
-     * loader choice used by the <code>resolveClass</code> method).  Unless any
-     * of the resolved interfaces are non-public, this same value of
-     * <code>loader</code> is also the class loader passed to
+     * where <code>loader</code> is determined as follows: if there is a
+     * method on the current thread's stack whose declaring class is not a
+     * <a href="../lang/ClassLoader.html#builtinLoaders">
+     * <em>platform class</em></a>, then <code>loader</code> is
+     * the class loader of such class; otherwise, <code>loader</code>
+     * is the {@linkplain ClassLoader#getPlatformClassLoader()
+     * platform class loader}.
+     * Unless any of the resolved interfaces are non-public, this same value
+     * of <code>loader</code> is also the class loader passed to
      * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
      * their class loader is passed instead (if more than one non-public
      * interface class loader is encountered, an
@@ -2154,10 +2157,11 @@ public class ObjectInputStream
                                               int ndoubles);
 
     /**
-     * Returns the first non-null class loader (not counting class loaders of
-     * generated reflection implementation classes) up the execution stack, or
-     * null if only code from the null class loader is on the stack.  This
-     * method is also called via reflection by the following RMI-IIOP class:
+     * Returns the first non-null and non-platform class loader
+     * (not counting class loaders of generated reflection implementation classes)
+     * up the execution stack, or null if only code from the bootstrap and
+     * platform class loader is on the stack.
+     * This method is also called via reflection by the following RMI-IIOP class:
      *
      *     com.sun.corba.se.internal.util.JDKClassLoader
      *
diff --git a/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java b/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java
index 0d597e6bef4..4fdb148baaf 100644
--- a/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java
+++ b/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -202,7 +202,12 @@ public class OutputStreamWriter extends Writer {
      * @param  off   Offset from which to start writing characters
      * @param  len   Number of characters to write
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(char cbuf[], int off, int len) throws IOException {
         se.write(cbuf, off, len);
@@ -215,7 +220,12 @@ public class OutputStreamWriter extends Writer {
      * @param  off  Offset from which to start writing characters
      * @param  len  Number of characters to write
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given string
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(String str, int off, int len) throws IOException {
         se.write(str, off, len);
diff --git a/jdk/src/java.base/share/classes/java/io/PipedWriter.java b/jdk/src/java.base/share/classes/java/io/PipedWriter.java
index 02201fbec1a..a4534b8604c 100644
--- a/jdk/src/java.base/share/classes/java/io/PipedWriter.java
+++ b/jdk/src/java.base/share/classes/java/io/PipedWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -125,19 +125,25 @@ public class PipedWriter extends Writer {
     }
 
     /**
-     * Writes <code>len</code> characters from the specified character array
-     * starting at offset <code>off</code> to this piped output stream.
+     * Writes {@code len} characters from the specified character array
+     * starting at offset {@code off} to this piped output stream.
      * This method blocks until all the characters are written to the output
      * stream.
      * If a thread was reading data characters from the connected piped input
      * stream, but the thread is no longer alive, then an
-     * <code>IOException</code> is thrown.
+     * {@code IOException} is thrown.
      *
      * @param      cbuf  the data.
      * @param      off   the start offset in the data.
      * @param      len   the number of characters to write.
-     * @exception  IOException  if the pipe is
-     *          <a href=PipedOutputStream.html#BROKEN> <code>broken</code></a>,
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
+     * @throws  IOException  if the pipe is
+     *          <a href=PipedOutputStream.html#BROKEN><code>broken</code></a>,
      *          {@link #connect(java.io.PipedReader) unconnected}, closed
      *          or an I/O error occurs.
      */
diff --git a/jdk/src/java.base/share/classes/java/io/PrintWriter.java b/jdk/src/java.base/share/classes/java/io/PrintWriter.java
index 662f930ef90..d516b8ef404 100644
--- a/jdk/src/java.base/share/classes/java/io/PrintWriter.java
+++ b/jdk/src/java.base/share/classes/java/io/PrintWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -410,6 +410,11 @@ public class PrintWriter extends Writer {
      * @param buf Array of characters
      * @param off Offset from which to start writing characters
      * @param len Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
      */
     public void write(char buf[], int off, int len) {
         try {
@@ -440,6 +445,11 @@ public class PrintWriter extends Writer {
      * @param s A String
      * @param off Offset from which to start writing characters
      * @param len Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
      */
     public void write(String s, int off, int len) {
         try {
diff --git a/jdk/src/java.base/share/classes/java/io/StringWriter.java b/jdk/src/java.base/share/classes/java/io/StringWriter.java
index 5d1babc3127..15022b353a8 100644
--- a/jdk/src/java.base/share/classes/java/io/StringWriter.java
+++ b/jdk/src/java.base/share/classes/java/io/StringWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -83,6 +83,11 @@ public class StringWriter extends Writer {
      * @param  cbuf  Array of characters
      * @param  off   Offset from which to start writing characters
      * @param  len   Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
      */
     public void write(char cbuf[], int off, int len) {
         if ((off < 0) || (off > cbuf.length) || (len < 0) ||
@@ -107,6 +112,11 @@ public class StringWriter extends Writer {
      * @param  str  String to be written
      * @param  off  Offset from which to start writing characters
      * @param  len  Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given string
      */
     public void write(String str, int off, int len)  {
         buf.append(str, off, off + len);
diff --git a/jdk/src/java.base/share/classes/java/io/Writer.java b/jdk/src/java.base/share/classes/java/io/Writer.java
index 5ad5e554fb3..17e8de3ef8a 100644
--- a/jdk/src/java.base/share/classes/java/io/Writer.java
+++ b/jdk/src/java.base/share/classes/java/io/Writer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,12 +32,11 @@ package java.io;
  * Most subclasses, however, will override some of the methods defined here in
  * order to provide higher efficiency, additional functionality, or both.
  *
- * @see Writer
  * @see   BufferedWriter
  * @see   CharArrayWriter
  * @see   FilterWriter
  * @see   OutputStreamWriter
- * @see     FileWriter
+ * @see   FileWriter
  * @see   PipedWriter
  * @see   PrintWriter
  * @see   StringWriter
@@ -139,6 +138,12 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
      * @param  len
      *         Number of characters to write
      *
+     * @throws  IndexOutOfBoundsException
+     *          Implementations should throw this exception
+     *          if {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
      * @throws  IOException
      *          If an I/O error occurs
      */
@@ -160,6 +165,11 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
     /**
      * Writes a portion of a string.
      *
+     * @implSpec
+     * The implementation in this class throws an
+     * {@code IndexOutOfBoundsException} for the indicated conditions;
+     * overriding methods may choose to do otherwise.
+     *
      * @param  str
      *         A String
      *
@@ -170,8 +180,9 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
      *         Number of characters to write
      *
      * @throws  IndexOutOfBoundsException
-     *          If {@code off} is negative, or {@code len} is negative,
-     *          or {@code off+len} is negative or greater than the length
+     *          Implementations should throw this exception
+     *          if {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
      *          of the given string
      *
      * @throws  IOException
diff --git a/jdk/src/java.base/share/classes/java/lang/Thread.java b/jdk/src/java.base/share/classes/java/lang/Thread.java
index 54fc27f31b5..310ada1b470 100644
--- a/jdk/src/java.base/share/classes/java/lang/Thread.java
+++ b/jdk/src/java.base/share/classes/java/lang/Thread.java
@@ -340,6 +340,45 @@ class Thread implements Runnable {
         sleep(millis);
     }
 
+    /**
+     * Indicates that the caller is momentarily unable to progress, until the
+     * occurrence of one or more actions on the part of other activities. By
+     * invoking this method within each iteration of a spin-wait loop construct,
+     * the calling thread indicates to the runtime that it is busy-waiting.
+     * The runtime may take action to improve the performance of invoking
+     * spin-wait loop constructions.
+     * <p>
+     * @apiNote
+     * As an example consider a method in a class that spins in a loop until
+     * some flag is set outside of that method. A call to the {@code onSpinWait}
+     * method should be placed inside the spin loop.
+     * <pre>{@code
+     *     class EventHandler {
+     *         volatile boolean eventNotificationNotReceived;
+     *         void waitForEventAndHandleIt() {
+     *             while ( eventNotificationNotReceived ) {
+     *                 java.lang.Thread.onSpinWait();
+     *             }
+     *             readAndProcessEvent();
+     *         }
+     *
+     *         void readAndProcessEvent() {
+     *             // Read event from some source and process it
+     *              . . .
+     *         }
+     *     }
+     * }</pre>
+     * <p>
+     * The code above would remain correct even if the {@code onSpinWait}
+     * method was not called at all. However on some architectures the Java
+     * Virtual Machine may issue the processor instructions to address such
+     * code patterns in a more beneficial way.
+     * <p>
+     * @since 9
+     */
+    @HotSpotIntrinsicCandidate
+    public static void onSpinWait() {}
+
     /**
      * Initializes a Thread with the current AccessControlContext.
      * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean)
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
index 08e38987bf2..da1700ffdb1 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
@@ -706,6 +706,9 @@ class InvokerBytecodeGenerator {
                 case ARRAY_STORE:
                     emitArrayStore(name);
                     continue;
+                case ARRAY_LENGTH:
+                    emitArrayLength(name);
+                    continue;
                 case IDENTITY:
                     assert(name.arguments.length == 1);
                     emitPushArguments(name);
@@ -740,15 +743,16 @@ class InvokerBytecodeGenerator {
         return classFile;
     }
 
-    void emitArrayLoad(Name name)  { emitArrayOp(name, Opcodes.AALOAD);  }
-    void emitArrayStore(Name name) { emitArrayOp(name, Opcodes.AASTORE); }
+    void emitArrayLoad(Name name)   { emitArrayOp(name, Opcodes.AALOAD);      }
+    void emitArrayStore(Name name)  { emitArrayOp(name, Opcodes.AASTORE);     }
+    void emitArrayLength(Name name) { emitArrayOp(name, Opcodes.ARRAYLENGTH); }
 
     void emitArrayOp(Name name, int arrayOpcode) {
-        assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE;
+        assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE || arrayOpcode == Opcodes.ARRAYLENGTH;
         Class<?> elementType = name.function.methodType().parameterType(0).getComponentType();
         assert elementType != null;
         emitPushArguments(name);
-        if (elementType.isPrimitive()) {
+        if (arrayOpcode != Opcodes.ARRAYLENGTH && elementType.isPrimitive()) {
             Wrapper w = Wrapper.forPrimitiveType(elementType);
             arrayOpcode = arrayInsnOpcode(arrayTypeCode(w), arrayOpcode);
         }
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java
index 29cc430f877..1aca86298fe 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java
@@ -95,12 +95,12 @@ class Invokers {
 
     /*non-public*/ MethodHandle varHandleMethodInvoker(VarHandle.AccessMode ak) {
         // TODO cache invoker
-        return makeVarHandleMethodInvoker(ak);
+        return makeVarHandleMethodInvoker(ak, false);
     }
 
     /*non-public*/ MethodHandle varHandleMethodExactInvoker(VarHandle.AccessMode ak) {
         // TODO cache invoker
-        return makeVarHandleMethodExactInvoker(ak);
+        return makeVarHandleMethodInvoker(ak, true);
     }
 
     private MethodHandle cachedInvoker(int idx) {
@@ -127,26 +127,11 @@ class Invokers {
         return invoker;
     }
 
-    private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak) {
+    private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak, boolean isExact) {
         MethodType mtype = targetType;
         MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
 
-        LambdaForm lform = varHandleMethodGenericInvokerHandleForm(ak.methodName(), mtype);
-        VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
-        MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
-
-        invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.methodName(), mtype), false);
-        assert(checkVarHandleInvoker(invoker));
-
-        maybeCompileToBytecode(invoker);
-        return invoker;
-    }
-
-    private MethodHandle makeVarHandleMethodExactInvoker(VarHandle.AccessMode ak) {
-        MethodType mtype = targetType;
-        MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
-
-        LambdaForm lform = varHandleMethodExactInvokerHandleForm(ak.methodName(), mtype);
+        LambdaForm lform = varHandleMethodInvokerHandleForm(ak.methodName(), mtype, isExact);
         VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
         MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
 
@@ -400,59 +385,7 @@ class Invokers {
         return lform;
     }
 
-    private static LambdaForm varHandleMethodExactInvokerHandleForm(String name, MethodType mtype) {
-        // TODO Cache form?
-
-        final int THIS_MH      = 0;
-        final int CALL_VH      = THIS_MH + 1;
-        final int ARG_BASE     = CALL_VH + 1;
-        final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
-        int nameCursor = ARG_LIMIT;
-        final int VAD_ARG      = nameCursor++;
-        final int CHECK_TYPE   = nameCursor++;
-        final int GET_MEMBER   = nameCursor++;
-        final int LINKER_CALL  = nameCursor++;
-
-        MethodType invokerFormType = mtype.insertParameterTypes(0, VarHandle.class)
-                .basicType()
-                .appendParameterTypes(MemberName.class);
-
-        MemberName linker = new MemberName(MethodHandle.class, "linkToStatic", invokerFormType, REF_invokeStatic);
-        try {
-            linker = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
-        } catch (ReflectiveOperationException ex) {
-            throw newInternalError(ex);
-        }
-
-        Name[] names = new Name[LINKER_CALL + 1];
-        names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
-        names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
-        for (int i = 0; i < mtype.parameterCount(); i++) {
-            names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
-        }
-
-        BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
-        names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
-
-        NamedFunction getter = speciesData.getterFunction(0);
-        names[VAD_ARG] = new Name(getter, names[THIS_MH]);
-
-        Object[] outArgs = Arrays.copyOfRange(names, CALL_VH, ARG_LIMIT + 1, Object[].class);
-
-        names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]);
-
-        names[GET_MEMBER] = new Name(NF_getVarHandleMemberName, names[CALL_VH], names[VAD_ARG]);
-        outArgs[outArgs.length - 1] = names[GET_MEMBER];
-
-        names[LINKER_CALL] = new Name(linker, outArgs);
-        LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)),
-                                          ARG_LIMIT, names);
-
-        lform.compileToBytecode();
-        return lform;
-    }
-
-    private static LambdaForm varHandleMethodGenericInvokerHandleForm(String name, MethodType mtype) {
+    private static LambdaForm varHandleMethodInvokerHandleForm(String name, MethodType mtype, boolean isExact) {
         // TODO Cache form?
 
         final int THIS_MH      = 0;
@@ -477,8 +410,11 @@ class Invokers {
         NamedFunction getter = speciesData.getterFunction(0);
         names[VAD_ARG] = new Name(getter, names[THIS_MH]);
 
-        names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]);
-
+        if (isExact) {
+            names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]);
+        } else {
+            names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]);
+        }
         Object[] outArgs = new Object[ARG_LIMIT];
         outArgs[0] = names[CHECK_TYPE];
         for (int i = 1; i < ARG_LIMIT; i++) {
@@ -488,7 +424,8 @@ class Invokers {
         MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
                 .basicType();
         names[LINKER_CALL] = new Name(outCallType, outArgs);
-        LambdaForm lform = new LambdaForm(name + ":VarHandle_invoker" + shortenSignature(basicTypeSignature(mtype)),
+        String debugName = isExact ? ":VarHandle_exactInvoker" : ":VarHandle_invoker";
+        LambdaForm lform = new LambdaForm(name + debugName + shortenSignature(basicTypeSignature(mtype)),
                                           ARG_LIMIT, names);
 
         lform.prepare();
@@ -511,21 +448,13 @@ class Invokers {
 
     /*non-public*/ static
     @ForceInline
-    void checkVarHandleExactType(VarHandle handle, VarHandle.AccessDescriptor ad) {
-        MethodType erasedTarget = handle.vform.methodType_table[ad.type];
-        MethodType erasedSymbolic = ad.symbolicMethodTypeErased;
-        if (erasedTarget != erasedSymbolic)
-            throw newWrongMethodTypeException(erasedTarget, erasedSymbolic);
-    }
-
-    /*non-public*/ static
-    @ForceInline
-    MemberName getVarHandleMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {
-        MemberName mn = handle.vform.memberName_table[ad.mode];
-        if (mn == null) {
-            throw handle.unsupported();
+    MethodHandle checkVarHandleExactType(VarHandle handle, VarHandle.AccessDescriptor ad) {
+        MethodHandle mh = handle.getMethodHandle(ad.mode);
+        MethodType mt = mh.type();
+        if (mt != ad.symbolicMethodTypeInvoker) {
+            throw newWrongMethodTypeException(mt, ad.symbolicMethodTypeInvoker);
         }
-        return mn;
+        return mh;
     }
 
     /*non-public*/ static
@@ -649,8 +578,7 @@ class Invokers {
         NF_getCallSiteTarget,
         NF_checkCustomized,
         NF_checkVarHandleGenericType,
-        NF_checkVarHandleExactType,
-        NF_getVarHandleMemberName;
+        NF_checkVarHandleExactType;
     static {
         try {
             NamedFunction nfs[] = {
@@ -666,8 +594,6 @@ class Invokers {
                         .getDeclaredMethod("checkVarHandleGenericType", VarHandle.class, VarHandle.AccessDescriptor.class)),
                 NF_checkVarHandleExactType = new NamedFunction(Invokers.class
                         .getDeclaredMethod("checkVarHandleExactType", VarHandle.class, VarHandle.AccessDescriptor.class)),
-                NF_getVarHandleMemberName = new NamedFunction(Invokers.class
-                        .getDeclaredMethod("getVarHandleMemberName", VarHandle.class, VarHandle.AccessDescriptor.class))
             };
             // Each nf must be statically invocable or we get tied up in our bootstraps.
             assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
index 782eff613ae..6f2f35b8773 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -66,25 +66,28 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
 
     /// Factory methods to create method handles:
 
-    static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
-        if (arrayClass == Object[].class)
-            return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER);
+    static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, ArrayAccess access) {
+        if (arrayClass == Object[].class) {
+            return ArrayAccess.objectAccessor(access);
+        }
         if (!arrayClass.isArray())
             throw newIllegalArgumentException("not an array: "+arrayClass);
         MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
-        int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX);
+        int cacheIndex = ArrayAccess.cacheIndex(access);
         MethodHandle mh = cache[cacheIndex];
         if (mh != null)  return mh;
-        mh = ArrayAccessor.getAccessor(arrayClass, isSetter);
-        MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter);
+        mh = ArrayAccessor.getAccessor(arrayClass, access);
+        MethodType correctType = ArrayAccessor.correctType(arrayClass, access);
         if (mh.type() != correctType) {
             assert(mh.type().parameterType(0) == Object[].class);
-            assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class);
-            assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType());
+            /* if access == SET */ assert(access != ArrayAccess.SET || mh.type().parameterType(2) == Object.class);
+            /* if access == GET */ assert(access != ArrayAccess.GET ||
+                    (mh.type().returnType() == Object.class &&
+                     correctType.parameterType(0).getComponentType() == correctType.returnType()));
             // safe to view non-strictly, because element type follows from array type
             mh = mh.viewAsType(correctType, false);
         }
-        mh = makeIntrinsic(mh, (isSetter ? Intrinsic.ARRAY_STORE : Intrinsic.ARRAY_LOAD));
+        mh = makeIntrinsic(mh, ArrayAccess.intrinsic(access));
         // Atomically update accessor cache.
         synchronized(cache) {
             if (cache[cacheIndex] == null) {
@@ -97,9 +100,52 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
         return mh;
     }
 
+    enum ArrayAccess {
+        GET, SET, LENGTH;
+
+        // As ArrayAccess and ArrayAccessor have a circular dependency, the ArrayAccess properties cannot be stored in
+        // final fields.
+
+        static String opName(ArrayAccess a) {
+            switch (a) {
+                case GET: return "getElement";
+                case SET: return "setElement";
+                case LENGTH: return "length";
+            }
+            throw new AssertionError();
+        }
+
+        static MethodHandle objectAccessor(ArrayAccess a) {
+            switch (a) {
+                case GET: return ArrayAccessor.OBJECT_ARRAY_GETTER;
+                case SET: return ArrayAccessor.OBJECT_ARRAY_SETTER;
+                case LENGTH: return ArrayAccessor.OBJECT_ARRAY_LENGTH;
+            }
+            throw new AssertionError();
+        }
+
+        static int cacheIndex(ArrayAccess a) {
+            switch (a) {
+                case GET: return ArrayAccessor.GETTER_INDEX;
+                case SET: return ArrayAccessor.SETTER_INDEX;
+                case LENGTH: return ArrayAccessor.LENGTH_INDEX;
+            }
+            throw new AssertionError();
+        }
+
+        static Intrinsic intrinsic(ArrayAccess a) {
+            switch (a) {
+                case GET: return Intrinsic.ARRAY_LOAD;
+                case SET: return Intrinsic.ARRAY_STORE;
+                case LENGTH: return Intrinsic.ARRAY_LENGTH;
+            }
+            throw new AssertionError();
+        }
+    }
+
     static final class ArrayAccessor {
-        /// Support for array element access
-        static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2;
+        /// Support for array element and length access
+        static final int GETTER_INDEX = 0, SETTER_INDEX = 1, LENGTH_INDEX = 2, INDEX_LIMIT = 3;
         static final ClassValue<MethodHandle[]> TYPED_ACCESSORS
                 = new ClassValue<MethodHandle[]>() {
                     @Override
@@ -107,14 +153,16 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
                         return new MethodHandle[INDEX_LIMIT];
                     }
                 };
-        static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER;
+        static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER, OBJECT_ARRAY_LENGTH;
         static {
             MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class);
-            cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, false), Intrinsic.ARRAY_LOAD);
-            cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, true),  Intrinsic.ARRAY_STORE);
+            cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.GET),    Intrinsic.ARRAY_LOAD);
+            cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.SET),    Intrinsic.ARRAY_STORE);
+            cache[LENGTH_INDEX] = OBJECT_ARRAY_LENGTH = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.LENGTH), Intrinsic.ARRAY_LENGTH);
 
             assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName()));
             assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName()));
+            assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_LENGTH.internalMemberName()));
         }
 
         static int     getElementI(int[]     a, int i)            { return              a[i]; }
@@ -137,31 +185,47 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
         static void    setElementC(char[]    a, int i, char    x) {              a[i] = x; }
         static void    setElementL(Object[]  a, int i, Object  x) {              a[i] = x; }
 
-        static String name(Class<?> arrayClass, boolean isSetter) {
+        static int     lengthI(int[]     a)                       { return a.length; }
+        static int     lengthJ(long[]    a)                       { return a.length; }
+        static int     lengthF(float[]   a)                       { return a.length; }
+        static int     lengthD(double[]  a)                       { return a.length; }
+        static int     lengthZ(boolean[] a)                       { return a.length; }
+        static int     lengthB(byte[]    a)                       { return a.length; }
+        static int     lengthS(short[]   a)                       { return a.length; }
+        static int     lengthC(char[]    a)                       { return a.length; }
+        static int     lengthL(Object[]  a)                       { return a.length; }
+
+        static String name(Class<?> arrayClass, ArrayAccess access) {
             Class<?> elemClass = arrayClass.getComponentType();
             if (elemClass == null)  throw newIllegalArgumentException("not an array", arrayClass);
-            return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
+            return ArrayAccess.opName(access) + Wrapper.basicTypeChar(elemClass);
         }
-        static MethodType type(Class<?> arrayClass, boolean isSetter) {
+        static MethodType type(Class<?> arrayClass, ArrayAccess access) {
             Class<?> elemClass = arrayClass.getComponentType();
             Class<?> arrayArgClass = arrayClass;
             if (!elemClass.isPrimitive()) {
                 arrayArgClass = Object[].class;
                 elemClass = Object.class;
             }
-            return !isSetter ?
-                    MethodType.methodType(elemClass,  arrayArgClass, int.class) :
-                    MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
+            switch (access) {
+                case GET:    return MethodType.methodType(elemClass,  arrayArgClass, int.class);
+                case SET:    return MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
+                case LENGTH: return MethodType.methodType(int.class,  arrayArgClass);
+            }
+            throw new IllegalStateException("should not reach here");
         }
-        static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
+        static MethodType correctType(Class<?> arrayClass, ArrayAccess access) {
             Class<?> elemClass = arrayClass.getComponentType();
-            return !isSetter ?
-                    MethodType.methodType(elemClass,  arrayClass, int.class) :
-                    MethodType.methodType(void.class, arrayClass, int.class, elemClass);
+            switch (access) {
+                case GET:    return MethodType.methodType(elemClass,  arrayClass, int.class);
+                case SET:    return MethodType.methodType(void.class, arrayClass, int.class, elemClass);
+                case LENGTH: return MethodType.methodType(int.class,  arrayClass);
+            }
+            throw new IllegalStateException("should not reach here");
         }
-        static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
-            String     name = name(arrayClass, isSetter);
-            MethodType type = type(arrayClass, isSetter);
+        static MethodHandle getAccessor(Class<?> arrayClass, ArrayAccess access) {
+            String     name = name(arrayClass, access);
+            MethodType type = type(arrayClass, access);
             try {
                 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
             } catch (ReflectiveOperationException ex) {
@@ -1282,6 +1346,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
         NEW_ARRAY,
         ARRAY_LOAD,
         ARRAY_STORE,
+        ARRAY_LENGTH,
         IDENTITY,
         ZERO,
         NONE // no intrinsic associated
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index c3a97a178a3..2be727ffb0f 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -2244,6 +2244,20 @@ return mh1;
         return ani.asType(ani.type().changeReturnType(arrayClass));
     }
 
+    /**
+     * Produces a method handle returning the length of an array.
+     * The type of the method handle will have {@code int} as return type,
+     * and its sole argument will be the array type.
+     * @param arrayClass an array type
+     * @return a method handle which can retrieve the length of an array of the given array type
+     * @throws NullPointerException if the argument is {@code null}
+     * @throws IllegalArgumentException if arrayClass is not an array type
+     */
+    public static
+    MethodHandle arrayLength(Class<?> arrayClass) throws IllegalArgumentException {
+        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.LENGTH);
+    }
+
     /**
      * Produces a method handle giving read access to elements of an array.
      * The type of the method handle will have a return type of the array's
@@ -2256,7 +2270,7 @@ return mh1;
      */
     public static
     MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
-        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, false);
+        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.GET);
     }
 
     /**
@@ -2271,7 +2285,7 @@ return mh1;
      */
     public static
     MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
-        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
+        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET);
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java
index 78a75bf05cc..ee7be4096bf 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java
@@ -26,6 +26,7 @@
 package java.lang.invoke;
 
 import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.util.Preconditions;
 import jdk.internal.vm.annotation.ForceInline;
 import jdk.internal.vm.annotation.Stable;
 
@@ -33,7 +34,6 @@ import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.function.BiFunction;
 import java.util.function.Function;
 
@@ -1475,11 +1475,11 @@ public abstract class VarHandle {
         TypesAndInvokers tis = getTypesAndInvokers();
         MethodHandle mh = tis.methodHandle_table[mode];
         if (mh == null) {
-            mh = tis.methodHandle_table[mode] = getMethodHandleUncached(tis, mode);
+            mh = tis.methodHandle_table[mode] = getMethodHandleUncached(mode);
         }
         return mh;
     }
-    private final MethodHandle getMethodHandleUncached(TypesAndInvokers tis, int mode) {
+    private final MethodHandle getMethodHandleUncached(int mode) {
         MethodType mt = accessModeType(AccessMode.values()[mode]).
                 insertParameterTypes(0, VarHandle.class);
         MemberName mn = vform.getMemberName(mode);
@@ -1501,7 +1501,7 @@ public abstract class VarHandle {
     }
 
     static final BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException>
-            AIOOBE_SUPPLIER = Objects.outOfBoundsExceptionFormatter(
+            AIOOBE_SUPPLIER = Preconditions.outOfBoundsExceptionFormatter(
             new Function<String, ArrayIndexOutOfBoundsException>() {
                 @Override
                 public ArrayIndexOutOfBoundsException apply(String s) {
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template
index 7a058afedec..ebb6dd31b79 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template
@@ -24,9 +24,11 @@
  */
 package java.lang.invoke;
 
-import java.util.Objects;
+import jdk.internal.util.Preconditions;
 import jdk.internal.vm.annotation.ForceInline;
 
+import java.util.Objects;
+
 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
 
 #warn
@@ -163,8 +165,7 @@ final class VarHandle$Type$s {
 
         @ForceInline
         static boolean weakCompareAndSetVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
-            // TODO defer to strong form until new Unsafe method is added
-            return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+            return UNSAFE.weakCompareAndSwap$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
                                                handle.fieldOffset,
                                                {#if[Object]?handle.fieldType.cast(expected):expected},
                                                {#if[Object]?handle.fieldType.cast(value):value});
@@ -345,8 +346,7 @@ final class VarHandle$Type$s {
 
         @ForceInline
         static boolean weakCompareAndSetVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
-            // TODO defer to strong form until new Unsafe method is added
-            return UNSAFE.compareAndSwap$Type$(handle.base,
+            return UNSAFE.weakCompareAndSwap$Type$Volatile(handle.base,
                                                handle.fieldOffset,
                                                {#if[Object]?handle.fieldType.cast(expected):expected},
                                                {#if[Object]?handle.fieldType.cast(value):value});
@@ -447,7 +447,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.get$Type$Volatile(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
         }
 
         @ForceInline
@@ -458,7 +458,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             UNSAFE.put$Type$Volatile(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(value):value});
         }
 
@@ -470,7 +470,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.get$Type$Opaque(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
         }
 
         @ForceInline
@@ -481,7 +481,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             UNSAFE.put$Type$Opaque(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(value):value});
         }
 
@@ -493,7 +493,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.get$Type$Acquire(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
         }
 
         @ForceInline
@@ -504,7 +504,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             UNSAFE.put$Type$Release(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(value):value});
         }
 #if[CAS]
@@ -517,7 +517,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.compareAndSwap$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -530,7 +530,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.compareAndExchange$Type$Volatile(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -543,7 +543,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.compareAndExchange$Type$Acquire(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -556,7 +556,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.compareAndExchange$Type$Release(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -569,7 +569,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.weakCompareAndSwap$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -581,9 +581,8 @@ final class VarHandle$Type$s {
 #else[Object]
             $type$[] array = ($type$[]) oarray;
 #end[Object]
-            // TODO defer to strong form until new Unsafe method is added
-            return UNSAFE.compareAndSwap$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+            return UNSAFE.weakCompareAndSwap$Type$Volatile(array,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -596,7 +595,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.weakCompareAndSwap$Type$Acquire(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -609,7 +608,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.weakCompareAndSwap$Type$Release(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(expected):expected},
                     {#if[Object]?handle.componentType.cast(value):value});
         }
@@ -622,7 +621,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.getAndSet$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     {#if[Object]?handle.componentType.cast(value):value});
         }
 #end[CAS]
@@ -636,7 +635,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.getAndAdd$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     value);
         }
 
@@ -648,7 +647,7 @@ final class VarHandle$Type$s {
             $type$[] array = ($type$[]) oarray;
 #end[Object]
             return UNSAFE.getAndAdd$Type$(array,
-                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
                     value) + value;
         }
 #end[AtomicAdd]
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template
index 8639e0d342e..66bf267476e 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template
@@ -25,6 +25,7 @@
 package java.lang.invoke;
 
 import jdk.internal.misc.Unsafe;
+import jdk.internal.util.Preconditions;
 import jdk.internal.vm.annotation.ForceInline;
 
 import java.nio.ByteBuffer;
@@ -81,7 +82,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
 
         @ForceInline
         static int index(byte[] ba, int index) {
-            return Objects.checkIndex(index, ba.length - ALIGN, null);
+            return Preconditions.checkIndex(index, ba.length - ALIGN, null);
         }
 
         @ForceInline
@@ -233,8 +234,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
         @ForceInline
         static boolean weakCompareAndSetVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
             byte[] ba = (byte[]) oba;
-            // TODO defer to strong form until new Unsafe method is added
-            return UNSAFE.compareAndSwap$RawType$(
+            return UNSAFE.weakCompareAndSwap$RawType$Volatile(
                     ba,
                     address(ba, index(ba, index)),
                     convEndian(handle.be, expected), convEndian(handle.be, value));
@@ -271,22 +271,33 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
 #if[AtomicAdd]
 
         @ForceInline
-        static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ value) {
+        static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ delta) {
             byte[] ba = (byte[]) oba;
-            return convEndian(handle.be,
-                              UNSAFE.getAndAdd$RawType$(
-                                      ba,
-                                      address(ba, index(ba, index)),
-                                      convEndian(handle.be, value)));
+            if (handle.be == BE) {
+                return UNSAFE.getAndAdd$RawType$(
+                        ba,
+                        address(ba, index(ba, index)),
+                        delta);
+            } else {
+                return getAndAddConvEndianWithCAS(ba, index, delta);
+            }
         }
 
         @ForceInline
-        static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ value) {
-            byte[] ba = (byte[]) oba;
-            return convEndian(handle.be, UNSAFE.getAndAdd$RawType$(
-                    ba,
-                    address(ba, index(ba, index)),
-                    convEndian(handle.be, value))) + value;
+        static $type$ getAndAddConvEndianWithCAS(byte[] ba, int index, $type$ delta) {
+            $type$ nativeExpectedValue, expectedValue;
+            long offset = address(ba, index(ba, index));
+            do {
+                nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset);
+                expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
+            } while (!UNSAFE.weakCompareAndSwap$RawType$Volatile(ba, offset,
+                    nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta)));
+            return expectedValue;
+        }
+
+        @ForceInline
+        static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ delta) {
+            return getAndAdd(handle, oba, index, delta) + delta;
         }
 #end[AtomicAdd]
 
@@ -307,14 +318,14 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
 
         @ForceInline
         static int index(ByteBuffer bb, int index) {
-            return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
+            return Preconditions.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
         }
 
         @ForceInline
         static int indexRO(ByteBuffer bb, int index) {
             if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY))
                 throw new ReadOnlyBufferException();
-            return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
+            return Preconditions.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
         }
 
         @ForceInline
@@ -466,8 +477,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
         @ForceInline
         static boolean weakCompareAndSetVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
             ByteBuffer bb = (ByteBuffer) obb;
-            // TODO defer to strong form until new Unsafe method is added
-            return UNSAFE.compareAndSwap$RawType$(
+            return UNSAFE.weakCompareAndSwap$RawType$Volatile(
                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
                     address(bb, indexRO(bb, index)),
                     convEndian(handle.be, expected), convEndian(handle.be, value));
@@ -504,23 +514,34 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
 #if[AtomicAdd]
 
         @ForceInline
-        static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+        static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ delta) {
             ByteBuffer bb = (ByteBuffer) obb;
-            return convEndian(handle.be,
-                              UNSAFE.getAndAdd$RawType$(
-                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
-                                      address(bb, indexRO(bb, index)),
-                                      convEndian(handle.be, value)));
+            if (handle.be == BE) {
+                return UNSAFE.getAndAdd$RawType$(
+                        UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                        address(bb, indexRO(bb, index)),
+                        delta);
+            } else {
+                return getAndAddConvEndianWithCAS(bb, index, delta);
+            }
         }
 
         @ForceInline
-        static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
-            ByteBuffer bb = (ByteBuffer) obb;
-            return convEndian(handle.be,
-                              UNSAFE.getAndAdd$RawType$(
-                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
-                                      address(bb, indexRO(bb, index)),
-                                      convEndian(handle.be, value))) + value;
+        static $type$ getAndAddConvEndianWithCAS(ByteBuffer bb, int index, $type$ delta) {
+            $type$ nativeExpectedValue, expectedValue;
+            Object base = UNSAFE.getObject(bb, BYTE_BUFFER_HB);
+            long offset = address(bb, indexRO(bb, index));
+            do {
+                nativeExpectedValue = UNSAFE.get$RawType$Volatile(base, offset);
+                expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
+            } while (!UNSAFE.weakCompareAndSwap$RawType$Volatile(base, offset,
+                    nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta)));
+            return expectedValue;
+        }
+
+        @ForceInline
+        static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ delta) {
+            return getAndAdd(handle, obb, index, delta) + delta;
         }
 #end[AtomicAdd]
 
diff --git a/jdk/src/java.base/share/classes/java/nio/Buffer.java b/jdk/src/java.base/share/classes/java/nio/Buffer.java
index d534fb3ae73..1f6bef17960 100644
--- a/jdk/src/java.base/share/classes/java/nio/Buffer.java
+++ b/jdk/src/java.base/share/classes/java/nio/Buffer.java
@@ -111,7 +111,7 @@ import java.util.Spliterator;
  * to zero.
  *
  *
- * <h2> Clearing, flipping, and rewinding </h2>
+ * <h2> Additional operations </h2>
  *
  * <p> In addition to methods for accessing the position, limit, and capacity
  * values and for marking and resetting, this class also defines the following
@@ -131,6 +131,12 @@ import java.util.Spliterator;
  *   it already contains: It leaves the limit unchanged and sets the position
  *   to zero.  </p></li>
  *
+ *   <li><p> {@link #slice} creates a subsequence of a buffer: It leaves the
+ *   limit and the position unchanged. </p></li>
+ *
+ *   <li><p> {@link #duplicate} creates a shallow copy of a buffer: It leaves
+ *   the limit and the position unchanged. </p></li>
+ *
  * </ul>
  *
  *
@@ -567,6 +573,46 @@ public abstract class Buffer {
      */
     public abstract boolean isDirect();
 
+    /**
+     * Creates a new buffer whose content is a shared subsequence of
+     * this buffer's content.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position.  Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of elements remaining in this buffer, its mark will be
+     * undefined. The new buffer will be direct if, and only if, this buffer is
+     * direct, and it will be read-only if, and only if, this buffer is
+     * read-only.  </p>
+     *
+     * @return  The new buffer
+     *
+     * @since 9
+     */
+    public abstract Buffer slice();
+
+    /**
+     * Creates a new buffer that shares this buffer's content.
+     *
+     * <p> The content of the new buffer will be that of this buffer.  Changes
+     * to this buffer's content will be visible in the new buffer, and vice
+     * versa; the two buffers' position, limit, and mark values will be
+     * independent.
+     *
+     * <p> The new buffer's capacity, limit, position and mark values will be
+     * identical to those of this buffer. The new buffer will be direct if, and
+     * only if, this buffer is direct, and it will be read-only if, and only if,
+     * this buffer is read-only.  </p>
+     *
+     * @return  The new buffer
+     *
+     * @since 9
+     */
+    public abstract Buffer duplicate();
+
 
     // -- Package-private methods for bounds checking, etc. --
 
diff --git a/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template b/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template
index 104f504b551..1292ca458c6 100644
--- a/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template
+++ b/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template
@@ -70,8 +70,7 @@ import java.util.stream.$Streamtype$Stream;
  *
 #end[byte]
  *
- *   <li><p> Methods for {@link #compact compacting}, {@link
- *   #duplicate duplicating}, and {@link #slice slicing}
+ *   <li><p> A method for {@link #compact compacting}
  *   $a$ $type$ buffer.  </p></li>
  *
  * </ul>
@@ -535,6 +534,7 @@ public abstract class $Type$Buffer
      * @see #alignedSlice(int)
 #end[byte]
      */
+    @Override
     public abstract $Type$Buffer slice();
 
     /**
@@ -557,6 +557,7 @@ public abstract class $Type$Buffer
      *
      * @return  The new $type$ buffer
      */
+    @Override
     public abstract $Type$Buffer duplicate();
 
     /**
diff --git a/jdk/src/java.base/share/classes/java/text/MessageFormat.java b/jdk/src/java.base/share/classes/java/text/MessageFormat.java
index f907f4f9bb7..134f84661af 100644
--- a/jdk/src/java.base/share/classes/java/text/MessageFormat.java
+++ b/jdk/src/java.base/share/classes/java/text/MessageFormat.java
@@ -1068,7 +1068,7 @@ public class MessageFormat extends Format {
      *            index information as described above.
      * @return An <code>Object</code> array parsed from the string. In case of
      *         error, returns null.
-     * @throws NullPointerException if {@code source} or {@code pos} is null.
+     * @throws NullPointerException if {@code pos} is null.
      */
     public Object parseObject(String source, ParsePosition pos) {
         return parse(source, pos);
diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java
index 9810a088b48..ec5fd9c8086 100644
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java
@@ -308,6 +308,7 @@ import java.util.Set;
  *   N       nano-of-day                 number            1234000000
  *
  *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
+ *   v       generic time-zone name      zone-name         Pacific Time; PT
  *   z       time-zone name              zone-name         Pacific Standard Time; PST
  *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00
  *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
@@ -365,9 +366,17 @@ import java.util.Set;
  * letters throws {@code IllegalArgumentException}.
  * <p>
  * <b>Zone names</b>: This outputs the display name of the time-zone ID. If the
- * count of letters is one, two or three, then the short name is output. If the
- * count of letters is four, then the full name is output. Five or more letters
- * throws {@code IllegalArgumentException}.
+ * pattern letter is 'z' the output is the daylight savings aware zone name.
+ * If there is insufficient information to determine whether DST applies,
+ * the name ignoring daylight savings time will be used.
+ * If the count of letters is one, two or three, then the short name is output.
+ * If the count of letters is four, then the full name is output.
+ * Five or more letters throws {@code IllegalArgumentException}.
+ * <p>
+ * If the pattern letter is 'v' the output provides the zone name ignoring
+ * daylight savings time. If the count of letters is one, then the short name is output.
+ * If the count of letters is four, then the full name is output.
+ * Two, three and five or more letters throw {@code IllegalArgumentException}.
  * <p>
  * <b>Offset X and x</b>: This formats the offset based on the number of pattern
  * letters. One letter outputs just the hour, such as '+01', unless the minute
diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
index 17364aef1e4..f3437950fc8 100644
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
@@ -81,9 +81,11 @@ import java.time.DateTimeException;
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.ChronoLocalDateTime;
 import java.time.chrono.Chronology;
 import java.time.chrono.Era;
 import java.time.chrono.IsoChronology;
@@ -1157,10 +1159,11 @@ public final class DateTimeFormatterBuilder {
      * result of {@link ZoneOffset#getId()}.
      * If the zone is not an offset, the textual name will be looked up
      * for the locale set in the {@link DateTimeFormatter}.
-     * If the temporal object being printed represents an instant, then the text
-     * will be the summer or winter time text as appropriate.
+     * If the temporal object being printed represents an instant, or if it is a
+     * local date-time that is not in a daylight saving gap or overlap then
+     * the text will be the summer or winter time text as appropriate.
      * If the lookup for text does not find any suitable result, then the
-     * {@link ZoneId#getId() ID} will be printed instead.
+     * {@link ZoneId#getId() ID} will be printed.
      * If the zone cannot be obtained then an exception is thrown unless the
      * section of the formatter is optional.
      * <p>
@@ -1177,7 +1180,7 @@ public final class DateTimeFormatterBuilder {
      * @return this, for chaining, not null
      */
     public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle) {
-        appendInternal(new ZoneTextPrinterParser(textStyle, null));
+        appendInternal(new ZoneTextPrinterParser(textStyle, null, false));
         return this;
     }
 
@@ -1193,10 +1196,11 @@ public final class DateTimeFormatterBuilder {
      * result of {@link ZoneOffset#getId()}.
      * If the zone is not an offset, the textual name will be looked up
      * for the locale set in the {@link DateTimeFormatter}.
-     * If the temporal object being printed represents an instant, then the text
+     * If the temporal object being printed represents an instant, or if it is a
+     * local date-time that is not in a daylight saving gap or overlap, then the text
      * will be the summer or winter time text as appropriate.
      * If the lookup for text does not find any suitable result, then the
-     * {@link ZoneId#getId() ID} will be printed instead.
+     * {@link ZoneId#getId() ID} will be printed.
      * If the zone cannot be obtained then an exception is thrown unless the
      * section of the formatter is optional.
      * <p>
@@ -1220,7 +1224,70 @@ public final class DateTimeFormatterBuilder {
     public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle,
                                                    Set<ZoneId> preferredZones) {
         Objects.requireNonNull(preferredZones, "preferredZones");
-        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones));
+        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones, false));
+        return this;
+    }
+    //----------------------------------------------------------------------
+    /**
+     * Appends the generic time-zone name, such as 'Pacific Time', to the formatter.
+     * <p>
+     * This appends an instruction to format/parse the generic textual
+     * name of the zone to the builder. The generic name is the same throughout the whole
+     * year, ignoring any daylight saving changes. For example, 'Pacific Time' is the
+     * generic name, whereas 'Pacific Standard Time' and 'Pacific Daylight Time' are the
+     * specific names, see {@link #appendZoneText(TextStyle)}.
+     * <p>
+     * During formatting, the zone is obtained using a mechanism equivalent
+     * to querying the temporal with {@link TemporalQueries#zoneId()}.
+     * If the zone is a {@code ZoneOffset} it will be printed using the
+     * result of {@link ZoneOffset#getId()}.
+     * If the zone is not an offset, the textual name will be looked up
+     * for the locale set in the {@link DateTimeFormatter}.
+     * If the lookup for text does not find any suitable result, then the
+     * {@link ZoneId#getId() ID} will be printed.
+     * If the zone cannot be obtained then an exception is thrown unless the
+     * section of the formatter is optional.
+     * <p>
+     * During parsing, either the textual zone name, the zone ID or the offset
+     * is accepted. Many textual zone names are not unique, such as CST can be
+     * for both "Central Standard Time" and "China Standard Time". In this
+     * situation, the zone id will be determined by the region information from
+     * formatter's  {@link DateTimeFormatter#getLocale() locale} and the standard
+     * zone id for that area, for example, America/New_York for the America Eastern zone.
+     * The {@link #appendGenericZoneText(TextStyle, Set)} may be used
+     * to specify a set of preferred {@link ZoneId} in this situation.
+     *
+     * @param textStyle  the text style to use, not null
+     * @return this, for chaining, not null
+     */
+    public DateTimeFormatterBuilder appendGenericZoneText(TextStyle textStyle) {
+        appendInternal(new ZoneTextPrinterParser(textStyle, null, true));
+        return this;
+    }
+
+    /**
+     * Appends the generic time-zone name, such as 'Pacific Time', to the formatter.
+     * <p>
+     * This appends an instruction to format/parse the generic textual
+     * name of the zone to the builder. The generic name is the same throughout the whole
+     * year, ignoring any daylight saving changes. For example, 'Pacific Time' is the
+     * generic name, whereas 'Pacific Standard Time' and 'Pacific Daylight Time' are the
+     * specific names, see {@link #appendZoneText(TextStyle)}.
+     * <p>
+     * This method also allows a set of preferred {@link ZoneId} to be
+     * specified for parsing. The matched preferred zone id will be used if the
+     * textural zone name being parsed is not unique.
+     * <p>
+     * See {@link #appendGenericZoneText(TextStyle)} for details about
+     * formatting and parsing.
+     *
+     * @param textStyle  the text style to use, not null
+     * @param preferredZones  the set of preferred zone ids, not null
+     * @return this, for chaining, not null
+     */
+    public DateTimeFormatterBuilder appendGenericZoneText(TextStyle textStyle,
+                                                          Set<ZoneId> preferredZones) {
+        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones, true));
         return this;
     }
 
@@ -1416,6 +1483,7 @@ public final class DateTimeFormatterBuilder {
      *   N       nano-of-day                 number            1234000000
      *
      *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
+     *   v       generic time-zone name      zone-name         PT, Pacific Time
      *   z       time-zone name              zone-name         Pacific Standard Time; PST
      *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
      *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
@@ -1537,6 +1605,8 @@ public final class DateTimeFormatterBuilder {
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
      *    VV      2      appendZoneId()
+     *    v       1      appendGenericZoneText(TextStyle.SHORT)
+     *    vvvv    4      appendGenericZoneText(TextStyle.FULL)
      *    z       1      appendZoneText(TextStyle.SHORT)
      *    zz      2      appendZoneText(TextStyle.SHORT)
      *    zzz     3      appendZoneText(TextStyle.SHORT)
@@ -1643,6 +1713,14 @@ public final class DateTimeFormatterBuilder {
                         throw new IllegalArgumentException("Pattern letter count must be 2: " + cur);
                     }
                     appendZoneId();
+                } else if (cur == 'v') {
+                    if (count == 1) {
+                        appendGenericZoneText(TextStyle.SHORT);
+                    } else if (count == 4) {
+                        appendGenericZoneText(TextStyle.FULL);
+                    } else {
+                        throw new IllegalArgumentException("Wrong number of  pattern letters: " + cur);
+                    }
                 } else if (cur == 'Z') {
                     if (count < 4) {
                         appendOffset("+HHMM", "+0000");
@@ -1894,6 +1972,8 @@ public final class DateTimeFormatterBuilder {
         // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4
         // 310 - Z - matches SimpleDateFormat and LDML
         // 310 - V - time-zone id, matches LDML
+        // 310 - v - general timezone names, not matching exactly with LDML because LDML specify to fall back
+        //           to 'VVVV' if general-nonlocation unavailable but here it's not falling back because of lack of data
         // 310 - p - prefix for padding
         // 310 - X - matches LDML, almost matches SDF for 1, exact match 2&3, extended 4&5
         // 310 - x - matches LDML
@@ -1901,7 +1981,6 @@ public final class DateTimeFormatterBuilder {
         // LDML - U - cycle year name, not supported by 310 yet
         // LDML - l - deprecated
         // LDML - j - not relevant
-        // LDML - v,V - extended time-zone names
     }
 
     //-----------------------------------------------------------------------
@@ -3723,9 +3802,12 @@ public final class DateTimeFormatterBuilder {
         /** The preferred zoneid map */
         private Set<String> preferredZones;
 
-        ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones) {
+        /**  Display in generic time-zone format. True in case of pattern letter 'v' */
+        private final boolean isGeneric;
+        ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones, boolean isGeneric) {
             super(TemporalQueries.zone(), "ZoneText(" + textStyle + ")");
             this.textStyle = Objects.requireNonNull(textStyle, "textStyle");
+            this.isGeneric = isGeneric;
             if (preferredZones != null && preferredZones.size() != 0) {
                 this.preferredZones = new HashSet<>();
                 for (ZoneId id : preferredZones) {
@@ -3788,11 +3870,21 @@ public final class DateTimeFormatterBuilder {
             String zname = zone.getId();
             if (!(zone instanceof ZoneOffset)) {
                 TemporalAccessor dt = context.getTemporal();
-                String name = getDisplayName(zname,
-                                             dt.isSupported(ChronoField.INSTANT_SECONDS)
-                                             ? (zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD)
-                                             : GENERIC,
-                                             context.getLocale());
+                int type = GENERIC;
+                if (!isGeneric) {
+                    if (dt.isSupported(ChronoField.INSTANT_SECONDS)) {
+                        type = zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD;
+                    } else if (dt.isSupported(ChronoField.EPOCH_DAY) &&
+                               dt.isSupported(ChronoField.NANO_OF_DAY)) {
+                        LocalDate date = LocalDate.ofEpochDay(dt.getLong(ChronoField.EPOCH_DAY));
+                        LocalTime time = LocalTime.ofNanoOfDay(dt.getLong(ChronoField.NANO_OF_DAY));
+                        LocalDateTime ldt = date.atTime(time);
+                        if (zone.getRules().getTransition(ldt) == null) {
+                            type = zone.getRules().isDaylightSavings(ldt.atZone(zone).toInstant()) ? DST : STD;
+                        }
+                    }
+                }
+                String name = getDisplayName(zname, type, context.getLocale());
                 if (name != null) {
                     zname = name;
                 }
diff --git a/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java b/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java
index 47190984db1..f6154857b8d 100644
--- a/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java
+++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java
@@ -614,7 +614,7 @@ public final class ZoneRules implements Serializable {
      * One technique, using this method, would be:
      * <pre>
      *  ZoneOffsetTransition trans = rules.getTransition(localDT);
-     *  if (trans == null) {
+     *  if (trans != null) {
      *    // Gap or Overlap: determine what to do from transition
      *  } else {
      *    // Normal case: only one valid offset
diff --git a/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java b/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java
index fbc0359ed37..97a48ae301c 100644
--- a/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java
+++ b/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -146,12 +146,26 @@ final class DualPivotQuicksort {
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
@@ -598,12 +612,26 @@ final class DualPivotQuicksort {
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
@@ -1086,12 +1114,26 @@ final class DualPivotQuicksort {
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
@@ -1574,12 +1616,26 @@ final class DualPivotQuicksort {
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
@@ -2158,12 +2214,26 @@ final class DualPivotQuicksort {
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
@@ -2701,12 +2771,26 @@ final class DualPivotQuicksort {
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
diff --git a/jdk/src/java.base/share/classes/java/util/Objects.java b/jdk/src/java.base/share/classes/java/util/Objects.java
index 28b39d08969..dad583b9206 100644
--- a/jdk/src/java.base/share/classes/java/util/Objects.java
+++ b/jdk/src/java.base/share/classes/java/util/Objects.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,9 @@
 
 package java.util;
 
-import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.util.Preconditions;
+import jdk.internal.vm.annotation.ForceInline;
 
-import java.util.function.BiFunction;
-import java.util.function.Function;
 import java.util.function.Supplier;
 
 /**
@@ -348,172 +347,6 @@ public final class Objects {
         return obj;
     }
 
-    /**
-     * Maps out-of-bounds values to a runtime exception.
-     *
-     * @param checkKind the kind of bounds check, whose name may correspond
-     *        to the name of one of the range check methods, checkIndex,
-     *        checkFromToIndex, checkFromIndexSize
-     * @param args the out-of-bounds arguments that failed the range check.
-     *        If the checkKind corresponds a the name of a range check method
-     *        then the bounds arguments are those that can be passed in order
-     *        to the method.
-     * @param oobef the exception formatter that when applied with a checkKind
-     *        and a list out-of-bounds arguments returns a runtime exception.
-     *        If {@code null} then, it is as if an exception formatter was
-     *        supplied that returns {@link IndexOutOfBoundsException} for any
-     *        given arguments.
-     * @return the runtime exception
-     */
-    private static RuntimeException outOfBounds(
-            BiFunction<String, List<Integer>, ? extends RuntimeException> oobef,
-            String checkKind,
-            Integer... args) {
-        List<Integer> largs = List.of(args);
-        RuntimeException e = oobef == null
-                             ? null : oobef.apply(checkKind, largs);
-        return e == null
-               ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e;
-    }
-
-    // Specific out-of-bounds exception producing methods that avoid
-    // the varargs-based code in the critical methods there by reducing their
-    // the byte code size, and therefore less likely to peturb inlining
-
-    private static RuntimeException outOfBoundsCheckIndex(
-            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
-            int index, int length) {
-        return outOfBounds(oobe, "checkIndex", index, length);
-    }
-
-    private static RuntimeException outOfBoundsCheckFromToIndex(
-            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
-            int fromIndex, int toIndex, int length) {
-        return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length);
-    }
-
-    private static RuntimeException outOfBoundsCheckFromIndexSize(
-            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
-            int fromIndex, int size, int length) {
-        return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length);
-    }
-
-    /**
-     * Returns an out-of-bounds exception formatter from an given exception
-     * factory.  The exception formatter is a function that formats an
-     * out-of-bounds message from its arguments and applies that message to the
-     * given exception factory to produce and relay an exception.
-     *
-     * <p>The exception formatter accepts two arguments: a {@code String}
-     * describing the out-of-bounds range check that failed, referred to as the
-     * <em>check kind</em>; and a {@code List<Integer>} containing the
-     * out-of-bound integer values that failed the check.  The list of
-     * out-of-bound values is not modified.
-     *
-     * <p>Three check kinds are supported {@code checkIndex},
-     * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding
-     * respectively to the specified application of an exception formatter as an
-     * argument to the out-of-bounds range check methods
-     * {@link #checkIndex(int, int, BiFunction) checkIndex},
-     * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and
-     * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}.
-     * Thus a supported check kind corresponds to a method name and the
-     * out-of-bound integer values correspond to method argument values, in
-     * order, preceding the exception formatter argument (similar in many
-     * respects to the form of arguments required for a reflective invocation of
-     * such a range check method).
-     *
-     * <p>Formatter arguments conforming to such supported check kinds will
-     * produce specific exception messages describing failed out-of-bounds
-     * checks.  Otherwise, more generic exception messages will be produced in
-     * any of the following cases: the check kind is supported but fewer
-     * or more out-of-bounds values are supplied, the check kind is not
-     * supported, the check kind is {@code null}, or the list of out-of-bound
-     * values is {@code null}.
-     *
-     * @apiNote
-     * This method produces an out-of-bounds exception formatter that can be
-     * passed as an argument to any of the supported out-of-bounds range check
-     * methods declared by {@code Objects}.  For example, a formatter producing
-     * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a
-     * {@code static final} field as follows:
-     * <pre>{@code
-     * static final
-     * BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException> AIOOBEF =
-     *     outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new);
-     * }</pre>
-     * The formatter instance {@code AIOOBEF} may be passed as an argument to an
-     * out-of-bounds range check method, such as checking if an {@code index}
-     * is within the bounds of a {@code limit}:
-     * <pre>{@code
-     * checkIndex(index, limit, AIOOBEF);
-     * }</pre>
-     * If the bounds check fails then the range check method will throw an
-     * {@code ArrayIndexOutOfBoundsException} with an appropriate exception
-     * message that is a produced from {@code AIOOBEF} as follows:
-     * <pre>{@code
-     * AIOOBEF.apply("checkIndex", List.of(index, limit));
-     * }</pre>
-     *
-     * @param f the exception factory, that produces an exception from a message
-     *        where the message is produced and formatted by the returned
-     *        exception formatter.  If this factory is stateless and side-effect
-     *        free then so is the returned formatter.
-     *        Exceptions thrown by the factory are relayed to the caller
-     *        of the returned formatter.
-     * @param <X> the type of runtime exception to be returned by the given
-     *        exception factory and relayed by the exception formatter
-     * @return the out-of-bounds exception formatter
-     */
-    public static <X extends RuntimeException>
-    BiFunction<String, List<Integer>, X> outOfBoundsExceptionFormatter(Function<String, X> f) {
-        // Use anonymous class to avoid bootstrap issues if this method is
-        // used early in startup
-        return new BiFunction<String, List<Integer>, X>() {
-            @Override
-            public X apply(String checkKind, List<Integer> args) {
-                return f.apply(outOfBoundsMessage(checkKind, args));
-            }
-        };
-    }
-
-    private static String outOfBoundsMessage(String checkKind, List<Integer> args) {
-        if (checkKind == null && args == null) {
-            return String.format("Range check failed");
-        } else if (checkKind == null) {
-            return String.format("Range check failed: %s", args);
-        } else if (args == null) {
-            return String.format("Range check failed: %s", checkKind);
-        }
-
-        int argSize = 0;
-        switch (checkKind) {
-            case "checkIndex":
-                argSize = 2;
-                break;
-            case "checkFromToIndex":
-            case "checkFromIndexSize":
-                argSize = 3;
-                break;
-            default:
-        }
-
-        // Switch to default if fewer or more arguments than required are supplied
-        switch ((args.size() != argSize) ? "" : checkKind) {
-            case "checkIndex":
-                return String.format("Index %d out-of-bounds for length %d",
-                                     args.get(0), args.get(1));
-            case "checkFromToIndex":
-                return String.format("Range [%d, %d) out-of-bounds for length %d",
-                                     args.get(0), args.get(1), args.get(2));
-            case "checkFromIndexSize":
-                return String.format("Range [%d, %<d + %d) out-of-bounds for length %d",
-                                     args.get(0), args.get(1), args.get(2));
-            default:
-                return String.format("Range check failed: %s %s", checkKind, args);
-        }
-    }
-
     /**
      * Checks if the {@code index} is within the bounds of the range from
      * {@code 0} (inclusive) to {@code length} (exclusive).
@@ -526,72 +359,16 @@ public final class Objects {
      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
      * </ul>
      *
-     * <p>This method behaves as if {@link #checkIndex(int, int, BiFunction)}
-     * was called with same out-of-bounds arguments and an exception formatter
-     * argument produced from an invocation of
-     * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may
-     * be more efficient).
-     *
      * @param index the index
      * @param length the upper-bound (exclusive) of the range
      * @return {@code index} if it is within bounds of the range
      * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds
      * @since 9
      */
+    @ForceInline
     public static
     int checkIndex(int index, int length) {
-        return checkIndex(index, length, null);
-    }
-
-    /**
-     * Checks if the {@code index} is within the bounds of the range from
-     * {@code 0} (inclusive) to {@code length} (exclusive).
-     *
-     * <p>The {@code index} is defined to be out-of-bounds if any of the
-     * following inequalities is true:
-     * <ul>
-     *  <li>{@code index < 0}</li>
-     *  <li>{@code index >= length}</li>
-     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
-     * </ul>
-     *
-     * <p>If the {@code index} is out-of-bounds, then a runtime exception is
-     * thrown that is the result of applying the following arguments to the
-     * exception formatter: the name of this method, {@code checkIndex};
-     * and an unmodifiable list integers whose values are, in order, the
-     * out-of-bounds arguments {@code index} and {@code length}.
-     *
-     * @param <X> the type of runtime exception to throw if the arguments are
-     *        out-of-bounds
-     * @param index the index
-     * @param length the upper-bound (exclusive) of the range
-     * @param oobef the exception formatter that when applied with this
-     *        method name and out-of-bounds arguments returns a runtime
-     *        exception.  If {@code null} or returns {@code null} then, it is as
-     *        if an exception formatter produced from an invocation of
-     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
-     *        instead (though it may be more efficient).
-     *        Exceptions thrown by the formatter are relayed to the caller.
-     * @return {@code index} if it is within bounds of the range
-     * @throws X if the {@code index} is out-of-bounds and the exception
-     *         formatter is non-{@code null}
-     * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds
-     *         and the exception formatter is {@code null}
-     * @since 9
-     *
-     * @implNote
-     * This method is made intrinsic in optimizing compilers to guide them to
-     * perform unsigned comparisons of the index and length when it is known the
-     * length is a non-negative value (such as that of an array length or from
-     * the upper bound of a loop)
-    */
-    @HotSpotIntrinsicCandidate
-    public static <X extends RuntimeException>
-    int checkIndex(int index, int length,
-                   BiFunction<String, List<Integer>, X> oobef) {
-        if (index < 0 || index >= length)
-            throw outOfBoundsCheckIndex(oobef, index, length);
-        return index;
+        return Preconditions.checkIndex(index, length, null);
     }
 
     /**
@@ -608,12 +385,6 @@ public final class Objects {
      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
      * </ul>
      *
-     * <p>This method behaves as if {@link #checkFromToIndex(int, int, int, BiFunction)}
-     * was called with same out-of-bounds arguments and an exception formatter
-     * argument produced from an invocation of
-     * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may
-     * be more efficient).
-     *
      * @param fromIndex the lower-bound (inclusive) of the sub-range
      * @param toIndex the upper-bound (exclusive) of the sub-range
      * @param length the upper-bound (exclusive) the range
@@ -623,54 +394,7 @@ public final class Objects {
      */
     public static
     int checkFromToIndex(int fromIndex, int toIndex, int length) {
-        return checkFromToIndex(fromIndex, toIndex, length, null);
-    }
-
-    /**
-     * Checks if the sub-range from {@code fromIndex} (inclusive) to
-     * {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
-     * (inclusive) to {@code length} (exclusive).
-     *
-     * <p>The sub-range is defined to be out-of-bounds if any of the following
-     * inequalities is true:
-     * <ul>
-     *  <li>{@code fromIndex < 0}</li>
-     *  <li>{@code fromIndex > toIndex}</li>
-     *  <li>{@code toIndex > length}</li>
-     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
-     * </ul>
-     *
-     * <p>If the sub-range  is out-of-bounds, then a runtime exception is
-     * thrown that is the result of applying the following arguments to the
-     * exception formatter: the name of this method, {@code checkFromToIndex};
-     * and an unmodifiable list integers whose values are, in order, the
-     * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}.
-     *
-     * @param <X> the type of runtime exception to throw if the arguments are
-     *        out-of-bounds
-     * @param fromIndex the lower-bound (inclusive) of the sub-range
-     * @param toIndex the upper-bound (exclusive) of the sub-range
-     * @param length the upper-bound (exclusive) the range
-     * @param oobef the exception formatter that when applied with this
-     *        method name and out-of-bounds arguments returns a runtime
-     *        exception.  If {@code null} or returns {@code null} then, it is as
-     *        if an exception formatter produced from an invocation of
-     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
-     *        instead (though it may be more efficient).
-     *        Exceptions thrown by the formatter are relayed to the caller.
-     * @return {@code fromIndex} if the sub-range within bounds of the range
-     * @throws X if the sub-range is out-of-bounds and the exception factory
-     *         function is non-{@code null}
-     * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and
-     *         the exception factory function is {@code null}
-     * @since 9
-     */
-    public static <X extends RuntimeException>
-    int checkFromToIndex(int fromIndex, int toIndex, int length,
-                         BiFunction<String, List<Integer>, X> oobef) {
-        if (fromIndex < 0 || fromIndex > toIndex || toIndex > length)
-            throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length);
-        return fromIndex;
+        return Preconditions.checkFromToIndex(fromIndex, toIndex, length, null);
     }
 
     /**
@@ -687,12 +411,6 @@ public final class Objects {
      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
      * </ul>
      *
-     * <p>This method behaves as if {@link #checkFromIndexSize(int, int, int, BiFunction)}
-     * was called with same out-of-bounds arguments and an exception formatter
-     * argument produced from an invocation of
-     * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may
-     * be more efficient).
-     *
      * @param fromIndex the lower-bound (inclusive) of the sub-interval
      * @param size the size of the sub-range
      * @param length the upper-bound (exclusive) of the range
@@ -702,54 +420,7 @@ public final class Objects {
      */
     public static
     int checkFromIndexSize(int fromIndex, int size, int length) {
-        return checkFromIndexSize(fromIndex, size, length, null);
+        return Preconditions.checkFromIndexSize(fromIndex, size, length, null);
     }
 
-    /**
-     * Checks if the sub-range from {@code fromIndex} (inclusive) to
-     * {@code fromIndex + size} (exclusive) is within the bounds of range from
-     * {@code 0} (inclusive) to {@code length} (exclusive).
-     *
-     * <p>The sub-range is defined to be out-of-bounds if any of the following
-     * inequalities is true:
-     * <ul>
-     *  <li>{@code fromIndex < 0}</li>
-     *  <li>{@code size < 0}</li>
-     *  <li>{@code fromIndex + size > length}, taking into account integer overflow</li>
-     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
-     * </ul>
-     *
-     * <p>If the sub-range  is out-of-bounds, then a runtime exception is
-     * thrown that is the result of applying the following arguments to the
-     * exception formatter: the name of this method, {@code checkFromIndexSize};
-     * and an unmodifiable list integers whose values are, in order, the
-     * out-of-bounds arguments {@code fromIndex}, {@code size}, and
-     * {@code length}.
-     *
-     * @param <X> the type of runtime exception to throw if the arguments are
-     *        out-of-bounds
-     * @param fromIndex the lower-bound (inclusive) of the sub-interval
-     * @param size the size of the sub-range
-     * @param length the upper-bound (exclusive) of the range
-     * @param oobef the exception formatter that when applied with this
-     *        method name and out-of-bounds arguments returns a runtime
-     *        exception.  If {@code null} or returns {@code null} then, it is as
-     *        if an exception formatter produced from an invocation of
-     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
-     *        instead (though it may be more efficient).
-     *        Exceptions thrown by the formatter are relayed to the caller.
-     * @return {@code fromIndex} if the sub-range within bounds of the range
-     * @throws X if the sub-range is out-of-bounds and the exception factory
-     *         function is non-{@code null}
-     * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and
-     *         the exception factory function is {@code null}
-     * @since 9
-     */
-    public static <X extends RuntimeException>
-    int checkFromIndexSize(int fromIndex, int size, int length,
-                           BiFunction<String, List<Integer>, X> oobef) {
-        if ((length | fromIndex | size) < 0 || size > length - fromIndex)
-            throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length);
-        return fromIndex;
-    }
 }
diff --git a/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java
index 1cba038d6e5..b97d0cf68c6 100644
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java
@@ -462,9 +462,13 @@ class ZipFile implements ZipConstants, Closeable {
 
     private class ZipEntryIterator implements Enumeration<ZipEntry>, Iterator<ZipEntry> {
         private int i = 0;
+        private final int entryCount;
 
         public ZipEntryIterator() {
-            ensureOpen();
+            synchronized (ZipFile.this) {
+                ensureOpen();
+                this.entryCount = zsrc.total;
+            }
         }
 
         public boolean hasMoreElements() {
@@ -472,10 +476,7 @@ class ZipFile implements ZipConstants, Closeable {
         }
 
         public boolean hasNext() {
-            synchronized (ZipFile.this) {
-                ensureOpen();
-                return i < zsrc.total;
-            }
+            return i < entryCount;
         }
 
         public ZipEntry nextElement() {
@@ -485,7 +486,7 @@ class ZipFile implements ZipConstants, Closeable {
         public ZipEntry next() {
             synchronized (ZipFile.this) {
                 ensureOpen();
-                if (i >= zsrc.total) {
+                if (!hasNext()) {
                     throw new NoSuchElementException();
                 }
                 // each "entry" has 3 ints in table entries
@@ -526,34 +527,34 @@ class ZipFile implements ZipConstants, Closeable {
     /* Checks ensureOpen() before invoke this method */
     private ZipEntry getZipEntry(String name, int pos) {
         byte[] cen = zsrc.cen;
-        ZipEntry e = new ZipEntry();
         int nlen = CENNAM(cen, pos);
         int elen = CENEXT(cen, pos);
         int clen = CENCOM(cen, pos);
-        e.flag = CENFLG(cen, pos);  // get the flag first
-        if (name != null) {
-            e.name = name;
-        } else {
-            if (!zc.isUTF8() && (e.flag & EFS) != 0) {
-                e.name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
+        int flag = CENFLG(cen, pos);
+        if (name == null) {
+            if (!zc.isUTF8() && (flag & EFS) != 0) {
+                name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
             } else {
-                e.name = zc.toString(cen, pos + CENHDR, nlen);
+                name = zc.toString(cen, pos + CENHDR, nlen);
             }
         }
+        ZipEntry e = new ZipEntry(name);
+        e.flag = flag;
         e.xdostime = CENTIM(cen, pos);
         e.crc = CENCRC(cen, pos);
         e.size = CENLEN(cen, pos);
         e.csize = CENSIZ(cen, pos);
         e.method = CENHOW(cen, pos);
         if (elen != 0) {
-            e.setExtra0(Arrays.copyOfRange(cen, pos + CENHDR + nlen,
-                                           pos + CENHDR + nlen + elen), true);
+            int start = pos + CENHDR + nlen;
+            e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true);
         }
         if (clen != 0) {
-            if (!zc.isUTF8() && (e.flag & EFS) != 0) {
-                e.comment = zc.toStringUTF8(cen, pos + CENHDR + nlen + elen, clen);
+            int start = pos + CENHDR + nlen + elen;
+            if (!zc.isUTF8() && (flag & EFS) != 0) {
+                e.comment = zc.toStringUTF8(cen, start, clen);
             } else {
-                e.comment = zc.toString(cen, pos + CENHDR + nlen + elen, clen);
+                e.comment = zc.toString(cen, start, clen);
             }
         }
         return e;
@@ -817,7 +818,7 @@ class ZipFile implements ZipConstants, Closeable {
         );
     }
 
-    /*
+    /**
      * Returns an array of strings representing the names of all entries
      * that begin with "META-INF/" (case ignored). This method is used
      * in JarFile, via SharedSecrets, as an optimization when looking up
@@ -827,14 +828,14 @@ class ZipFile implements ZipConstants, Closeable {
     private String[] getMetaInfEntryNames() {
         synchronized (this) {
             ensureOpen();
-            if (zsrc.metanames.size() == 0) {
+            if (zsrc.metanames == null) {
                 return null;
             }
-            String[] names = new String[zsrc.metanames.size()];
+            String[] names = new String[zsrc.metanames.length];
             byte[] cen = zsrc.cen;
             for (int i = 0; i < names.length; i++) {
-                int pos = zsrc.metanames.get(i);
-                names[i] = new String(cen, pos + CENHDR,  CENNAM(cen, pos),
+                int pos = zsrc.metanames[i];
+                names[i] = new String(cen, pos + CENHDR, CENNAM(cen, pos),
                                       StandardCharsets.UTF_8);
             }
             return names;
@@ -850,7 +851,7 @@ class ZipFile implements ZipConstants, Closeable {
         private long locpos;                 // position of first LOC header (usually 0)
         private byte[] comment;              // zip file comment
                                              // list of meta entries in META-INF dir
-        private ArrayList<Integer> metanames = new ArrayList<>();
+        private int[] metanames;
         private final boolean startsWithLoc; // true, if zip file starts with LOCSIG (usually true)
 
         // A Hashmap for all entries.
@@ -1159,7 +1160,7 @@ class ZipFile implements ZipConstants, Closeable {
             int next = -1;
 
             // list for all meta entries
-            metanames = new ArrayList<>();
+            ArrayList<Integer> metanamesList = null;
 
             // Iterate through the entries in the central directory
             int i = 0;
@@ -1194,13 +1195,21 @@ class ZipFile implements ZipConstants, Closeable {
                 idx = addEntry(idx, hash, next, pos);
                 // Adds name to metanames.
                 if (isMetaName(cen, pos + CENHDR, nlen)) {
-                    metanames.add(pos);
+                    if (metanamesList == null)
+                        metanamesList = new ArrayList<>(4);
+                    metanamesList.add(pos);
                 }
                 // skip ext and comment
                 pos += (CENHDR + nlen + elen + clen);
                 i++;
             }
             total = i;
+            if (metanamesList != null) {
+                metanames = new int[metanamesList.size()];
+                for (int j = 0, len = metanames.length; j < len; j++) {
+                    metanames[j] = metanamesList.get(j);
+                }
+            }
             if (pos + ENDHDR != cen.length) {
                 zerror("invalid CEN header (bad header size)");
             }
@@ -1265,30 +1274,23 @@ class ZipFile implements ZipConstants, Closeable {
             }
         }
 
-        private static byte[] metainf = new byte[] {
-            'M', 'E', 'T', 'A', '-', 'I' , 'N', 'F', '/',
-        };
-
-        /*
-         * Returns true if the specified entry's name begins with the string
-         * "META-INF/" irrespective of case.
+        /**
+         * Returns true if the bytes represent a non-directory name
+         * beginning with "META-INF/", disregarding ASCII case.
          */
-        private static boolean isMetaName(byte[] name,  int off, int len) {
-            if (len < 9 || (name[off] != 'M' && name[off] != 'm')) {  //  sizeof("META-INF/") - 1
-                return false;
-            }
-            off++;
-            for (int i = 1; i < metainf.length; i++) {
-                byte c = name[off++];
-                // Avoid toupper; it's locale-dependent
-                if (c >= 'a' && c <= 'z') {
-                    c += 'A' - 'a';
-                }
-                if (metainf[i] != c) {
-                    return false;
-                }
-            }
-            return true;
+        private static boolean isMetaName(byte[] name, int off, int len) {
+            // Use the "oldest ASCII trick in the book"
+            return len > 9                     // "META-INF/".length()
+                && name[off + len - 1] != '/'  // non-directory
+                && (name[off++] | 0x20) == 'm'
+                && (name[off++] | 0x20) == 'e'
+                && (name[off++] | 0x20) == 't'
+                && (name[off++] | 0x20) == 'a'
+                && (name[off++]       ) == '-'
+                && (name[off++] | 0x20) == 'i'
+                && (name[off++] | 0x20) == 'n'
+                && (name[off++] | 0x20) == 'f'
+                && (name[off]         ) == '/';
         }
 
         /*
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java
index 7a946099fdf..bc2396f10c3 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java
@@ -68,13 +68,14 @@ public class ClassLoaders {
         if (s != null && s.length() > 0)
             bcp = toURLClassPath(s);
 
-        // we have a class path if -cp is specified or -m is not specified
+        // we have a class path if -cp is specified or -m is not specified.
+        // If neither is specified then default to -cp <working directory>.
         URLClassPath ucp = null;
         String mainMid = System.getProperty("jdk.module.main");
         String cp = System.getProperty("java.class.path");
-        if (mainMid == null && (cp == null || cp.length() == 0))
-            cp = ".";
-        if (cp != null && cp.length() > 0)
+        if (mainMid == null && cp == null)
+            cp = "";
+        if (cp != null)
             ucp = toURLClassPath(cp);
 
 
@@ -197,7 +198,7 @@ public class ClassLoaders {
          * @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch
          */
         void appendToClassPathForInstrumentation(String path) {
-            appendToUCP(path, ucp);
+            addClassPathToUCP(path, ucp);
         }
 
         /**
@@ -224,7 +225,7 @@ public class ClassLoaders {
      */
     private static URLClassPath toURLClassPath(String cp) {
         URLClassPath ucp = new URLClassPath(new URL[0]);
-        appendToUCP(cp, ucp);
+        addClassPathToUCP(cp, ucp);
         return ucp;
     }
 
@@ -232,20 +233,28 @@ public class ClassLoaders {
      * Converts the elements in the given class path to file URLs and adds
      * them to the given URLClassPath.
      */
-    private static void appendToUCP(String cp, URLClassPath ucp) {
-        String[] elements = cp.split(File.pathSeparator);
-        if (elements.length == 0) {
-            // contains path separator(s) only, default to current directory
-            // to be compatible with long standing behavior
-            elements = new String[] { "" };
+    private static void addClassPathToUCP(String cp, URLClassPath ucp) {
+        int off = 0;
+        int next;
+        while ((next = cp.indexOf(File.pathSeparator, off)) != -1) {
+            addURLToUCP(cp.substring(off, next), ucp);
+            off = next + 1;
         }
-        for (String s: elements) {
-            try {
-                URL url = Paths.get(s).toRealPath().toUri().toURL();
-                ucp.addURL(url);
-            } catch (InvalidPathException | IOException ignore) {
-                // malformed path string or class path element does not exist
-            }
+
+        // remaining
+        addURLToUCP(cp.substring(off), ucp);
+    }
+
+    /**
+     * Attempts to convert to the given string to a file URL and adds it
+     * to the given URLClassPath.
+     */
+    private static void addURLToUCP(String s, URLClassPath ucp) {
+        try {
+            URL url = Paths.get(s).toRealPath().toUri().toURL();
+            ucp.addURL(url);
+        } catch (InvalidPathException | IOException ignore) {
+            // malformed path string or class path element does not exist
         }
     }
 
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
index 735d1b86143..bc7aaa5a6f3 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
@@ -33,6 +33,7 @@ import jdk.internal.reflect.Reflection;
 import jdk.internal.misc.VM;
 
 import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.vm.annotation.ForceInline;
 
 
 /**
@@ -209,46 +210,103 @@ public final class Unsafe {
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native boolean getBoolean(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putBoolean(Object o, long offset, boolean x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native byte    getByte(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putByte(Object o, long offset, byte x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native short   getShort(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putShort(Object o, long offset, short x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native char    getChar(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putChar(Object o, long offset, char x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native long    getLong(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putLong(Object o, long offset, long x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native float   getFloat(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putFloat(Object o, long offset, float x);
+
     /** @see #getInt(Object, long) */
     @HotSpotIntrinsicCandidate
     public native double  getDouble(Object o, long offset);
+
     /** @see #putInt(Object, long, int) */
     @HotSpotIntrinsicCandidate
     public native void    putDouble(Object o, long offset, double x);
 
+    /**
+     * Fetches a native pointer from a given memory address.  If the address is
+     * zero, or does not point into a block obtained from {@link
+     * #allocateMemory}, the results are undefined.
+     *
+     * <p>If the native pointer is less than 64 bits wide, it is extended as
+     * an unsigned number to a Java long.  The pointer may be indexed by any
+     * given byte offset, simply by adding that offset (as a simple integer) to
+     * the long representing the pointer.  The number of bytes actually read
+     * from the target address may be determined by consulting {@link
+     * #addressSize}.
+     *
+     * @see #allocateMemory
+     * @see #getInt(Object, long)
+     */
+    @ForceInline
+    public long getAddress(Object o, long offset) {
+        if (ADDRESS_SIZE == 4) {
+            return Integer.toUnsignedLong(getInt(o, offset));
+        } else {
+            return getLong(o, offset);
+        }
+    }
+
+    /**
+     * Stores a native pointer into a given memory address.  If the address is
+     * zero, or does not point into a block obtained from {@link
+     * #allocateMemory}, the results are undefined.
+     *
+     * <p>The number of bytes actually written at the target address may be
+     * determined by consulting {@link #addressSize}.
+     *
+     * @see #allocateMemory
+     * @see #putInt(Object, long, int)
+     */
+    @ForceInline
+    public void putAddress(Object o, long offset, long x) {
+        if (ADDRESS_SIZE == 4) {
+            putInt(o, offset, (int)x);
+        } else {
+            putLong(o, offset, x);
+        }
+    }
+
     // These read VM internal data.
 
     /**
@@ -287,8 +345,10 @@ public final class Unsafe {
      *
      * @see #allocateMemory
      */
-    @HotSpotIntrinsicCandidate
-    public native byte    getByte(long address);
+    @ForceInline
+    public byte getByte(long address) {
+        return getByte(null, address);
+    }
 
     /**
      * Stores a value into a given memory address.  If the address is zero, or
@@ -297,75 +357,94 @@ public final class Unsafe {
      *
      * @see #getByte(long)
      */
-    @HotSpotIntrinsicCandidate
-    public native void    putByte(long address, byte x);
+    @ForceInline
+    public void putByte(long address, byte x) {
+        putByte(null, address, x);
+    }
 
     /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native short   getShort(long address);
-    /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putShort(long address, short x);
-    /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native char    getChar(long address);
-    /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putChar(long address, char x);
-    /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native int     getInt(long address);
-    /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putInt(long address, int x);
-    /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native long    getLong(long address);
-    /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putLong(long address, long x);
-    /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native float   getFloat(long address);
-    /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putFloat(long address, float x);
-    /** @see #getByte(long) */
-    @HotSpotIntrinsicCandidate
-    public native double  getDouble(long address);
-    /** @see #putByte(long, byte) */
-    @HotSpotIntrinsicCandidate
-    public native void    putDouble(long address, double x);
+    @ForceInline
+    public short getShort(long address) {
+        return getShort(null, address);
+    }
 
-    /**
-     * Fetches a native pointer from a given memory address.  If the address is
-     * zero, or does not point into a block obtained from {@link
-     * #allocateMemory}, the results are undefined.
-     *
-     * <p>If the native pointer is less than 64 bits wide, it is extended as
-     * an unsigned number to a Java long.  The pointer may be indexed by any
-     * given byte offset, simply by adding that offset (as a simple integer) to
-     * the long representing the pointer.  The number of bytes actually read
-     * from the target address may be determined by consulting {@link
-     * #addressSize}.
-     *
-     * @see #allocateMemory
-     */
-    @HotSpotIntrinsicCandidate
-    public native long getAddress(long address);
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putShort(long address, short x) {
+        putShort(null, address, x);
+    }
 
-    /**
-     * Stores a native pointer into a given memory address.  If the address is
-     * zero, or does not point into a block obtained from {@link
-     * #allocateMemory}, the results are undefined.
-     *
-     * <p>The number of bytes actually written at the target address may be
-     * determined by consulting {@link #addressSize}.
-     *
-     * @see #getAddress(long)
-     */
-    @HotSpotIntrinsicCandidate
-    public native void putAddress(long address, long x);
+    /** @see #getByte(long) */
+    @ForceInline
+    public char getChar(long address) {
+        return getChar(null, address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putChar(long address, char x) {
+        putChar(null, address, x);
+    }
+
+    /** @see #getByte(long) */
+    @ForceInline
+    public int getInt(long address) {
+        return getInt(null, address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putInt(long address, int x) {
+        putInt(null, address, x);
+    }
+
+    /** @see #getByte(long) */
+    @ForceInline
+    public long getLong(long address) {
+        return getLong(null, address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putLong(long address, long x) {
+        putLong(null, address, x);
+    }
+
+    /** @see #getByte(long) */
+    @ForceInline
+    public float getFloat(long address) {
+        return getFloat(null, address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putFloat(long address, float x) {
+        putFloat(null, address, x);
+    }
+
+    /** @see #getByte(long) */
+    @ForceInline
+    public double getDouble(long address) {
+        return getDouble(null, address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putDouble(long address, double x) {
+        putDouble(null, address, x);
+    }
+
+    /** @see #getAddress(Object, long) */
+    @ForceInline
+    public long getAddress(long address) {
+        return getAddress(null, address);
+    }
+
+    /** @see #putAddress(Object, long, long) */
+    @ForceInline
+    public void putAddress(long address, long x) {
+        putAddress(null, address, x);
+    }
 
 
 
@@ -1271,6 +1350,13 @@ public final class Unsafe {
         return compareAndSwapObject(o, offset, expected, x);
     }
 
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapObjectVolatile(Object o, long offset,
+                                                                Object expected,
+                                                                Object x) {
+        return compareAndSwapObject(o, offset, expected, x);
+    }
+
     /**
      * Atomically updates Java variable to {@code x} if it is currently
      * holding {@code expected}.
@@ -1325,6 +1411,13 @@ public final class Unsafe {
         return compareAndSwapInt(o, offset, expected, x);
     }
 
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapIntVolatile(Object o, long offset,
+                                                             int expected,
+                                                             int x) {
+        return compareAndSwapInt(o, offset, expected, x);
+    }
+
     /**
      * Atomically updates Java variable to {@code x} if it is currently
      * holding {@code expected}.
@@ -1379,6 +1472,13 @@ public final class Unsafe {
         return compareAndSwapLong(o, offset, expected, x);
     }
 
+    @HotSpotIntrinsicCandidate
+    public final boolean weakCompareAndSwapLongVolatile(Object o, long offset,
+                                                              long expected,
+                                                              long x) {
+        return compareAndSwapLong(o, offset, expected, x);
+    }
+
     /**
      * Fetches a reference value from a given Java variable, with volatile
      * load semantics. Otherwise identical to {@link #getObject(Object, long)}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
index e49d17b0830..af8d3253a22 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
@@ -390,10 +390,25 @@ public class VM {
     private static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
 
     /*
-     * Returns the first non-null class loader up the execution stack,
-     * or null if only code from the null class loader is on the stack.
+     * Returns the first user-defined class loader up the execution stack,
+     * or the platform class loader if only code from the platform or
+     * bootstrap class loader is on the stack.
      */
-    public static native ClassLoader latestUserDefinedLoader();
+    public static ClassLoader latestUserDefinedLoader() {
+        ClassLoader loader = latestUserDefinedLoader0();
+        return loader != null ? loader : ClassLoader.getPlatformClassLoader();
+    }
+
+    /*
+     * Returns the first user-defined class loader up the execution stack,
+     * or null if only code from the platform or bootstrap class loader is
+     * on the stack.  VM does not keep a reference of platform loader and so
+     * it returns null.
+     *
+     * This method should be replaced with StackWalker::walk and then we can
+     * remove the logic in the VM.
+     */
+    private static native ClassLoader latestUserDefinedLoader0();
 
     /**
      * Returns {@code true} if we are in a set UID program.
diff --git a/jdk/src/java.base/share/classes/jdk/internal/util/Preconditions.java b/jdk/src/java.base/share/classes/jdk/internal/util/Preconditions.java
new file mode 100644
index 00000000000..cb1b748f620
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/util/Preconditions.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.util;
+
+import jdk.internal.HotSpotIntrinsicCandidate;
+
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Utility methods to check if state or arguments are correct.
+ *
+ */
+public class Preconditions {
+
+    /**
+     * Maps out-of-bounds values to a runtime exception.
+     *
+     * @param checkKind the kind of bounds check, whose name may correspond
+     *        to the name of one of the range check methods, checkIndex,
+     *        checkFromToIndex, checkFromIndexSize
+     * @param args the out-of-bounds arguments that failed the range check.
+     *        If the checkKind corresponds a the name of a range check method
+     *        then the bounds arguments are those that can be passed in order
+     *        to the method.
+     * @param oobef the exception formatter that when applied with a checkKind
+     *        and a list out-of-bounds arguments returns a runtime exception.
+     *        If {@code null} then, it is as if an exception formatter was
+     *        supplied that returns {@link IndexOutOfBoundsException} for any
+     *        given arguments.
+     * @return the runtime exception
+     */
+    private static RuntimeException outOfBounds(
+            BiFunction<String, List<Integer>, ? extends RuntimeException> oobef,
+            String checkKind,
+            Integer... args) {
+        List<Integer> largs = List.of(args);
+        RuntimeException e = oobef == null
+                             ? null : oobef.apply(checkKind, largs);
+        return e == null
+               ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e;
+    }
+
+    private static RuntimeException outOfBoundsCheckIndex(
+            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
+            int index, int length) {
+        return outOfBounds(oobe, "checkIndex", index, length);
+    }
+
+    private static RuntimeException outOfBoundsCheckFromToIndex(
+            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
+            int fromIndex, int toIndex, int length) {
+        return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length);
+    }
+
+    private static RuntimeException outOfBoundsCheckFromIndexSize(
+            BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
+            int fromIndex, int size, int length) {
+        return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length);
+    }
+
+    /**
+     * Returns an out-of-bounds exception formatter from an given exception
+     * factory.  The exception formatter is a function that formats an
+     * out-of-bounds message from its arguments and applies that message to the
+     * given exception factory to produce and relay an exception.
+     *
+     * <p>The exception formatter accepts two arguments: a {@code String}
+     * describing the out-of-bounds range check that failed, referred to as the
+     * <em>check kind</em>; and a {@code List<Integer>} containing the
+     * out-of-bound integer values that failed the check.  The list of
+     * out-of-bound values is not modified.
+     *
+     * <p>Three check kinds are supported {@code checkIndex},
+     * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding
+     * respectively to the specified application of an exception formatter as an
+     * argument to the out-of-bounds range check methods
+     * {@link #checkIndex(int, int, BiFunction) checkIndex},
+     * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and
+     * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}.
+     * Thus a supported check kind corresponds to a method name and the
+     * out-of-bound integer values correspond to method argument values, in
+     * order, preceding the exception formatter argument (similar in many
+     * respects to the form of arguments required for a reflective invocation of
+     * such a range check method).
+     *
+     * <p>Formatter arguments conforming to such supported check kinds will
+     * produce specific exception messages describing failed out-of-bounds
+     * checks.  Otherwise, more generic exception messages will be produced in
+     * any of the following cases: the check kind is supported but fewer
+     * or more out-of-bounds values are supplied, the check kind is not
+     * supported, the check kind is {@code null}, or the list of out-of-bound
+     * values is {@code null}.
+     *
+     * @apiNote
+     * This method produces an out-of-bounds exception formatter that can be
+     * passed as an argument to any of the supported out-of-bounds range check
+     * methods declared by {@code Objects}.  For example, a formatter producing
+     * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a
+     * {@code static final} field as follows:
+     * <pre>{@code
+     * static final
+     * BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException> AIOOBEF =
+     *     outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new);
+     * }</pre>
+     * The formatter instance {@code AIOOBEF} may be passed as an argument to an
+     * out-of-bounds range check method, such as checking if an {@code index}
+     * is within the bounds of a {@code limit}:
+     * <pre>{@code
+     * checkIndex(index, limit, AIOOBEF);
+     * }</pre>
+     * If the bounds check fails then the range check method will throw an
+     * {@code ArrayIndexOutOfBoundsException} with an appropriate exception
+     * message that is a produced from {@code AIOOBEF} as follows:
+     * <pre>{@code
+     * AIOOBEF.apply("checkIndex", List.of(index, limit));
+     * }</pre>
+     *
+     * @param f the exception factory, that produces an exception from a message
+     *        where the message is produced and formatted by the returned
+     *        exception formatter.  If this factory is stateless and side-effect
+     *        free then so is the returned formatter.
+     *        Exceptions thrown by the factory are relayed to the caller
+     *        of the returned formatter.
+     * @param <X> the type of runtime exception to be returned by the given
+     *        exception factory and relayed by the exception formatter
+     * @return the out-of-bounds exception formatter
+     */
+    public static <X extends RuntimeException>
+    BiFunction<String, List<Integer>, X> outOfBoundsExceptionFormatter(Function<String, X> f) {
+        // Use anonymous class to avoid bootstrap issues if this method is
+        // used early in startup
+        return new BiFunction<String, List<Integer>, X>() {
+            @Override
+            public X apply(String checkKind, List<Integer> args) {
+                return f.apply(outOfBoundsMessage(checkKind, args));
+            }
+        };
+    }
+
+    private static String outOfBoundsMessage(String checkKind, List<Integer> args) {
+        if (checkKind == null && args == null) {
+            return String.format("Range check failed");
+        } else if (checkKind == null) {
+            return String.format("Range check failed: %s", args);
+        } else if (args == null) {
+            return String.format("Range check failed: %s", checkKind);
+        }
+
+        int argSize = 0;
+        switch (checkKind) {
+            case "checkIndex":
+                argSize = 2;
+                break;
+            case "checkFromToIndex":
+            case "checkFromIndexSize":
+                argSize = 3;
+                break;
+            default:
+        }
+
+        // Switch to default if fewer or more arguments than required are supplied
+        switch ((args.size() != argSize) ? "" : checkKind) {
+            case "checkIndex":
+                return String.format("Index %d out-of-bounds for length %d",
+                                     args.get(0), args.get(1));
+            case "checkFromToIndex":
+                return String.format("Range [%d, %d) out-of-bounds for length %d",
+                                     args.get(0), args.get(1), args.get(2));
+            case "checkFromIndexSize":
+                return String.format("Range [%d, %<d + %d) out-of-bounds for length %d",
+                                     args.get(0), args.get(1), args.get(2));
+            default:
+                return String.format("Range check failed: %s %s", checkKind, args);
+        }
+    }
+
+    /**
+     * Checks if the {@code index} is within the bounds of the range from
+     * {@code 0} (inclusive) to {@code length} (exclusive).
+     *
+     * <p>The {@code index} is defined to be out-of-bounds if any of the
+     * following inequalities is true:
+     * <ul>
+     *  <li>{@code index < 0}</li>
+     *  <li>{@code index >= length}</li>
+     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
+     * </ul>
+     *
+     * <p>If the {@code index} is out-of-bounds, then a runtime exception is
+     * thrown that is the result of applying the following arguments to the
+     * exception formatter: the name of this method, {@code checkIndex};
+     * and an unmodifiable list integers whose values are, in order, the
+     * out-of-bounds arguments {@code index} and {@code length}.
+     *
+     * @param <X> the type of runtime exception to throw if the arguments are
+     *        out-of-bounds
+     * @param index the index
+     * @param length the upper-bound (exclusive) of the range
+     * @param oobef the exception formatter that when applied with this
+     *        method name and out-of-bounds arguments returns a runtime
+     *        exception.  If {@code null} or returns {@code null} then, it is as
+     *        if an exception formatter produced from an invocation of
+     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
+     *        instead (though it may be more efficient).
+     *        Exceptions thrown by the formatter are relayed to the caller.
+     * @return {@code index} if it is within bounds of the range
+     * @throws X if the {@code index} is out-of-bounds and the exception
+     *         formatter is non-{@code null}
+     * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds
+     *         and the exception formatter is {@code null}
+     * @since 9
+     *
+     * @implNote
+     * This method is made intrinsic in optimizing compilers to guide them to
+     * perform unsigned comparisons of the index and length when it is known the
+     * length is a non-negative value (such as that of an array length or from
+     * the upper bound of a loop)
+    */
+    @HotSpotIntrinsicCandidate
+    public static <X extends RuntimeException>
+    int checkIndex(int index, int length,
+                   BiFunction<String, List<Integer>, X> oobef) {
+        if (index < 0 || index >= length)
+            throw outOfBoundsCheckIndex(oobef, index, length);
+        return index;
+    }
+
+    /**
+     * Checks if the sub-range from {@code fromIndex} (inclusive) to
+     * {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
+     * (inclusive) to {@code length} (exclusive).
+     *
+     * <p>The sub-range is defined to be out-of-bounds if any of the following
+     * inequalities is true:
+     * <ul>
+     *  <li>{@code fromIndex < 0}</li>
+     *  <li>{@code fromIndex > toIndex}</li>
+     *  <li>{@code toIndex > length}</li>
+     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
+     * </ul>
+     *
+     * <p>If the sub-range  is out-of-bounds, then a runtime exception is
+     * thrown that is the result of applying the following arguments to the
+     * exception formatter: the name of this method, {@code checkFromToIndex};
+     * and an unmodifiable list integers whose values are, in order, the
+     * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}.
+     *
+     * @param <X> the type of runtime exception to throw if the arguments are
+     *        out-of-bounds
+     * @param fromIndex the lower-bound (inclusive) of the sub-range
+     * @param toIndex the upper-bound (exclusive) of the sub-range
+     * @param length the upper-bound (exclusive) the range
+     * @param oobef the exception formatter that when applied with this
+     *        method name and out-of-bounds arguments returns a runtime
+     *        exception.  If {@code null} or returns {@code null} then, it is as
+     *        if an exception formatter produced from an invocation of
+     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
+     *        instead (though it may be more efficient).
+     *        Exceptions thrown by the formatter are relayed to the caller.
+     * @return {@code fromIndex} if the sub-range within bounds of the range
+     * @throws X if the sub-range is out-of-bounds and the exception factory
+     *         function is non-{@code null}
+     * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and
+     *         the exception factory function is {@code null}
+     * @since 9
+     */
+    public static <X extends RuntimeException>
+    int checkFromToIndex(int fromIndex, int toIndex, int length,
+                         BiFunction<String, List<Integer>, X> oobef) {
+        if (fromIndex < 0 || fromIndex > toIndex || toIndex > length)
+            throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length);
+        return fromIndex;
+    }
+
+    /**
+     * Checks if the sub-range from {@code fromIndex} (inclusive) to
+     * {@code fromIndex + size} (exclusive) is within the bounds of range from
+     * {@code 0} (inclusive) to {@code length} (exclusive).
+     *
+     * <p>The sub-range is defined to be out-of-bounds if any of the following
+     * inequalities is true:
+     * <ul>
+     *  <li>{@code fromIndex < 0}</li>
+     *  <li>{@code size < 0}</li>
+     *  <li>{@code fromIndex + size > length}, taking into account integer overflow</li>
+     *  <li>{@code length < 0}, which is implied from the former inequalities</li>
+     * </ul>
+     *
+     * <p>If the sub-range  is out-of-bounds, then a runtime exception is
+     * thrown that is the result of applying the following arguments to the
+     * exception formatter: the name of this method, {@code checkFromIndexSize};
+     * and an unmodifiable list integers whose values are, in order, the
+     * out-of-bounds arguments {@code fromIndex}, {@code size}, and
+     * {@code length}.
+     *
+     * @param <X> the type of runtime exception to throw if the arguments are
+     *        out-of-bounds
+     * @param fromIndex the lower-bound (inclusive) of the sub-interval
+     * @param size the size of the sub-range
+     * @param length the upper-bound (exclusive) of the range
+     * @param oobef the exception formatter that when applied with this
+     *        method name and out-of-bounds arguments returns a runtime
+     *        exception.  If {@code null} or returns {@code null} then, it is as
+     *        if an exception formatter produced from an invocation of
+     *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
+     *        instead (though it may be more efficient).
+     *        Exceptions thrown by the formatter are relayed to the caller.
+     * @return {@code fromIndex} if the sub-range within bounds of the range
+     * @throws X if the sub-range is out-of-bounds and the exception factory
+     *         function is non-{@code null}
+     * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and
+     *         the exception factory function is {@code null}
+     * @since 9
+     */
+    public static <X extends RuntimeException>
+    int checkFromIndexSize(int fromIndex, int size, int length,
+                           BiFunction<String, List<Integer>, X> oobef) {
+        if ((length | fromIndex | size) < 0 || size > length - fromIndex)
+            throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length);
+        return fromIndex;
+    }
+}
diff --git a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties
index 6390b9792d4..32aa8ec65b3 100644
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties
@@ -100,7 +100,6 @@ java.launcher.X.usage=\
 \    -Xdiag            show additional diagnostic messages\n\
 \    -Xdiag:resolver   show resolver diagnostic messages\n\
 \    -Xnoclassgc       disable class garbage collection\n\
-\    -Xincgc           enable incremental garbage collection\n\
 \    -Xloggc:<file>    log GC status to a file with time stamps\n\
 \    -Xbatch           disable background compilation\n\
 \    -Xms<size>        set initial Java heap size\n\
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java b/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java
index 64f1c9da9fe..ea4b77535b2 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -441,17 +441,89 @@ final class ByteArrayAccess {
             (outOfs < 0) || ((out.length - outOfs) < len)) {
             throw new ArrayIndexOutOfBoundsException();
         }
-        len += outOfs;
-        while (outOfs < len) {
-            long i = in[inOfs++];
-            out[outOfs++] = (byte)(i >> 56);
-            out[outOfs++] = (byte)(i >> 48);
-            out[outOfs++] = (byte)(i >> 40);
-            out[outOfs++] = (byte)(i >> 32);
-            out[outOfs++] = (byte)(i >> 24);
-            out[outOfs++] = (byte)(i >> 16);
-            out[outOfs++] = (byte)(i >>  8);
-            out[outOfs++] = (byte)(i      );
+        if (littleEndianUnaligned) {
+            outOfs += byteArrayOfs;
+            len += outOfs;
+            while (outOfs < len) {
+                unsafe.putLong(out, (long)outOfs, reverseBytes(in[inOfs++]));
+                outOfs += 8;
+            }
+        } else {
+            len += outOfs;
+            while (outOfs < len) {
+                long i = in[inOfs++];
+                out[outOfs++] = (byte)(i >> 56);
+                out[outOfs++] = (byte)(i >> 48);
+                out[outOfs++] = (byte)(i >> 40);
+                out[outOfs++] = (byte)(i >> 32);
+                out[outOfs++] = (byte)(i >> 24);
+                out[outOfs++] = (byte)(i >> 16);
+                out[outOfs++] = (byte)(i >>  8);
+                out[outOfs++] = (byte)(i      );
+            }
+        }
+    }
+
+    /**
+     * byte[] to long[] conversion, little endian byte order
+     */
+    static void b2lLittle(byte[] in, int inOfs, long[] out, int outOfs, int len) {
+        if ((inOfs < 0) || ((in.length - inOfs) < len) ||
+            ((outOfs < 0) || (out.length - outOfs) < len/8)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (littleEndianUnaligned) {
+            inOfs += byteArrayOfs;
+            len += inOfs;
+            while (inOfs < len) {
+                out[outOfs++] = unsafe.getLong(in, (long)inOfs);
+                inOfs += 8;
+            }
+       } else {
+            len += inOfs;
+            while (inOfs < len) {
+                out[outOfs++] = ((in[inOfs    ] & 0xffL)
+                   | ((in[inOfs + 1] & 0xffL) <<  8)
+                   | ((in[inOfs + 2] & 0xffL) << 16)
+                   | ((in[inOfs + 3] & 0xffL) << 24)
+                   | ((in[inOfs + 4] & 0xffL) << 32)
+                   | ((in[inOfs + 5] & 0xffL) << 40)
+                   | ((in[inOfs + 6] & 0xffL) << 48)
+                   | ((in[inOfs + 7] & 0xffL) << 56));
+                inOfs += 8;
+            }
+        }
+    }
+
+
+    /**
+     * long[] to byte[] conversion, little endian byte order
+     */
+    static void l2bLittle(long[] in, int inOfs, byte[] out, int outOfs, int len) {
+        if ((inOfs < 0) || ((in.length - inOfs) < len/8) ||
+            (outOfs < 0) || ((out.length - outOfs) < len)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (littleEndianUnaligned) {
+            outOfs += byteArrayOfs;
+            len += outOfs;
+            while (outOfs < len) {
+                unsafe.putLong(out, (long)outOfs, in[inOfs++]);
+                outOfs += 8;
+            }
+        } else {
+            len += outOfs;
+            while (outOfs < len) {
+                long i = in[inOfs++];
+                out[outOfs++] = (byte)(i      );
+                out[outOfs++] = (byte)(i >>  8);
+                out[outOfs++] = (byte)(i >> 16);
+                out[outOfs++] = (byte)(i >> 24);
+                out[outOfs++] = (byte)(i >> 32);
+                out[outOfs++] = (byte)(i >> 40);
+                out[outOfs++] = (byte)(i >> 48);
+                out[outOfs++] = (byte)(i >> 56);
+            }
         }
     }
 }
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java b/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java
index 5861b6c7a85..861fa692471 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -259,14 +259,10 @@ public class PolicyFile extends java.security.Policy {
 
     private static final Debug debug = Debug.getInstance("policy");
 
-    private static final String NONE = "NONE";
-    private static final String P11KEYSTORE = "PKCS11";
-
     private static final String SELF = "${{self}}";
     private static final String X500PRINCIPAL =
                         "javax.security.auth.x500.X500Principal";
     private static final String POLICY = "java.security.policy";
-    private static final String SECURITY_MANAGER = "java.security.manager";
     private static final String POLICY_URL = "policy.url.";
     private static final String AUTH_POLICY = "java.security.auth.policy";
     private static final String AUTH_POLICY_URL = "auth.policy.url.";
@@ -287,6 +283,17 @@ public class PolicyFile extends java.security.Policy {
     private static final Class<?>[] PARAMS1 = { String.class };
     private static final Class<?>[] PARAMS2 = { String.class, String.class };
 
+    /**
+     * When a policy file has a syntax error, the exception code may generate
+     * another permission check and this can cause the policy file to be parsed
+     * repeatedly, leading to a StackOverflowError or ClassCircularityError.
+     * To avoid this, this set is populated with policy files that have been
+     * previously parsed and have syntax errors, so that they can be
+     * subsequently ignored.
+     */
+    private static AtomicReference<Set<URL>> badPolicyURLs =
+        new AtomicReference<>(new HashSet<>());
+
     /**
      * Initializes the Policy object and reads the default policy
      * configuration file(s) into the Policy object.
@@ -580,6 +587,16 @@ public class PolicyFile extends java.security.Policy {
      * @param policyFile the policy Reader object.
      */
     private boolean init(URL policy, PolicyInfo newInfo) {
+
+        // skip parsing policy file if it has been previously parsed and
+        // has syntax errors
+        if (badPolicyURLs.get().contains(policy)) {
+            if (debug != null) {
+                debug.println("skipping bad policy file: " + policy);
+            }
+            return false;
+        }
+
         boolean success = false;
         PolicyParser pp = new PolicyParser(expandProperties);
         InputStreamReader isr = null;
@@ -622,13 +639,18 @@ public class PolicyFile extends java.security.Policy {
                 addGrantEntry(ge, keyStore, newInfo);
             }
         } catch (PolicyParser.ParsingException pe) {
+            // record bad policy file to avoid later reparsing it
+            badPolicyURLs.updateAndGet(k -> {
+                k.add(policy);
+                return k;
+            });
             MessageFormat form = new MessageFormat(ResourcesMgr.getString
                 (POLICY + ".error.parsing.policy.message"));
             Object[] source = {policy, pe.getLocalizedMessage()};
             System.err.println(form.format(source));
-            if (debug != null)
+            if (debug != null) {
                 pe.printStackTrace();
-
+            }
         } catch (Exception e) {
             if (debug != null) {
                 debug.println("error parsing "+policy);
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java b/jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java
index ba8ed750254..f8aa620fc77 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -213,7 +213,9 @@ public class PolicyParser {
                             new MessageFormat(ResourcesMgr.getString(
                                 "duplicate.keystore.domain.name"));
                         Object[] source = {domainName};
-                        throw new ParsingException(form.format(source));
+                        String msg = "duplicate keystore domain name: " +
+                                     domainName;
+                        throw new ParsingException(msg, form, source);
                     }
                 }
             } else {
@@ -743,7 +745,8 @@ public class PolicyParser {
                     ResourcesMgr.getString
                             ("expected.expect.read.end.of.file."));
             Object[] source = {expect};
-            throw new ParsingException(form.format(source));
+            String msg = "expected [" + expect + "], read [end of file]";
+            throw new ParsingException(msg, form, source);
         case StreamTokenizer.TT_WORD:
             if (expect.equalsIgnoreCase(st.sval)) {
                 lookahead = st.nextToken();
@@ -1244,7 +1247,8 @@ public class PolicyParser {
                 MessageFormat form = new MessageFormat(ResourcesMgr.getString(
                     "duplicate.keystore.name"));
                 Object[] source = {keystoreName};
-                throw new ParsingException(form.format(source));
+                String msg = "duplicate keystore name: " + keystoreName;
+                throw new ParsingException(msg, form, source);
             }
         }
 
@@ -1316,6 +1320,8 @@ public class PolicyParser {
         private static final long serialVersionUID = -4330692689482574072L;
 
         private String i18nMessage;
+        private MessageFormat form;
+        private Object[] source;
 
         /**
          * Constructs a ParsingException with the specified
@@ -1330,26 +1336,34 @@ public class PolicyParser {
             i18nMessage = msg;
         }
 
+        public ParsingException(String msg, MessageFormat form,
+                                Object[] source) {
+            super(msg);
+            this.form = form;
+            this.source = source;
+        }
+
         public ParsingException(int line, String msg) {
             super("line " + line + ": " + msg);
-            MessageFormat form = new MessageFormat
-                (ResourcesMgr.getString("line.number.msg"));
-            Object[] source = {line, msg};
-            i18nMessage = form.format(source);
+            // don't call form.format unless getLocalizedMessage is called
+            // to avoid unnecessary permission checks
+            form = new MessageFormat(ResourcesMgr.getString("line.number.msg"));
+            source = new Object[] {line, msg};
         }
 
         public ParsingException(int line, String expect, String actual) {
             super("line " + line + ": expected [" + expect +
                 "], found [" + actual + "]");
-            MessageFormat form = new MessageFormat(ResourcesMgr.getString
+            // don't call form.format unless getLocalizedMessage is called
+            // to avoid unnecessary permission checks
+            form = new MessageFormat(ResourcesMgr.getString
                 ("line.number.expected.expect.found.actual."));
-            Object[] source = {line, expect, actual};
-            i18nMessage = form.format(source);
+            source = new Object[] {line, expect, actual};
         }
 
         @Override
         public String getLocalizedMessage() {
-            return i18nMessage;
+            return i18nMessage != null ? i18nMessage : form.format(source);
         }
     }
 
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/SHA3.java b/jdk/src/java.base/share/classes/sun/security/provider/SHA3.java
new file mode 100644
index 00000000000..1751c5b9fbb
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SHA3.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.provider;
+
+import static sun.security.provider.ByteArrayAccess.*;
+import java.nio.*;
+import java.util.*;
+import java.security.*;
+
+/**
+ * This class implements the Secure Hash Algorithm SHA-3 developed by
+ * the National Institute of Standards and Technology along with the
+ * National Security Agency as defined in FIPS PUB 202.
+ *
+ * <p>It implements java.security.MessageDigestSpi, and can be used
+ * through Java Cryptography Architecture (JCA), as a pluggable
+ * MessageDigest implementation.
+ *
+ * @since       9
+ * @author      Valerie Peng
+ */
+abstract class SHA3 extends DigestBase {
+
+    private static final int WIDTH = 200; // in bytes, e.g. 1600 bits
+    private static final int DM = 5; // dimension of lanes
+
+    private static final int NR = 24; // number of rounds
+
+    // precomputed round constants needed by the step mapping Iota
+    private static final long[] RC_CONSTANTS = {
+        0x01L, 0x8082L, 0x800000000000808aL,
+        0x8000000080008000L, 0x808bL, 0x80000001L,
+        0x8000000080008081L, 0x8000000000008009L, 0x8aL,
+        0x88L, 0x80008009L, 0x8000000aL,
+        0x8000808bL, 0x800000000000008bL, 0x8000000000008089L,
+        0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L,
+        0x800aL, 0x800000008000000aL, 0x8000000080008081L,
+        0x8000000000008080L, 0x80000001L, 0x8000000080008008L,
+    };
+
+    private byte[] state;
+
+    /**
+     * Creates a new SHA-3 object.
+     */
+    SHA3(String name, int digestLength) {
+        super(name, digestLength, (WIDTH - (2 * digestLength)));
+        implReset();
+    }
+
+    /**
+     * Core compression function. Processes blockSize bytes at a time
+     * and updates the state of this object.
+     */
+    void implCompress(byte[] b, int ofs) {
+        for (int i = 0; i < buffer.length; i++) {
+            state[i] ^= b[ofs++];
+        }
+        state = keccak(state);
+    }
+
+    /**
+     * Return the digest. Subclasses do not need to reset() themselves,
+     * DigestBase calls implReset() when necessary.
+     */
+    void implDigest(byte[] out, int ofs) {
+        int numOfPadding =
+            setPaddingBytes(buffer, (int)(bytesProcessed % buffer.length));
+        if (numOfPadding < 1) {
+            throw new ProviderException("Incorrect pad size: " + numOfPadding);
+        }
+        for (int i = 0; i < buffer.length; i++) {
+            state[i] ^= buffer[i];
+        }
+        state = keccak(state);
+        System.arraycopy(state, 0, out, ofs, engineGetDigestLength());
+    }
+
+    /**
+     * Resets the internal state to start a new hash.
+     */
+    void implReset() {
+        state = new byte[WIDTH];
+    }
+
+    /**
+     * Utility function for circular shift the specified long
+     * value to the left for n bits.
+     */
+    private static long circularShiftLeft(long lane, int n) {
+        return ((lane << n) | (lane >>> (64 - n)));
+    }
+
+    /**
+     * Utility function for padding the specified data based on the
+     * pad10*1 algorithm (section 5.1) and the 2-bit suffix "01" required
+     * for SHA-3 hash (section 6.1).
+     */
+    private static int setPaddingBytes(byte[] in, int len) {
+        if (len != in.length) {
+            // erase leftover values
+            Arrays.fill(in, len, in.length, (byte)0);
+            // directly store the padding bytes into the input
+            // as the specified buffer is allocated w/ size = rateR
+            in[len] |= (byte) 0x06;
+            in[in.length - 1] |= (byte) 0x80;
+        }
+        return (in.length - len);
+    }
+
+    /**
+     * Utility function for transforming the specified state from
+     * the byte array format into array of lanes as defined in
+     * section 3.1.2.
+     */
+    private static long[][] bytes2Lanes(byte[] s) {
+        if (s.length != WIDTH) {
+            throw new ProviderException("Error: incorrect input size " +
+                s.length);
+        }
+        // The conversion traverses along x-axis before y-axis. So, y is the
+        // first dimension and x is the second dimension.
+        long[][] s2 = new long[DM][DM];
+        int sOfs = 0;
+        for (int y = 0; y < DM; y++, sOfs += 40) {
+            b2lLittle(s, sOfs, s2[y], 0, 40);
+        }
+        return s2;
+    }
+
+    /**
+     * Utility function for transforming the specified arrays of
+     * lanes into a byte array as defined in section 3.1.3.
+     */
+    private static byte[] lanes2Bytes(long[][] m) {
+        byte[] s = new byte[WIDTH];
+        int sOfs = 0;
+        // The conversion traverses along x-axis before y-axis. So, y is the
+        // first dimension and x is the second dimension.
+        for (int y = 0; y < DM; y++, sOfs += 40) {
+            l2bLittle(m[y], 0, s, sOfs, 40);
+        }
+        return s;
+    }
+
+    /**
+     * Step mapping Theta as defined in section 3.2.1 .
+     */
+    private static long[][] smTheta(long[][] a) {
+        long[] c = new long[DM];
+        for (int i = 0; i < DM; i++) {
+            c[i] = a[0][i]^a[1][i]^a[2][i]^a[3][i]^a[4][i];
+        }
+        long[] d = new long[DM];
+        for (int i = 0; i < DM; i++) {
+            long c1 = c[(i + 4) % DM];
+            // left shift and wrap the leftmost bit into the rightmost bit
+            long c2 = circularShiftLeft(c[(i + 1) % DM], 1);
+            d[i] = c1^c2;
+        }
+        for (int y = 0; y < DM; y++) {
+            for (int x = 0; x < DM; x++) {
+                a[y][x] ^= d[x];
+            }
+        }
+        return a;
+    }
+
+    /**
+     * Step mapping Rho as defined in section 3.2.2.
+     */
+    private static long[][] smRho(long[][] a) {
+        long[][] a2 = new long[DM][DM];
+        a2[0][0] = a[0][0];
+        int xNext, yNext;
+        for (int t = 0, x = 1, y = 0; t <= 23; t++, x = xNext, y = yNext) {
+            int numberOfShift = ((t + 1)*(t + 2)/2) % 64;
+            a2[y][x] = circularShiftLeft(a[y][x], numberOfShift);
+            xNext = y;
+            yNext = (2 * x + 3 * y) % DM;
+        }
+        return a2;
+    }
+
+    /**
+     * Step mapping Pi as defined in section 3.2.3.
+     */
+    private static long[][] smPi(long[][] a) {
+        long[][] a2 = new long[DM][DM];
+        for (int y = 0; y < DM; y++) {
+            for (int x = 0; x < DM; x++) {
+                a2[y][x] = a[x][(x + 3 * y) % DM];
+            }
+        }
+        return a2;
+    }
+
+    /**
+     * Step mapping Chi as defined in section 3.2.4.
+     */
+    private static long[][] smChi(long[][] a) {
+        long[][] a2 = new long[DM][DM];
+        for (int y = 0; y < DM; y++) {
+            for (int x = 0; x < DM; x++) {
+                a2[y][x] = a[y][x] ^
+                    ((a[y][(x + 1) % DM] ^ 0xFFFFFFFFFFFFFFFFL) &
+                     a[y][(x + 2) % DM]);
+            }
+        }
+        return a2;
+    }
+
+    /**
+     * Step mapping Iota as defined in section 3.2.5.
+     *
+     * @return the processed state array
+     * @param state the state array to be processed
+     */
+    private static long[][] smIota(long[][] a, int rndIndex) {
+        a[0][0] ^= RC_CONSTANTS[rndIndex];
+        return a;
+    }
+
+    /**
+     * The function Keccak as defined in section 5.2 with
+     * rate r = 1600 and capacity c = (digest length x 2).
+     */
+    private static byte[] keccak(byte[] state) {
+        long[][] lanes = bytes2Lanes(state);
+        for (int ir = 0; ir < NR; ir++) {
+            lanes = smIota(smChi(smPi(smRho(smTheta(lanes)))), ir);
+        }
+        return lanes2Bytes(lanes);
+    }
+
+    public Object clone() throws CloneNotSupportedException {
+        SHA3 copy = (SHA3) super.clone();
+        copy.state = copy.state.clone();
+        return copy;
+    }
+
+    /**
+     * SHA3-224 implementation class.
+     */
+    public static final class SHA224 extends SHA3 {
+        public SHA224() {
+            super("SHA3-224", 28);
+        }
+    }
+
+    /**
+     * SHA3-256 implementation class.
+     */
+    public static final class SHA256 extends SHA3 {
+        public SHA256() {
+            super("SHA3-256", 32);
+        }
+    }
+
+    /**
+     * SHAs-384 implementation class.
+     */
+    public static final class SHA384 extends SHA3 {
+        public SHA384() {
+            super("SHA3-384", 48);
+        }
+    }
+
+    /**
+     * SHA3-512 implementation class.
+     */
+    public static final class SHA512 extends SHA3 {
+        public SHA512() {
+            super("SHA3-512", 64);
+        }
+    }
+}
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java b/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java
index 0ff50002713..ea090fa6898 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java
@@ -211,6 +211,25 @@ final class SunEntries {
         map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.6",
                 "SHA-512/256");
 
+        map.put("MessageDigest.SHA3-224", "sun.security.provider.SHA3$SHA224");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.7", "SHA3-224");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.7",
+                "SHA3-224");
+
+        map.put("MessageDigest.SHA3-256", "sun.security.provider.SHA3$SHA256");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.8", "SHA3-256");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.8",
+                "SHA3-256");
+        map.put("MessageDigest.SHA3-384", "sun.security.provider.SHA3$SHA384");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.9", "SHA3-384");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.9",
+                "SHA3-384");
+        map.put("MessageDigest.SHA3-512", "sun.security.provider.SHA3$SHA512");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.10", "SHA3-512");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.10",
+                "SHA3-512");
+
+
         /*
          * Algorithm Parameter Generator engines
          */
diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java
index 4a32fdf902e..2a3775da7df 100644
--- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -108,7 +108,7 @@ final class HandshakeHash {
      * a hash for the certificate verify message is required.
      */
     HandshakeHash(boolean needCertificateVerify) {
-        clonesNeeded = needCertificateVerify ? 3 : 2;
+        clonesNeeded = needCertificateVerify ? 4 : 3;
     }
 
     void reserve(ByteBuffer input) {
diff --git a/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java b/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
index 20e66d561fb..0bf5fcbe1fc 100644
--- a/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
+++ b/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
@@ -145,11 +145,10 @@ public class SignatureFileVerifier {
      */
     public static boolean isBlockOrSF(String s) {
         // we currently only support DSA and RSA PKCS7 blocks
-        if (s.endsWith(".SF") || s.endsWith(".DSA") ||
-                s.endsWith(".RSA") || s.endsWith(".EC")) {
-            return true;
-        }
-        return false;
+        return s.endsWith(".SF")
+            || s.endsWith(".DSA")
+            || s.endsWith(".RSA")
+            || s.endsWith(".EC");
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java b/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java
index 60b0b922190..3ff90bf483a 100644
--- a/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java
+++ b/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java
@@ -552,58 +552,61 @@ public class AlgorithmId implements Serializable, DerEncoder {
             return AlgorithmId.sha512WithECDSA_oid;
         }
 
-        // See if any of the installed providers supply a mapping from
-        // the given algorithm name to an OID string
-        String oidString;
-        if (!initOidTable) {
-            Provider[] provs = Security.getProviders();
-            for (int i=0; i<provs.length; i++) {
-                for (Enumeration<Object> enum_ = provs[i].keys();
-                     enum_.hasMoreElements(); ) {
-                    String alias = (String)enum_.nextElement();
-                    String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH);
-                    int index;
-                    if (upperCaseAlias.startsWith("ALG.ALIAS") &&
-                            (index=upperCaseAlias.indexOf("OID.", 0)) != -1) {
-                        index += "OID.".length();
-                        if (index == alias.length()) {
-                            // invalid alias entry
-                            break;
-                        }
-                        if (oidTable == null) {
-                            oidTable = new HashMap<>();
-                        }
-                        oidString = alias.substring(index);
-                        String stdAlgName = provs[i].getProperty(alias);
-                        if (stdAlgName != null) {
-                            stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH);
-                        }
-                        if (stdAlgName != null &&
-                                oidTable.get(stdAlgName) == null) {
-                            oidTable.put(stdAlgName,
-                                         new ObjectIdentifier(oidString));
-                        }
-                    }
-                }
-            }
-
-            if (oidTable == null) {
-                oidTable = Collections.<String,ObjectIdentifier>emptyMap();
-            }
-            initOidTable = true;
-        }
-
-        return oidTable.get(name.toUpperCase(Locale.ENGLISH));
+        return oidTable().get(name.toUpperCase(Locale.ENGLISH));
     }
 
     private static ObjectIdentifier oid(int ... values) {
         return ObjectIdentifier.newInternal(values);
     }
 
-    private static boolean initOidTable = false;
-    private static Map<String,ObjectIdentifier> oidTable;
+    private static volatile Map<String,ObjectIdentifier> oidTable;
     private static final Map<ObjectIdentifier,String> nameTable;
 
+    /** Returns the oidTable, lazily initializing it on first access. */
+    private static Map<String,ObjectIdentifier> oidTable()
+        throws IOException {
+        // Double checked locking; safe because oidTable is volatile
+        Map<String,ObjectIdentifier> tab;
+        if ((tab = oidTable) == null) {
+            synchronized (AlgorithmId.class) {
+                if ((tab = oidTable) == null)
+                    oidTable = tab = computeOidTable();
+            }
+        }
+        return tab;
+    }
+
+    /** Collects the algorithm names from the installed providers. */
+    private static HashMap<String,ObjectIdentifier> computeOidTable()
+        throws IOException {
+        HashMap<String,ObjectIdentifier> tab = new HashMap<>();
+        for (Provider provider : Security.getProviders()) {
+            for (Object key : provider.keySet()) {
+                String alias = (String)key;
+                String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH);
+                int index;
+                if (upperCaseAlias.startsWith("ALG.ALIAS") &&
+                    (index=upperCaseAlias.indexOf("OID.", 0)) != -1) {
+                    index += "OID.".length();
+                    if (index == alias.length()) {
+                        // invalid alias entry
+                        break;
+                    }
+                    String oidString = alias.substring(index);
+                    String stdAlgName = provider.getProperty(alias);
+                    if (stdAlgName != null) {
+                        stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH);
+                    }
+                    if (stdAlgName != null &&
+                        tab.get(stdAlgName) == null) {
+                        tab.put(stdAlgName, new ObjectIdentifier(oidString));
+                    }
+                }
+            }
+        }
+        return tab;
+    }
+
     /*****************************************************************/
 
     /*
diff --git a/jdk/src/java.base/share/conf/security/java.policy b/jdk/src/java.base/share/conf/security/java.policy
index 0400ebfd546..32d31472394 100644
--- a/jdk/src/java.base/share/conf/security/java.policy
+++ b/jdk/src/java.base/share/conf/security/java.policy
@@ -80,6 +80,10 @@ grant codeBase "jrt:/jdk.naming.dns" {
         permission java.security.AllPermission;
 };
 
+grant codeBase "jrt:/java.scripting" {
+        permission java.security.AllPermission;
+};
+
 grant codeBase "jrt:/jdk.scripting.nashorn" {
         permission java.security.AllPermission;
 };
diff --git a/jdk/src/java.base/share/native/include/jvmti.h b/jdk/src/java.base/share/native/include/jvmti.h
index 684fd2d7046..5f8835c0baa 100644
--- a/jdk/src/java.base/share/native/include/jvmti.h
+++ b/jdk/src/java.base/share/native/include/jvmti.h
@@ -704,7 +704,8 @@ typedef struct {
     unsigned int can_generate_resource_exhaustion_heap_events : 1;
     unsigned int can_generate_resource_exhaustion_threads_events : 1;
     unsigned int can_generate_early_vmstart : 1;
-    unsigned int : 6;
+    unsigned int can_generate_early_class_hook_events : 1;
+    unsigned int : 5;
     unsigned int : 16;
     unsigned int : 16;
     unsigned int : 16;
diff --git a/jdk/src/java.base/share/native/libjava/VM.c b/jdk/src/java.base/share/native/libjava/VM.c
index 61bae65f815..53837efc518 100644
--- a/jdk/src/java.base/share/native/libjava/VM.c
+++ b/jdk/src/java.base/share/native/libjava/VM.c
@@ -36,7 +36,7 @@ static JNINativeMethod methods[] = {
 };
 
 JNIEXPORT jobject JNICALL
-Java_jdk_internal_misc_VM_latestUserDefinedLoader(JNIEnv *env, jclass cls) {
+Java_jdk_internal_misc_VM_latestUserDefinedLoader0(JNIEnv *env, jclass cls) {
     return JVM_LatestUserDefinedLoader(env);
 }
 
diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java
index b3ff5c311e4..ae0d19c6cde 100644
--- a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java
@@ -26,7 +26,6 @@ package java.net.http;
 import java.io.Closeable;
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.concurrent.ExecutorService;
 import java.util.function.Consumer;
@@ -557,25 +556,37 @@ public class AsyncSSLDelegate implements Closeable, AsyncConnection {
     }
 
     static void logParams(SSLParameters p) {
-        if (!Log.ssl())
+        if (!Log.ssl()) {
             return;
+        }
+
         Log.logSSL("SSLParameters:");
         if (p == null) {
             Log.logSSL("Null params");
             return;
         }
-        for (String cipher : p.getCipherSuites()) {
-            Log.logSSL("cipher: {0}\n", cipher);
+
+        if (p.getCipherSuites() != null) {
+            for (String cipher : p.getCipherSuites()) {
+                Log.logSSL("cipher: {0}\n", cipher);
+            }
         }
+
+        // SSLParameters.getApplicationProtocols() can't return null
         for (String approto : p.getApplicationProtocols()) {
             Log.logSSL("application protocol: {0}\n", approto);
         }
-        for (String protocol : p.getProtocols()) {
-            Log.logSSL("protocol: {0}\n", protocol);
+
+        if (p.getProtocols() != null) {
+            for (String protocol : p.getProtocols()) {
+                Log.logSSL("protocol: {0}\n", protocol);
+            }
         }
-        if (p.getServerNames() != null)
+
+        if (p.getServerNames() != null) {
             for (SNIServerName sname : p.getServerNames()) {
                 Log.logSSL("server name: {0}\n", sname.toString());
+            }
         }
     }
 
diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java
index 446987d6b5d..226cee95c55 100644
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java
@@ -35,6 +35,7 @@ import java.nio.channels.ClosedChannelException;
 import java.nio.channels.SelectableChannel;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -155,6 +156,15 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
         selmgr.register(exchange);
     }
 
+    /**
+     * Only used from RawChannel to disconnect the channel from
+     * the selector
+     */
+    void cancelRegistration(SocketChannel s) {
+        selmgr.cancel(s);
+    }
+
+
     Http2ClientImpl client2() {
         return client2;
     }
@@ -220,6 +230,13 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
             selector.wakeup();
         }
 
+        synchronized void cancel(SocketChannel e) {
+            SelectionKey key = e.keyFor(selector);
+            if (key != null)
+                key.cancel();
+            selector.wakeup();
+        }
+
         void wakeupSelector() {
             selector.wakeup();
         }
diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java
index 10758d6db99..dcbfbdb8f1a 100644
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java
@@ -176,7 +176,7 @@ class HttpResponseImpl extends HttpResponse {
      *
      * @return
      */
-    RawChannel rawChannel() {
+    RawChannel rawChannel() throws IOException {
         if (rawchan == null) {
             rawchan = new RawChannel(request.client(), connection);
         }
diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Log.java b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java
index 991edfefa6c..51e5ce9633e 100644
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Log.java
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java
@@ -88,7 +88,7 @@ abstract class Log implements System.Logger {
                         logging |= TRACE;
                         break;
                     case "all":
-                        logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE;
+                        logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE|SSL;
                         break;
                 }
                 if (val.startsWith("frames")) {
diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java
index e4dc3b00b8d..5f6fb4df6c0 100644
--- a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java
@@ -29,6 +29,7 @@ import java.nio.channels.ByteChannel;
 import java.nio.channels.GatheringByteChannel;
 import java.nio.channels.SelectableChannel;
 import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
 
 //
 // Used to implement WebSocket. Each RawChannel corresponds to a TCP connection
@@ -56,9 +57,21 @@ final class RawChannel implements ByteChannel, GatheringByteChannel {
     interface NonBlockingEvent extends RawEvent {
     }
 
-    RawChannel(HttpClientImpl client, HttpConnection connection) {
+    RawChannel(HttpClientImpl client, HttpConnection connection)
+                                                throws IOException {
         this.client = client;
         this.connection = connection;
+        SocketChannel chan = connection.channel();
+        client.cancelRegistration(chan);
+        chan.configureBlocking(false);
+    }
+
+    SocketChannel socketChannel() {
+        return connection.channel();
+    }
+
+    ByteBuffer getRemaining() {
+        return connection.getRemaining();
     }
 
     private class RawAsyncEvent extends AsyncEvent {
diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java
index cea95c8f2f6..91252c93b88 100644
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java
@@ -32,6 +32,9 @@ import java.nio.ByteBuffer;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.function.BiFunction;
 import java.util.function.LongConsumer;
 
@@ -409,13 +412,20 @@ class Stream extends ExchangeImpl {
     @Override
     HttpResponseImpl getResponse() throws IOException {
         try {
-            return getResponseAsync(null).join();
-        } catch (Throwable e) {
+            if (request.timeval() > 0) {
+                return getResponseAsync(null).get(
+                        request.timeval(), TimeUnit.MILLISECONDS);
+            } else {
+                return getResponseAsync(null).join();
+            }
+        } catch (TimeoutException e) {
+            throw new HttpTimeoutException("Response timed out");
+        } catch (InterruptedException | ExecutionException e) {
             Throwable t = e.getCause();
             if (t instanceof IOException) {
                 throw (IOException)t;
             }
-            throw e;
+            throw new IOException(e);
         }
     }
 
diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java b/jdk/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java
index 6a7ddaa882c..d3cc7da3520 100644
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java
@@ -24,6 +24,8 @@
  */
 package java.net.http;
 
+import java.io.UncheckedIOException;
+import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
@@ -126,6 +128,8 @@ final class WSOpeningHandshake {
                         return CompletableFuture.completedFuture(result);
                     } catch (WebSocketHandshakeException e) {
                         return CompletableFuture.failedFuture(e);
+                    } catch (UncheckedIOException ee) {
+                        return CompletableFuture.failedFuture(ee.getCause());
                     }
                 });
     }
@@ -149,7 +153,12 @@ final class WSOpeningHandshake {
         checkAccept(response, h);
         checkExtensions(response, h);
         String subprotocol = checkAndReturnSubprotocol(response, h);
-        RawChannel channel = ((HttpResponseImpl) response).rawChannel();
+        RawChannel channel = null;
+        try {
+            channel = ((HttpResponseImpl) response).rawChannel();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
         return new Result(subprotocol, channel);
     }
 
diff --git a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c
index 0c57f8b289d..a74b2b725ba 100644
--- a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c
+++ b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c
@@ -518,18 +518,22 @@ static void
 splitPathList(const char* str, int* pathCount, char*** paths) {
     int count = 0;
     char** segments = NULL;
+    char** new_segments;
     char* c = (char*) str;
     while (*c != '\0') {
         while (*c == ' ') c++;          /* skip leading spaces */
         if (*c == '\0') {
             break;
         }
-        if (segments == NULL) {
-            segments = (char**)malloc( sizeof(char**) );
-        } else {
-            segments = (char**)realloc( segments, (count+1)*sizeof(char**) );
+        new_segments = (char**)realloc(segments, (count+1)*sizeof(char*));
+        if (new_segments == NULL) {
+            jplis_assert(0);
+            free(segments);
+            count = 0;
+            segments = NULL;
+            break;
         }
-        jplis_assert(segments != (char**)NULL);
+        segments = new_segments;
         segments[count++] = c;
         c = strchr(c, ' ');
         if (c == NULL) {
diff --git a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java
index bc06286e8da..f429452419e 100644
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java
@@ -2506,15 +2506,12 @@ public class LogManager {
         }
     }
 
-    // Management Support
-    private static LoggingMXBean loggingMXBean = null;
     /**
      * String representation of the
      * {@link javax.management.ObjectName} for the management interface
      * for the logging facility.
      *
      * @see java.lang.management.PlatformLoggingMXBean
-     * @see java.util.logging.LoggingMXBean
      *
      * @since 1.5
      */
@@ -2523,24 +2520,21 @@ public class LogManager {
 
     /**
      * Returns {@code LoggingMXBean} for managing loggers.
-     * An alternative way to manage loggers is through the
-     * {@link java.lang.management.PlatformLoggingMXBean} interface
-     * that can be obtained by calling:
-     * <pre>
-     *     PlatformLoggingMXBean logging = {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
-     *         ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class);
-     * </pre>
      *
      * @return a {@link LoggingMXBean} object.
      *
+     * @deprecated {@code java.util.logging.LoggingMXBean} is deprecated and
+     *      replaced with {@code java.lang.management.PlatformLoggingMXBean}. Use
+     *      {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
+     *      ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class)
+     *      instead.
+     *
      * @see java.lang.management.PlatformLoggingMXBean
      * @since 1.5
      */
+    @Deprecated(since="9")
     public static synchronized LoggingMXBean getLoggingMXBean() {
-        if (loggingMXBean == null) {
-            loggingMXBean =  new Logging();
-        }
-        return loggingMXBean;
+        return Logging.getInstance();
     }
 
     /**
diff --git a/jdk/src/java.logging/share/classes/java/util/logging/Logging.java b/jdk/src/java.logging/share/classes/java/util/logging/Logging.java
index 70c59503e4e..716e8bc150d 100644
--- a/jdk/src/java.logging/share/classes/java/util/logging/Logging.java
+++ b/jdk/src/java.logging/share/classes/java/util/logging/Logging.java
@@ -44,16 +44,18 @@ import java.util.ArrayList;
  * @see Logger
  * @see LogManager
  */
-class Logging implements LoggingMXBean {
+@SuppressWarnings("deprecation") // implements LoggingMXBean
+final class Logging implements LoggingMXBean {
 
     private static LogManager logManager = LogManager.getLogManager();
 
     /** Constructor of Logging which is the implementation class
      *  of LoggingMXBean.
      */
-    Logging() {
+    private Logging() {
     }
 
+    @Override
     public List<String> getLoggerNames() {
         Enumeration<String> loggers = logManager.getLoggerNames();
         ArrayList<String> array = new ArrayList<>();
@@ -65,6 +67,7 @@ class Logging implements LoggingMXBean {
     }
 
     private static String EMPTY_STRING = "";
+    @Override
     public String getLoggerLevel(String loggerName) {
         Logger l = logManager.getLogger(loggerName);
         if (l == null) {
@@ -79,6 +82,7 @@ class Logging implements LoggingMXBean {
         }
     }
 
+    @Override
     public void setLoggerLevel(String loggerName, String levelName) {
         if (loggerName == null) {
             throw new NullPointerException("loggerName is null");
@@ -102,6 +106,7 @@ class Logging implements LoggingMXBean {
         logger.setLevel(level);
     }
 
+    @Override
     public String getParentLoggerName( String loggerName ) {
         Logger l = logManager.getLogger( loggerName );
         if (l == null) {
@@ -116,4 +121,11 @@ class Logging implements LoggingMXBean {
             return p.getName();
         }
     }
+
+    static Logging getInstance() {
+        return INSTANCE;
+    }
+
+    private static final Logging INSTANCE = new Logging();
+
 }
diff --git a/jdk/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java b/jdk/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java
index 9d545d8d28d..812eb36622d 100644
--- a/jdk/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java
@@ -27,30 +27,23 @@ package java.util.logging;
 
 
 /**
- * The management interface for the logging facility. It is recommended
- * to use the {@link java.lang.management.PlatformLoggingMXBean} management
- * interface that implements all attributes defined in this
- * {@code LoggingMXBean}.  The
- * {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
- * ManagementFactory.getPlatformMXBean} method can be used to obtain
- * the {@code PlatformLoggingMXBean} object representing the management
- * interface for logging.
+ * The management interface for the logging facility.
  *
- * <p>There is a single global instance of the {@code LoggingMXBean}.
- * This instance is an {@link javax.management.MXBean MXBean} that
- * can be obtained by calling the {@link LogManager#getLoggingMXBean}
- * method or from the
- * {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer
+ * {@link java.lang.management.PlatformLoggingMXBean
+ * java.lang.management.PlatformLoggingMXBean} is the management interface
+ * for logging facility registered in the {@link
+ * java.lang.management.ManagementFactory#getPlatformMBeanServer()
  * platform MBeanServer}.
- * <p>
- * The {@link javax.management.ObjectName ObjectName} that uniquely identifies
- * the management interface for logging within the {@code MBeanServer} is:
- * <pre>
- *    {@link LogManager#LOGGING_MXBEAN_NAME java.util.logging:type=Logging}
- * </pre>
- * <p>
- * The instance registered in the platform {@code MBeanServer}
- * is also a {@link java.lang.management.PlatformLoggingMXBean}.
+ * It is recommended to use the {@code PlatformLoggingMXBean} obtained via
+ * the {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
+ * ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class)} method.
+ *
+ * @deprecated {@code LoggingMXBean} is no longer a {@link
+ * java.lang.management.PlatformManagedObject platform MXBean} and is replaced
+ * with {@link java.lang.management.PlatformLoggingMXBean}.
+ * It will not register in the platform {@code MBeanServer}.
+ * Use {@code ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class)}
+ * instead.
  *
  * @author  Ron Mann
  * @author  Mandy Chung
@@ -58,6 +51,7 @@ package java.util.logging;
  *
  * @see java.lang.management.PlatformLoggingMXBean
  */
+@Deprecated(since="9")
 public interface LoggingMXBean {
 
     /**
diff --git a/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java b/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java
index 8d0083ff807..9a6252add85 100644
--- a/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java
+++ b/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java
@@ -598,9 +598,8 @@ public class ManagementFactory {
 
         try {
             final ObjectName objName = new ObjectName(mxbeanName);
-            // skip the isInstanceOf check for LoggingMXBean
             String intfName = mxbeanInterface.getName();
-            if (!connection.isInstanceOf(objName, intfName)) {
+            if (!isInstanceOf(connection, objName, intfName)) {
                 throw new IllegalArgumentException(mxbeanName +
                     " is not an instance of " + mxbeanInterface);
             }
@@ -616,6 +615,33 @@ public class ManagementFactory {
         }
     }
 
+    // This makes it possible to obtain an instance of LoggingMXBean
+    // using newPlatformMXBeanProxy(mbs, on, LoggingMXBean.class)
+    // even though the underlying MXBean no longer implements
+    // java.util.logging.LoggingMXBean.
+    // Altough java.util.logging.LoggingMXBean is deprecated, an application
+    // that uses newPlatformMXBeanProxy(mbs, on, LoggingMXBean.class) will
+    // continue to work.
+    //
+    private static boolean isInstanceOf(MBeanServerConnection connection,
+            ObjectName objName, String intfName)
+            throws InstanceNotFoundException, IOException
+    {
+        // special case for java.util.logging.LoggingMXBean.
+        // java.util.logging.LoggingMXBean is deprecated and
+        // replaced with java.lang.management.PlatformLoggingMXBean,
+        // so we will consider that any MBean implementing
+        // java.lang.management.PlatformLoggingMXBean also implements
+        // java.util.logging.LoggingMXBean.
+        if ("java.util.logging.LoggingMXBean".equals(intfName)) {
+            if (connection.isInstanceOf(objName,
+                    PlatformLoggingMXBean.class.getName())) {
+                return true;
+            }
+        }
+        return connection.isInstanceOf(objName, intfName);
+    }
+
     /**
      * Returns the platform MXBean implementing
      * the given {@code mxbeanInterface} which is specified
diff --git a/jdk/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java b/jdk/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java
index d18d0b30c40..80595dd75d6 100644
--- a/jdk/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java
+++ b/jdk/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java
@@ -44,10 +44,6 @@ package java.lang.management;
  *      {@link java.util.logging.LogManager#LOGGING_MXBEAN_NAME java.util.logging:type=Logging}
  * </pre>
  *
- * <p>The instance registered in the platform {@code MBeanServer} with
- * this {@code ObjectName} implements all attributes defined by
- * {@link java.util.logging.LoggingMXBean}.
- *
  * @since   1.7
  */
 public interface PlatformLoggingMXBean extends PlatformManagedObject {
diff --git a/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java b/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java
index 44682b29971..4eb5742b2ba 100644
--- a/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java
+++ b/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java
@@ -26,6 +26,8 @@
 package sun.management;
 
 import java.lang.management.*;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
 import javax.management.MBeanServer;
@@ -43,9 +45,13 @@ import jdk.internal.misc.SharedSecrets;
 import java.util.ArrayList;
 import java.util.List;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Module;
+import java.lang.reflect.UndeclaredThrowableException;
 import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
 
 /**
  * ManagementFactoryHelper provides static factory methods to create
@@ -66,6 +72,7 @@ public class ManagementFactoryHelper {
         return jvm;
     }
 
+    static final String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging";
     private static ClassLoadingImpl    classMBean = null;
     private static MemoryImpl          memoryMBean = null;
     private static ThreadImpl          threadMBean = null;
@@ -145,74 +152,138 @@ public class ManagementFactoryHelper {
     }
 
     public static PlatformLoggingMXBean getPlatformLoggingMXBean() {
-        if (LoggingMXBeanSupport.isAvailable()) {
-            return PlatformLoggingImpl.instance;
+        if (LoggingMXBeanAccess.isAvailable()) {
+            return PlatformLoggingImpl.MBEAN;
         } else {
             return null;
         }
     }
 
     public static boolean isPlatformLoggingMXBeanAvailable() {
-        return LoggingMXBeanSupport.isAvailable();
+        return LoggingMXBeanAccess.isAvailable();
     }
 
-    /**
-     * The logging MXBean object is an instance of
-     * PlatformLoggingMXBean and java.util.logging.LoggingMXBean
-     * but it can't directly implement two MXBean interfaces
-     * as a compliant MXBean implements exactly one MXBean interface,
-     * or if it implements one interface that is a subinterface of
-     * all the others; otherwise, it is a non-compliant MXBean
-     * and MBeanServer will throw NotCompliantMBeanException.
-     * See the Definition of an MXBean section in javax.management.MXBean spec.
-     *
-     * To create a compliant logging MXBean, define a LoggingMXBean interface
-     * that extend PlatformLoggingMXBean and j.u.l.LoggingMXBean
-    */
-    public interface LoggingMXBean
-        extends PlatformLoggingMXBean, java.util.logging.LoggingMXBean {
-    }
-
-    // This is a trick: if java.util.logging is not present then
-    // attempting to access something that implements
-    // java.util.logging.LoggingMXBean will trigger a CNFE.
-    // So we cannot directly call any static method or access any static field
-    // on PlatformLoggingImpl, as we would risk raising a CNFE.
-    // Instead we use this intermediate LoggingMXBeanSupport class to determine
+    // The LoggingMXBeanAccess class uses reflection to determine
     // whether java.util.logging is present, and load the actual LoggingMXBean
     // implementation.
     //
-    static final class LoggingMXBeanSupport {
-        final static Object loggingImpl =
-                AccessController.doPrivileged(new PrivilegedAction<Object>() {
-            @Override
-            public Object run() {
-                try {
-                    // create a LoggingProxyImpl instance when
-                    // java.util.logging classes exist
-                    Class<?> c = Class.forName("java.util.logging.Logging", true, null);
-                    Constructor<?> cons = c.getDeclaredConstructor();
-                    cons.setAccessible(true);
-                    return cons.newInstance();
-                } catch (ClassNotFoundException cnf) {
-                    return null;
-                } catch (NoSuchMethodException | InstantiationException
-                        | IllegalAccessException | InvocationTargetException e) {
-                    throw new AssertionError(e);
-                }
-            }});
+    static final class LoggingMXBeanAccess {
+
+        final static String LOG_MANAGER_CLASS_NAME = "java.util.logging.LogManager";
+        final static String LOGGING_MXBEAN_CLASS_NAME = "java.util.logging.LoggingMXBean";
+        final static Class<?> LOG_MANAGER_CLASS = loadLoggingClass(LOG_MANAGER_CLASS_NAME);
 
         static boolean isAvailable() {
-            return loggingImpl != null;
+            return LOG_MANAGER_CLASS != null;
         }
+
+        private static Class<?> loadLoggingClass(String className) {
+            return AccessController.doPrivileged(new PrivilegedAction<>() {
+                @Override
+                public Class<?> run() {
+                    Optional<Module> logging = java.lang.reflect.Layer.boot()
+                        .findModule("java.logging");
+                    if (logging.isPresent()) {
+                        return Class.forName(logging.get(), className);
+                    }
+                    return null;
+                }
+            });
+        }
+
+        private Map<String, Method> initMethodMap(Object impl) {
+            if (impl == null) {
+                return Collections.emptyMap();
+            }
+            Class<?> intfClass = loadLoggingClass(LOGGING_MXBEAN_CLASS_NAME);
+            final Map<String, Method> methodsMap = new HashMap<>();
+            for (Method m : intfClass.getMethods()) {
+                try {
+                    // Sanity checking: all public methods present in
+                    // java.util.logging.LoggingMXBean should
+                    // also be in PlatformLoggingMXBean
+                    Method specMethod = PlatformLoggingMXBean.class
+                             .getMethod(m.getName(), m.getParameterTypes());
+                    if (specMethod.getReturnType().isAssignableFrom(m.getReturnType())) {
+                        if (methodsMap.putIfAbsent(m.getName(), m) != null) {
+                            throw new RuntimeException("unexpected polymorphic method: "
+                                     + m.getName());
+                        }
+                    }
+                } catch (NoSuchMethodException x) {
+                    // All methods in java.util.logging.LoggingMXBean should
+                    // also be in PlatformLoggingMXBean
+                    throw new InternalError(x);
+                }
+            }
+            return Collections.unmodifiableMap(methodsMap);
+        }
+
+        private static Object getMXBeanImplementation() {
+            if (!isAvailable()) {
+                // should not happen
+                throw new NoClassDefFoundError(LOG_MANAGER_CLASS_NAME);
+            }
+            try {
+                final Method m = LOG_MANAGER_CLASS.getMethod("getLoggingMXBean");
+                return m.invoke(null);
+            } catch (NoSuchMethodException
+                    | IllegalAccessException
+                    | InvocationTargetException x) {
+                throw new ExceptionInInitializerError(x);
+            }
+         }
+
+        // The implementation object, which will be invoked through
+        // reflection. The implementation does not need to implement
+        // PlatformLoggingMXBean, but must declare the same methods
+        // with same signatures, and they must be public, with one
+        // exception:
+        // getObjectName will not be called on the implementation object,
+        // so the implementation object does not need to declare such
+        // a method.
+        final Object impl = getMXBeanImplementation();
+        final Map<String, Method> methods = initMethodMap(impl);
+
+        LoggingMXBeanAccess() {
+        }
+
+        <T> T invoke(String methodName, Object... args) {
+            Method m = methods.get(methodName);
+            if (m == null) {
+                throw new UnsupportedOperationException(methodName);
+            }
+            try {
+                @SuppressWarnings("unchecked")
+                T result = (T) m.invoke(impl, args);
+                return result;
+            } catch (IllegalAccessException ex) {
+                throw new UnsupportedOperationException(ex);
+            } catch (InvocationTargetException ex) {
+                throw unwrap(ex);
+            }
+        }
+
+        private static RuntimeException unwrap(InvocationTargetException x) {
+            Throwable t = x.getCause();
+            if (t instanceof RuntimeException) {
+                return (RuntimeException)t;
+            }
+            if (t instanceof Error) {
+                throw (Error)t;
+            }
+            return new UndeclaredThrowableException(t == null ? x : t);
+        }
+
+
     }
 
-    static class PlatformLoggingImpl implements LoggingMXBean
-    {
-        final static java.util.logging.LoggingMXBean impl =
-                (java.util.logging.LoggingMXBean) LoggingMXBeanSupport.loggingImpl;
-        final static PlatformLoggingMXBean instance = new PlatformLoggingImpl();
-        final static String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging";
+    static final class PlatformLoggingImpl implements PlatformLoggingMXBean {
+
+        private final LoggingMXBeanAccess loggingAccess;
+        private PlatformLoggingImpl(LoggingMXBeanAccess loggingAccess) {
+            this.loggingAccess = loggingAccess;
+        }
 
         private volatile ObjectName objname;  // created lazily
         @Override
@@ -232,23 +303,29 @@ public class ManagementFactoryHelper {
 
         @Override
         public java.util.List<String> getLoggerNames() {
-            return impl.getLoggerNames();
+            return loggingAccess.invoke("getLoggerNames");
         }
 
         @Override
         public String getLoggerLevel(String loggerName) {
-            return impl.getLoggerLevel(loggerName);
+            return loggingAccess.invoke("getLoggerLevel", loggerName);
         }
 
         @Override
         public void setLoggerLevel(String loggerName, String levelName) {
-            impl.setLoggerLevel(loggerName, levelName);
+            loggingAccess.invoke("setLoggerLevel", loggerName, levelName);
         }
 
         @Override
         public String getParentLoggerName(String loggerName) {
-            return impl.getParentLoggerName(loggerName);
+            return loggingAccess.invoke("getParentLoggerName", loggerName);
         }
+
+        private static PlatformLoggingImpl getInstance() {
+            return new PlatformLoggingImpl(new LoggingMXBeanAccess());
+         }
+
+        static final PlatformLoggingMXBean MBEAN = getInstance();
     }
 
     private static List<BufferPoolMXBean> bufferPools = null;
diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java
index 59c0be3360e..2944e5d0f13 100644
--- a/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java
@@ -194,7 +194,7 @@ public class MarshalInputStream extends ObjectInputStream {
         /*
          * Unless we were told to skip this consideration, choose the
          * "default loader" to simulate the default ObjectInputStream
-         * resolveClass mechanism (that is, choose the first non-null
+         * resolveClass mechanism (that is, choose the first non-platform
          * loader on the execution stack) to maximize the likelihood of
          * type compatibility with calling code.  (This consideration
          * is skipped during server parameter unmarshalling using the 1.2
@@ -268,8 +268,9 @@ public class MarshalInputStream extends ObjectInputStream {
     }
 
     /*
-     * Returns the first non-null class loader up the execution stack, or null
-     * if only code from the null class loader is on the stack.
+     * Returns the first non-platform class loader up the execution stack,
+     * or platform class loader if only code from the platform class loader or null
+     * is on the stack.
      */
     private static ClassLoader latestUserDefinedLoader() {
         return jdk.internal.misc.VM.latestUserDefinedLoader();
diff --git a/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java b/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
index 4a9562b069f..a5e965e5ec3 100644
--- a/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
+++ b/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
@@ -258,7 +258,7 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine {
     /*
      * Convenience method for simple commands
      */
-    private InputStream executeCommand(String cmd, Object ... args) throws IOException {
+    public InputStream executeCommand(String cmd, Object ... args) throws IOException {
         try {
             return execute(cmd, args);
         } catch (AgentLoadException x) {
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/LibMDMech.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/LibMDMech.java
new file mode 100644
index 00000000000..b2f2b569859
--- /dev/null
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/LibMDMech.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+/**
+ * Enum for representing the ucrypto mechanisms.
+ *
+ * @since 9
+ */
+public enum LibMDMech {
+
+    MD5(new ServiceDesc[]
+        { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigestMD$MD5")
+        }),
+    SHA_1(new ServiceDesc[]
+        { sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigestMD$SHA1",
+             "SHA-1", "SHA1")
+        }),
+    SHA_256(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigestMD$SHA256",
+             "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1")
+        }),
+    SHA_384(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigestMD$SHA384",
+             "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2")
+        }),
+    SHA_512(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigestMD$SHA512",
+             "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3")
+        });
+
+    ServiceDesc[] serviceDescs;
+
+    private static ServiceDesc sd(String type, String algo, String cn, String... aliases) {
+        return new ServiceDesc(type, algo, cn, aliases);
+    }
+
+    LibMDMech(ServiceDesc[] serviceDescs) {
+        this.serviceDescs = serviceDescs;
+    }
+
+    public ServiceDesc[] getServiceDescriptions() { return serviceDescs; }
+}
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java
index 9c0929a95b2..98292eb5561 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,23 +33,67 @@ import java.util.concurrent.ConcurrentSkipListSet;
 import java.security.*;
 
 /**
- * MessageDigest implementation class. This class currently supports
- * MD5, SHA1, SHA256, SHA384, and SHA512
+ * MessageDigest implementation class using native Ucrypto API.
+ * This class currently supports: MD5, SHA-2 (224, 256, 384, 512)
+ * and SHA-3 (224, 256, 384, 512) digests
  *
  * @since 9
  */
-public abstract class NativeDigest extends MessageDigestSpi
-        implements Cloneable {
+abstract class NativeDigest extends MessageDigestSpi {
 
-    private static final int MECH_MD5 = 1;
-    private static final int MECH_SHA1 = 2;
-    private static final int MECH_SHA256 = 3;
-    private static final int MECH_SHA224 = 4;
-    private static final int MECH_SHA384 = 5;
-    private static final int MECH_SHA512 = 6;
+    public static final class MD5 extends NativeDigest {
+        public MD5() {
+            super(UcryptoMech.CRYPTO_MD5, 16);
+        }
+    }
+    public static final class SHA1 extends NativeDigest {
+        public SHA1() {
+            super(UcryptoMech.CRYPTO_SHA1, 20);
+        }
+    }
+    public static final class SHA224 extends NativeDigest {
+        public SHA224() {
+            super(UcryptoMech.CRYPTO_SHA224, 28);
+        }
+    }
+    public static final class SHA256 extends NativeDigest {
+        public SHA256() {
+            super(UcryptoMech.CRYPTO_SHA256, 32);
+        }
+    }
+    public static final class SHA384 extends NativeDigest {
+        public SHA384() {
+            super(UcryptoMech.CRYPTO_SHA384, 48);
+        }
+    }
+    public static final class SHA512 extends NativeDigest {
+        public SHA512() {
+            super(UcryptoMech.CRYPTO_SHA512, 64);
+        }
+    }
+    public static final class SHA3_224 extends NativeDigest {
+        public SHA3_224() {
+            super(UcryptoMech.CRYPTO_SHA3_224, 28);
+        }
+    }
+    public static final class SHA3_256 extends NativeDigest {
+        public SHA3_256() {
+            super(UcryptoMech.CRYPTO_SHA3_256, 32);
+        }
+    }
+    public static final class SHA3_384 extends NativeDigest {
+        public SHA3_384() {
+            super(UcryptoMech.CRYPTO_SHA3_384, 48);
+        }
+    }
+    public static final class SHA3_512 extends NativeDigest {
+        public SHA3_512() {
+            super(UcryptoMech.CRYPTO_SHA3_512, 64);
+        }
+    }
 
     private final int digestLen;
-    private final int mech;
+    private final UcryptoMech mech;
 
     // field for ensuring native memory is freed
     private DigestContextRef pCtxt = null;
@@ -64,10 +108,9 @@ public abstract class NativeDigest extends MessageDigestSpi
         // referents are GC'ed so we can do post-mortem processing
         private static Set<DigestContextRef> refList =
             new ConcurrentSkipListSet<DigestContextRef>();
-            //            Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>());
 
         private final long id;
-        private final int mech;
+        private final UcryptoMech mech;
 
         private static void drainRefQueueBounded() {
             while (true) {
@@ -77,7 +120,7 @@ public abstract class NativeDigest extends MessageDigestSpi
             }
         }
 
-        DigestContextRef(NativeDigest nc, long id, int mech) {
+        DigestContextRef(NativeDigest nc, long id, UcryptoMech mech) {
             super(nc, refQueue);
             this.id = id;
             this.mech = mech;
@@ -98,18 +141,22 @@ public abstract class NativeDigest extends MessageDigestSpi
             refList.remove(this);
             try {
                 if (needFree) {
-                    UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id);
-                    NativeDigest.nativeFree(mech, id);
-                } else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id);
+                    UcryptoProvider.debug("Resource: free Digest Ctxt " +
+                        this.id);
+                    NativeDigest.nativeFree(mech.value(), id);
+                } else {
+                    UcryptoProvider.debug("Resource: discard Digest Ctxt " +
+                        this.id);
+                }
             } finally {
                 this.clear();
             }
         }
     }
 
-    NativeDigest(int mech, int digestLen) {
-        this.digestLen = digestLen;
+    NativeDigest(UcryptoMech mech, int digestLen) {
         this.mech = mech;
+        this.digestLen = digestLen;
     }
 
     // see JCA spec
@@ -153,10 +200,10 @@ public abstract class NativeDigest extends MessageDigestSpi
         }
 
         if (pCtxt == null) {
-            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+            pCtxt = new DigestContextRef(this, nativeInit(mech.value()), mech);
         }
         try {
-            int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen);
+            int status = nativeDigest(mech.value(), pCtxt.id, out, ofs, digestLen);
             if (status != 0) {
                 throw new DigestException("Internal error: " + status);
             }
@@ -183,64 +230,24 @@ public abstract class NativeDigest extends MessageDigestSpi
                 + len + ". in.length: " + in.length);
         }
         if (pCtxt == null) {
-            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+            pCtxt = new DigestContextRef(this, nativeInit(mech.value()), mech);
         }
-        nativeUpdate(mech, pCtxt.id, in, ofs, len);
+        nativeUpdate(mech.value(), pCtxt.id, in, ofs, len);
     }
 
     /**
      * Clone this digest.
      */
     public synchronized Object clone() throws CloneNotSupportedException {
-        NativeDigest copy = (NativeDigest) super.clone();
-        // re-work the fields that cannot be copied over
-        if (pCtxt != null) {
-            copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech);
-        }
-        return copy;
+        throw new CloneNotSupportedException("Clone is not supported");
     }
 
     // return pointer to the context
-    protected static native long nativeInit(int mech);
+    protected static final native long nativeInit(int mech);
     // return status code; always 0
-    protected static native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
+    protected static final native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
     // return status code; always 0
-    protected static native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
-    // return pointer to the duplicated context
-    protected static native long nativeClone(int mech, long pCtxt);
+    protected static final native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
     // free the specified context
-    private native static void nativeFree(int mech, long id);
-
-
-    public static final class MD5 extends NativeDigest {
-        public MD5() {
-            super(MECH_MD5, 16);
-        }
-    }
-
-    public static final class SHA1 extends NativeDigest {
-        public SHA1() {
-            super(MECH_SHA1, 20);
-        }
-    }
-
-    public static final class SHA256 extends NativeDigest {
-        public SHA256() {
-            super(MECH_SHA256, 32);
-        }
-    }
-
-
-    public static final class SHA384 extends NativeDigest {
-        public SHA384() {
-            super(MECH_SHA384, 48);
-        }
-    }
-
-
-    public static final class SHA512 extends NativeDigest {
-        public SHA512() {
-            super(MECH_SHA512, 64);
-        }
-    }
+    private static final native void nativeFree(int mech, long id);
 }
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigestMD.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigestMD.java
new file mode 100644
index 00000000000..132fcafa9b4
--- /dev/null
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigestMD.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.lang.ref.*;
+
+import java.io.ByteArrayOutputStream;
+import java.util.*;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.security.*;
+
+/**
+ * MessageDigest implementation class for libMD API. This class currently supports
+ * MD5, SHA1, SHA256, SHA384, and SHA512
+ *
+ * @since 9
+ */
+public abstract class NativeDigestMD extends MessageDigestSpi
+        implements Cloneable {
+
+    private static final int MECH_MD5 = 1;
+    private static final int MECH_SHA1 = 2;
+    private static final int MECH_SHA256 = 3;
+    private static final int MECH_SHA224 = 4;
+    private static final int MECH_SHA384 = 5;
+    private static final int MECH_SHA512 = 6;
+
+    private final int digestLen;
+    private final int mech;
+
+    // field for ensuring native memory is freed
+    private DigestContextRef pCtxt = null;
+
+    private static class DigestContextRef extends PhantomReference<NativeDigestMD>
+        implements Comparable<DigestContextRef> {
+
+        private static ReferenceQueue<NativeDigestMD> refQueue =
+            new ReferenceQueue<NativeDigestMD>();
+
+        // Needed to keep these references from being GC'ed until when their
+        // referents are GC'ed so we can do post-mortem processing
+        private static Set<DigestContextRef> refList =
+            new ConcurrentSkipListSet<DigestContextRef>();
+            //            Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>());
+
+        private final long id;
+        private final int mech;
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                DigestContextRef next = (DigestContextRef) refQueue.poll();
+                if (next == null) break;
+                next.dispose(true);
+            }
+        }
+
+        DigestContextRef(NativeDigestMD nc, long id, int mech) {
+            super(nc, refQueue);
+            this.id = id;
+            this.mech = mech;
+            refList.add(this);
+            UcryptoProvider.debug("Resource: track Digest Ctxt " + this.id);
+            drainRefQueueBounded();
+        }
+
+        public int compareTo(DigestContextRef other) {
+            if (this.id == other.id) {
+                return 0;
+            } else {
+                return (this.id < other.id) ? -1 : 1;
+            }
+        }
+
+        void dispose(boolean needFree) {
+            refList.remove(this);
+            try {
+                if (needFree) {
+                    UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id);
+                    NativeDigestMD.nativeFree(mech, id);
+                } else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id);
+            } finally {
+                this.clear();
+            }
+        }
+    }
+
+    NativeDigestMD(int mech, int digestLen) {
+        this.digestLen = digestLen;
+        this.mech = mech;
+    }
+
+    // see JCA spec
+    protected int engineGetDigestLength() {
+        return digestLen;
+    }
+
+    // see JCA spec
+    protected synchronized void engineReset() {
+        if (pCtxt != null) {
+            pCtxt.dispose(true);
+            pCtxt = null;
+        }
+    }
+
+    // see JCA spec
+    protected synchronized byte[] engineDigest() {
+        byte[] digest = new byte[digestLen];
+        try {
+            int len = engineDigest(digest, 0, digestLen);
+            if (len != digestLen) {
+                throw new UcryptoException("Digest length mismatch." +
+                    " Len: " + len + ". digestLen: " + digestLen);
+            }
+            return digest;
+        } catch (DigestException de) {
+            throw new UcryptoException("Internal error", de);
+        }
+    }
+
+    // see JCA spec
+    protected synchronized int engineDigest(byte[] out, int ofs, int len)
+            throws DigestException {
+        if (len < digestLen) {
+            throw new DigestException("Output buffer must be at least " +
+                          digestLen + " bytes long. Got: " + len);
+        }
+        if ((ofs < 0) || (len < 0) || (ofs > out.length - len)) {
+            throw new DigestException("Buffer too short to store digest. " +
+                "ofs: " + ofs + ". len: " + len + ". out.length: " + out.length);
+        }
+
+        if (pCtxt == null) {
+            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+        }
+        try {
+            int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen);
+            if (status != 0) {
+                throw new DigestException("Internal error: " + status);
+            }
+        } finally {
+            pCtxt.dispose(false);
+            pCtxt = null;
+        }
+        return digestLen;
+    }
+
+    // see JCA spec
+    protected synchronized void engineUpdate(byte in) {
+        byte[] temp = { in };
+        engineUpdate(temp, 0, 1);
+    }
+
+    // see JCA spec
+    protected synchronized void engineUpdate(byte[] in, int ofs, int len) {
+        if (len == 0) {
+            return;
+        }
+        if ((ofs < 0) || (len < 0) || (ofs > in.length - len)) {
+            throw new ArrayIndexOutOfBoundsException("ofs: " + ofs + ". len: "
+                + len + ". in.length: " + in.length);
+        }
+        if (pCtxt == null) {
+            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+        }
+        nativeUpdate(mech, pCtxt.id, in, ofs, len);
+    }
+
+    /**
+     * Clone this digest.
+     */
+    public synchronized Object clone() throws CloneNotSupportedException {
+        NativeDigestMD copy = (NativeDigestMD) super.clone();
+        // re-work the fields that cannot be copied over
+        if (pCtxt != null) {
+            copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech);
+        }
+        return copy;
+    }
+
+    // return pointer to the context
+    protected static final native long nativeInit(int mech);
+    // return status code; always 0
+    protected static final native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
+    // return status code; always 0
+    protected static final native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
+    // return pointer to the duplicated context
+    protected static final native long nativeClone(int mech, long pCtxt);
+    // free the specified context
+    private static final native void nativeFree(int mech, long id);
+
+
+    public static final class MD5 extends NativeDigestMD {
+        public MD5() {
+            super(MECH_MD5, 16);
+        }
+    }
+
+    public static final class SHA1 extends NativeDigestMD {
+        public SHA1() {
+            super(MECH_SHA1, 20);
+        }
+    }
+
+    public static final class SHA256 extends NativeDigestMD {
+        public SHA256() {
+            super(MECH_SHA256, 32);
+        }
+    }
+
+
+    public static final class SHA384 extends NativeDigestMD {
+        public SHA384() {
+            super(MECH_SHA384, 48);
+        }
+    }
+
+
+    public static final class SHA512 extends NativeDigestMD {
+        public SHA512() {
+            super(MECH_SHA512, 64);
+        }
+    }
+}
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java
index cb6b4ffe597..ebc436a52c8 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
 
 package com.oracle.security.ucrypto;
 
-import java.util.HashMap;
-
 /**
  * Enum for representing the ucrypto mechanisms.
  *
@@ -35,78 +33,126 @@ import java.util.HashMap;
 // Check /usr/include/libsoftcrypto.h for updates
 public enum UcryptoMech {
 
-    CRYPTO_AES_ECB(1, new ServiceDesc[]
+    CRYPTO_AES_ECB(new ServiceDesc[]
         { sd("Cipher", "AES/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding"),
           sd("Cipher", "AES/ECB/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesEcbPKCS5",
              "AES"),
-          sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes128EcbNoPadding",
+          sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
              "2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"),
-          sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes192EcbNoPadding",
+          sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
              "2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"),
-          sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes256EcbNoPadding",
+          sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
              "2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41")
         }),
-    CRYPTO_AES_CBC(2, new ServiceDesc[]
+    CRYPTO_AES_CBC(new ServiceDesc[]
         { sd("Cipher", "AES/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding"),
           sd("Cipher", "AES/CBC/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCbcPKCS5"),
-          sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes128CbcNoPadding",
+          sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
              "2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"),
-          sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes192CbcNoPadding",
+          sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
              "2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"),
-          sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes256CbcNoPadding",
+          sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
              "2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42")
         }),
-    CRYPTO_AES_CBC_PAD(3, null), // No support from Solaris yet
-    CRYPTO_AES_CTR(4, new ServiceDesc[]
+//  CRYPTO_AES_CBC_PAD(null), // Support added since S11.1; however we still use CRYPTO_AES_CBC due to known bug
+    CRYPTO_AES_CTR(new ServiceDesc[]
         { sd("Cipher", "AES/CTR/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCtrNoPadding") }),
-    CRYPTO_AES_CCM(5, null), // Cannot support due to lack of Java API which corresponds to CK_AES_CCM_PARAMS
-    CRYPTO_AES_GCM(6, new ServiceDesc[]
+//  CRYPTO_AES_CCM(null), // Need Java API for CK_AES_CCM_PARAMS
+    CRYPTO_AES_GCM(new ServiceDesc[]
         { sd("Cipher", "AES/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding"),
-          sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes128GcmNoPadding",
+          sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
              "2.16.840.1.101.3.4.1.6", "OID.2.16.840.1.101.3.4.1.6"),
-          sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes192GcmNoPadding",
+          sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
              "2.16.840.1.101.3.4.1.26", "OID.2.16.840.1.101.3.4.1.26"),
-          sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes256GcmNoPadding",
+          sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
              "2.16.840.1.101.3.4.1.46", "OID.2.16.840.1.101.3.4.1.46")
         }),
-    CRYPTO_AES_GMAC(7, null), // No support from Solaris yet
-    CRYPTO_AES_CFB128(8, new ServiceDesc[]
+//  CRYPTO_AES_GMAC(null), // No support from Solaris
+    CRYPTO_AES_CFB128(new ServiceDesc[]
         { sd("Cipher", "AES/CFB128/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCfb128NoPadding"),
-          sd("Cipher", "AES/CFB128/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5") }),
-    CRYPTO_RSA_PKCS(31, new ServiceDesc[]
+          sd("Cipher", "AES/CFB128/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5")
+        }),
+
+    CRYPTO_RSA_PKCS(new ServiceDesc[]
         { sd("Cipher", "RSA/ECB/PKCS1Padding", "com.oracle.security.ucrypto.NativeRSACipher$PKCS1Padding",
-             "RSA") }),
-    CRYPTO_RSA_X_509(32, new ServiceDesc[]
+             "RSA")
+        }),
+    CRYPTO_RSA_X_509(new ServiceDesc[]
         { sd("Cipher", "RSA/ECB/NoPadding", "com.oracle.security.ucrypto.NativeRSACipher$NoPadding") }),
-    CRYPTO_MD5_RSA_PKCS(33, new ServiceDesc[]
+    CRYPTO_MD5_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "MD5withRSA", "com.oracle.security.ucrypto.NativeRSASignature$MD5",
-             "1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4") }),
-    CRYPTO_SHA1_RSA_PKCS(34, new ServiceDesc[]
+             "1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4")
+        }),
+    CRYPTO_SHA1_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA1withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA1",
              "1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5",
-             "1.3.14.3.2.29") }),
-    CRYPTO_SHA256_RSA_PKCS(35, new ServiceDesc[]
+             "1.3.14.3.2.29")
+        }),
+    CRYPTO_SHA256_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA256withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA256",
-             "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11") }),
-    CRYPTO_SHA384_RSA_PKCS(36, new ServiceDesc[]
+             "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11")
+        }),
+    CRYPTO_SHA384_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA384withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA384",
-             "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12") }),
-    CRYPTO_SHA512_RSA_PKCS(37, new ServiceDesc[]
+             "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12")
+        }),
+    CRYPTO_SHA512_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA512withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA512",
-             "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13") });
+             "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13")
+        }),
 
-    private final int mech;
+    CRYPTO_MD5(new ServiceDesc[]
+        { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigest$MD5") }),
+    CRYPTO_SHA1(new ServiceDesc[]
+        { sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigest$SHA1", "SHA-1", "SHA1") }),
+    CRYPTO_SHA224(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-224", "com.oracle.security.ucrypto.NativeDigest$SHA224",
+             "2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4")
+    }),
+    CRYPTO_SHA256(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigest$SHA256",
+             "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1")
+    }),
+    CRYPTO_SHA384(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigest$SHA384",
+             "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2")
+    }),
+    CRYPTO_SHA512(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigest$SHA512",
+             "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3")
+    }),
+    CRYPTO_SHA3_224(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-224", "com.oracle.security.ucrypto.NativeDigest$SHA3_224",
+             "2.16.840.1.101.3.4.2.7", "OID.2.16.840.1.101.3.4.2.7")
+    }),
+    CRYPTO_SHA3_256(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-256", "com.oracle.security.ucrypto.NativeDigest$SHA3_256",
+             "2.16.840.1.101.3.4.2.8", "OID.2.16.840.1.101.3.4.2.8")
+    }),
+    CRYPTO_SHA3_384(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-384", "com.oracle.security.ucrypto.NativeDigest$SHA3_384",
+             "2.16.840.1.101.3.4.2.9", "OID.2.16.840.1.101.3.4.2.9")
+    }),
+    CRYPTO_SHA3_512(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-512", "com.oracle.security.ucrypto.NativeDigest$SHA3_512",
+             "2.16.840.1.101.3.4.2.10", "OID.2.16.840.1.101.3.4.2.10")
+    });
+
+    private int mech = 0;
     private final ServiceDesc[] serviceDescs;
 
     private static ServiceDesc sd(String type, String algo, String cn, String... aliases) {
         return new ServiceDesc(type, algo, cn, aliases);
     }
 
-    UcryptoMech(int mech, ServiceDesc[] serviceDescs) {
-        this.mech = mech;
+    UcryptoMech(ServiceDesc[] serviceDescs) {
         this.serviceDescs = serviceDescs;
     }
 
+    public void setValue(int nativeMechValue) {
+        this.mech = nativeMechValue;
+    }
+
     public int value() { return mech; }
     public ServiceDesc[] getServiceDescriptions() { return serviceDescs; }
 }
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java
index e3595359019..35cceda0757 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@ package com.oracle.security.ucrypto;
 
 import java.io.IOException;
 import java.io.File;
+import java.lang.reflect.Constructor;
 import java.util.*;
 import java.security.*;
 
@@ -74,48 +75,52 @@ public final class UcryptoProvider extends Provider {
             if (provProp != null) {
                 boolean[] result = loadLibraries();
                 if (result.length == 2) {
-                    if (result[0]) { // successfully loaded libmd
-                        provProp.put("MessageDigest.MD5",
-                            sd("MessageDigest", "MD5",
-                               "com.oracle.security.ucrypto.NativeDigest$MD5"));
-                        provProp.put("MessageDigest.SHA",
-                            sd("MessageDigest", "SHA",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA1",
-                               "SHA-1", "SHA1"));
-                        provProp.put("MessageDigest.SHA-256",
-                            sd("MessageDigest", "SHA-256",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA256",
-                               "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"));
-
-                        provProp.put("MessageDigest.SHA-384",
-                            sd("MessageDigest", "SHA-384",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA384",
-                               "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"));
-
-                        provProp.put("MessageDigest.SHA-512",
-                            sd("MessageDigest", "SHA-512",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA512",
-                               "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"));
-                    };
-                    if (result[1]) { // successfully loaded libsoftcrypto
+                    // true when libsoftcrypto or libucrypto(S12) has been successfully loaded
+                    if (result[1]) {
                         String supportedMechs = getMechList();
                         debug("Prov: supported mechs = " + supportedMechs);
-                        for (UcryptoMech m : UcryptoMech.values()) {
-                            if (supportedMechs.indexOf(m.name() + ",") != -1) {
+                        StringTokenizer st = new StringTokenizer(supportedMechs, ":,;");
+                        // format: numOfSupportedMechs:[mechName,mechValue;]+
+                        // skip the first one which is numberOfSupportedMechs
+                        st.nextToken();
+                        while (st.hasMoreTokens()) {
+                            String mechName = st.nextToken();
+                            int nativeMechVal = Integer.parseInt(st.nextToken());
+                            try {
+                                UcryptoMech m = Enum.valueOf(UcryptoMech.class, mechName);
+                                m.setValue(nativeMechVal);
                                 ServiceDesc[] services = m.getServiceDescriptions();
-                                // skip unsupported UcryptoMech
-                                if (services == null || services.length == 0) continue;
+                                // defined in UcryptoMech as unsupported
+                                if (services == null || services.length == 0) {
+                                    debug("Skip Unsupported Algorithm: " + mechName);
+                                    continue;
+                                }
                                 for (int p = 0; p < services.length; p++) {
                                     ServiceDesc entry = services[p];
                                     provProp.put(entry.getType() + "." + entry.getAlgorithm(),
                                                  entry);
                                 }
+                            } catch (IllegalArgumentException iae) {
+                                // not defined in UcryptoMech
+                                debug("Skip Unrecognized Algorithm: " + mechName);
                             }
                         }
                         // NOTE: GCM support is only available since jdk 7
                         provProp.put("AlgorithmParameters.GCM",
-                                     sd("AlgorithmParameters", "GCM", "com.oracle.security.ucrypto.GCMParameters"));
+                                     sd("AlgorithmParameters", "GCM",
+                                        "com.oracle.security.ucrypto.GCMParameters"));
                     }
+                    // true when libmd is needed and has been successfully loaded
+                    if (result[0]) {
+                        for (LibMDMech m : LibMDMech.values()) {
+                            ServiceDesc[] services = m.getServiceDescriptions();
+                            for (ServiceDesc entry : services) {
+                                String sKey = entry.getType() + "." + entry.getAlgorithm();
+                                //  only register if none has been registered
+                                provProp.putIfAbsent(sKey, entry);
+                            }
+                        }
+                    };
                 } else {
                     debug("Prov: unexpected ucrypto library loading error, got " + result.length);
                 }
@@ -138,6 +143,7 @@ public final class UcryptoProvider extends Provider {
                   sd.getAliases(), null);
         }
 
+        @SuppressWarnings("deprecation")
         @Override
         public Object newInstance(Object ctrParamObj)
             throws NoSuchAlgorithmException {
@@ -152,53 +158,19 @@ public final class UcryptoProvider extends Provider {
                     int keySize = -1;
                     if (algo.charAt(3) == '_') {
                         keySize = Integer.parseInt(algo.substring(4, 7))/8;
-                        algo = algo.substring(0, 3) + algo.substring(7);
                     }
-                    if (algo.equals("AES/ECB/NoPadding")) {
-                        return new NativeCipher.AesEcbNoPadding(keySize);
-                    } else if (algo.equals("AES/ECB/PKCS5Padding")) {
-                        return new NativeCipherWithJavaPadding.AesEcbPKCS5();
-                    } else if (algo.equals("AES/CBC/NoPadding")) {
-                        return new NativeCipher.AesCbcNoPadding(keySize);
-                    } else if (algo.equals("AES/CBC/PKCS5Padding")) {
-                        return new NativeCipherWithJavaPadding.AesCbcPKCS5();
-                    } else if (algo.equals("AES/CTR/NoPadding")) {
-                        return new NativeCipher.AesCtrNoPadding();
-                    } else if (algo.equals("AES/GCM/NoPadding")) {
-                        return new NativeGCMCipher.AesGcmNoPadding(keySize);
-                    } else if (algo.equals("AES/CFB128/NoPadding")) {
-                        return new NativeCipher.AesCfb128NoPadding();
-                    } else if (algo.equals("AES/CFB128/PKCS5Padding")) {
-                        return new NativeCipherWithJavaPadding.AesCfb128PKCS5();
-                    } else if (algo.equals("RSA/ECB/NoPadding")) {
-                        return new NativeRSACipher.NoPadding();
-                    } else if (algo.equals("RSA/ECB/PKCS1Padding")) {
-                        return new NativeRSACipher.PKCS1Padding();
-                    }
-                } else if (type.equals("Signature")) {
-                    if (algo.equals("SHA1withRSA")) {
-                        return new NativeRSASignature.SHA1();
-                    } else if (algo.equals("SHA256withRSA")) {
-                        return new NativeRSASignature.SHA256();
-                    } else if (algo.equals("SHA384withRSA")) {
-                        return new NativeRSASignature.SHA384();
-                    } else if (algo.equals("SHA512withRSA")) {
-                        return new NativeRSASignature.SHA512();
-                    } else if (algo.equals("MD5withRSA")) {
-                        return new NativeRSASignature.MD5();
-                    }
-                } else if (type.equals("MessageDigest")) {
-                    if (algo.equals("SHA")) {
-                        return new NativeDigest.SHA1();
-                    } else if (algo.equals("SHA-256")) {
-                        return new NativeDigest.SHA256();
-                    } else if (algo.equals("SHA-384")) {
-                        return new NativeDigest.SHA384();
-                    } else if (algo.equals("SHA-512")) {
-                        return new NativeDigest.SHA512();
-                    } else if (algo.equals("MD5")) {
-                        return new NativeDigest.MD5();
+                    String implClass = getClassName();
+                    Class<?> clz = Class.forName(implClass);
+                    if (keySize != -1) {
+                        Constructor<?> ctr = clz.getConstructor(int.class);
+                        return ctr.newInstance(keySize);
+                    } else {
+                        return clz.newInstance();
                     }
+                } else if (type.equals("Signature") || type.equals("MessageDigest")) {
+                    String implClass = getClassName();
+                    Class<?> clz = Class.forName(implClass);
+                    return clz.newInstance();
                 } else if (type.equals("AlgorithmParameters")) {
                     if (algo.equals("GCM")) {
                         return new GCMParameters();
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/libsoftcrypto.h b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/libsoftcrypto.h
deleted file mode 100644
index 17c38557dc5..00000000000
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/libsoftcrypto.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _LIBSOFTCRYPTO_H
-#define _LIBSOFTCRYPTO_H
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <strings.h>
-
-typedef enum ucrypto_mech {
-    CRYPTO_AES_ECB = 1,
-    CRYPTO_AES_CBC,
-    CRYPTO_AES_CBC_PAD,
-    CRYPTO_AES_CTR,
-    CRYPTO_AES_CCM,
-    CRYPTO_AES_GCM,
-    CRYPTO_AES_GMAC,
-    CRYPTO_AES_CFB128,
-    CRYPTO_RSA_PKCS = 31,
-    CRYPTO_RSA_X_509,
-    CRYPTO_MD5_RSA_PKCS,
-    CRYPTO_SHA1_RSA_PKCS,
-    CRYPTO_SHA256_RSA_PKCS,
-    CRYPTO_SHA384_RSA_PKCS,
-    CRYPTO_SHA512_RSA_PKCS
-} ucrypto_mech_t;
-
-typedef struct crypto_ctx {
-    void *cc_provider;
-    uint_t    cc_session;
-    void            *cc_provider_private;    /* owned by provider */
-    void            *cc_framework_private;    /* owned by framework */
-    uint32_t        cc_flags;        /* flags */
-    void            *cc_opstate;        /* state */
-} crypto_ctx_t;
-
-extern int ucrypto_encrypt_init(crypto_ctx_t *context,
-    ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
-    void *iv, size_t iv_len);
-
-extern int ucrypto_encrypt_update(crypto_ctx_t *context, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-extern int ucrypto_encrypt_final(crypto_ctx_t *context, uchar_t *out,
-    size_t *out_len);
-
-/* Encrypt atomic */
-extern int ucrypto_encrypt(ucrypto_mech_t mech_type, uchar_t *key_str,
-    size_t key_len, void *iv, size_t iv_len, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-/* Decrypt multi-part */
-extern int ucrypto_decrypt_init(crypto_ctx_t *context,
-    ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
-    void *iv, size_t iv_len);
-
-extern int ucrypto_decrypt_update(crypto_ctx_t *context, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-extern int ucrypto_decrypt_final(crypto_ctx_t *context, uchar_t *out,
-    size_t *out_len);
-
-/* Decrypt atomic */
-extern int ucrypto_decrypt(ucrypto_mech_t mech_type, uchar_t *key_str,
-    size_t key_len, void *iv, size_t iv_len, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-/* Sign multi-part */
-extern int ucrypto_sign_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len);
-
-extern int ucrypto_sign_update(crypto_ctx_t *context,
-    uchar_t *data_str, size_t data_len);
-
-extern int ucrypto_sign_final(crypto_ctx_t *context,
-    uchar_t *sig_str, size_t *sig_len);
-
-/* Sign atomic */
-extern int ucrypto_sign(ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len,
-    uchar_t *data_str, size_t data_len, uchar_t *sig_str, size_t *sig_len);
-
-/* Verify multi-part */
-extern int ucrypto_verify_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len);
-
-extern int ucrypto_verify_update(crypto_ctx_t *context,
-    uchar_t *data_str, size_t data_len);
-
-extern int ucrypto_verify_final(crypto_ctx_t *context,
-    uchar_t *sig_str, size_t *sig_len);
-
-/* Verify atomic */
-extern int ucrypto_verify(ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len,
-    uchar_t *data_str, size_t data_len, uchar_t *sig, size_t *sig_len);
-
-extern int ucrypto_get_mechlist(char *str);
-
-extern const char *ucrypto_id2mech(ucrypto_mech_t mech_type);
-
-extern ucrypto_mech_t ucrypto_mech2id(const char *str);
-
-extern int ucrypto_version();
-
-typedef struct CK_AES_CTR_PARAMS {
-    ulong_t    ulCounterBits;
-    uint8_t cb[16];
-} CK_AES_CTR_PARAMS;
-
-typedef struct CK_AES_GCM_PARAMS {
-    uchar_t *pIv;
-    ulong_t ulIvLen;
-    ulong_t ulIvBits;
-    uchar_t *pAAD;
-    ulong_t ulAADLen;
-    ulong_t ulTagBits;
-} CK_AES_GCM_PARAMS;
-
-typedef struct crypto_object_attribute {
-    uint64_t    oa_type;    /* attribute type */
-    caddr_t            oa_value;    /* attribute value */
-    ssize_t            oa_value_len;    /* length of attribute value */
-} crypto_object_attribute_t;
-
-/* Attribute types to use for passing a RSA public key or a private key. */
-#define    SUN_CKA_MODULUS            0x00000120
-#define    SUN_CKA_MODULUS_BITS        0x00000121
-#define    SUN_CKA_PUBLIC_EXPONENT        0x00000122
-#define    SUN_CKA_PRIVATE_EXPONENT    0x00000123
-#define    SUN_CKA_PRIME_1            0x00000124
-#define    SUN_CKA_PRIME_2            0x00000125
-#define    SUN_CKA_EXPONENT_1        0x00000126
-#define    SUN_CKA_EXPONENT_2        0x00000127
-#define    SUN_CKA_COEFFICIENT        0x00000128
-#define    SUN_CKA_PRIME            0x00000130
-#define    SUN_CKA_SUBPRIME        0x00000131
-#define    SUN_CKA_BASE            0x00000132
-
-#define    CKK_EC            0x00000003
-#define    CKK_GENERIC_SECRET    0x00000010
-#define    CKK_RC4            0x00000012
-#define    CKK_AES            0x0000001F
-#define    CKK_DES            0x00000013
-#define    CKK_DES2        0x00000014
-#define    CKK_DES3        0x00000015
-
-#define    CKO_PUBLIC_KEY        0x00000002
-#define    CKO_PRIVATE_KEY        0x00000003
-#define    CKA_CLASS        0x00000000
-#define    CKA_VALUE        0x00000011
-#define    CKA_KEY_TYPE        0x00000100
-#define    CKA_VALUE_LEN        0x00000161
-#define    CKA_EC_PARAMS        0x00000180
-#define    CKA_EC_POINT        0x00000181
-
-#endif /* _LIBSOFTCRYPTO_H */
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c
index 6ddbdc2bed2..126da6d37bd 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,22 @@
 #include "nativeCrypto.h"
 #include "nativeFunc.h"
 
+/*
+ * Dumps out byte array in hex with and name and length info
+ */
+void printError(char* header, int mech, int rv) {
+  if (mech != -1) {
+    printf("%s, mech = %d, rv = 0x%0x\n", header, mech, rv);
+  } else {
+    printf("%s, rv = 0x%0x\n", header, rv);
+  }
+  if (*ftab->ucryptoStrerror != NULL) {
+    char * reason = (*ftab->ucryptoStrerror)(rv);
+    printf("\tcause = %s\n", reason);
+    free(reason);
+  }
+}
+
 /*
  * Dumps out byte array in hex with and name and length info
  */
@@ -60,6 +76,16 @@ void throwOutOfMemoryError(JNIEnv *env, const char *msg)
   (*env)->DeleteLocalRef(env, jExClass);
 }
 
+/*
+ * De-allocates all memory associated with crypto_ctx_t
+ */
+void freeContext(crypto_ctx_t *context) {
+  if (ftab->ucryptoFreeContext != NULL) {
+    (*ftab->ucryptoFreeContext)(context);
+  }
+  free(context);
+}
+
 JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
     return JNI_VERSION_1_4;
 }
@@ -203,10 +229,10 @@ CipherInit(crypto_ctx_t *context, int encrypt, ucrypto_mech_t mech,
   }
   if (encrypt) {
     rv = (*ftab->ucryptoEncryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
-    if (rv != 0 && DEBUG) printf("ucryptoEncryptInit: ret = 0x%x\n", rv);
+    if (rv != 0 && DEBUG) printError("ucryptoEncryptInit", mech, rv);
   } else {
     rv =(*ftab->ucryptoDecryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
-    if (rv != 0 && DEBUG) printf("ucryptoDecryptInit: ret = 0x%x\n", rv);
+    if (rv != 0 && DEBUG) printError("ucryptoDecryptInit", mech, rv);
   }
 
   if (iv != jIv) {
@@ -234,15 +260,15 @@ CipherUpdate(crypto_ctx_t *context, int encrypt, unsigned char *bufIn, int inOfs
   }
   if (encrypt) {
     rv = (*ftab->ucryptoEncryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoEncryptUpdate: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoEncryptUpdate", -1, rv);
     } else {
       *outLen = (int)outLength;
     }
   } else {
     rv = (*ftab->ucryptoDecryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoDecryptUpdate: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoDecryptUpdate", -1, rv);
     } else {
       if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
       *outLen = (int)outLength;
@@ -263,16 +289,16 @@ CipherFinal(crypto_ctx_t *context, int encrypt, unsigned char *bufOut, int outOf
   if (DEBUG) printf("CipherFinal: OutOfs %i, outLen %i\n", outOfs, *outLen);
   if (encrypt) {
     rv = (*ftab->ucryptoEncryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoDecryptFinal", -1, rv);
     } else {
       if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
       *outLen = (int)outLength;
     }
   } else {
     rv = (*ftab->ucryptoDecryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoDecryptFinal", -1, rv);
     } else {
       if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
       *outLen = (int)outLength;
@@ -285,102 +311,61 @@ CipherFinal(crypto_ctx_t *context, int encrypt, unsigned char *bufOut, int outOf
 // SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
 ////////////////////////////////////////////////////////
 jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit(jint mech) {
-  void *pContext = NULL;
+  crypto_ctx_t *context = NULL;
+  int rv;
 
-  switch (mech) {
-  case com_oracle_security_ucrypto_NativeDigest_MECH_SHA1:
-    pContext = (SHA1_CTX *) malloc(sizeof(SHA1_CTX));
-    if (pContext != NULL) {
-      (*ftab->sha1Init)((SHA1_CTX *)pContext);
+  context = malloc(sizeof(crypto_ctx_t));
+  if (context != NULL) {
+    rv = (*ftab->ucryptoDigestInit)(context, (ucrypto_mech_t) mech, NULL, 0);
+    if (rv) {
+      freeContext(context);
+      if (DEBUG) printError("ucryptoDigestInit", mech, rv);
+      return 0L;
     }
-    break;
-  case com_oracle_security_ucrypto_NativeDigest_MECH_MD5:
-    pContext = (MD5_CTX *) malloc(sizeof(MD5_CTX));
-    if (pContext != NULL) {
-      (*ftab->md5Init)((MD5_CTX *)pContext);
-    }
-    break;
-  case com_oracle_security_ucrypto_NativeDigest_MECH_SHA256:
-    pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
-    if (pContext != NULL) {
-      (*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext);
-    }
-    break;
-  case com_oracle_security_ucrypto_NativeDigest_MECH_SHA384:
-    pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
-    if (pContext != NULL) {
-      (*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext);
-    }
-    break;
-  case com_oracle_security_ucrypto_NativeDigest_MECH_SHA512:
-    pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
-    if (pContext != NULL) {
-      (*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext);
-    }
-    break;
-  default:
-    if (DEBUG) printf("ERROR: Unsupported mech %i\n", mech);
   }
-  return (jlong) pContext;
+  return (jlong) context;
 }
 
 jint JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
   (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
-  if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
-    (*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len);
-  } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
-    (*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len);
-  } else { // SHA-2 family
-    (*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  crypto_ctx_t *context;
+  jint rv = 0;
+
+  context = (crypto_ctx_t *) pContext;
+  rv = (*ftab->ucryptoDigestUpdate)(context, (const unsigned char*)(in + ofs),
+                                    (size_t) len);
+
+  if (rv) {
+    freeContext(context);
+    if (DEBUG) printError("ucryptoDigestUpdate", mech, rv);
   }
-  return 0;
+
+  return -rv; // use negative value to indicate error
 }
 
-// Do digest and free the context immediately
 jint JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest
   (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
+  crypto_ctx_t *context;
+  jint rv = 0;
+  size_t digest_len = digestLen;
 
-  if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
-    (*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext);
-    free((SHA1_CTX *)pContext);
-  } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
-    (*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext);
-    free((MD5_CTX *)pContext);
-  } else { // SHA-2 family
-    (*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext);
-    free((SHA2_CTX *)pContext);
+  context = (crypto_ctx_t *) pContext;
+  rv = (*ftab->ucryptoDigestFinal)(context, (unsigned char*)(out + ofs),
+                                   &digest_len);
+  if (rv) {
+    freeContext(context);
+    if (DEBUG) printError("ucryptoDigestFinal", mech, rv);
   }
-  return 0;
-}
 
-jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone
-  (jint mech, jlong pContext) {
-  void *copy = NULL;
-  size_t len = 0;
-
-  if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
-    len = sizeof(SHA1_CTX);
-  } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
-    len = sizeof(MD5_CTX);
-  } else { // SHA-2 family
-    len = sizeof(SHA2_CTX);
-  }
-  copy = (void*) malloc(len);
-  if (copy != NULL) {
-    bcopy((void *)pContext, copy, len);
-  }
-  return (jlong) copy;
+  return -rv; // use negative value to indicate error
 }
 
 void JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree
   (jint mech, jlong pContext) {
-  if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
-    free((SHA1_CTX*) pContext);
-  } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
-    free((MD5_CTX*) pContext);
-  } else { // SHA-2 family
-    free((SHA2_CTX*) pContext);
-  }
+  crypto_ctx_t *context;
+
+  context = (crypto_ctx_t *) pContext;
+  freeContext(context);
 }
 
 // AES
@@ -395,7 +380,7 @@ jlong JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit
     rv = CipherInit(context, encrypt, (ucrypto_mech_t) mech, bufKey, keyLen,
                     bufIv, ivLen, tagLen, bufAad, aadLen);
     if (rv) {
-      free(context);
+      freeContext(context);
       return 0L;
     }
   }
@@ -417,8 +402,7 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate
   context = (crypto_ctx_t *) pContext;
   rv = CipherUpdate(context, encrypt, (unsigned char*)bufIn, inOfs, inLen, (unsigned char*)bufOut, outOfs, &outLen);
   if (rv) {
-    free(context);
-    context = 0;
+    freeContext(context);
     return -rv; // use negative value to indicate error!
   }
 
@@ -443,7 +427,7 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeFinal
     outLen = 0;
   }
   rv = CipherFinal(context, encrypt, bufOut, outOfs, &outLen);
-  free(context);
+  freeContext(context);
   if (rv) {
      return -rv; // use negative value to indicate error!
   }
@@ -451,8 +435,6 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeFinal
   return outLen;
 }
 
-
-
 /*
  * Class:     com_oracle_security_ucrypto_NativeDigest
  * Method:    nativeInit
@@ -475,13 +457,15 @@ JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeInit
 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
   unsigned char *bufIn;
+  jint rv = 0;
+
 
   bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
   if (!(*env)->ExceptionCheck(env)) {
-    JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
+    rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
     free(bufIn);
   }
-  return 0;
+  return rv;
 }
 
 /*
@@ -492,6 +476,7 @@ JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdat
 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest
   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
   unsigned char *bufOut;
+  jint rv = 0;
 
   bufOut = (unsigned char *) malloc(digestLen);
   if (bufOut == NULL) {
@@ -499,21 +484,12 @@ JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeDiges
     return 0;
   }
 
-  JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
-
-  (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
+  rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
+  if (rv == 0) {
+      (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
+  }
   free(bufOut);
-  return 0;
-}
-
-/*
- * Class:     com_oracle_security_ucrypto_NativeDigest
- * Method:    nativeClone
- * Signature: (IJ)J
- */
-JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeClone
-  (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
-  return JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone(mech, pContext);
+  return rv;
 }
 
 /*
@@ -582,7 +558,7 @@ JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeInit
 
 cleanup:
   if ((result == 0L) && (context != NULL)) {
-    free(context);
+    freeContext(context);
   }
   if (bufKey != NULL) {
     (*env)->ReleaseByteArrayElements(env, jKey, (jbyte *)bufKey, 0);
@@ -626,7 +602,7 @@ JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdat
 
   rv = CipherUpdate(context, encrypt, bufIn, 0, inLen, bufOut, 0, &outLen);
   if (rv) {
-    free(context);
+    freeContext(context);
     free(bufIn);
     free(bufOut);
     return -rv;
@@ -683,6 +659,7 @@ JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal
   return rc;
 }
 
+
 /*
  * Class:     com_oracle_security_ucrypto_NativeKey
  * Method:    nativeFree
@@ -984,9 +961,9 @@ jlong JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeIn
   }
 
   if (DEBUG) {
-    printf("RSAPublicKey Init: keyValue=%ld, keyLen=2\n", pKey);
-    printBytes("RSA PublicKey mod: ", (unsigned char*) mod, modLen);
-    printBytes("RSA PublicKey pubExp: ", (unsigned char*) pub, pubLen);
+    printf("RSAPublicKey.nativeInit: keyValue=%ld, keyLen=2\n", pKey);
+    printBytes("\tmod: ", (unsigned char*) mod, modLen);
+    printBytes("\tpubExp: ", (unsigned char*) pub, pubLen);
   }
 
   pKey[0].oa_type = SUN_CKA_MODULUS;
@@ -1062,7 +1039,7 @@ SignatureInit(crypto_ctx_t *context, jint mechVal, jboolean sign,
   if (DEBUG) {
     printf("SignatureInit: context=%ld, mech=%d, sign=%d, keyValue=%ld, keyLength=%d\n",
            context, mech, sign, pKey, keyLength);
-    printf("SignatureInit, ret =>  0x%x\n", rv);
+    printError("SignatureInit", mech, rv);
   }
   return rv;
 }
@@ -1083,7 +1060,7 @@ jlong JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit
     pKey = (uchar_t *) jKey;
     rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
     if (rv) {
-      free(context);
+      freeContext(context);
       return 0L;
     }
   }
@@ -1105,7 +1082,7 @@ JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeRSASignature_nati
   pKey = (uchar_t *) jKey;
   rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
   if (rv) {
-    free(context);
+    freeContext(context);
     throwUCExceptionUsingRV(env, rv);
     return 0L;
   }
@@ -1125,7 +1102,7 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__J
 
   context = (crypto_ctx_t *) pCtxt;
   if (DEBUG) {
-    printf("Signature update: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n",
+    printf("NativeRSASignature.nativeUpdate: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n",
            context, sign, jIn, jInOfs, jInLen);
   }
   if (sign) {
@@ -1133,9 +1110,9 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__J
   } else {
     rv = (*ftab->ucryptoVerifyUpdate)(context, (uchar_t *) (jIn + jInOfs), (size_t) jInLen);
   }
-  if (DEBUG) printf("Signature update, ret =>  0x%x\n", rv);
   if (rv) {
-    free(context);
+    freeContext(context);
+    if (DEBUG) printError("NativeRSASignature.nativeUpdate", -1, rv);
     return -rv; // use negative value to indicate error!
   }
 
@@ -1194,9 +1171,9 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal
 
   context = (crypto_ctx_t *) pCtxt;
   if (DEBUG) {
-      printf("Signature final: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n",
+      printf("NativeRSASignature.nativeFinal: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n",
              context, sign, bufSig, sigOfs, jSigLen);
-      printBytes("Before Final: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
+      printBytes("Before: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
   }
   if (sign) {
     rv = (*ftab->ucryptoSignFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
@@ -1204,18 +1181,17 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal
     rv = (*ftab->ucryptoVerifyFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
   }
 
-  if (DEBUG) {
-    printf("Signature nativeFinal, ret =>  0x%x\n", rv);
-    if (sigLength != jSigLen) {
-      printf("SIG actual output len=%d\n", sigLength);
-    }
-    if (sign) {
-      printBytes("After nativeFinal: ", (unsigned char*) (bufSig + sigOfs), jSigLen);
-    }
-  }
-
-  free(context);
+  freeContext(context);
   if (rv) {
+    if (DEBUG) {
+      printError("NativeRSASignature.nativeFinal", -1, rv);
+      if (sigLength != jSigLen) {
+        printf("NativeRSASignature.nativeFinal out sig len=%d\n", sigLength);
+      }
+      if (sign) {
+        printBytes("After: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
+      }
+    }
     return -rv;
   } else return 0;
 }
@@ -1273,10 +1249,10 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic
 
   pKey = (uchar_t *) keyValue;
   if (DEBUG) {
-    printf("Cipher nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n",
+    printf("NativeRSACipher.nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n",
            mech, encrypt, pKey, keyLength);
-    printBytes("Before nativeAtomic: in: ", (unsigned char*) bufIn, jInLen);
-    printBytes("Before nativeAtomic: out: ", (unsigned char*) (bufOut + jOutOfs), jOutLen);
+    printBytes("Before: in  = ", (unsigned char*) bufIn, jInLen);
+    printBytes("Before: out = ", (unsigned char*) (bufOut + jOutOfs), jOutLen);
   }
 
   if (encrypt) {
@@ -1289,11 +1265,11 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic
       (uchar_t *)(bufOut + jOutOfs), &outLength);
   }
   if (DEBUG) {
-    printf("Cipher nativeAtomic, ret =>  0x%x\n", rv);
+    printError("NativeRSACipher.nativeAtomic", mech, rv);
     if (outLength != jOutLen) {
-      printf("CIP actual output len=%d\n", outLength);
+      printf("NativeRSACipher.nativeAtomic out len=%d\n", outLength);
     }
-    printBytes("After nativeAtomic: ", (unsigned char*) (bufOut + jOutOfs), outLength);
+    printBytes("After: ", (unsigned char*) (bufOut + jOutOfs), outLength);
   }
 
   if (rv) {
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h
index 9ad3891d0d0..a3ea195387e 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,18 +29,18 @@
 extern "C" {
 #endif
 
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_MD5
-#define com_oracle_security_ucrypto_NativeDigest_MECH_MD5 1L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA1
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA1 2L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA256
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA256 3L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA224
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA224 4L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA384
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA384 5L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA512
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA512 6L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5 1L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1 2L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256 3L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA224
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA224 4L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384 5L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512 6L
 
 #define DEBUG 0
 
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c
new file mode 100644
index 00000000000..df60ce3613a
--- /dev/null
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <jni.h>
+#include "jni_util.h"
+#include <libsoftcrypto.h>
+#include "nativeCrypto.h"
+#include "nativeFunc.h"
+
+
+extern void throwOutOfMemoryError(JNIEnv *env, const char *msg);
+extern jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len);
+
+///////////////////////////////////////////////////////
+// SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
+////////////////////////////////////////////////////////
+jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(jint mech) {
+  void *pContext = NULL;
+
+  switch (mech) {
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1:
+    pContext = malloc(sizeof(SHA1_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha1Init)((SHA1_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5:
+    pContext = malloc(sizeof(MD5_CTX));
+    if (pContext != NULL) {
+      (*ftab->md5Init)((MD5_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256:
+    pContext = malloc(sizeof(SHA2_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384:
+    pContext = malloc(sizeof(SHA2_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512:
+    pContext = malloc(sizeof(SHA2_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext);
+    }
+    break;
+  default:
+    if (DEBUG) printf("ERROR: Unsupported mech %i\n", mech);
+  }
+  return (jlong) pContext;
+}
+
+jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
+  (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    (*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    (*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  } else { // SHA-2 family
+    (*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  }
+  return 0;
+}
+
+// Do digest and free the context immediately
+jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
+  (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
+
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    (*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext);
+    free((SHA1_CTX *)pContext);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    (*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext);
+    free((MD5_CTX *)pContext);
+  } else { // SHA-2 family
+    (*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext);
+    free((SHA2_CTX *)pContext);
+  }
+  return 0;
+}
+
+jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
+  (jint mech, jlong pContext) {
+  void *copy = NULL;
+  size_t len = 0;
+
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    len = sizeof(SHA1_CTX);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    len = sizeof(MD5_CTX);
+  } else { // SHA-2 family
+    len = sizeof(SHA2_CTX);
+  }
+  copy = malloc(len);
+  if (copy != NULL) {
+    bcopy((void *)pContext, copy, len);
+  }
+  return (jlong) copy;
+}
+
+void JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
+  (jint mech, jlong pContext) {
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    free((SHA1_CTX*) pContext);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    free((MD5_CTX*) pContext);
+  } else { // SHA-2 family
+    free((SHA2_CTX*) pContext);
+  }
+}
+
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeInit
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit
+  (JNIEnv *env, jclass jcls, jint mech) {
+  jlong result = JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(mech);
+  if (result == NULL) {
+     throwOutOfMemoryError(env, NULL);
+  }
+  return result;
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeUpdate
+ * Signature: (IJ[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
+  unsigned char *bufIn;
+
+  bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
+  if (!(*env)->ExceptionCheck(env)) {
+    JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
+    free(bufIn);
+  }
+  return 0;
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeDigest
+ * Signature: (IJ[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
+  unsigned char *bufOut;
+
+  bufOut = (unsigned char *) malloc(digestLen);
+  if (bufOut == NULL) {
+    throwOutOfMemoryError(env, NULL);
+    return 0;
+  }
+
+  JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
+
+  (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
+  free(bufOut);
+  return 0;
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeClone
+ * Signature: (IJ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
+  return JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone(mech, pContext);
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeFree
+ * Signature: (IJ)V
+ */
+JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
+  JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree(mech, pContext);
+}
+
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c
index c1ee9027e92..2756977d09c 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,21 +42,33 @@ static const char SHA2_UPDATE[]                  = "SHA2Update";
 static const char SHA2_FINAL[]                   = "SHA2Final";
 static const char UCRYPTO_VERSION[]              = "ucrypto_version";
 static const char UCRYPTO_GET_MECHLIST[]         = "ucrypto_get_mechlist";
+
 static const char UCRYPTO_ENCRYPT_INIT[]         = "ucrypto_encrypt_init";
 static const char UCRYPTO_ENCRYPT_UPDATE[]       = "ucrypto_encrypt_update";
 static const char UCRYPTO_ENCRYPT_FINAL[]        = "ucrypto_encrypt_final";
 static const char UCRYPTO_ENCRYPT[]              = "ucrypto_encrypt";
+
 static const char UCRYPTO_DECRYPT_INIT[]         = "ucrypto_decrypt_init";
 static const char UCRYPTO_DECRYPT_UPDATE[]       = "ucrypto_decrypt_update";
 static const char UCRYPTO_DECRYPT_FINAL[]        = "ucrypto_decrypt_final";
 static const char UCRYPTO_DECRYPT[]              = "ucrypto_decrypt";
+
 static const char UCRYPTO_SIGN_INIT[]            = "ucrypto_sign_init";
 static const char UCRYPTO_SIGN_UPDATE[]          = "ucrypto_sign_update";
 static const char UCRYPTO_SIGN_FINAL[]           = "ucrypto_sign_final";
+
 static const char UCRYPTO_VERIFY_INIT[]          = "ucrypto_verify_init";
 static const char UCRYPTO_VERIFY_UPDATE[]        = "ucrypto_verify_update";
 static const char UCRYPTO_VERIFY_FINAL[]         = "ucrypto_verify_final";
 
+static const char UCRYPTO_DIGEST_INIT[]          = "ucrypto_digest_init";
+static const char UCRYPTO_DIGEST_UPDATE[]        = "ucrypto_digest_update";
+static const char UCRYPTO_DIGEST_FINAL[]         = "ucrypto_digest_final";
+
+static const char UCRYPTO_FREE_CONTEXT[]         = "ucrypto_free_context";
+
+static const char UCRYPTO_STRERROR[]             = "ucrypto_strerror";
+
 /**
  * Initialize native T4 crypto function pointers
  */
@@ -73,28 +85,6 @@ jboolean* loadNative() {
     return NULL;
   }
 
-  lib = dlopen("libmd.so", RTLD_NOW);
-  if (lib != NULL) {
-    ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT);
-    ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE);
-    ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL);
-    ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT);
-    ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE);
-    ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL);
-    ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT);
-    ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE);
-    ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL);
-    if (ftab->md5Init != NULL && ftab->md5Update != NULL &&
-        ftab->md5Final != NULL && ftab->sha1Init != NULL &&
-        ftab->sha1Update != NULL && ftab->sha1Final != NULL &&
-        ftab->sha2Init != NULL && ftab->sha2Update != NULL &&
-        ftab->sha2Final != NULL) {
-      buf[0] = JNI_TRUE;
-    } else {
-      dlclose(lib);
-    }
-  }
-
   lib = dlopen("libsoftcrypto.so", RTLD_NOW);
   if (lib != NULL) {
     // These APIs aren't available for v0 lib on Solaris 10
@@ -102,7 +92,6 @@ jboolean* loadNative() {
       dlsym(lib, UCRYPTO_VERSION);
     ftab->ucryptoGetMechList = (UCRYPTO_GET_MECHLIST_FN_PTR)
       dlsym(lib, UCRYPTO_GET_MECHLIST);
-    //??
     ftab->ucryptoSignInit = (UCRYPTO_SIGN_INIT_FN_PTR)
       dlsym(lib, UCRYPTO_SIGN_INIT);
     ftab->ucryptoSignUpdate = (UCRYPTO_SIGN_UPDATE_FN_PTR)
@@ -116,6 +105,21 @@ jboolean* loadNative() {
     ftab->ucryptoVerifyFinal = (UCRYPTO_VERIFY_FINAL_FN_PTR)
       dlsym(lib, UCRYPTO_VERIFY_FINAL);
 
+    // These APS are added starting S12
+    ftab->ucryptoDigestInit = (UCRYPTO_DIGEST_INIT_FN_PTR)
+      dlsym(lib, UCRYPTO_DIGEST_INIT);
+    ftab->ucryptoDigestUpdate = (UCRYPTO_DIGEST_UPDATE_FN_PTR)
+      dlsym(lib, UCRYPTO_DIGEST_UPDATE);
+    ftab->ucryptoDigestFinal = (UCRYPTO_DIGEST_FINAL_FN_PTR)
+      dlsym(lib, UCRYPTO_DIGEST_FINAL);
+
+    ftab->ucryptoFreeContext = (UCRYPTO_FREE_CONTEXT_FN_PTR)
+      dlsym(lib, UCRYPTO_FREE_CONTEXT);
+
+    ftab->ucryptoStrerror = (UCRYPTO_STRERROR_FN_PTR)
+      dlsym(lib, UCRYPTO_STRERROR);
+
+
     // These should be avilable for all libsoftcrypto libs
     ftab->ucryptoEncryptInit = (UCRYPTO_ENCRYPT_INIT_FN_PTR)
       dlsym(lib, UCRYPTO_ENCRYPT_INIT);
@@ -147,6 +151,34 @@ jboolean* loadNative() {
     } else {
       dlclose(lib);
     }
+
+    // proceed with libmd when libucrypto does not support digest operations
+    if (ftab->ucryptoDigestInit == NULL ||
+        ftab->ucryptoDigestUpdate == NULL ||
+        ftab->ucryptoDigestFinal == NULL) {
+
+      lib = dlopen("libmd.so", RTLD_NOW);
+      if (lib != NULL) {
+        ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT);
+        ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE);
+        ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL);
+        ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT);
+        ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE);
+        ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL);
+        ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT);
+        ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE);
+        ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL);
+        if (ftab->md5Init != NULL && ftab->md5Update != NULL &&
+            ftab->md5Final != NULL && ftab->sha1Init != NULL &&
+            ftab->sha1Update != NULL && ftab->sha1Final != NULL &&
+            ftab->sha2Init != NULL && ftab->sha2Update != NULL &&
+            ftab->sha2Final != NULL) {
+          buf[0] = JNI_TRUE;
+        } else {
+          dlclose(lib);
+        }
+      }
+    }
   }
 
   return buf;
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h
index d45272f9bab..5f3a9ba87e3 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,15 +69,12 @@ typedef int (*UCRYPTO_ENCRYPT_INIT_FN_PTR)
      (crypto_ctx_t *context, ucrypto_mech_t mech_type,
       uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_ENCRYPT_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *in,
       size_t in_len, uchar_t *out, size_t *out_len);
-
 typedef int (*UCRYPTO_ENCRYPT_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *out,
       size_t *out_len);
-
 typedef int (*UCRYPTO_ENCRYPT_FN_PTR)
      (ucrypto_mech_t mech_type, uchar_t *key_str,
       size_t key_len, void *iv, size_t iv_len, uchar_t *in,
@@ -87,15 +84,12 @@ typedef int (*UCRYPTO_DECRYPT_INIT_FN_PTR)
      (crypto_ctx_t *context,
       ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_DECRYPT_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *in,
       size_t in_len, uchar_t *out, size_t *out_len);
-
 typedef int (*UCRYPTO_DECRYPT_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *out,
       size_t *out_len);
-
 typedef int (*UCRYPTO_DECRYPT_FN_PTR)
      (ucrypto_mech_t mech_type, uchar_t *key_str,
       size_t key_len, void *iv, size_t iv_len, uchar_t *in,
@@ -105,10 +99,8 @@ typedef int (*UCRYPTO_SIGN_INIT_FN_PTR)
      (crypto_ctx_t *context, ucrypto_mech_t mech_type,
       uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_SIGN_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *data_str, size_t data_len);
-
 typedef int (*UCRYPTO_SIGN_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len);
 
@@ -116,13 +108,24 @@ typedef int (*UCRYPTO_VERIFY_INIT_FN_PTR)
      (crypto_ctx_t *context, ucrypto_mech_t mech_type,
       uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_VERIFY_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *data_str, size_t data_len);
-
 typedef int (*UCRYPTO_VERIFY_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len);
 
+typedef int (*UCRYPTO_DIGEST_INIT_FN_PTR)
+     (crypto_ctx_t *context, ucrypto_mech_t mech_type,
+      void *param, size_t param_len);
+typedef int (*UCRYPTO_DIGEST_UPDATE_FN_PTR)
+     (crypto_ctx_t *context, const uchar_t *data, size_t data_len);
+typedef int (*UCRYPTO_DIGEST_FINAL_FN_PTR)
+     (crypto_ctx_t *context, uchar_t *digest, size_t *digest_len);
+
+typedef void (*UCRYPTO_FREE_CONTEXT_FN_PTR)
+     (crypto_ctx_t *context);
+
+typedef char* (*UCRYPTO_STRERROR_FN_PTR)(int rv);
+
 
 
 /* dynamically resolved functions from libmd, and libsoftcrypto
@@ -153,6 +156,11 @@ typedef struct T4CRYPTO_FUNCTION_TABLE {
   UCRYPTO_VERIFY_INIT_FN_PTR     ucryptoVerifyInit;
   UCRYPTO_VERIFY_UPDATE_FN_PTR   ucryptoVerifyUpdate;
   UCRYPTO_VERIFY_FINAL_FN_PTR    ucryptoVerifyFinal;
+  UCRYPTO_DIGEST_INIT_FN_PTR     ucryptoDigestInit;
+  UCRYPTO_DIGEST_UPDATE_FN_PTR   ucryptoDigestUpdate;
+  UCRYPTO_DIGEST_FINAL_FN_PTR    ucryptoDigestFinal;
+  UCRYPTO_FREE_CONTEXT_FN_PTR    ucryptoFreeContext;
+  UCRYPTO_STRERROR_FN_PTR        ucryptoStrerror;
 } T4CRYPTO_FUNCTION_TABLE;
 
 typedef T4CRYPTO_FUNCTION_TABLE *T4CRYPTO_FUNCTION_TABLE_PTR;
diff --git a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java b/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java
deleted file mode 100644
index 55be308348a..00000000000
--- a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.vm.agent.spi;
-
-/**
- * Service interface for jdk.hotspot.agent to provide the tools that
- * jstack, jmap, jinfo will invoke, if present.
- */
-public interface ToolProvider {
-    /**
-     * Returns the name of the tool provider
-     */
-    String getName();
-
-    /**
-     * Invoke the tool provider with the given arguments
-     */
-    void run(String... arguments);
-}
diff --git a/jdk/src/jdk.jcmd/share/classes/module-info.java b/jdk/src/jdk.jcmd/share/classes/module-info.java
index 4b8dbce1304..c78803b774c 100644
--- a/jdk/src/jdk.jcmd/share/classes/module-info.java
+++ b/jdk/src/jdk.jcmd/share/classes/module-info.java
@@ -26,9 +26,4 @@
 module jdk.jcmd {
     requires jdk.attach;
     requires jdk.jvmstat;
-
-    exports jdk.internal.vm.agent.spi to jdk.hotspot.agent;
-
-    uses jdk.internal.vm.agent.spi.ToolProvider;
 }
-
diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java
new file mode 100644
index 00000000000..e08b11d6cb5
--- /dev/null
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.common;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.VirtualMachineDescriptor;
+
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredHost;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.MonitoredVmUtil;
+import sun.jvmstat.monitor.VmIdentifier;
+
+/**
+ * Class for finding process matching a process argument,
+ * excluding tool it self and returning a list containing
+ * the process identifiers.
+ */
+public class ProcessArgumentMatcher {
+    private String excludeCls;
+    private String matchClass = null;
+    private String singlePid = null;
+    private boolean matchAll = false;
+
+    public ProcessArgumentMatcher(String pidArg, Class<?> excludeClass) {
+        excludeCls = excludeClass.getName();
+        if (pidArg == null || pidArg.isEmpty()) {
+            throw new IllegalArgumentException("Pid string is invalid");
+        }
+        if (pidArg.charAt(0) == '-') {
+            throw new IllegalArgumentException("Unrecognized " + pidArg);
+        }
+        try {
+            long pid = Long.parseLong(pidArg);
+            if (pid == 0) {
+                matchAll = true;
+            } else {
+                singlePid = String.valueOf(pid);
+            }
+        } catch (NumberFormatException nfe) {
+            matchClass = pidArg;
+        }
+    }
+
+    private boolean check(VirtualMachineDescriptor vmd) {
+        String mainClass = null;
+        try {
+            VmIdentifier vmId = new VmIdentifier(vmd.id());
+            MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId);
+            MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1);
+            mainClass = MonitoredVmUtil.mainClass(monitoredVm, true);
+            monitoredHost.detach(monitoredVm);
+        } catch (NullPointerException npe) {
+            // There is a potential race, where a running java app is being
+            // queried, unfortunately the java app has shutdown after this
+            // method is started but before getMonitoredVM is called.
+            // If this is the case, then the /tmp/hsperfdata_xxx/pid file
+            // will have disappeared and we will get a NullPointerException.
+            // Handle this gracefully....
+            return false;
+        } catch (MonitorException | URISyntaxException e) {
+            if (e.getMessage() != null) {
+                System.err.println(e.getMessage());
+            } else {
+                Throwable cause = e.getCause();
+                if ((cause != null) && (cause.getMessage() != null)) {
+                    System.err.println(cause.getMessage());
+                } else {
+                    e.printStackTrace();
+                }
+            }
+            return false;
+        }
+
+        if (mainClass.equals(excludeCls)) {
+            return false;
+        }
+
+        if (matchAll || mainClass.indexOf(matchClass) != -1) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public Collection<String> getPids() {
+        Collection<String> pids = new ArrayList<>();
+        if (singlePid != null) {
+            pids.add(singlePid);
+            return pids;
+        }
+        List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
+        for (VirtualMachineDescriptor vmd : vmds) {
+            if (check(vmd)) {
+                pids.add(vmd.id());
+            }
+        }
+        return pids;
+    }
+}
diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java
index fbd4ca9aae4..80708f5aa37 100644
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java
@@ -33,16 +33,14 @@ class Arguments {
     private boolean listProcesses = false;
     private boolean listCounters  = false;
     private boolean showUsage     = false;
-    private int     pid           = -1;
     private String  command       = null;
-    private String  processSubstring;
+    private String  processString = null;
 
     public boolean isListProcesses() { return listProcesses; }
     public boolean isListCounters() { return listCounters; }
     public boolean isShowUsage() { return showUsage; }
-    public int getPid() { return pid; }
     public String getCommand() { return command; }
-    public String getProcessSubstring() { return processSubstring; }
+    public String getProcessString() { return processString; }
 
     public Arguments(String[] args) {
         if (args.length == 0 || args[0].equals("-l")) {
@@ -55,15 +53,7 @@ class Arguments {
             return;
         }
 
-        try {
-            pid = Integer.parseInt(args[0]);
-        } catch (NumberFormatException ex) {
-            // use as a partial class-name instead
-            if (args[0].charAt(0) != '-') {
-                // unless it starts with a '-'
-                processSubstring = args[0];
-            }
-        }
+        processString = args[0];
 
         StringBuilder sb = new StringBuilder();
         for (int i = 1; i < args.length; i++) {
diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java
index 0ff46323ec6..ab77547a077 100644
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java
@@ -29,22 +29,22 @@ import java.io.InputStream;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.List;
-import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.net.URISyntaxException;
 
 import com.sun.tools.attach.AttachOperationFailedException;
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.VirtualMachineDescriptor;
-import com.sun.tools.attach.AgentLoadException;
 import com.sun.tools.attach.AttachNotSupportedException;
 
 import sun.tools.attach.HotSpotVirtualMachine;
+import sun.tools.common.ProcessArgumentMatcher;
 import sun.tools.jstat.JStatLogger;
 import sun.jvmstat.monitor.Monitor;
 import sun.jvmstat.monitor.MonitoredHost;
 import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.MonitoredVmUtil;
 import sun.jvmstat.monitor.MonitorException;
 import sun.jvmstat.monitor.VmIdentifier;
 
@@ -73,52 +73,18 @@ public class JCmd {
             System.exit(0);
         }
 
-        List<String> pids = new ArrayList<String>();
-        if (arg.getPid() == 0) {
-            // find all VMs
-            List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
-            for (VirtualMachineDescriptor vmd : vmds) {
-                if (!isJCmdProcess(vmd)) {
-                    pids.add(vmd.id());
-                }
-            }
-        } else if (arg.getProcessSubstring() != null) {
-            // use the partial class-name match
-            List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
-            for (VirtualMachineDescriptor vmd : vmds) {
-                if (isJCmdProcess(vmd)) {
-                    continue;
-                }
-                try {
-                    String mainClass = getMainClass(vmd);
-                    if (mainClass != null
-                        && mainClass.indexOf(arg.getProcessSubstring()) != -1) {
-                            pids.add(vmd.id());
-                    }
-                } catch (MonitorException|URISyntaxException e) {
-                    if (e.getMessage() != null) {
-                        System.err.println(e.getMessage());
-                    } else {
-                        Throwable cause = e.getCause();
-                        if ((cause != null) && (cause.getMessage() != null)) {
-                            System.err.println(cause.getMessage());
-                        } else {
-                            e.printStackTrace();
-                        }
-                    }
-                }
-            }
-            if (pids.isEmpty()) {
-                System.err.println("Could not find any processes matching : '"
-                                   + arg.getProcessSubstring() + "'");
-                System.exit(1);
-            }
-        } else if (arg.getPid() == -1) {
+        Collection<String> pids = Collections.emptyList();
+        try {
+            ProcessArgumentMatcher ap = new ProcessArgumentMatcher(arg.getProcessString(), JCmd.class);
+            pids = ap.getPids();
+        } catch (IllegalArgumentException iae) {
             System.err.println("Invalid pid specified");
             System.exit(1);
-        } else {
-            // Use the found pid
-            pids.add(arg.getPid() + "");
+        }
+        if (pids.isEmpty()) {
+            System.err.println("Could not find any processes matching : '"
+                               + arg.getProcessString() + "'");
+            System.exit(1);
         }
 
         boolean success = true;
@@ -199,36 +165,6 @@ public class JCmd {
         }
     }
 
-    private static boolean isJCmdProcess(VirtualMachineDescriptor vmd) {
-        try {
-            String mainClass = getMainClass(vmd);
-            return mainClass != null && mainClass.equals(JCmd.class.getName());
-        } catch (URISyntaxException|MonitorException ex) {
-            return false;
-        }
-    }
-
-    private static String getMainClass(VirtualMachineDescriptor vmd)
-            throws URISyntaxException, MonitorException {
-        try {
-            String mainClass = null;
-            VmIdentifier vmId = new VmIdentifier(vmd.id());
-            MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId);
-            MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1);
-            mainClass = MonitoredVmUtil.mainClass(monitoredVm, true);
-            monitoredHost.detach(monitoredVm);
-            return mainClass;
-        } catch(NullPointerException e) {
-            // There is a potential race, where a running java app is being
-            // queried, unfortunately the java app has shutdown after this
-            // method is started but before getMonitoredVM is called.
-            // If this is the case, then the /tmp/hsperfdata_xxx/pid file
-            // will have disappeared and we will get a NullPointerException.
-            // Handle this gracefully....
-            return null;
-        }
-    }
-
     /**
      * Class to compare two Monitor objects by name in ascending order.
      * (from jstat)
diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java
index f19b6d159f0..ca774122a17 100644
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java
@@ -25,15 +25,14 @@
 
 package sun.tools.jinfo;
 
-import java.util.Arrays;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Collection;
 
 import com.sun.tools.attach.VirtualMachine;
 
 import sun.tools.attach.HotSpotVirtualMachine;
-import jdk.internal.vm.agent.spi.ToolProvider;
-import jdk.internal.vm.agent.spi.ToolProviderFinder;
+import sun.tools.common.ProcessArgumentMatcher;
 
 /*
  * This class is the main class for the JInfo utility. It parses its arguments
@@ -41,155 +40,94 @@ import jdk.internal.vm.agent.spi.ToolProviderFinder;
  * or an SA tool.
  */
 final public class JInfo {
-    private static final String SA_JINFO_TOOL_NAME = "jinfo";
-    private boolean useSA = false;
-    private String[] args = null;
-
-    private JInfo(String[] args) throws IllegalArgumentException {
-        if (args.length == 0) {
-            throw new IllegalArgumentException();
-        }
-
-        int argCopyIndex = 0;
-        // First determine if we should launch SA or not
-        if (args[0].equals("-F")) {
-            // delete the -F
-            argCopyIndex = 1;
-            useSA = true;
-        } else if (args[0].equals("-flags")
-                   || args[0].equals("-sysprops"))
-        {
-            if (args.length == 2) {
-                if (!isPid(args[1])) {
-                    // If args[1] doesn't parse to a number then
-                    // it must be the SA debug server
-                    // (otherwise it is the pid)
-                    useSA = true;
-                }
-            } else if (args.length == 3) {
-                // arguments include an executable and a core file
-                useSA = true;
-            } else {
-                throw new IllegalArgumentException();
-            }
-        } else if (!args[0].startsWith("-")) {
-            if (args.length == 2) {
-                // the only arguments are an executable and a core file
-                useSA = true;
-            } else if (args.length == 1) {
-                if (!isPid(args[0])) {
-                    // The only argument is not a PID; it must be SA debug
-                    // server
-                    useSA = true;
-                }
-            } else {
-                throw new IllegalArgumentException();
-            }
-        } else if (args[0].equals("-h") || args[0].equals("-help")) {
-            if (args.length > 1) {
-                throw new IllegalArgumentException();
-            }
-        } else if (args[0].equals("-flag")) {
-            if (args.length == 3) {
-                if (!isPid(args[2])) {
-                    throw new IllegalArgumentException();
-                }
-            } else {
-                throw new IllegalArgumentException();
-            }
-        } else {
-            throw new IllegalArgumentException();
-        }
-
-        this.args = Arrays.copyOfRange(args, argCopyIndex, args.length);
-    }
-
-    @SuppressWarnings("fallthrough")
-    private void execute() throws Exception {
-        if (args[0].equals("-h")
-            || args[0].equals("-help")) {
-            usage(0);
-        }
-
-        if (useSA) {
-            // SA only supports -flags or -sysprops
-            if (args[0].startsWith("-")) {
-                if (!(args[0].equals("-flags") || args[0].equals("-sysprops"))) {
-                    usage(1);
-                }
-            }
-
-            // invoke SA which does it's own argument parsing
-            runTool();
-
-        } else {
-            // Now we can parse arguments for the non-SA case
-            String pid = null;
-
-            switch(args[0]) {
-                case "-flag":
-                    if (args.length != 3) {
-                        usage(1);
-                    }
-                    String option = args[1];
-                    pid = args[2];
-                    flag(pid, option);
-                    break;
-                case "-flags":
-                    if (args.length != 2) {
-                        usage(1);
-                    }
-                    pid = args[1];
-                    flags(pid);
-                    break;
-                case "-sysprops":
-                    if (args.length != 2) {
-                        usage(1);
-                    }
-                    pid = args[1];
-                    sysprops(pid);
-                    break;
-                case "-help":
-                case "-h":
-                    usage(0);
-                    // Fall through
-                default:
-                    if (args.length == 1) {
-                        // no flags specified, we do -sysprops and -flags
-                        pid = args[0];
-                        sysprops(pid);
-                        System.out.println();
-                        flags(pid);
-                        System.out.println();
-                        commandLine(pid);
-                    } else {
-                        usage(1);
-                    }
-            }
-        }
-    }
 
     public static void main(String[] args) throws Exception {
-        JInfo jinfo = null;
-        try {
-            jinfo = new JInfo(args);
-            jinfo.execute();
-        } catch (IllegalArgumentException e) {
+        if (args.length == 0) {
+            usage(1); // no arguments
+        }
+        checkForUnsupportedOptions(args);
+
+        boolean doFlag = false;
+        boolean doFlags = false;
+        boolean doSysprops = false;
+
+        // Parse the options (arguments starting with "-" )
+        int optionCount = 0;
+        while (optionCount < args.length) {
+            String arg = args[optionCount];
+            if (!arg.startsWith("-")) {
+                break;
+            }
+
+            optionCount++;
+
+            if (arg.equals("-help") || arg.equals("-h")) {
+                usage(0);
+            }
+
+            if (arg.equals("-flag")) {
+                doFlag = true;
+                continue;
+            }
+
+            if (arg.equals("-flags")) {
+                doFlags = true;
+                continue;
+            }
+
+            if (arg.equals("-sysprops")) {
+                doSysprops = true;
+                continue;
+            }
+        }
+
+        // Next we check the parameter count. -flag allows extra parameters
+        int paramCount = args.length - optionCount;
+        if ((doFlag && paramCount != 2) || ((!doFlag && paramCount != 1))) {
             usage(1);
         }
-    }
 
-    private static boolean isPid(String arg) {
-        return arg.matches("[0-9]+");
-    }
-
-    // Invoke SA tool with the given arguments
-    private void runTool() throws Exception {
-        ToolProvider tool = ToolProviderFinder.find(SA_JINFO_TOOL_NAME);
-        if (tool == null) {
-            usage(1);
+        if (!doFlag && !doFlags && !doSysprops) {
+            // Print flags and sysporps if no options given
+            ProcessArgumentMatcher ap = new ProcessArgumentMatcher(args[optionCount], JInfo.class);
+            Collection<String> pids = ap.getPids();
+            for (String pid : pids) {
+                if (pids.size() > 1) {
+                    System.out.println("Pid:" + pid);
+                }
+                sysprops(pid);
+                System.out.println();
+                flags(pid);
+                System.out.println();
+                commandLine(pid);
+            }
+        }
+
+        if (doFlag) {
+            ProcessArgumentMatcher ap = new ProcessArgumentMatcher(args[optionCount+1], JInfo.class);
+            Collection<String> pids = ap.getPids();
+            for (String pid : pids) {
+                if (pids.size() > 1) {
+                    System.out.println("Pid:" + pid);
+                }
+                flag(pid, args[optionCount]);
+            }
+        }
+        else if (doFlags || doSysprops) {
+            ProcessArgumentMatcher ap = new ProcessArgumentMatcher(args[optionCount], JInfo.class);
+            Collection<String> pids = ap.getPids();
+            for (String pid : pids) {
+                if (pids.size() > 1) {
+                    System.out.println("Pid:" + pid);
+                }
+                if (doFlags) {
+                    flags(pid);
+                }
+                else if (doSysprops) {
+                    sysprops(pid);
+                }
+            }
         }
-        tool.run(args);
     }
 
     private static void flag(String pid, String option) throws IOException {
@@ -274,46 +212,49 @@ final public class JInfo {
         vm.detach();
     }
 
+    private static void checkForUnsupportedOptions(String[] args) {
+        // Check arguments for -F, and non-numeric value
+        // and warn the user that SA is not supported anymore
+        int maxCount = 1;
+        int paramCount = 0;
 
-    // print usage message
-    private static void usage(int exit) {
-        boolean usageSA = ToolProviderFinder.find(SA_JINFO_TOOL_NAME) != null;
-
-        System.err.println("Usage:");
-        if (usageSA) {
-            System.err.println("    jinfo [option] <pid>");
-            System.err.println("        (to connect to a running process)");
-            System.err.println("    jinfo -F [option] <pid>");
-            System.err.println("        (to connect to a hung process)");
-            System.err.println("    jinfo [option] <executable> <core>");
-            System.err.println("        (to connect to a core file)");
-            System.err.println("    jinfo [option] [server_id@]<remote server IP or hostname>");
-            System.err.println("        (to connect to remote debug server)");
-            System.err.println("");
-            System.err.println("where <option> is one of:");
-            System.err.println("  for running processes:");
-            System.err.println("    -flag <name>         to print the value of the named VM flag");
-            System.err.println("    -flag [+|-]<name>    to enable or disable the named VM flag");
-            System.err.println("    -flag <name>=<value> to set the named VM flag to the given value");
-            System.err.println("  for running or hung processes and core files:");
-            System.err.println("    -flags               to print VM flags");
-            System.err.println("    -sysprops            to print Java system properties");
-            System.err.println("    <no option>          to print both VM flags and system properties");
-            System.err.println("    -h | -help           to print this help message");
-        } else {
-            System.err.println("    jinfo <option> <pid>");
-            System.err.println("       (to connect to a running process)");
-            System.err.println("");
-            System.err.println("where <option> is one of:");
-            System.err.println("    -flag <name>         to print the value of the named VM flag");
-            System.err.println("    -flag [+|-]<name>    to enable or disable the named VM flag");
-            System.err.println("    -flag <name>=<value> to set the named VM flag to the given value");
-            System.err.println("    -flags               to print VM flags");
-            System.err.println("    -sysprops            to print Java system properties");
-            System.err.println("    <no option>          to print both VM flags and system properties");
-            System.err.println("    -h | -help           to print this help message");
+        for (String s : args) {
+            if (s.equals("-F")) {
+                SAOptionError("-F option used");
+            }
+            if (s.equals("-flag")) {
+                maxCount = 2;
+            }
+            if (! s.startsWith("-")) {
+                paramCount += 1;
+            }
         }
 
+        if (paramCount > maxCount) {
+            SAOptionError("More than " + maxCount + " non-option argument");
+        }
+    }
+
+    private static void SAOptionError(String msg) {
+        System.err.println("Error: " + msg);
+        System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jinfo instead");
+        System.exit(1);
+    }
+
+     // print usage message
+    private static void usage(int exit) {
+        System.err.println("Usage:");
+        System.err.println("    jinfo <option> <pid>");
+        System.err.println("       (to connect to a running process)");
+        System.err.println("");
+        System.err.println("where <option> is one of:");
+        System.err.println("    -flag <name>         to print the value of the named VM flag");
+        System.err.println("    -flag [+|-]<name>    to enable or disable the named VM flag");
+        System.err.println("    -flag <name>=<value> to set the named VM flag to the given value");
+        System.err.println("    -flags               to print VM flags");
+        System.err.println("    -sysprops            to print Java system properties");
+        System.err.println("    <no option>          to print both VM flags and system properties");
+        System.err.println("    -h | -help           to print this help message");
         System.exit(exit);
     }
 }
diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java
index cb7651e476b..810a44eee6f 100644
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java
@@ -28,12 +28,13 @@ package sun.tools.jmap;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Collection;
 
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.AttachNotSupportedException;
 import sun.tools.attach.HotSpotVirtualMachine;
-import jdk.internal.vm.agent.spi.ToolProvider;
-import jdk.internal.vm.agent.spi.ToolProviderFinder;
+import sun.tools.common.ProcessArgumentMatcher;
 
 /*
  * This class is the main class for the JMap utility. It parses its arguments
@@ -44,34 +45,18 @@ import jdk.internal.vm.agent.spi.ToolProviderFinder;
  */
 public class JMap {
 
-    // Options handled by the attach mechanism
-    private static String HISTO_OPTION = "-histo";
-    private static String LIVE_HISTO_OPTION = "-histo:live";
-    private static String DUMP_OPTION_PREFIX = "-dump:";
-
-    // These options imply the use of a SA tool
-    private static String SA_TOOL_OPTIONS =
-      "-heap|-heap:format=b|-clstats|-finalizerinfo";
-
-    // The -F (force) option is currently not passed through to SA
-    private static String FORCE_SA_OPTION = "-F";
-
-    // Default option (if nothing provided)
-    private static String DEFAULT_OPTION = "-pmap";
-
     public static void main(String[] args) throws Exception {
         if (args.length == 0) {
             usage(1); // no arguments
         }
 
-        // used to indicate if we should use SA
-        boolean useSA = false;
+        checkForUnsupportedOptions(args);
 
-        // the chosen option (-heap, -dump:*, ... )
+        // the chosen option
         String option = null;
 
         // First iterate over the options (arguments starting with -).  There should be
-        // one (but maybe two if -F is also used).
+        // one.
         int optionCount = 0;
         while (optionCount < args.length) {
             String arg = args[optionCount];
@@ -80,8 +65,6 @@ public class JMap {
             }
             if (arg.equals("-help") || arg.equals("-h")) {
                 usage(0);
-            } else if (arg.equals(FORCE_SA_OPTION)) {
-                useSA = true;
             } else {
                 if (option != null) {
                     usage(1);  // option already specified
@@ -93,123 +76,102 @@ public class JMap {
 
         // if no option provided then use default.
         if (option == null) {
-            option = DEFAULT_OPTION;
-        }
-        if (option.matches(SA_TOOL_OPTIONS)) {
-            useSA = true;
+            usage(0);
         }
 
-        // Next we check the parameter count. For the SA tools there are
-        // one or two parameters. For the built-in -dump option there is
-        // only one parameter (the process-id)
+        // Next we check the parameter count.
         int paramCount = args.length - optionCount;
-        if (paramCount == 0 || paramCount > 2) {
+        if (paramCount != 1) {
             usage(1);
         }
 
-        if (optionCount == 0 || paramCount != 1) {
-            useSA = true;
-        } else {
-            // the parameter for the -dump option is a process-id.
-            // If it doesn't parse to a number then it must be SA
-            // debug server
-            if (!args[optionCount].matches("[0-9]+")) {
-                useSA = true;
+        String pidArg = args[1];
+        // Here we handle the built-in options
+        // As more options are added we should create an abstract tool class and
+        // have a table to map the options
+        ProcessArgumentMatcher ap = new ProcessArgumentMatcher(pidArg, JMap.class);
+        Collection<String> pids = ap.getPids();
+        for (String pid : pids) {
+            if (pids.size() > 1) {
+                System.out.println("Pid:" + pid);
             }
-        }
-
-
-        // at this point we know if we are executing an SA tool or a built-in
-        // option.
-
-        if (useSA) {
-            // parameters (<pid> or <exe> <core>)
-            String params[] = new String[paramCount];
-            for (int i=optionCount; i<args.length; i++ ){
-                params[i-optionCount] = args[i];
-            }
-            runTool(option, params);
-
-        } else {
-            String pid = args[1];
-            // Here we handle the built-in options
-            // As more options are added we should create an abstract tool class and
-            // have a table to map the options
-            if (option.equals(HISTO_OPTION)) {
-                histo(pid, false);
-            } else if (option.equals(LIVE_HISTO_OPTION)) {
-                histo(pid, true);
-            } else if (option.startsWith(DUMP_OPTION_PREFIX)) {
-                dump(pid, option);
+            if (option.equals("-histo")) {
+                histo(pid, "");
+            } else if (option.startsWith("-histo:")) {
+                histo(pid, option.substring("-histo:".length()));
+            } else if (option.startsWith("-dump:")) {
+                dump(pid, option.substring("-dump:".length()));
+            } else if (option.equals("-finalizerinfo")) {
+                executeCommandForPid(pid, "jcmd", "GC.finalizer_info");
+            } else if (option.equals("-clstats")) {
+                executeCommandForPid(pid, "jcmd", "GC.class_stats");
             } else {
-                usage(1);
+              usage(1);
             }
         }
     }
 
-    // Invoke SA tool  with the given arguments
-    private static void runTool(String option, String args[]) throws Exception {
-        String[][] tools = {
-            { "-pmap",          "pmap"             },
-            { "-heap",          "heapSummary"      },
-            { "-heap:format=b", "heapDumper"       },
-            { "-histo",         "objectHistogram"  },
-            { "-clstats",       "classLoaderStats" },
-            { "-finalizerinfo", "finalizerInfo"    },
-        };
+    private static void executeCommandForPid(String pid, String command, Object ... args)
+        throws AttachNotSupportedException, IOException,
+               UnsupportedEncodingException {
+        VirtualMachine vm = VirtualMachine.attach(pid);
 
-        String name = null;
-
-        // -dump option needs to be handled in a special way
-        if (option.startsWith(DUMP_OPTION_PREFIX)) {
-            // first check that the option can be parsed
-            String fn = parseDumpOptions(option);
-            if (fn == null) {
-                usage(1);
-            }
-
-            // tool for heap dumping
-            name = "heapDumper";
-
-            // HeapDumper -f <file>
-            args = prepend(fn, args);
-            args = prepend("-f", args);
-        } else {
-            int i=0;
-            while (i < tools.length) {
-                if (option.equals(tools[i][0])) {
-                    name = tools[i][1];
-                    break;
-                }
-                i++;
-            }
-        }
-        if (name == null) {
-            usage(1);   // no mapping to tool
+        // Cast to HotSpotVirtualMachine as this is an
+        // implementation specific method.
+        HotSpotVirtualMachine hvm = (HotSpotVirtualMachine) vm;
+        try (InputStream in = hvm.executeCommand(command, args)) {
+          // read to EOF and just print output
+          byte b[] = new byte[256];
+          int n;
+          do {
+              n = in.read(b);
+              if (n > 0) {
+                  String s = new String(b, 0, n, "UTF-8");
+                  System.out.print(s);
+              }
+          } while (n > 0);
         }
+        vm.detach();
+    }
 
-        // Tool not available on this platform.
-        ToolProvider tool = ToolProviderFinder.find(name);
-        if (tool == null) {
+    private static void histo(String pid, String options)
+        throws AttachNotSupportedException, IOException,
+               UnsupportedEncodingException {
+        String liveopt = "-all";
+        if (options.equals("") || options.equals("all")) {
+            //  pass
+        }
+        else if (options.equals("live")) {
+            liveopt = "-live";
+        }
+        else {
             usage(1);
         }
 
-        // invoke the main method with the arguments
-        tool.run(args);
+        // inspectHeap is not the same as jcmd GC.class_histogram
+        executeCommandForPid(pid, "inspectheap", liveopt);
     }
 
-    private static final String LIVE_OBJECTS_OPTION = "-live";
-    private static final String ALL_OBJECTS_OPTION = "-all";
-    private static void histo(String pid, boolean live) throws IOException {
-        VirtualMachine vm = attach(pid);
-        InputStream in = ((HotSpotVirtualMachine)vm).
-            heapHisto(live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION);
-        drain(vm, in);
-    }
+    private static void dump(String pid, String options)
+        throws AttachNotSupportedException, IOException,
+               UnsupportedEncodingException {
+
+        String subopts[] = options.split(",");
+        String filename = null;
+        String liveopt = "-all";
+
+        for (int i = 0; i < subopts.length; i++) {
+            String subopt = subopts[i];
+            if (subopt.equals("live")) {
+                liveopt = "-live";
+            } else if (subopt.startsWith("file=")) {
+                // file=<file> - check that <file> is specified
+                if (subopt.length() > 5) {
+                    filename = subopt.substring(5);
+                }
+            }
+        }
 
-    private static void dump(String pid, String options) throws IOException {
-        // parse the options to get the dump filename
-        String filename = parseDumpOptions(options);
         if (filename == null) {
             usage(1);  // invalid options or no filename
         }
@@ -219,156 +181,73 @@ public class JMap {
         // working directory rather than the directory where jmap
         // is executed.
         filename = new File(filename).getCanonicalPath();
-
-        // dump live objects only or not
-        boolean live = isDumpLiveObjects(options);
-
-        VirtualMachine vm = attach(pid);
-        System.out.println("Dumping heap to " + filename + " ...");
-        InputStream in = ((HotSpotVirtualMachine)vm).
-            dumpHeap((Object)filename,
-                     (live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION));
-        drain(vm, in);
+        // dumpHeap is not the same as jcmd GC.heap_dump
+        executeCommandForPid(pid, "dumpheap", filename, liveopt);
     }
 
-    // Parse the options to the -dump option. Valid options are format=b and
-    // file=<file>. Returns <file> if provided. Returns null if <file> not
-    // provided, or invalid option.
-    private static String parseDumpOptions(String arg) {
-        assert arg.startsWith(DUMP_OPTION_PREFIX);
+    private static void checkForUnsupportedOptions(String[] args) {
+        // Check arguments for -F, -m, and non-numeric value
+        // and warn the user that SA is not supported anymore
 
-        String filename = null;
+        int paramCount = 0;
 
-        // options are separated by comma (,)
-        String options[] = arg.substring(DUMP_OPTION_PREFIX.length()).split(",");
+        for (String s : args) {
+            if (s.equals("-F")) {
+                SAOptionError("-F option used");
+            }
 
-        for (int i=0; i<options.length; i++) {
-            String option = options[i];
+            if (s.equals("-heap")) {
+                SAOptionError("-heap option used");
+            }
 
-            if (option.equals("format=b")) {
-                // ignore format (not needed at this time)
-            } else if (option.equals("live")) {
-                // a valid suboption
-            } else {
+            /* Reimplemented using jcmd, output format is different
+               from original one
 
-                // file=<file> - check that <file> is specified
-                if (option.startsWith("file=")) {
-                    filename = option.substring(5);
-                    if (filename.length() == 0) {
-                        return null;
-                    }
-                } else {
-                    return null;  // option not recognized
-                }
+            if (s.equals("-clstats")) {
+                warnSA("-clstats option used");
+            }
+
+            if (s.equals("-finalizerinfo")) {
+                warnSA("-finalizerinfo option used");
+            }
+            */
+
+            if (! s.startsWith("-")) {
+                paramCount += 1;
             }
         }
-        return filename;
-    }
 
-    private static boolean isDumpLiveObjects(String arg) {
-        // options are separated by comma (,)
-        String options[] = arg.substring(DUMP_OPTION_PREFIX.length()).split(",");
-        for (String suboption : options) {
-            if (suboption.equals("live")) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    // Attach to <pid>, existing if we fail to attach
-    private static VirtualMachine attach(String pid) {
-        try {
-            return VirtualMachine.attach(pid);
-        } catch (Exception x) {
-            String msg = x.getMessage();
-            if (msg != null) {
-                System.err.println(pid + ": " + msg);
-            } else {
-                x.printStackTrace();
-            }
-            if ((x instanceof AttachNotSupportedException) && haveSA()) {
-                System.err.println("The -F option can be used when the " +
-                  "target process is not responding");
-            }
-            System.exit(1);
-            return null; // keep compiler happy
+        if (paramCount > 1) {
+            SAOptionError("More than one non-option argument");
         }
     }
 
-    // Read the stream from the target VM until EOF, then detach
-    private static void drain(VirtualMachine vm, InputStream in) throws IOException {
-        // read to EOF and just print output
-        byte b[] = new byte[256];
-        int n;
-        do {
-            n = in.read(b);
-            if (n > 0) {
-                String s = new String(b, 0, n, "UTF-8");
-                System.out.print(s);
-            }
-        } while (n > 0);
-        in.close();
-        vm.detach();
-    }
-
-    // return a new string array with arg as the first element
-    private static String[] prepend(String arg, String args[]) {
-        String[] newargs = new String[args.length+1];
-        newargs[0] = arg;
-        System.arraycopy(args, 0, newargs, 1, args.length);
-        return newargs;
-    }
-
-    // returns true if SA is available
-    private static boolean haveSA() {
-        return ToolProviderFinder.find("heapSummary") != null;
+    private static void SAOptionError(String msg) {
+        System.err.println("Error: " + msg);
+        System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jmap instead");
+        System.exit(1);
     }
 
     // print usage message
     private static void usage(int exit) {
         System.err.println("Usage:");
-        if (haveSA()) {
-            System.err.println("    jmap [option] <pid>");
-            System.err.println("        (to connect to running process)");
-            System.err.println("    jmap [option] <executable <core>");
-            System.err.println("        (to connect to a core file)");
-            System.err.println("    jmap [option] [server_id@]<remote server IP or hostname>");
-            System.err.println("        (to connect to remote debug server)");
-            System.err.println("");
-            System.err.println("where <option> is one of:");
-            System.err.println("    <none>               to print same info as Solaris pmap");
-            System.err.println("    -heap                to print java heap summary");
-            System.err.println("    -histo[:live]        to print histogram of java object heap; if the \"live\"");
-            System.err.println("                         suboption is specified, only count live objects");
-            System.err.println("    -clstats             to print class loader statistics");
-            System.err.println("    -finalizerinfo       to print information on objects awaiting finalization");
-            System.err.println("    -dump:<dump-options> to dump java heap in hprof binary format");
-            System.err.println("                         dump-options:");
-            System.err.println("                           live         dump only live objects; if not specified,");
-            System.err.println("                                        all objects in the heap are dumped.");
-            System.err.println("                           format=b     binary format");
-            System.err.println("                           file=<file>  dump heap to <file>");
-            System.err.println("                         Example: jmap -dump:live,format=b,file=heap.bin <pid>");
-            System.err.println("    -F                   force. Use with -dump:<dump-options> <pid> or -histo");
-            System.err.println("                         to force a heap dump or histogram when <pid> does not");
-            System.err.println("                         respond. The \"live\" suboption is not supported");
-            System.err.println("                         in this mode.");
-            System.err.println("    -h | -help           to print this help message");
-            System.err.println("    -J<flag>             to pass <flag> directly to the runtime system");
-        } else {
-            System.err.println("    jmap -histo <pid>");
-            System.err.println("      (to connect to running process and print histogram of java object heap");
-            System.err.println("    jmap -dump:<dump-options> <pid>");
-            System.err.println("      (to connect to running process and dump java heap)");
-            System.err.println("");
-            System.err.println("    dump-options:");
-            System.err.println("      format=b     binary default");
-            System.err.println("      file=<file>  dump heap to <file>");
-            System.err.println("");
-            System.err.println("    Example:       jmap -dump:format=b,file=heap.bin <pid>");
-        }
-
+        System.err.println("    jmap -clstats <pid>");
+        System.err.println("        to connect to running process and print class loader statistics");
+        System.err.println("    jmap -finalizerinfo <pid>");
+        System.err.println("        to connect to running process and print information on objects awaiting finalization");
+        System.err.println("    jmap -histo[:live] <pid>");
+        System.err.println("        to connect to running process and print histogram of java object heap");
+        System.err.println("        if the \"live\" suboption is specified, only count live objects");
+        System.err.println("    jmap -dump:<dump-options> <pid>");
+        System.err.println("        to connect to running process and dump java heap");
+        System.err.println("");
+        System.err.println("    dump-options:");
+        System.err.println("      live         dump only live objects; if not specified,");
+        System.err.println("                   all objects in the heap are dumped.");
+        System.err.println("      format=b     binary format");
+        System.err.println("      file=<file>  dump heap to <file>");
+        System.err.println("");
+        System.err.println("    Example: jmap -dump:live,format=b,file=heap.bin <pid>");
         System.exit(exit);
     }
 }
diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java
index 355328474fd..7d629e3854e 100644
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java
@@ -26,12 +26,11 @@
 package sun.tools.jstack;
 
 import java.io.InputStream;
+import java.util.Collection;
 
 import com.sun.tools.attach.VirtualMachine;
-import com.sun.tools.attach.AttachNotSupportedException;
 import sun.tools.attach.HotSpotVirtualMachine;
-import jdk.internal.vm.agent.spi.ToolProvider;
-import jdk.internal.vm.agent.spi.ToolProviderFinder;
+import sun.tools.common.ProcessArgumentMatcher;
 
 /*
  * This class is the main class for the JStack utility. It parses its arguments
@@ -39,15 +38,14 @@ import jdk.internal.vm.agent.spi.ToolProviderFinder;
  * obtained the thread dump from a target process using the VM attach mechanism
  */
 public class JStack {
-    private static final String SA_JSTACK_TOOL_NAME = "jstack";
 
     public static void main(String[] args) throws Exception {
         if (args.length == 0) {
             usage(1); // no arguments
         }
 
-        boolean useSA = false;
-        boolean mixed = false;
+        checkForUnsupportedOptions(args);
+
         boolean locks = false;
 
         // Parse the options (arguments starting with "-" )
@@ -60,87 +58,40 @@ public class JStack {
             if (arg.equals("-help") || arg.equals("-h")) {
                 usage(0);
             }
-            else if (arg.equals("-F")) {
-                useSA = true;
-            }
             else {
-                if (arg.equals("-m")) {
-                    mixed = true;
+                if (arg.equals("-l")) {
+                    locks = true;
                 } else {
-                    if (arg.equals("-l")) {
-                       locks = true;
-                    } else {
-                        usage(1);
-                    }
+                    usage(1);
                 }
             }
             optionCount++;
         }
 
-        // mixed stack implies SA tool
-        if (mixed) {
-            useSA = true;
-        }
-
-        // Next we check the parameter count. If there are two parameters
-        // we assume core file and executable so we use SA.
+        // Next we check the parameter count.
         int paramCount = args.length - optionCount;
-        if (paramCount == 0 || paramCount > 2) {
+        if (paramCount != 1) {
             usage(1);
         }
-        if (paramCount == 2) {
-            useSA = true;
-        } else {
-            // If we can't parse it as a pid then it must be debug server
-            if (!args[optionCount].matches("[0-9]+")) {
-                useSA = true;
-            }
-        }
 
-        // now execute using the SA JStack tool or the built-in thread dumper
-        if (useSA) {
-            // parameters (<pid> or <exe> <core>
-            String params[] = new String[paramCount];
-            for (int i=optionCount; i<args.length; i++ ){
-                params[i-optionCount] = args[i];
-            }
-            runJStackTool(mixed, locks, params);
+        // pass -l to thread dump operation to get extra lock info
+        String pidArg = args[optionCount];
+        String params[];
+        if (locks) {
+            params = new String[] { "-l" };
         } else {
-            // pass -l to thread dump operation to get extra lock info
-            String pid = args[optionCount];
-            String params[];
-            if (locks) {
-                params = new String[] { "-l" };
-            } else {
-                params = new String[0];
+            params = new String[0];
+        }
+        ProcessArgumentMatcher ap = new ProcessArgumentMatcher(pidArg, JStack.class);
+        Collection<String> pids = ap.getPids();
+        for (String pid : pids) {
+            if (pids.size() > 1) {
+                System.out.println("Pid:" + pid);
             }
             runThreadDump(pid, params);
         }
     }
 
-    // SA JStack tool
-    private static boolean isAgentToolPresent() {
-        return ToolProviderFinder.find(SA_JSTACK_TOOL_NAME) != null;
-    }
-
-    private static void runJStackTool(boolean mixed, boolean locks, String args[]) throws Exception {
-        ToolProvider tool = ToolProviderFinder.find(SA_JSTACK_TOOL_NAME);
-        if (tool == null) {
-            usage(1);            // SA not available
-        }
-
-        // JStack tool also takes -m and -l arguments
-        if (mixed) {
-            args = prepend("-m", args);
-        }
-        if (locks) {
-            args = prepend("-l", args);
-        }
-
-        tool.run(args);
-    }
-
-
     // Attach to pid and perform a thread dump
     private static void runThreadDump(String pid, String args[]) throws Exception {
         VirtualMachine vm = null;
@@ -153,10 +104,6 @@ public class JStack {
             } else {
                 x.printStackTrace();
             }
-            if ((x instanceof AttachNotSupportedException) && isAgentToolPresent()) {
-                System.err.println("The -F option can be used when the target " +
-                    "process is not responding");
-            }
             System.exit(1);
         }
 
@@ -178,12 +125,35 @@ public class JStack {
         vm.detach();
     }
 
-    // return a new string array with arg as the first element
-    private static String[] prepend(String arg, String args[]) {
-        String[] newargs = new String[args.length+1];
-        newargs[0] = arg;
-        System.arraycopy(args, 0, newargs, 1, args.length);
-        return newargs;
+    private static void checkForUnsupportedOptions(String[] args) {
+        // Check arguments for -F, -m, and non-numeric value
+        // and warn the user that SA is not supported anymore
+
+        int paramCount = 0;
+
+        for (String s : args) {
+            if (s.equals("-F")) {
+                SAOptionError("-F option used");
+            }
+
+            if (s.equals("-m")) {
+                SAOptionError("-m option used");
+            }
+
+            if (! s.startsWith("-")) {
+                paramCount += 1;
+            }
+        }
+
+        if (paramCount > 1) {
+            SAOptionError("More than one non-option argument");
+        }
+    }
+
+    private static void SAOptionError(String msg) {
+        System.err.println("Error: " + msg);
+        System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jstack instead");
+        System.exit(1);
     }
 
     // print usage message
@@ -191,25 +161,8 @@ public class JStack {
         System.err.println("Usage:");
         System.err.println("    jstack [-l] <pid>");
         System.err.println("        (to connect to running process)");
-
-        if (isAgentToolPresent()) {
-            System.err.println("    jstack -F [-m] [-l] <pid>");
-            System.err.println("        (to connect to a hung process)");
-            System.err.println("    jstack [-m] [-l] <executable> <core>");
-            System.err.println("        (to connect to a core file)");
-            System.err.println("    jstack [-m] [-l] [server_id@]<remote server IP or hostname>");
-            System.err.println("        (to connect to a remote debug server)");
-        }
-
         System.err.println("");
         System.err.println("Options:");
-
-        if (isAgentToolPresent()) {
-            System.err.println("    -F  to force a thread dump. Use when jstack <pid> does not respond" +
-                " (process is hung)");
-            System.err.println("    -m  to print both java and native frames (mixed mode)");
-        }
-
         System.err.println("    -l  long listing. Prints additional information about locks");
         System.err.println("    -h or -help to print this help message");
         System.exit(exit);
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java
index bbae8bc44c8..5e6438d887a 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java
@@ -1534,7 +1534,6 @@ class Commands {
             PathSearchingVirtualMachine vm = (PathSearchingVirtualMachine)Env.vm();
             MessageOutput.println("base directory:", vm.baseDirectory());
             MessageOutput.println("classpath:", vm.classPath().toString());
-            MessageOutput.println("bootclasspath:", vm.bootClassPath().toString());
         } else {
             MessageOutput.println("The VM does not use paths");
         }
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java
index fe6dd070f0d..cd416ccf24e 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, 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
@@ -133,6 +133,10 @@ public class EventHandler implements Runnable {
             if (!vmDied) {
                 vmDisconnectEvent(event);
             }
+            /*
+             * Inform jdb command line processor that jdb is being shutdown. JDK-8154144.
+             */
+            ((TTY)notifier).setShuttingDown(true);
             Env.shutdown(shutdownMessageKey);
             return false;
         } else {
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java
index 0bd403af2b9..ee716a55dcb 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, 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
@@ -56,6 +56,16 @@ public class TTY implements EventNotifier {
      */
     private static final String progname = "jdb";
 
+    private volatile boolean shuttingDown = false;
+
+    public void setShuttingDown(boolean s) {
+       shuttingDown = s;
+    }
+
+    public boolean isShuttingDown() {
+        return shuttingDown;
+    }
+
     @Override
     public void vmStartEvent(VMStartEvent se)  {
         Thread.yield();  // fetch output
@@ -750,7 +760,13 @@ public class TTY implements EventNotifier {
             while (true) {
                 String ln = in.readLine();
                 if (ln == null) {
-                    MessageOutput.println("Input stream closed.");
+                    /*
+                     *  Jdb is being shutdown because debuggee exited, ignore any 'null'
+                     *  returned by readLine() during shutdown. JDK-8154144.
+                     */
+                    if (!isShuttingDown()) {
+                        MessageOutput.println("Input stream closed.");
+                    }
                     ln = "quit";
                 }
 
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java
index c412743c4b6..39e703d88b8 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java
@@ -74,7 +74,6 @@ public class TTYResources extends java.util.ListResourceBundle {
         {"Array element is not a method", "Array element is not a method"},
         {"Array index must be a integer type", "Array index must be a integer type"},
         {"base directory:", "base directory: {0}"},
-        {"bootclasspath:", "bootclasspath: {0}"},
         {"Breakpoint hit:", "Breakpoint hit: "},
         {"breakpoint", "breakpoint {0}"},
         {"Breakpoints set:", "Breakpoints set:"},
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_ja.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_ja.java
index 1cb6d231d50..b3562226398 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_ja.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_ja.java
@@ -74,7 +74,6 @@ public class TTYResources_ja extends java.util.ListResourceBundle {
         {"Array element is not a method", "\u914D\u5217\u8981\u7D20\u306F\u30E1\u30BD\u30C3\u30C9\u3067\u306F\u3042\u308A\u307E\u305B\u3093"},
         {"Array index must be a integer type", "\u914D\u5217\u306E\u6DFB\u3048\u5B57\u306F\u6574\u6570\u578B\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059"},
         {"base directory:", "\u30D9\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA: {0}"},
-        {"bootclasspath:", "\u30D6\u30FC\u30C8\u30FB\u30AF\u30E9\u30B9\u30D1\u30B9: {0}"},
         {"Breakpoint hit:", "\u30D2\u30C3\u30C8\u3057\u305F\u30D6\u30EC\u30FC\u30AF\u30DD\u30A4\u30F3\u30C8: "},
         {"breakpoint", "\u30D6\u30EC\u30FC\u30AF\u30DD\u30A4\u30F3\u30C8{0}"},
         {"Breakpoints set:", "\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u30D6\u30EC\u30FC\u30AF\u30DD\u30A4\u30F3\u30C8:"},
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_zh_CN.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_zh_CN.java
index 50790cb9d72..79dc9268da0 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_zh_CN.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_zh_CN.java
@@ -74,7 +74,6 @@ public class TTYResources_zh_CN extends java.util.ListResourceBundle {
         {"Array element is not a method", "\u6570\u7EC4\u5143\u7D20\u4E0D\u662F\u65B9\u6CD5"},
         {"Array index must be a integer type", "\u6570\u7EC4\u7D22\u5F15\u5FC5\u987B\u4E3A\u6574\u6570\u7C7B\u578B"},
         {"base directory:", "\u57FA\u76EE\u5F55: {0}"},
-        {"bootclasspath:", "\u5F15\u5BFC\u7C7B\u8DEF\u5F84: {0}"},
         {"Breakpoint hit:", "\u65AD\u70B9\u547D\u4E2D: "},
         {"breakpoint", "\u65AD\u70B9{0}"},
         {"Breakpoints set:", "\u65AD\u70B9\u96C6:"},
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java
index 47e743483e3..28c3dfbfa3c 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java
@@ -1439,7 +1439,7 @@ class VirtualMachineImpl extends MirrorImpl
    }
 
    public List<String> bootClassPath() {
-       return Arrays.asList(getClasspath().bootclasspaths);
+       return Collections.emptyList();
    }
 
    public String baseDirectory() {
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c
index 2718ad1e3a4..8e1639c5e2e 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c
@@ -126,7 +126,7 @@ classesForSignature(PacketInputStream *in, PacketOutputStream *out)
             int writtenCount = 0;
             int i;
 
-            for (i=0; i<classCount; i++) {
+            for (i = 0; i < classCount; i++) {
                 jclass clazz = theClasses[i];
                 jint status = classStatus(clazz);
                 char *candidate_signature = NULL;
@@ -141,7 +141,13 @@ classesForSignature(PacketInputStream *in, PacketOutputStream *out)
 
                 error = classSignature(clazz, &candidate_signature, NULL);
                 if (error != JVMTI_ERROR_NONE) {
-                    break;
+                  // Clazz become invalid since the time we get the class list
+                  // Skip this entry
+                  if (error == JVMTI_ERROR_INVALID_CLASS) {
+                    continue;
+                  }
+
+                  break;
                 }
 
                 if (strcmp(candidate_signature, signature) == 0) {
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c
index cd1cd2f7dc0..3baf486c233 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c
@@ -277,12 +277,14 @@ invoker_enableInvokeRequests(jthread thread)
 
     JDI_ASSERT(thread);
 
+    debugMonitorEnter(invokerLock);
     request = threadControl_getInvokeRequest(thread);
     if (request == NULL) {
         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request");
     }
 
     request->available = JNI_TRUE;
+    debugMonitorExit(invokerLock);
 }
 
 jvmtiError
@@ -738,30 +740,21 @@ invoker_completeInvokeRequest(jthread thread)
     }
 }
 
-jboolean
-invoker_isPending(jthread thread)
-{
-    InvokeRequest *request;
-
-    JDI_ASSERT(thread);
-    request = threadControl_getInvokeRequest(thread);
-    if (request == NULL) {
-        EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request");
-    }
-    return request->pending;
-}
-
 jboolean
 invoker_isEnabled(jthread thread)
 {
     InvokeRequest *request;
+    jboolean isEnabled;
 
     JDI_ASSERT(thread);
+    debugMonitorEnter(invokerLock);
     request = threadControl_getInvokeRequest(thread);
     if (request == NULL) {
         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request");
     }
-    return request->available;
+    isEnabled = request->available;
+    debugMonitorExit(invokerLock);
+    return isEnabled;
 }
 
 void
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.h
index 29ecdb5d59c..e004ce6ef8e 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.h
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.h
@@ -67,7 +67,6 @@ jvmtiError invoker_requestInvoke(jbyte invokeType, jbyte options, jint id,
 jboolean invoker_doInvoke(jthread thread);
 
 void invoker_completeInvokeRequest(jthread thread);
-jboolean invoker_isPending(jthread thread);
 jboolean invoker_isEnabled(jthread thread);
 void invoker_detach(InvokeRequest *request);
 
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java
index 92d7eb64fcf..e899d378963 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java
@@ -34,11 +34,9 @@ import java.util.Objects;
 import java.util.Set;
 import jdk.tools.jlink.internal.JlinkTask;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.PluginContext;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.builder.ImageBuilder;
-import jdk.tools.jlink.internal.PluginContextImpl;
 import jdk.tools.jlink.internal.PluginRepository;
 
 /**
@@ -71,7 +69,6 @@ public final class Jlink {
         private final List<Plugin> plugins;
         private final ImageBuilder imageBuilder;
         private final String lastSorterPluginName;
-        private final PluginContext pluginContext;
 
         /**
          * Empty plugins configuration.
@@ -86,7 +83,7 @@ public final class Jlink {
          * @param plugins List of plugins.
          */
         public PluginsConfiguration(List<Plugin> plugins) {
-            this(plugins, null, null, null);
+            this(plugins, null, null);
         }
 
         /**
@@ -101,28 +98,10 @@ public final class Jlink {
          */
         public PluginsConfiguration(List<Plugin> plugins,
                 ImageBuilder imageBuilder, String lastSorterPluginName) {
-            this(plugins, imageBuilder, lastSorterPluginName, null);
-        }
-
-        /**
-         * Plugins configuration with a last sorter and an ImageBuilder. No
-         * sorting can occur after the last sorter plugin. The ImageBuilder is
-         * in charge to layout the image content on disk.
-         *
-         * @param plugins List of transformer plugins.
-         * @param imageBuilder Image builder.
-         * @param lastSorterPluginName Name of last sorter plugin, no sorting
-         * @param ctx the plugin context
-         * can occur after it.
-         */
-        public PluginsConfiguration(List<Plugin> plugins,
-                ImageBuilder imageBuilder, String lastSorterPluginName,
-                PluginContext ctx) {
             this.plugins = plugins == null ? Collections.emptyList()
                     : plugins;
             this.imageBuilder = imageBuilder;
             this.lastSorterPluginName = lastSorterPluginName;
-            this.pluginContext = ctx != null? ctx : new PluginContextImpl();
         }
 
         /**
@@ -146,13 +125,6 @@ public final class Jlink {
             return lastSorterPluginName;
         }
 
-        /**
-         * @return the pluginContext
-         */
-        public PluginContext getPluginContext() {
-            return pluginContext;
-        }
-
         @Override
         public String toString() {
             StringBuilder builder = new StringBuilder();
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java
index a3943145c06..2c0620a99db 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -24,8 +25,6 @@
  */
 package jdk.tools.jlink.builder;
 
-import jdk.tools.jlink.plugin.ExecutableImage;
-import jdk.tools.jlink.plugin.PluginException;
 import java.io.BufferedOutputStream;
 import java.io.BufferedWriter;
 import java.io.ByteArrayInputStream;
@@ -47,8 +46,10 @@ import java.nio.file.StandardOpenOption;
 import java.nio.file.attribute.PosixFileAttributeView;
 import java.nio.file.attribute.PosixFilePermission;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Properties;
@@ -56,23 +57,40 @@ import java.util.Set;
 import jdk.tools.jlink.internal.BasicImageWriter;
 import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
 import jdk.tools.jlink.internal.plugins.FileCopierPlugin.SymImageFile;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.Module;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.PluginException;
 
 /**
  *
  * Default Image Builder. This builder creates the default runtime image layout.
  */
-public class DefaultImageBuilder implements ImageBuilder {
+public final class DefaultImageBuilder implements ImageBuilder {
 
     /**
      * The default java executable Image.
      */
-    static class DefaultExecutableImage extends ExecutableImage {
+    static final class DefaultExecutableImage implements ExecutableImage {
+
+        private final Path home;
+        private final List<String> args;
+        private final Set<String> modules;
 
         public DefaultExecutableImage(Path home, Set<String> modules) {
-            super(home, modules, createArgs(home));
+            this(home, modules, createArgs(home));
+        }
+
+        private DefaultExecutableImage(Path home, Set<String> modules,
+                List<String> args) {
+            Objects.requireNonNull(home);
+            Objects.requireNonNull(args);
+            if (!Files.exists(home)) {
+                throw new IllegalArgumentException("Invalid image home");
+            }
+            this.home = home;
+            this.modules = Collections.unmodifiableSet(modules);
+            this.args = Collections.unmodifiableList(args);
         }
 
         private static List<String> createArgs(Path home) {
@@ -83,6 +101,21 @@ public class DefaultImageBuilder implements ImageBuilder {
             return javaArgs;
         }
 
+        @Override
+        public Path getHome() {
+            return home;
+        }
+
+        @Override
+        public Set<String> getModules() {
+            return modules;
+        }
+
+        @Override
+        public List<String> getExecutionArgs() {
+            return args;
+        }
+
         @Override
         public void storeLaunchArgs(List<String> args) {
             try {
@@ -111,17 +144,19 @@ public class DefaultImageBuilder implements ImageBuilder {
         Files.createDirectories(mdir);
     }
 
-    private void storeFiles(Set<String> modules, Properties release) throws IOException {
+    private void storeFiles(Set<String> modules, Map<String, String> release) throws IOException {
         if (release != null) {
-            addModules(release, modules);
+            Properties props = new Properties();
+            props.putAll(release);
+            addModules(props, modules);
             File r = new File(root.toFile(), "release");
             try (FileOutputStream fo = new FileOutputStream(r)) {
-                release.store(fo, null);
+                props.store(fo, null);
             }
         }
     }
 
-    private void addModules(Properties release, Set<String> modules) throws IOException {
+    private void addModules(Properties props, Set<String> modules) throws IOException {
         StringBuilder builder = new StringBuilder();
         int i = 0;
         for (String m : modules) {
@@ -131,28 +166,32 @@ public class DefaultImageBuilder implements ImageBuilder {
             }
             i++;
         }
-        release.setProperty("MODULES", builder.toString());
+        props.setProperty("MODULES", builder.toString());
     }
 
     @Override
-    public void storeFiles(Pool files, Properties release) {
+    public void storeFiles(ModulePool files) {
         try {
-            for (ModuleData f : files.getContent()) {
-               if (!f.getType().equals(Pool.ModuleDataType.CLASS_OR_RESOURCE)) {
-                    accept(f);
+            files.entries().forEach(f -> {
+                if (!f.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
+                    try {
+                        accept(f);
+                    } catch (IOException ioExp) {
+                        throw new UncheckedIOException(ioExp);
+                    }
                 }
-            }
-            for (Module m : files.getModules()) {
+            });
+            files.modules().forEach(m -> {
                 // Only add modules that contain packages
                 if (!m.getAllPackages().isEmpty()) {
                     // Skip the fake module used by FileCopierPlugin when copying files.
                     if (m.getName().equals(FileCopierPlugin.FAKE_MODULE)) {
-                       continue;
+                        return;
                     }
                     modules.add(m.getName());
                 }
-            }
-            storeFiles(modules, release);
+            });
+            storeFiles(modules, files.getReleaseProperties());
 
             if (Files.getFileStore(root).supportsFileAttributeView(PosixFileAttributeView.class)) {
                 // launchers in the bin directory need execute permission
@@ -168,8 +207,8 @@ public class DefaultImageBuilder implements ImageBuilder {
                 Path lib = root.resolve("lib");
                 if (Files.isDirectory(lib)) {
                     Files.find(lib, 2, (path, attrs) -> {
-                        return path.getFileName().toString().equals("jspawnhelper") ||
-                               path.getFileName().toString().equals("jexec");
+                        return path.getFileName().toString().equals("jspawnhelper")
+                                || path.getFileName().toString().equals("jexec");
                     }).forEach(this::setExecutable);
                 }
             }
@@ -180,27 +219,23 @@ public class DefaultImageBuilder implements ImageBuilder {
         }
     }
 
-    @Override
-    public void storeFiles(Pool files) {
-        storeFiles(files, new Properties());
-    }
-
     /**
      * Generates launcher scripts.
+     *
      * @param imageContent The image content.
      * @param modules The set of modules that the runtime image contains.
      * @throws IOException
      */
-    protected void prepareApplicationFiles(Pool imageContent, Set<String> modules) throws IOException {
+    protected void prepareApplicationFiles(ModulePool imageContent, Set<String> modules) throws IOException {
         // generate launch scripts for the modules with a main class
         for (String module : modules) {
             String path = "/" + module + "/module-info.class";
-            ModuleData res = imageContent.get(path);
-            if (res == null) {
+            Optional<ModuleEntry> res = imageContent.findEntry(path);
+            if (!res.isPresent()) {
                 throw new IOException("module-info.class not found for " + module + " module");
             }
             Optional<String> mainClass;
-            ByteArrayInputStream stream = new ByteArrayInputStream(res.getBytes());
+            ByteArrayInputStream stream = new ByteArrayInputStream(res.get().getBytes());
             mainClass = ModuleDescriptor.read(stream).mainClass();
             if (mainClass.isPresent()) {
                 Path cmd = root.resolve("bin").resolve(module);
@@ -263,9 +298,9 @@ public class DefaultImageBuilder implements ImageBuilder {
         }
     }
 
-    private void accept(ModuleData file) throws IOException {
+    private void accept(ModuleEntry file) throws IOException {
         String fullPath = file.getPath();
-        String module = "/" + file.getModule()+ "/";
+        String module = "/" + file.getModule() + "/";
         String filename = fullPath.substring(module.length());
         // Remove radical native|config|...
         filename = filename.substring(filename.indexOf('/') + 1);
@@ -404,8 +439,7 @@ public class DefaultImageBuilder implements ImageBuilder {
 
     public static ExecutableImage getExecutableImage(Path root) {
         if (Files.exists(root.resolve("bin").resolve(getJavaProcessName()))) {
-            return new DefaultImageBuilder.DefaultExecutableImage(root,
-                    retrieveModules(root));
+            return new DefaultExecutableImage(root, retrieveModules(root));
         }
         return null;
     }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java
index dc0bf71c535..10cea85d363 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java
@@ -29,7 +29,7 @@ import java.util.Properties;
 
 import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModulePool;
 
 /**
  * Implement this interface to develop your own image layout. First the jimage
@@ -45,7 +45,7 @@ public interface ImageBuilder {
      * @param release the release properties
      * @throws PluginException
      */
-    public default void storeFiles(Pool content, Properties release) {
+    public default void storeFiles(ModulePool content, Properties release) {
         storeFiles(content);
     }
 
@@ -55,7 +55,7 @@ public interface ImageBuilder {
      * @param content Pool of module content.
      * @throws PluginException
      */
-    public default void storeFiles(Pool content) {
+    public default void storeFiles(ModulePool content) {
         throw new UnsupportedOperationException("storeFiles");
     }
 
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java
index e0347e52a21..f765be2919b 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java
@@ -44,12 +44,11 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import jdk.tools.jlink.internal.Archive.Entry;
 import jdk.tools.jlink.internal.Archive.Entry.EntryType;
-import jdk.tools.jlink.internal.PoolImpl.CompressedModuleData;
+import jdk.tools.jlink.internal.ModulePoolImpl.CompressedModuleData;
 import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ModuleEntry;
 
 /**
  * An image (native endian.)
@@ -145,7 +144,7 @@ public final class ImageFileCreator {
                                     }));
             ByteOrder order = ByteOrder.nativeOrder();
             BasicImageWriter writer = new BasicImageWriter(order);
-            PoolImpl pool = createPools(archives, entriesForModule, order, writer);
+            ModulePoolImpl pool = createPools(archives, entriesForModule, order, writer);
             try (OutputStream fos = Files.newOutputStream(jimageFile);
                     BufferedOutputStream bos = new BufferedOutputStream(fos);
                     DataOutputStream out = new DataOutputStream(bos)) {
@@ -163,9 +162,9 @@ public final class ImageFileCreator {
             ByteOrder byteOrder)
             throws IOException {
         BasicImageWriter writer = new BasicImageWriter(byteOrder);
-        PoolImpl allContent = createPools(archives,
+        ModulePoolImpl allContent = createPools(archives,
                 entriesForModule, byteOrder, writer);
-        PoolImpl result = generateJImage(allContent,
+        ModulePoolImpl result = generateJImage(allContent,
              writer, plugins, plugins.getJImageFileOutputStream());
 
         //Handle files.
@@ -176,12 +175,12 @@ public final class ImageFileCreator {
         }
     }
 
-    private static PoolImpl generateJImage(PoolImpl allContent,
+    private static ModulePoolImpl generateJImage(ModulePoolImpl allContent,
             BasicImageWriter writer,
             ImagePluginStack pluginSupport,
             DataOutputStream out
     ) throws IOException {
-        PoolImpl resultResources;
+        ModulePoolImpl resultResources;
         try {
             resultResources = pluginSupport.visitResources(allContent);
         } catch (PluginException pe) {
@@ -190,14 +189,14 @@ public final class ImageFileCreator {
             throw new IOException(ex);
         }
         Set<String> duplicates = new HashSet<>();
-        long offset = 0;
+        long[] offset = new long[1];
 
-        List<ModuleData> content = new ArrayList<>();
+        List<ModuleEntry> content = new ArrayList<>();
         List<String> paths = new ArrayList<>();
                  // the order of traversing the resources and the order of
         // the module content being written must be the same
-        for (ModuleData res : resultResources.getContent()) {
-            if (res.getType().equals(ModuleDataType.CLASS_OR_RESOURCE)) {
+        resultResources.entries().forEach(res -> {
+            if (res.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
                 String path = res.getPath();
                 content.add(res);
                 long uncompressedSize = res.getLength();
@@ -216,24 +215,24 @@ public final class ImageFileCreator {
                     // TODO Need to hang bytes on resource and write
                     // from resource not zip.
                     // Skipping resource throws off writing from zip.
-                    offset += onFileSize;
-                    continue;
+                    offset[0] += onFileSize;
+                    return;
                 }
                 duplicates.add(path);
-                writer.addLocation(path, offset, compressedSize, uncompressedSize);
+                writer.addLocation(path, offset[0], compressedSize, uncompressedSize);
                 paths.add(path);
-                offset += onFileSize;
+                offset[0] += onFileSize;
             }
-        }
+        });
 
-        ImageResourcesTree tree = new ImageResourcesTree(offset, writer, paths);
+        ImageResourcesTree tree = new ImageResourcesTree(offset[0], writer, paths);
 
         // write header and indices
         byte[] bytes = writer.getBytes();
         out.write(bytes, 0, bytes.length);
 
         // write module content
-        for (ModuleData res : content) {
+        for (ModuleEntry res : content) {
             byte[] buf = res.getBytes();
             out.write(buf, 0, buf.length);
         }
@@ -245,26 +244,26 @@ public final class ImageFileCreator {
         return resultResources;
     }
 
-    private static Pool.ModuleDataType mapImageFileType(EntryType type) {
+    private static ModuleEntry.Type mapImageFileType(EntryType type) {
         switch(type) {
             case CONFIG: {
-                return Pool.ModuleDataType.CONFIG;
+                return ModuleEntry.Type.CONFIG;
             }
             case NATIVE_CMD: {
-                return Pool.ModuleDataType.NATIVE_CMD;
+                return ModuleEntry.Type.NATIVE_CMD;
             }
             case NATIVE_LIB: {
-                return Pool.ModuleDataType.NATIVE_LIB;
+                return ModuleEntry.Type.NATIVE_LIB;
             }
         }
         return null;
     }
 
-    private static PoolImpl createPools(Set<Archive> archives,
+    private static ModulePoolImpl createPools(Set<Archive> archives,
             Map<String, List<Entry>> entriesForModule,
             ByteOrder byteOrder,
             BasicImageWriter writer) throws IOException {
-        PoolImpl resources = new PoolImpl(byteOrder, new StringTable() {
+        ModulePoolImpl resources = new ModulePoolImpl(byteOrder, new StringTable() {
 
             @Override
             public int addString(String str) {
@@ -291,7 +290,7 @@ public final class ImageFileCreator {
                             path = "/" + mn + "/" + path;
                         }
                         try {
-                            resources.add(Pool.newResource(path, bytes));
+                            resources.add(ModuleEntry.create(path, bytes));
                         } catch (Exception ex) {
                             throw new IOException(ex);
                         }
@@ -300,7 +299,7 @@ public final class ImageFileCreator {
                     try {
                         // Entry.path() contains the kind of file native, conf, bin, ...
                         // Keep it to avoid naming conflict (eg: native/jvm.cfg and config/jvm.cfg
-                        resources.add(Pool.newImageFile(mn,
+                        resources.add(ModuleEntry.create(mn,
                                 "/" + mn + "/" + entry.path(), mapImageFileType(entry.type()),
                                 entry.stream(), entry.size()));
                     } catch (Exception ex) {
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java
index 7bd631a8c72..08ff3cb7e64 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java
@@ -28,22 +28,17 @@ import java.io.DataOutputStream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Properties;
 import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.builder.ImageBuilder;
 import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.PluginContext;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Plugin.CATEGORY;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Plugin.Category;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.PostProcessorPlugin;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
@@ -52,17 +47,18 @@ import jdk.tools.jlink.plugin.TransformerPlugin;
  */
 public final class ImagePluginConfiguration {
 
-    private static final List<Plugin.CATEGORY> CATEGORIES_ORDER = new ArrayList<>();
+    private static final List<Plugin.Category> CATEGORIES_ORDER = new ArrayList<>();
 
     static {
-        CATEGORIES_ORDER.add(Plugin.CATEGORY.FILTER);
-        CATEGORIES_ORDER.add(Plugin.CATEGORY.TRANSFORMER);
-        CATEGORIES_ORDER.add(Plugin.CATEGORY.MODULEINFO_TRANSFORMER);
-        CATEGORIES_ORDER.add(Plugin.CATEGORY.SORTER);
-        CATEGORIES_ORDER.add(Plugin.CATEGORY.COMPRESSOR);
-        CATEGORIES_ORDER.add(Plugin.CATEGORY.VERIFIER);
-        CATEGORIES_ORDER.add(Plugin.CATEGORY.PROCESSOR);
-        CATEGORIES_ORDER.add(Plugin.CATEGORY.PACKAGER);
+        CATEGORIES_ORDER.add(Plugin.Category.FILTER);
+        CATEGORIES_ORDER.add(Plugin.Category.TRANSFORMER);
+        CATEGORIES_ORDER.add(Plugin.Category.MODULEINFO_TRANSFORMER);
+        CATEGORIES_ORDER.add(Plugin.Category.SORTER);
+        CATEGORIES_ORDER.add(Plugin.Category.COMPRESSOR);
+        CATEGORIES_ORDER.add(Plugin.Category.METAINFO_ADDER);
+        CATEGORIES_ORDER.add(Plugin.Category.VERIFIER);
+        CATEGORIES_ORDER.add(Plugin.Category.PROCESSOR);
+        CATEGORIES_ORDER.add(Plugin.Category.PACKAGER);
     }
 
     private ImagePluginConfiguration() {
@@ -76,8 +72,8 @@ public final class ImagePluginConfiguration {
         if (pluginsConfiguration == null) {
             return new ImagePluginStack();
         }
-        Map<Plugin.CATEGORY, List<Plugin>> plugins = new LinkedHashMap<>();
-        for (Plugin.CATEGORY cat : CATEGORIES_ORDER) {
+        Map<Plugin.Category, List<Plugin>> plugins = new LinkedHashMap<>();
+        for (Plugin.Category cat : CATEGORIES_ORDER) {
             plugins.put(cat, new ArrayList<>());
         }
 
@@ -89,7 +85,7 @@ public final class ImagePluginConfiguration {
                         + " added more than once to stack ");
             }
             seen.add(plug.getName());
-            CATEGORY category = Utils.getCategory(plug);
+            Category category = Utils.getCategory(plug);
             if (category == null) {
                 throw new PluginException("Invalid category for "
                         + plug.getName());
@@ -100,10 +96,10 @@ public final class ImagePluginConfiguration {
 
         List<TransformerPlugin> transformerPlugins = new ArrayList<>();
         List<PostProcessorPlugin> postProcessingPlugins = new ArrayList<>();
-        for (Entry<Plugin.CATEGORY, List<Plugin>> entry : plugins.entrySet()) {
+        for (Entry<Plugin.Category, List<Plugin>> entry : plugins.entrySet()) {
             // Sort according to plugin constraints
             List<Plugin> orderedPlugins = PluginOrderingGraph.sort(entry.getValue());
-            CATEGORY category = entry.getKey();
+            Category category = entry.getKey();
             for (Plugin p : orderedPlugins) {
                 if (Utils.isPostProcessor(category)) {
                     @SuppressWarnings("unchecked")
@@ -143,14 +139,13 @@ public final class ImagePluginConfiguration {
                 }
 
                 @Override
-                public void storeFiles(Pool files) {
+                public void storeFiles(ModulePool files) {
                     throw new PluginException("No directory setup to store files");
                 }
             };
         }
 
-        PluginContext ctxt = pluginsConfiguration.getPluginContext();
         return new ImagePluginStack(builder, transformerPlugins,
-                lastSorter, postProcessingPlugins, ctxt);
+                lastSorter, postProcessingPlugins);
     }
 }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java
index 6a5db82ccdf..24b8aeb632d 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java
@@ -37,20 +37,21 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Properties;
+import java.util.Optional;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import jdk.internal.jimage.decompressor.Decompressor;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.PluginContext;
 import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.builder.ImageBuilder;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.LinkModule;
+import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.PostProcessorPlugin;
 
 /**
@@ -64,9 +65,9 @@ public final class ImagePluginStack {
         ExecutableImage retrieve(ImagePluginStack stack) throws IOException;
     }
 
-    public static final class OrderedResourcePool extends PoolImpl {
+    public static final class OrderedResourcePool extends ModulePoolImpl {
 
-        private final List<ModuleData> orderedList = new ArrayList<>();
+        private final List<ModuleEntry> orderedList = new ArrayList<>();
 
         public OrderedResourcePool(ByteOrder order, StringTable table) {
             super(order, table);
@@ -78,22 +79,22 @@ public final class ImagePluginStack {
          * @param resource The Resource to add.
          */
         @Override
-        public void add(ModuleData resource) {
+        public void add(ModuleEntry resource) {
             super.add(resource);
             orderedList.add(resource);
         }
 
-        List<ModuleData> getOrderedList() {
+        List<ModuleEntry> getOrderedList() {
             return Collections.unmodifiableList(orderedList);
         }
     }
 
-    private final static class CheckOrderResourcePool extends PoolImpl {
+    private final static class CheckOrderResourcePool extends ModulePoolImpl {
 
-        private final List<ModuleData> orderedList;
+        private final List<ModuleEntry> orderedList;
         private int currentIndex;
 
-        public CheckOrderResourcePool(ByteOrder order, List<ModuleData> orderedList, StringTable table) {
+        public CheckOrderResourcePool(ByteOrder order, List<ModuleEntry> orderedList, StringTable table) {
             super(order, table);
             this.orderedList = orderedList;
         }
@@ -104,8 +105,8 @@ public final class ImagePluginStack {
          * @param resource The Resource to add.
          */
         @Override
-        public void add(ModuleData resource) {
-            ModuleData ordered = orderedList.get(currentIndex);
+        public void add(ModuleEntry resource) {
+            ModuleEntry ordered = orderedList.get(currentIndex);
             if (!resource.equals(ordered)) {
                 throw new PluginException("Resource " + resource.getPath() + " not in the right order");
             }
@@ -166,26 +167,16 @@ public final class ImagePluginStack {
     private final List<ResourcePrevisitor> resourcePrevisitors = new ArrayList<>();
 
     private final ImageBuilder imageBuilder;
-    private final Properties release;
 
     public ImagePluginStack() {
         this(null, Collections.emptyList(), null,
-                Collections.emptyList(), null);
+                Collections.emptyList());
     }
 
     public ImagePluginStack(ImageBuilder imageBuilder,
             List<TransformerPlugin> contentPlugins,
             Plugin lastSorter,
             List<PostProcessorPlugin> postprocessingPlugins) {
-        this(imageBuilder, contentPlugins, lastSorter,
-            postprocessingPlugins, null);
-    }
-
-    public ImagePluginStack(ImageBuilder imageBuilder,
-            List<TransformerPlugin> contentPlugins,
-            Plugin lastSorter,
-            List<PostProcessorPlugin> postprocessingPlugins,
-            PluginContext ctxt) {
         Objects.requireNonNull(contentPlugins);
         this.lastSorter = lastSorter;
         for (TransformerPlugin p : contentPlugins) {
@@ -200,7 +191,6 @@ public final class ImagePluginStack {
             this.postProcessingPlugins.add(p);
         }
         this.imageBuilder = imageBuilder;
-        this.release = ctxt != null? ctxt.getReleaseProperties() : new Properties();
     }
 
     public void operate(ImageProvider provider) throws Exception {
@@ -231,12 +221,12 @@ public final class ImagePluginStack {
      * @return The result of the visit.
      * @throws IOException
      */
-    public PoolImpl visitResources(PoolImpl resources)
+    public ModulePoolImpl visitResources(ModulePoolImpl resources)
             throws Exception {
         Objects.requireNonNull(resources);
         resources.setReadOnly();
         if (resources.isEmpty()) {
-            return new PoolImpl(resources.getByteOrder(),
+            return new ModulePoolImpl(resources.getByteOrder(),
                     resources.getStringTable());
         }
         PreVisitStrings previsit = new PreVisitStrings();
@@ -250,11 +240,11 @@ public final class ImagePluginStack {
             resources.getStringTable().addString(s);
         }
 
-        PoolImpl current = resources;
-        List<Pool.ModuleData> frozenOrder = null;
+        ModulePoolImpl current = resources;
+        List<ModuleEntry> frozenOrder = null;
         for (TransformerPlugin p : contentPlugins) {
             current.setReadOnly();
-            PoolImpl output = null;
+            ModulePoolImpl output = null;
             if (p == lastSorter) {
                 if (frozenOrder != null) {
                     throw new Exception("Order of resources is already frozen. Plugin "
@@ -268,7 +258,7 @@ public final class ImagePluginStack {
                     output = new CheckOrderResourcePool(current.getByteOrder(),
                             frozenOrder, resources.getStringTable());
                 } else {
-                    output = new PoolImpl(current.getByteOrder(),
+                    output = new ModulePoolImpl(current.getByteOrder(),
                             resources.getStringTable());
                 }
             }
@@ -287,15 +277,15 @@ public final class ImagePluginStack {
     }
 
     /**
-     * This pool wrap the original pool and automatically uncompress moduledata
+     * This pool wrap the original pool and automatically uncompress ModuleEntry
      * if needed.
      */
-    private class LastPool extends Pool {
-        private class LastModule implements Module {
+    private class LastPool implements ModulePool {
+        private class LastModule implements LinkModule {
 
-            private final Module module;
+            final LinkModule module;
 
-            LastModule(Module module) {
+            LastModule(LinkModule module) {
                 this.module = module;
             }
 
@@ -305,9 +295,9 @@ public final class ImagePluginStack {
             }
 
             @Override
-            public ModuleData get(String path) {
-                ModuleData d = module.get(path);
-                return getUncompressed(d);
+            public Optional<ModuleEntry> findEntry(String path) {
+                Optional<ModuleEntry> d = module.findEntry(path);
+                return d.isPresent()? Optional.of(getUncompressed(d.get())) : Optional.empty();
             }
 
             @Override
@@ -316,7 +306,7 @@ public final class ImagePluginStack {
             }
 
             @Override
-            public void add(ModuleData data) {
+            public void add(ModuleEntry data) {
                 throw new PluginException("pool is readonly");
             }
 
@@ -331,19 +321,24 @@ public final class ImagePluginStack {
             }
 
             @Override
-            public Collection<ModuleData> getContent() {
-                List<ModuleData> lst = new ArrayList<>();
-                for(ModuleData md : module.getContent()) {
+            public Stream<ModuleEntry> entries() {
+                List<ModuleEntry> lst = new ArrayList<>();
+                module.entries().forEach(md -> {
                     lst.add(getUncompressed(md));
-                }
-                return lst;
+                });
+                return lst.stream();
+            }
+
+            @Override
+            public int getEntryCount() {
+                return module.getEntryCount();
             }
         }
-        private final PoolImpl pool;
+        private final ModulePoolImpl pool;
         Decompressor decompressor = new Decompressor();
-        Collection<ModuleData> content;
+        Collection<ModuleEntry> content;
 
-        LastPool(PoolImpl pool) {
+        LastPool(ModulePoolImpl pool) {
             this.pool = pool;
         }
 
@@ -353,23 +348,14 @@ public final class ImagePluginStack {
         }
 
         @Override
-        public void add(ModuleData resource) {
+        public void add(ModuleEntry resource) {
             throw new PluginException("pool is readonly");
         }
 
-        /**
-         * Retrieves the module of the provided name.
-         *
-         * @param name The module name
-         * @return the module or null if the module doesn't exist.
-         */
         @Override
-        public Module getModule(String name) {
-            Module module = pool.getModule(name);
-            if (module != null) {
-                module = new LastModule(module);
-            }
-            return module;
+        public Optional<LinkModule> findModule(String name) {
+            Optional<LinkModule> module = pool.findModule(name);
+            return module.isPresent()? Optional.of(new LastModule(module.get())) : Optional.empty();
         }
 
         /**
@@ -378,45 +364,55 @@ public final class ImagePluginStack {
          * @return The collection of modules.
          */
         @Override
-        public Collection<Module> getModules() {
-            List<Module> modules = new ArrayList<>();
-            for (Module m : pool.getModules()) {
+        public Stream<? extends LinkModule> modules() {
+            List<LinkModule> modules = new ArrayList<>();
+            pool.modules().forEach(m -> {
                 modules.add(new LastModule(m));
-            }
-            return modules;
+            });
+            return modules.stream();
+        }
+
+        @Override
+        public int getModuleCount() {
+            return pool.getModuleCount();
         }
 
         /**
          * Get all resources contained in this pool instance.
          *
-         * @return The collection of resources;
+         * @return The stream of resources;
          */
         @Override
-        public Collection<ModuleData> getContent() {
+        public Stream<? extends ModuleEntry> entries() {
             if (content == null) {
                 content = new ArrayList<>();
-                for (ModuleData md : pool.getContent()) {
+                pool.entries().forEach(md -> {
                     content.add(getUncompressed(md));
-                }
+                });
             }
-            return content;
+            return content.stream();
+        }
+
+        @Override
+        public int getEntryCount() {
+            return pool.getEntryCount();
         }
 
         /**
          * Get the resource for the passed path.
          *
          * @param path A resource path
-         * @return A Resource instance or null if the resource is not found
+         * @return A Resource instance if the resource is found
          */
         @Override
-        public ModuleData get(String path) {
+        public Optional<ModuleEntry> findEntry(String path) {
             Objects.requireNonNull(path);
-            Pool.ModuleData res = pool.get(path);
-            return getUncompressed(res);
+            Optional<ModuleEntry> res = pool.findEntry(path);
+            return res.isPresent()? Optional.of(getUncompressed(res.get())) : Optional.empty();
         }
 
         @Override
-        public boolean contains(ModuleData res) {
+        public boolean contains(ModuleEntry res) {
             return pool.contains(res);
         }
 
@@ -426,8 +422,8 @@ public final class ImagePluginStack {
         }
 
         @Override
-        public void visit(Visitor visitor, Pool output) {
-            pool.visit(visitor, output);
+        public void transformAndCopy(Function<ModuleEntry, ModuleEntry> visitor, ModulePool output) {
+            pool.transformAndCopy(visitor, output);
         }
 
         @Override
@@ -435,14 +431,19 @@ public final class ImagePluginStack {
             return pool.getByteOrder();
         }
 
-        private ModuleData getUncompressed(ModuleData res) {
+        @Override
+        public Map<String, String> getReleaseProperties() {
+            return Collections.unmodifiableMap(pool.getReleaseProperties());
+        }
+
+        private ModuleEntry getUncompressed(ModuleEntry res) {
             if (res != null) {
-                if (res instanceof PoolImpl.CompressedModuleData) {
+                if (res instanceof ModulePoolImpl.CompressedModuleData) {
                     try {
                         byte[] bytes = decompressor.decompressResource(getByteOrder(),
                                 (int offset) -> pool.getStringTable().getString(offset),
                                 res.getBytes());
-                        res = Pool.newResource(res.getPath(),
+                        res = ModuleEntry.create(res.getPath(),
                                 new ByteArrayInputStream(bytes),
                                 bytes.length);
                     } catch (IOException ex) {
@@ -462,20 +463,24 @@ public final class ImagePluginStack {
      * @param writer
      * @throws java.lang.Exception
      */
-    public void storeFiles(PoolImpl original, PoolImpl transformed,
+    public void storeFiles(ModulePoolImpl original, ModulePoolImpl transformed,
             BasicImageWriter writer)
             throws Exception {
         Objects.requireNonNull(original);
-        try {
-            // fill release information available from transformed "java.base" module!
-            ModuleDescriptor desc = transformed.getModule("java.base").getDescriptor();
-            desc.osName().ifPresent(s -> release.put("OS_NAME", s));
-            desc.osVersion().ifPresent(s -> release.put("OS_VERSION", s));
-            desc.osArch().ifPresent(s -> release.put("OS_ARCH", s));
-        } catch (Exception ignored) {
-        }
+        Objects.requireNonNull(transformed);
+        Optional<LinkModule> javaBase = transformed.findModule("java.base");
+        javaBase.ifPresent(mod -> {
+            try {
+                Map<String, String> release = transformed.getReleaseProperties();
+                // fill release information available from transformed "java.base" module!
+                ModuleDescriptor desc = mod.getDescriptor();
+                desc.osName().ifPresent(s -> release.put("OS_NAME", s));
+                desc.osVersion().ifPresent(s -> release.put("OS_VERSION", s));
+                desc.osArch().ifPresent(s -> release.put("OS_ARCH", s));
+            } catch (Exception ignored) {}
+        });
 
-        imageBuilder.storeFiles(new LastPool(transformed), release);
+        imageBuilder.storeFiles(new LastPool(transformed));
     }
 
     public ExecutableImage getExecutableImage() throws IOException {
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryImpl.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryImpl.java
new file mode 100644
index 00000000000..30c07a3b2d7
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryImpl.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.util.Objects;
+import jdk.tools.jlink.plugin.ModuleEntry;
+
+/**
+ * A LinkModuleEntry is the elementary unit of data inside an image. It is
+ * generally a file. e.g.: a java class file, a resource file, a shared library,
+ * ...
+ * <br>
+ * A LinkModuleEntry is identified by a path of the form:
+ * <ul>
+ * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
+ * name}</li>
+ * <li>For other files (shared lib, launchers, config, ...):/{module name}/
+ * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}</li>
+ * </ul>
+ */
+public class ModuleEntryImpl implements ModuleEntry {
+
+    private final Type type;
+    private final String path;
+    private final String module;
+    private final long length;
+    private final InputStream stream;
+    private byte[] buffer;
+
+    /**
+     * Create a new LinkModuleEntry.
+     *
+     * @param module The module name.
+     * @param path The data path identifier.
+     * @param type The data type.
+     * @param stream The data content stream.
+     * @param length The stream length.
+     */
+    public ModuleEntryImpl(String module, String path, Type type, InputStream stream, long length) {
+        Objects.requireNonNull(module);
+        Objects.requireNonNull(path);
+        Objects.requireNonNull(type);
+        Objects.requireNonNull(stream);
+        this.path = path;
+        this.type = type;
+        this.module = module;
+        this.stream = stream;
+        this.length = length;
+    }
+
+    /**
+     * The LinkModuleEntry module name.
+     *
+     * @return The module name.
+     */
+    @Override
+    public final String getModule() {
+        return module;
+    }
+
+    /**
+     * The LinkModuleEntry path.
+     *
+     * @return The module path.
+     */
+    @Override
+    public final String getPath() {
+        return path;
+    }
+
+    /**
+     * The LinkModuleEntry's type.
+     *
+     * @return The data type.
+     */
+    @Override
+    public final Type getType() {
+        return type;
+    }
+
+    /**
+     * The LinkModuleEntry content as an array of byte.
+     *
+     * @return An Array of bytes.
+     */
+    @Override
+    public byte[] getBytes() {
+        if (buffer == null) {
+            try (InputStream is = stream) {
+                buffer = is.readAllBytes();
+            } catch (IOException ex) {
+                throw new UncheckedIOException(ex);
+            }
+        }
+        return buffer;
+    }
+
+    /**
+     * The LinkModuleEntry content length.
+     *
+     * @return The length.
+     */
+    @Override
+    public long getLength() {
+        return length;
+    }
+
+    /**
+     * The LinkModuleEntry stream.
+     *
+     * @return The module data stream.
+     */
+    @Override
+    public InputStream stream() {
+        return stream;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 7;
+        hash = 89 * hash + Objects.hashCode(this.path);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof ModuleEntryImpl)) {
+            return false;
+        }
+        ModuleEntryImpl f = (ModuleEntryImpl) other;
+        return f.path.equals(path);
+    }
+
+    @Override
+    public String toString() {
+        return getPath();
+    }
+}
\ No newline at end of file
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java
new file mode 100644
index 00000000000..a572fa48637
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.lang.module.ModuleDescriptor;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import jdk.internal.jimage.decompressor.CompressedResourceHeader;
+import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.LinkModule;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
+
+/**
+ * Pool of module data.
+ */
+public class ModulePoolImpl implements ModulePool {
+
+    private class ModuleImpl implements LinkModule {
+
+        final Map<String, ModuleEntry> moduleContent = new LinkedHashMap<>();
+        private ModuleDescriptor descriptor;
+        final String name;
+
+        private ModuleImpl(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public Optional<ModuleEntry> findEntry(String path) {
+            if (!path.startsWith("/")) {
+                path = "/" + path;
+            }
+            if (!path.startsWith("/" + name)) {
+                path = "/" + name + path;
+            }
+            return Optional.ofNullable(moduleContent.get(path));
+        }
+
+        @Override
+        public ModuleDescriptor getDescriptor() {
+            if (descriptor == null) {
+                String p = "/" + name + "/module-info.class";
+                Optional<ModuleEntry> content = findEntry(p);
+                if (!content.isPresent()) {
+                    throw new PluginException("No module-info for " + name
+                            + " module");
+                }
+                ByteBuffer bb = ByteBuffer.wrap(content.get().getBytes());
+                descriptor = ModuleDescriptor.read(bb);
+            }
+            return descriptor;
+        }
+
+        @Override
+        public void add(ModuleEntry data) {
+            if (isReadOnly()) {
+                throw new PluginException("LinkConfiguration is readonly");
+            }
+            Objects.requireNonNull(data);
+            if (!data.getModule().equals(name)) {
+                throw new PluginException("Can't add resource " + data.getPath()
+                        + " to module " + name);
+            }
+            ModulePoolImpl.this.add(data);
+        }
+
+        @Override
+        public Set<String> getAllPackages() {
+            Set<String> pkgs = new HashSet<>();
+            moduleContent.values().stream().filter(m -> m.getType().
+                    equals(ModuleEntry.Type.CLASS_OR_RESOURCE)).forEach(res -> {
+                // Module metadata only contains packages with .class files
+                if (ImageFileCreator.isClassPackage(res.getPath())) {
+                    String[] split = ImageFileCreator.splitPath(res.getPath());
+                    String pkg = split[1];
+                    if (pkg != null && !pkg.isEmpty()) {
+                        pkgs.add(pkg);
+                    }
+                }
+            });
+            return pkgs;
+        }
+
+        @Override
+        public String toString() {
+            return getName();
+        }
+
+        @Override
+        public Stream<? extends ModuleEntry> entries() {
+            return moduleContent.values().stream();
+        }
+
+        @Override
+        public int getEntryCount() {
+            return moduleContent.values().size();
+        }
+    }
+
+    private final Map<String, ModuleEntry> resources = new LinkedHashMap<>();
+    private final Map<String, ModuleImpl> modules = new LinkedHashMap<>();
+    private final ModuleImpl fileCopierModule = new ModuleImpl(FileCopierPlugin.FAKE_MODULE);
+    private Map<String, String> releaseProps = new HashMap<>();
+
+    private final ByteOrder order;
+
+    private boolean isReadOnly;
+    private final StringTable table;
+
+    public ModulePoolImpl() {
+        this(ByteOrder.nativeOrder());
+    }
+
+    public ModulePoolImpl(ByteOrder order) {
+        this(order, new StringTable() {
+
+            @Override
+            public int addString(String str) {
+                return -1;
+            }
+
+            @Override
+            public String getString(int id) {
+                return null;
+            }
+        });
+    }
+
+    public ModulePoolImpl(ByteOrder order, StringTable table) {
+        this.order = order;
+        this.table = table;
+    }
+
+    /**
+     * Add a ModuleEntry.
+     *
+     * @param data The ModuleEntry to add.
+     */
+    @Override
+    public void add(ModuleEntry data) {
+        if (isReadOnly()) {
+            throw new PluginException("LinkConfiguration is readonly");
+        }
+        Objects.requireNonNull(data);
+        if (resources.get(data.getPath()) != null) {
+            throw new PluginException("Resource " + data.getPath()
+                    + " already present");
+        }
+        String modulename = data.getModule();
+        ModuleImpl m = modules.get(modulename);
+        // ## TODO: FileCopierPlugin should not add content to a module
+        // FAKE_MODULE is not really a module to be added in the image
+        if (FileCopierPlugin.FAKE_MODULE.equals(modulename)) {
+            m = fileCopierModule;
+        }
+        if (m == null) {
+            m = new ModuleImpl(modulename);
+            modules.put(modulename, m);
+        }
+        resources.put(data.getPath(), data);
+        m.moduleContent.put(data.getPath(), data);
+    }
+
+    /**
+     * Retrieves the module for the provided name.
+     *
+     * @param name The module name
+     * @return the module of matching name, if found
+     */
+    @Override
+    public Optional<LinkModule> findModule(String name) {
+        Objects.requireNonNull(name);
+        return Optional.ofNullable(modules.get(name));
+    }
+
+    /**
+     * The stream of modules contained in this LinkConfiguration.
+     *
+     * @return The stream of modules.
+     */
+    @Override
+    public Stream<? extends LinkModule> modules() {
+        return modules.values().stream();
+    }
+
+    /**
+     * Return the number of LinkModule count in this LinkConfiguration.
+     *
+     * @return the module count.
+     */
+    @Override
+    public int getModuleCount() {
+        return modules.size();
+    }
+
+    /**
+     * Get all ModuleEntry contained in this LinkConfiguration instance.
+     *
+     * @return The stream of LinkModuleEntries.
+     */
+    @Override
+    public Stream<? extends ModuleEntry> entries() {
+        return resources.values().stream();
+    }
+
+    /**
+     * Return the number of ModuleEntry count in this LinkConfiguration.
+     *
+     * @return the entry count.
+     */
+    @Override
+    public int getEntryCount() {
+        return resources.values().size();
+    }
+
+    /**
+     * Get the ModuleEntry for the passed path.
+     *
+     * @param path A data path
+     * @return A ModuleEntry instance or null if the data is not found
+     */
+    @Override
+    public Optional<ModuleEntry> findEntry(String path) {
+        Objects.requireNonNull(path);
+        return Optional.ofNullable(resources.get(path));
+    }
+
+    /**
+     * Check if the LinkConfiguration contains the given ModuleEntry.
+     *
+     * @param data The module data to check existence for.
+     * @return The module data or null if not found.
+     */
+    @Override
+    public boolean contains(ModuleEntry data) {
+        Objects.requireNonNull(data);
+        return findEntry(data.getPath()).isPresent();
+    }
+
+    /**
+     * Check if the LinkConfiguration contains some content at all.
+     *
+     * @return True, no content, false otherwise.
+     */
+    @Override
+    public boolean isEmpty() {
+        return resources.isEmpty();
+    }
+
+    /**
+     * Visit each ModuleEntry in this LinkConfiguration to transform it and
+     * copy the transformed ModuleEntry to the output LinkConfiguration.
+     *
+     * @param transform The function called for each ModuleEntry found in
+     * the LinkConfiguration. The transform function should return a
+     * ModuleEntry instance which will be added to the output or it should
+     * return null if the passed ModuleEntry is to be ignored for the
+     * output.
+     *
+     * @param output The LinkConfiguration to be filled with Visitor returned
+     * ModuleEntry.
+     */
+    @Override
+    public void transformAndCopy(Function<ModuleEntry, ModuleEntry> transform,
+            ModulePool output) {
+        entries().forEach(resource -> {
+            ModuleEntry res = transform.apply(resource);
+            if (res != null) {
+                output.add(res);
+            }
+        });
+    }
+
+    /**
+     * The ByteOrder currently in use when generating the jimage file.
+     *
+     * @return The ByteOrder.
+     */
+    @Override
+    public ByteOrder getByteOrder() {
+        return order;
+    }
+
+    @Override
+    public Map<String, String> getReleaseProperties() {
+        return isReadOnly()? Collections.unmodifiableMap(releaseProps) : releaseProps;
+    }
+
+    public StringTable getStringTable() {
+        return table;
+    }
+
+    /**
+     * Make this Resources instance read-only. No resource can be added.
+     */
+    public void setReadOnly() {
+        isReadOnly = true;
+    }
+
+    /**
+     * Read only state.
+     *
+     * @return true if readonly false otherwise.
+     */
+    @Override
+    public boolean isReadOnly() {
+        return isReadOnly;
+    }
+
+    /**
+     * A resource that has been compressed.
+     */
+    public static final class CompressedModuleData extends ModuleEntryImpl {
+
+        final long uncompressed_size;
+
+        private CompressedModuleData(String module, String path,
+                InputStream stream, long size,
+                long uncompressed_size) {
+            super(module, path, ModuleEntry.Type.CLASS_OR_RESOURCE, stream, size);
+            this.uncompressed_size = uncompressed_size;
+        }
+
+        public long getUncompressedSize() {
+            return uncompressed_size;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof CompressedModuleData)) {
+                return false;
+            }
+            CompressedModuleData f = (CompressedModuleData) other;
+            return f.getPath().equals(getPath());
+        }
+
+        @Override
+        public int hashCode() {
+            return super.hashCode();
+        }
+    }
+
+    public static CompressedModuleData newCompressedResource(ModuleEntry original,
+            ByteBuffer compressed,
+            String plugin, String pluginConfig, StringTable strings,
+            ByteOrder order) {
+        Objects.requireNonNull(original);
+        Objects.requireNonNull(compressed);
+        Objects.requireNonNull(plugin);
+
+        boolean isTerminal = !(original instanceof CompressedModuleData);
+        long uncompressed_size = original.getLength();
+        if (original instanceof CompressedModuleData) {
+            CompressedModuleData comp = (CompressedModuleData) original;
+            uncompressed_size = comp.getUncompressedSize();
+        }
+        int nameOffset = strings.addString(plugin);
+        int configOffset = -1;
+        if (pluginConfig != null) {
+            configOffset = strings.addString(plugin);
+        }
+        CompressedResourceHeader rh
+                = new CompressedResourceHeader(compressed.limit(), original.getLength(),
+                        nameOffset, configOffset, isTerminal);
+        // Merge header with content;
+        byte[] h = rh.getBytes(order);
+        ByteBuffer bb = ByteBuffer.allocate(compressed.limit() + h.length);
+        bb.order(order);
+        bb.put(h);
+        bb.put(compressed);
+        byte[] contentWithHeader = bb.array();
+
+        CompressedModuleData compressedResource
+                = new CompressedModuleData(original.getModule(), original.getPath(),
+                        new ByteArrayInputStream(contentWithHeader),
+                        contentWithHeader.length, uncompressed_size);
+        return compressedResource;
+    }
+
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PoolImpl.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PoolImpl.java
deleted file mode 100644
index 2b1dd827bae..00000000000
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PoolImpl.java
+++ /dev/null
@@ -1,167 +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;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Objects;
-import jdk.internal.jimage.decompressor.CompressedResourceHeader;
-import jdk.tools.jlink.plugin.Pool;
-
-/**
- * Pool of module data.
- */
-public class PoolImpl extends Pool {
-
-    /**
-     * A resource that has been compressed.
-     */
-    public static final class CompressedModuleData extends ModuleData {
-
-        private final long uncompressed_size;
-
-        private CompressedModuleData(String module, String path,
-                InputStream stream, long size,
-                long uncompressed_size) {
-            super(module, path, ModuleDataType.CLASS_OR_RESOURCE, stream, size);
-            this.uncompressed_size = uncompressed_size;
-        }
-
-        public long getUncompressedSize() {
-            return uncompressed_size;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof CompressedModuleData)) {
-                return false;
-            }
-            CompressedModuleData f = (CompressedModuleData) other;
-            return f.getPath().equals(getPath());
-        }
-
-        @Override
-        public int hashCode() {
-            return super.hashCode();
-        }
-    }
-
-    private boolean isReadOnly;
-    private final StringTable table;
-
-    public PoolImpl() {
-        this(ByteOrder.nativeOrder(), new StringTable() {
-
-            @Override
-            public int addString(String str) {
-                return -1;
-            }
-            @Override
-            public String getString(int id) {
-                return null;
-            }
-        });
-    }
-
-    public PoolImpl(ByteOrder order) {
-        this(order, new StringTable() {
-
-            @Override
-            public int addString(String str) {
-                return -1;
-            }
-            @Override
-            public String getString(int id) {
-                return null;
-            }
-        });
-    }
-
-    public PoolImpl(ByteOrder order, StringTable table) {
-        super(order);
-        this.table = table;
-    }
-
-    public StringTable getStringTable() {
-        return table;
-    }
-
-    /**
-     * Make this Resources instance read-only. No resource can be added.
-     */
-    public void setReadOnly() {
-        isReadOnly = true;
-    }
-
-    /**
-     * Read only state.
-     *
-     * @return true if readonly false otherwise.
-     */
-    @Override
-    public boolean isReadOnly() {
-        return isReadOnly;
-    }
-
-    public static CompressedModuleData newCompressedResource(ModuleData original,
-            ByteBuffer compressed,
-            String plugin, String pluginConfig, StringTable strings,
-            ByteOrder order) {
-        Objects.requireNonNull(original);
-        Objects.requireNonNull(compressed);
-        Objects.requireNonNull(plugin);
-
-        boolean isTerminal = !(original instanceof CompressedModuleData);
-        long uncompressed_size = original.getLength();
-        if (original instanceof CompressedModuleData) {
-            CompressedModuleData comp = (CompressedModuleData) original;
-            uncompressed_size = comp.getUncompressedSize();
-        }
-        int nameOffset = strings.addString(plugin);
-        int configOffset = -1;
-        if (pluginConfig != null) {
-            configOffset = strings.addString(plugin);
-        }
-        CompressedResourceHeader rh
-                = new CompressedResourceHeader(compressed.limit(), original.getLength(),
-                        nameOffset, configOffset, isTerminal);
-        // Merge header with content;
-        byte[] h = rh.getBytes(order);
-        ByteBuffer bb = ByteBuffer.allocate(compressed.limit() + h.length);
-        bb.order(order);
-        bb.put(h);
-        bb.put(compressed);
-        byte[] contentWithHeader = bb.array();
-
-        CompressedModuleData compressedResource
-                = new CompressedModuleData(original.getModule(), original.getPath(),
-                        new ByteArrayInputStream(contentWithHeader),
-                        contentWithHeader.length, uncompressed_size);
-        return compressedResource;
-    }
-
-}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java
index d9c5bab9a61..c8b8bc79ed6 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java
@@ -24,7 +24,7 @@
  */
 package jdk.tools.jlink.internal;
 
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModulePool;
 
 /**
  * Plugin wishing to pre-visit the resources must implement this interface.
@@ -44,5 +44,5 @@ public interface ResourcePrevisitor {
      * usage.
      * @throws PluginException
      */
-    public void previsit(Pool resources, StringTable strings);
+    public void previsit(ModulePool resources, StringTable strings);
 }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java
index 31064ab79d6..b255312bbf4 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java
@@ -52,7 +52,7 @@ import jdk.internal.module.ConfigurableModuleFinder.Phase;
 import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.Jlink.PluginsConfiguration;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.Plugin.CATEGORY;
+import jdk.tools.jlink.plugin.Plugin.Category;
 import jdk.tools.jlink.builder.DefaultImageBuilder;
 import jdk.tools.jlink.builder.ImageBuilder;
 import jdk.tools.jlink.plugin.PluginException;
@@ -346,7 +346,6 @@ public final class TaskHelper {
                 }
             }
 
-            PluginContextImpl pluginContext = new PluginContextImpl();
             List<Plugin> pluginsList = new ArrayList<>();
             for (Entry<Plugin, List<Map<String, String>>> entry : pluginToMaps.entrySet()) {
                 Plugin plugin = entry.getKey();
@@ -356,7 +355,7 @@ public final class TaskHelper {
                 // we call configure once for each occurrence. It is upto the plugin
                 // to 'merge' and/or 'override' arguments.
                 for (Map<String, String> map : argsMaps) {
-                    plugin.configure(Collections.unmodifiableMap(map), pluginContext);
+                    plugin.configure(Collections.unmodifiableMap(map));
                 }
 
                 if (!Utils.isDisabled(plugin)) {
@@ -371,7 +370,7 @@ public final class TaskHelper {
 
             }
             return new Jlink.PluginsConfiguration(pluginsList,
-                    builder, lastSorter, pluginContext);
+                    builder, lastSorter);
         }
     }
 
@@ -594,7 +593,7 @@ public final class TaskHelper {
                          + ": " + plugin.getClass().getName());
                     log.println(bundleHelper.getMessage("main.plugin.module")
                          + ": " + plugin.getClass().getModule().getName());
-                    CATEGORY category = Utils.getCategory(plugin);
+                    Category category = Utils.getCategory(plugin);
                     log.println(bundleHelper.getMessage("main.plugin.category")
                          + ": " + category.getName());
                     log.println(bundleHelper.getMessage("main.plugin.state")
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java
index a8a9a45a5f4..0e29969a034 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java
@@ -30,7 +30,6 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.function.Function;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.Plugin.PluginType;
 
 public class Utils {
 
@@ -50,25 +49,26 @@ public class Utils {
         return arguments;
     };
 
-    public static boolean isPostProcessor(Plugin.CATEGORY category) {
-        return category.equals(Plugin.CATEGORY.VERIFIER)
-                || category.equals(Plugin.CATEGORY.PROCESSOR)
-                || category.equals(Plugin.CATEGORY.PACKAGER);
+    public static boolean isPostProcessor(Plugin.Category category) {
+        return category.equals(Plugin.Category.VERIFIER)
+                || category.equals(Plugin.Category.PROCESSOR)
+                || category.equals(Plugin.Category.PACKAGER);
     }
 
-    public static boolean isPreProcessor(Plugin.CATEGORY category) {
-        return category.equals(Plugin.CATEGORY.COMPRESSOR)
-                || category.equals(Plugin.CATEGORY.FILTER)
-                || category.equals(Plugin.CATEGORY.MODULEINFO_TRANSFORMER)
-                || category.equals(Plugin.CATEGORY.SORTER)
-                || category.equals(Plugin.CATEGORY.TRANSFORMER);
+    public static boolean isPreProcessor(Plugin.Category category) {
+        return category.equals(Plugin.Category.COMPRESSOR)
+                || category.equals(Plugin.Category.FILTER)
+                || category.equals(Plugin.Category.MODULEINFO_TRANSFORMER)
+                || category.equals(Plugin.Category.SORTER)
+                || category.equals(Plugin.Category.TRANSFORMER)
+                || category.equals(Plugin.Category.METAINFO_ADDER);
     }
 
     public static boolean isPostProcessor(Plugin prov) {
         if (prov.getType() != null) {
-            for (PluginType pt : prov.getType()) {
-                if (pt instanceof Plugin.CATEGORY) {
-                    return isPostProcessor((Plugin.CATEGORY) pt);
+            for (Plugin.Category pt : prov.getType()) {
+                if (pt instanceof Plugin.Category) {
+                    return isPostProcessor(pt);
                 }
             }
         }
@@ -77,20 +77,20 @@ public class Utils {
 
     public static boolean isPreProcessor(Plugin prov) {
         if (prov.getType() != null) {
-            for (PluginType pt : prov.getType()) {
-                if (pt instanceof Plugin.CATEGORY) {
-                    return isPreProcessor((Plugin.CATEGORY) pt);
+            for (Plugin.Category pt : prov.getType()) {
+                if (pt instanceof Plugin.Category) {
+                    return isPreProcessor(pt);
                 }
             }
         }
         return false;
     }
 
-    public static Plugin.CATEGORY getCategory(Plugin provider) {
+    public static Plugin.Category getCategory(Plugin provider) {
         if (provider.getType() != null) {
-            for (Plugin.PluginType t : provider.getType()) {
-                if (t instanceof Plugin.CATEGORY) {
-                    return (Plugin.CATEGORY) t;
+            for (Plugin.Category t : provider.getType()) {
+                if (t instanceof Plugin.Category) {
+                    return t;
                 }
             }
         }
@@ -140,15 +140,15 @@ public class Utils {
     }
 
     public static boolean isFunctional(Plugin prov) {
-        return prov.getState().contains(Plugin.STATE.FUNCTIONAL);
+        return prov.getState().contains(Plugin.State.FUNCTIONAL);
     }
 
     public static boolean isAutoEnabled(Plugin prov) {
-        return prov.getState().contains(Plugin.STATE.AUTO_ENABLED);
+        return prov.getState().contains(Plugin.State.AUTO_ENABLED);
     }
 
     public static boolean isDisabled(Plugin prov) {
-        return prov.getState().contains(Plugin.STATE.DISABLED);
+        return prov.getState().contains(Plugin.State.DISABLED);
     }
 
     // is this a builtin (jdk.jlink) plugin?
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java
index e448acd0b1d..874b338c93f 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java
@@ -30,7 +30,7 @@ import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.builder.ImageBuilder;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.builder.*;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModulePool;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java
index aa068f1136e..43eb6f27dec 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java
@@ -26,16 +26,13 @@ package jdk.tools.jlink.internal.plugins;
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.internal.PoolImpl;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import jdk.tools.jlink.internal.ImagePluginStack;
 import jdk.tools.jlink.internal.ResourcePrevisitor;
@@ -62,10 +59,10 @@ public final class DefaultCompressPlugin implements TransformerPlugin, ResourceP
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
+    public void visit(ModulePool in, ModulePool out) {
         if (ss != null && zip != null) {
-            Pool output = new ImagePluginStack.OrderedResourcePool(in.getByteOrder(),
-                    ((PoolImpl) in).getStringTable());
+            ModulePool output = new ImagePluginStack.OrderedResourcePool(in.getByteOrder(),
+                    ((ModulePoolImpl) in).getStringTable());
             ss.visit(in, output);
             zip.visit(output, out);
         } else if (ss != null) {
@@ -76,16 +73,16 @@ public final class DefaultCompressPlugin implements TransformerPlugin, ResourceP
     }
 
     @Override
-    public void previsit(Pool resources, StringTable strings) {
+    public void previsit(ModulePool resources, StringTable strings) {
         if (ss != null) {
             ss.previsit(resources, strings);
         }
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.COMPRESSOR);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.COMPRESSOR);
         return Collections.unmodifiableSet(set);
     }
 
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java
index 0271670e4c1..628d8f6346e 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java
@@ -32,8 +32,8 @@ import java.util.Map;
 import java.util.Set;
 import java.util.function.Predicate;
 import jdk.tools.jlink.plugin.TransformerPlugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.internal.Utils;
 
 /**
@@ -51,9 +51,9 @@ public final class ExcludeFilesPlugin implements TransformerPlugin {
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
-        in.visit((file) -> {
-            if (!file.getType().equals(ModuleDataType.CLASS_OR_RESOURCE)) {
+    public void visit(ModulePool in, ModulePool out) {
+        in.transformAndCopy((file) -> {
+            if (!file.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
                 file = predicate.test(file.getPath()) ? file : null;
             }
             return file;
@@ -61,9 +61,9 @@ public final class ExcludeFilesPlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.FILTER);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.FILTER);
         return Collections.unmodifiableSet(set);
     }
 
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java
index 6d4737a4661..626087b76be 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java
@@ -32,7 +32,8 @@ import java.util.Set;
 import java.util.function.Predicate;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.TransformerPlugin;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.internal.Utils;
 
 /**
@@ -50,9 +51,9 @@ public final class ExcludePlugin implements TransformerPlugin {
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
-        in.visit((resource) -> {
-            if (resource.getType().equals(Pool.ModuleDataType.CLASS_OR_RESOURCE)) {
+    public void visit(ModulePool in, ModulePool out) {
+        in.transformAndCopy((resource) -> {
+            if (resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
                 resource = predicate.test(resource.getPath()) ? resource : null;
             }
             return resource;
@@ -75,9 +76,9 @@ public final class ExcludePlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.FILTER);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.FILTER);
         return Collections.unmodifiableSet(set);
     }
 
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java
index 4d502904c37..753d63e5cfc 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java
@@ -40,9 +40,10 @@ import java.util.TreeSet;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import jdk.tools.jlink.plugin.TransformerPlugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.internal.Utils;
+import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.PluginException;
 
 /**
@@ -102,24 +103,24 @@ public final class ExcludeVMPlugin implements TransformerPlugin {
      * e.g.: /java.base/native/amd64/server/libjvm.so
      * /java.base/native/server/libjvm.dylib
      */
-    private List<Pool.ModuleData> getVMs(Pool in) {
+    private List<ModuleEntry> getVMs(ModulePool in) {
         String jvmlib = jvmlib();
-        List<Pool.ModuleData> ret = in.getModule("java.base").getContent().stream().filter((t) -> {
+        List<ModuleEntry> ret = in.findModule("java.base").get().entries().filter((t) -> {
             return t.getPath().endsWith("/" + jvmlib);
         }).collect(Collectors.toList());
         return ret;
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
+    public void visit(ModulePool in, ModulePool out) {
         String jvmlib = jvmlib();
         TreeSet<Jvm> existing = new TreeSet<>(new JvmComparator());
         TreeSet<Jvm> removed = new TreeSet<>(new JvmComparator());
         if (!keepAll) {
             // First retrieve all available VM names and removed VM
-            List<Pool.ModuleData> jvms = getVMs(in);
+            List<ModuleEntry> jvms = getVMs(in);
             for (Jvm jvm : Jvm.values()) {
-                for (Pool.ModuleData md : jvms) {
+                for (ModuleEntry md : jvms) {
                     if (md.getPath().endsWith("/" + jvm.getName() + "/" + jvmlib)) {
                         existing.add(jvm);
                         if (isRemoved(md)) {
@@ -137,9 +138,9 @@ public final class ExcludeVMPlugin implements TransformerPlugin {
         }
 
         // Rewrite the jvm.cfg file.
-        in.visit((file) -> {
+        in.transformAndCopy((file) -> {
             if (!keepAll) {
-                if (file.getType().equals(ModuleDataType.NATIVE_LIB)) {
+                if (file.getType().equals(ModuleEntry.Type.NATIVE_LIB)) {
                     if (file.getPath().endsWith(JVM_CFG)) {
                         try {
                             file = handleJvmCfgFile(file, existing, removed);
@@ -155,14 +156,14 @@ public final class ExcludeVMPlugin implements TransformerPlugin {
 
     }
 
-    private boolean isRemoved(Pool.ModuleData file) {
+    private boolean isRemoved(ModuleEntry file) {
         return !predicate.test(file.getPath());
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.FILTER);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.FILTER);
         return Collections.unmodifiableSet(set);
     }
 
@@ -217,7 +218,7 @@ public final class ExcludeVMPlugin implements TransformerPlugin {
         }
     }
 
-    private Pool.ModuleData handleJvmCfgFile(Pool.ModuleData orig,
+    private ModuleEntry handleJvmCfgFile(ModuleEntry orig,
             TreeSet<Jvm> existing,
             TreeSet<Jvm> removed) throws IOException {
         if (keepAll) {
@@ -253,7 +254,7 @@ public final class ExcludeVMPlugin implements TransformerPlugin {
 
         byte[] content = builder.toString().getBytes(StandardCharsets.UTF_8);
 
-        return Pool.newImageFile(orig.getModule(),
+        return ModuleEntry.create(orig.getModule(),
                 orig.getPath(),
                 orig.getType(),
                 new ByteArrayInputStream(content), content.length);
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java
index 7a51d6cbcdf..497d97e50a6 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java
@@ -41,10 +41,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import jdk.tools.jlink.internal.ModuleEntryImpl;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import jdk.tools.jlink.internal.Utils;
 
@@ -68,12 +68,12 @@ public class FileCopierPlugin implements TransformerPlugin {
     /**
      * Symbolic link to another path.
      */
-    public static abstract class SymImageFile extends Pool.ModuleData {
+    public static abstract class SymImageFile extends ModuleEntryImpl {
 
         private final String targetPath;
 
         public SymImageFile(String targetPath, String module, String path,
-                Pool.ModuleDataType type, InputStream stream, long size) {
+                ModuleEntry.Type type, InputStream stream, long size) {
             super(module, path, type, stream, size);
             this.targetPath = targetPath;
         }
@@ -86,7 +86,7 @@ public class FileCopierPlugin implements TransformerPlugin {
     private static final class SymImageFileImpl extends SymImageFile {
 
         public SymImageFileImpl(String targetPath, Path file, String module,
-                String path, ModuleDataType type) {
+                String path, ModuleEntry.Type type) {
             super(targetPath, module, path, type, newStream(file), length(file));
         }
     }
@@ -110,11 +110,11 @@ public class FileCopierPlugin implements TransformerPlugin {
     private static final class DirectoryCopy implements FileVisitor<Path> {
 
         private final Path source;
-        private final Pool pool;
+        private final ModulePool pool;
         private final String targetDir;
         private final List<SymImageFile> symlinks = new ArrayList<>();
 
-        DirectoryCopy(Path source, Pool pool, String targetDir) {
+        DirectoryCopy(Path source, ModulePool pool, String targetDir) {
             this.source = source;
             this.pool = pool;
             this.targetDir = targetDir;
@@ -148,7 +148,7 @@ public class FileCopierPlugin implements TransformerPlugin {
                 }
                 SymImageFileImpl impl = new SymImageFileImpl(symTarget.toString(),
                         file, path, Objects.requireNonNull(file.getFileName()).toString(),
-                        Pool.ModuleDataType.OTHER);
+                        ModuleEntry.Type.OTHER);
                 symlinks.add(impl);
             } else {
                 addFile(pool, file, path);
@@ -172,14 +172,14 @@ public class FileCopierPlugin implements TransformerPlugin {
         }
     }
 
-    private static void addFile(Pool pool, Path file, String path)
+    private static void addFile(ModulePool pool, Path file, String path)
             throws IOException {
         Objects.requireNonNull(pool);
         Objects.requireNonNull(file);
         Objects.requireNonNull(path);
-        ModuleData impl = Pool.newImageFile(FAKE_MODULE,
+        ModuleEntry impl = ModuleEntry.create(FAKE_MODULE,
                 "/" + FAKE_MODULE + "/other/" + path,
-                Pool.ModuleDataType.OTHER, newStream(file), length(file));
+                ModuleEntry.Type.OTHER, newStream(file), length(file));
         try {
             pool.add(impl);
         } catch (Exception ex) {
@@ -188,9 +188,9 @@ public class FileCopierPlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.TRANSFORMER);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.TRANSFORMER);
         return Collections.unmodifiableSet(set);
     }
 
@@ -239,8 +239,8 @@ public class FileCopierPlugin implements TransformerPlugin {
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
-        in.visit((file) -> {
+    public void visit(ModulePool in, ModulePool out) {
+        in.transformAndCopy((file) -> {
             return file;
         }, out);
 
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java
index d2b2995bdda..9e0805ec361 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java
@@ -33,8 +33,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
+import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 /**
@@ -60,8 +61,8 @@ public final class GenerateJLIClassesPlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<PluginType> getType() {
-        return Collections.singleton(CATEGORY.TRANSFORMER);
+    public Set<Category> getType() {
+        return Collections.singleton(Category.TRANSFORMER);
     }
 
     @Override
@@ -75,8 +76,8 @@ public final class GenerateJLIClassesPlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<STATE> getState() {
-        return EnumSet.of(STATE.AUTO_ENABLED, STATE.FUNCTIONAL);
+    public Set<State> getState() {
+        return EnumSet.of(State.AUTO_ENABLED, State.FUNCTIONAL);
     }
 
     @Override
@@ -151,8 +152,8 @@ public final class GenerateJLIClassesPlugin implements TransformerPlugin {
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
-        for (Pool.ModuleData data : in.getContent()) {
+    public void visit(ModulePool in, ModulePool out) {
+        in.entries().forEach(data -> {
             if (("/java.base/" + BMH + ".class").equals(data.getPath())) {
                 // Add BoundMethodHandle unchanged
                 out.add(data);
@@ -162,11 +163,11 @@ public final class GenerateJLIClassesPlugin implements TransformerPlugin {
                     out.add(data);
                 }
             }
-        }
+        });
     }
 
     @SuppressWarnings("unchecked")
-    private void generateConcreteClass(String types, Pool.ModuleData data, Pool out) {
+    private void generateConcreteClass(String types, ModuleEntry data, ModulePool out) {
         try {
             // Generate class
             Map.Entry<String, byte[]> result = (Map.Entry<String, byte[]>)
@@ -175,9 +176,9 @@ public final class GenerateJLIClassesPlugin implements TransformerPlugin {
             byte[] bytes = result.getValue();
 
             // Add class to pool
-            Pool.ModuleData ndata = new Pool.ModuleData(data.getModule(),
+            ModuleEntry ndata = ModuleEntry.create(data.getModule(),
                     "/java.base/" + className + ".class",
-                    Pool.ModuleDataType.CLASS_OR_RESOURCE,
+                    ModuleEntry.Type.CLASS_OR_RESOURCE,
                     new ByteArrayInputStream(bytes), bytes.length);
             if (!out.contains(ndata)) {
                 out.add(ndata);
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java
index b8b7aa46cc1..3083c19d2ba 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java
@@ -34,6 +34,7 @@ import java.util.IllformedLocaleException;
 import java.util.Locale;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.Predicate;
 import java.util.regex.Pattern;
@@ -44,9 +45,10 @@ import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.tools.jlink.internal.ResourcePrevisitor;
 import jdk.tools.jlink.internal.StringTable;
 import jdk.tools.jlink.internal.Utils;
+import jdk.tools.jlink.plugin.LinkModule;
+import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 /**
@@ -112,19 +114,19 @@ public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePr
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
-        in.visit((resource) -> {
+    public void visit(ModulePool in, ModulePool out) {
+        in.transformAndCopy((resource) -> {
             if (resource.getModule().equals(MODULENAME)) {
                 String path = resource.getPath();
                 resource = predicate.test(path) ? resource: null;
                 if (resource != null &&
-                    resource.getType().equals(ModuleDataType.CLASS_OR_RESOURCE)) {
+                    resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
                     byte[] bytes = resource.getBytes();
                     ClassReader cr = new ClassReader(bytes);
                     if (Arrays.stream(cr.getInterfaces())
                         .anyMatch(i -> i.contains(METAINFONAME)) &&
                         stripUnsupportedLocales(bytes, cr)) {
-                        resource = new Pool.ModuleData(MODULENAME, path,
+                        resource = ModuleEntry.create(MODULENAME, path,
                             resource.getType(),
                             new ByteArrayInputStream(bytes), bytes.length);
                     }
@@ -135,9 +137,9 @@ public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePr
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.FILTER);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.FILTER);
         return Collections.unmodifiableSet(set);
     }
 
@@ -172,12 +174,13 @@ public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePr
     }
 
     @Override
-    public void previsit(Pool resources, StringTable strings) {
+    public void previsit(ModulePool resources, StringTable strings) {
         final Pattern p = Pattern.compile(".*((Data_)|(Names_))(?<tag>.*)\\.class");
-        Pool.Module module = resources.getModule(MODULENAME);
+        Optional<LinkModule> optMod = resources.findModule(MODULENAME);
 
         // jdk.localedata module validation
-        if (module != null) {
+        if (optMod.isPresent()) {
+            LinkModule module = optMod.get();
             Set<String> packages = module.getAllPackages();
             if (!packages.containsAll(LOCALEDATA_PACKAGES)) {
                 throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".missingpackages") +
@@ -186,7 +189,7 @@ public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePr
                         .collect(Collectors.joining(",\n\t")));
             }
 
-            available = Stream.concat(module.getContent().stream()
+            available = Stream.concat(module.entries()
                                         .map(md -> p.matcher(md.getPath()))
                                         .filter(m -> m.matches())
                                         .map(m -> m.group("tag").replaceAll("_", "-")),
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java
index 4f8e5eade53..9632cdf9b95 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java
@@ -24,7 +24,6 @@
  */
 package jdk.tools.jlink.internal.plugins;
 
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -287,9 +286,9 @@ public final class OptimizationPlugin extends AsmPlugin {
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.TRANSFORMER);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.TRANSFORMER);
         return Collections.unmodifiableSet(set);
     }
 }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java
index 8fb124dd775..5060bf5c519 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java
@@ -36,9 +36,8 @@ import java.util.Map;
 import java.util.Set;
 import java.util.function.ToIntFunction;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import jdk.tools.jlink.internal.Utils;
 
@@ -62,15 +61,15 @@ public final class OrderResourcesPlugin implements TransformerPlugin {
     }
 
     static class SortWrapper {
-        private final ModuleData resource;
+        private final ModuleEntry resource;
         private final int ordinal;
 
-        SortWrapper(ModuleData resource, int ordinal) {
+        SortWrapper(ModuleEntry resource, int ordinal) {
             this.resource = resource;
             this.ordinal = ordinal;
         }
 
-        ModuleData getResource() {
+        ModuleEntry getResource() {
             return resource;
         }
 
@@ -95,7 +94,7 @@ public final class OrderResourcesPlugin implements TransformerPlugin {
         return path;
     }
 
-    private int getOrdinal(ModuleData resource) {
+    private int getOrdinal(ModuleEntry resource) {
         String path = resource.getPath();
 
         Integer value = orderedPaths.get(stripModule(path));
@@ -126,23 +125,23 @@ public final class OrderResourcesPlugin implements TransformerPlugin {
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
-        in.getContent().stream()
+    public void visit(ModulePool in, ModulePool out) {
+        in.entries()
                 .filter(resource -> resource.getType()
-                        .equals(ModuleDataType.CLASS_OR_RESOURCE))
+                        .equals(ModuleEntry.Type.CLASS_OR_RESOURCE))
                 .map((resource) -> new SortWrapper(resource, getOrdinal(resource)))
                 .sorted(OrderResourcesPlugin::compare)
                 .forEach((wrapper) -> out.add(wrapper.getResource()));
-        in.getContent().stream()
+        in.entries()
                 .filter(other -> !other.getType()
-                        .equals(ModuleDataType.CLASS_OR_RESOURCE))
+                        .equals(ModuleEntry.Type.CLASS_OR_RESOURCE))
                 .forEach((other) -> out.add(other));
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.SORTER);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.SORTER);
 
         return Collections.unmodifiableSet(set);
     }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java
index bbc7428a41e..579aace7e0a 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java
@@ -24,34 +24,33 @@
  */
 package jdk.tools.jlink.internal.plugins;
 
-import java.lang.module.ModuleDescriptor;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.EnumSet;
-import java.util.List;
+import java.util.HashMap;
 import java.util.Map;
-import java.util.Set;
 import java.util.Properties;
-
+import java.util.Set;
+import java.util.function.Function;
 import jdk.tools.jlink.internal.Utils;
-import jdk.tools.jlink.plugin.ExecutableImage;
-import jdk.tools.jlink.plugin.PluginContext;
-import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.PostProcessorPlugin;
+import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.Plugin.Category;
+import jdk.tools.jlink.plugin.Plugin.State;
+import jdk.tools.jlink.plugin.TransformerPlugin;
 
 /**
  * This plugin adds/deletes information for 'release' file.
  */
-public final class ReleaseInfoPlugin implements PostProcessorPlugin {
+public final class ReleaseInfoPlugin implements TransformerPlugin {
     // option name
     public static final String NAME = "release-info";
     public static final String KEYS = "keys";
+    private final Map<String, String> release = new HashMap<>();
 
     @Override
-    public Set<PluginType> getType() {
-        return Collections.singleton(CATEGORY.PROCESSOR);
+    public Set<Category> getType() {
+        return Collections.singleton(Category.METAINFO_ADDER);
     }
 
     @Override
@@ -65,8 +64,8 @@ public final class ReleaseInfoPlugin implements PostProcessorPlugin {
     }
 
     @Override
-    public Set<STATE> getState() {
-        return EnumSet.of(STATE.FUNCTIONAL);
+    public Set<State> getState() {
+        return EnumSet.of(State.FUNCTIONAL);
     }
 
     @Override
@@ -80,49 +79,49 @@ public final class ReleaseInfoPlugin implements PostProcessorPlugin {
     }
 
     @Override
-    public void configure(Map<String, String> config, PluginContext ctx) {
-        Properties release = ctx != null? ctx.getReleaseProperties() : null;
-        if (release != null) {
-            String operation = config.get(NAME);
-            switch (operation) {
-                case "add": {
-                    // leave it to open-ended! source, java_version, java_full_version
-                    // can be passed via this option like:
-                    //
-                    //     --release-info add:build_type=fastdebug,source=openjdk,java_version=9
-                    // and put whatever value that was passed in command line.
+    public void configure(Map<String, String> config) {
+        String operation = config.get(NAME);
+        switch (operation) {
+            case "add": {
+                // leave it to open-ended! source, java_version, java_full_version
+                // can be passed via this option like:
+                //
+                //     --release-info add:build_type=fastdebug,source=openjdk,java_version=9
+                // and put whatever value that was passed in command line.
 
-                    config.keySet().stream().
-                        filter(s -> !NAME.equals(s)).
-                        forEach(s -> release.put(s, config.get(s)));
-                }
-                break;
-
-                case "del": {
-                    // --release-info del:keys=openjdk,java_version
-                    String[] keys = Utils.listParser.apply(config.get(KEYS));
-                    for (String k : keys) {
-                        release.remove(k);
-                    }
-                }
-                break;
-
-                default: {
-                    // --release-info <file>
-                    try (FileInputStream fis = new FileInputStream(operation)) {
-                        release.load(fis);
-                    } catch (IOException exp) {
-                        throw new RuntimeException(exp);
-                    }
-                }
-                break;
+                config.keySet().stream().
+                    filter(s -> !NAME.equals(s)).
+                    forEach(s -> release.put(s, config.get(s)));
             }
+            break;
+
+            case "del": {
+                // --release-info del:keys=openjdk,java_version
+                String[] keys = Utils.listParser.apply(config.get(KEYS));
+                for (String k : keys) {
+                    release.remove(k);
+                }
+            }
+            break;
+
+            default: {
+                // --release-info <file>
+                Properties props = new Properties();
+                try (FileInputStream fis = new FileInputStream(operation)) {
+                    props.load(fis);
+                } catch (IOException exp) {
+                    throw new RuntimeException(exp);
+                }
+                props.forEach((k, v) -> release.put(k.toString(), v.toString()));
+            }
+            break;
         }
     }
 
     @Override
-    public List<String> process(ExecutableImage image) {
-        // Nothing to do! Release info copied already during configure!
-        return Collections.emptyList();
+    public void visit(ModulePool in, ModulePool out) {
+        in.transformAndCopy(Function.identity(), out);
+        out.getReleaseProperties().putAll(in.getReleaseProperties());
+        out.getReleaseProperties().putAll(release);
     }
 }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java
index a4aa8f9d5ca..b3a1e7cf3cf 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java
@@ -56,11 +56,11 @@ import java.util.stream.Collectors;
 import jdk.internal.jimage.decompressor.CompressIndexes;
 import jdk.internal.jimage.decompressor.SignatureParser;
 import jdk.internal.jimage.decompressor.StringSharingDecompressor;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.internal.ResourcePrevisitor;
 import jdk.tools.jlink.internal.StringTable;
 import jdk.tools.jlink.internal.Utils;
@@ -228,7 +228,7 @@ public class StringSharingPlugin implements TransformerPlugin, ResourcePrevisito
             }
         }
 
-        public byte[] transform(ModuleData resource, Pool out,
+        public byte[] transform(ModuleEntry resource, ModulePool out,
                 StringTable strings) throws IOException, Exception {
             byte[] content = resource.getBytes();
             ClassFile cf;
@@ -243,7 +243,7 @@ public class StringSharingPlugin implements TransformerPlugin, ResourcePrevisito
         }
 
         @SuppressWarnings("fallthrough")
-        private byte[] optimize(ModuleData resource, Pool resources,
+        private byte[] optimize(ModuleEntry resource, ModulePool resources,
                 StringTable strings,
                 Set<Integer> descriptorIndexes, byte[] content) throws Exception {
             DataInputStream stream = new DataInputStream(new ByteArrayInputStream(content));
@@ -348,27 +348,27 @@ public class StringSharingPlugin implements TransformerPlugin, ResourcePrevisito
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.COMPRESSOR);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.COMPRESSOR);
         return Collections.unmodifiableSet(set);
     }
 
     @Override
-    public void visit(Pool in, Pool result) {
+    public void visit(ModulePool in, ModulePool result) {
         CompactCPHelper visit = new CompactCPHelper();
-        in.visit((resource) -> {
-            ModuleData res = resource;
+        in.transformAndCopy((resource) -> {
+            ModuleEntry res = resource;
             if (predicate.test(resource.getPath()) && resource.getPath().endsWith(".class")) {
                 byte[] compressed = null;
                 try {
-                    compressed = visit.transform(resource, result, ((PoolImpl) in).getStringTable());
+                    compressed = visit.transform(resource, result, ((ModulePoolImpl) in).getStringTable());
                 } catch (Exception ex) {
                     throw new PluginException(ex);
                 }
-                res = PoolImpl.newCompressedResource(resource,
+                res = ModulePoolImpl.newCompressedResource(resource,
                         ByteBuffer.wrap(compressed), getName(), null,
-                        ((PoolImpl) in).getStringTable(), in.getByteOrder());
+                        ((ModulePoolImpl) in).getStringTable(), in.getByteOrder());
             }
             return res;
         }, result);
@@ -405,10 +405,10 @@ public class StringSharingPlugin implements TransformerPlugin, ResourcePrevisito
     }
 
     @Override
-    public void previsit(Pool resources, StringTable strings) {
+    public void previsit(ModulePool resources, StringTable strings) {
         CompactCPHelper preVisit = new CompactCPHelper();
-        for (ModuleData resource : resources.getContent()) {
-            if (resource.getType().equals(Pool.ModuleDataType.CLASS_OR_RESOURCE)
+        resources.entries().forEach(resource -> {
+            if (resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)
                     && resource.getPath().endsWith(".class") && predicate.test(resource.getPath())) {
                 try {
                     preVisit.transform(resource, null, strings);
@@ -416,6 +416,6 @@ public class StringSharingPlugin implements TransformerPlugin, ResourcePrevisito
                     throw new PluginException(ex);
                 }
             }
-        }
+        });
     }
 }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java
index ae927952226..4e7a036d838 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java
@@ -29,14 +29,12 @@ import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 import java.util.function.Predicate;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 /**
@@ -61,9 +59,9 @@ public final class StripDebugPlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.TRANSFORMER);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.TRANSFORMER);
         return Collections.unmodifiableSet(set);
     }
 
@@ -73,11 +71,11 @@ public final class StripDebugPlugin implements TransformerPlugin {
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
+    public void visit(ModulePool in, ModulePool out) {
         //remove *.diz files as well as debug attributes.
-        in.visit((resource) -> {
-            ModuleData res = resource;
-            if (resource.getType().equals(ModuleDataType.CLASS_OR_RESOURCE)) {
+        in.transformAndCopy((resource) -> {
+            ModuleEntry res = resource;
+            if (resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
                 String path = resource.getPath();
                 if (path.endsWith(".class")) {
                     if (path.endsWith("module-info.class")) {
@@ -87,7 +85,7 @@ public final class StripDebugPlugin implements TransformerPlugin {
                         ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                         reader.accept(writer, ClassReader.SKIP_DEBUG);
                         byte[] content = writer.toByteArray();
-                        res = Pool.newResource(path, new ByteArrayInputStream(content), content.length);
+                        res = ModuleEntry.create(path, new ByteArrayInputStream(content), content.length);
                     }
                 }
             } else if (predicate.test(res.getPath())) {
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java
index dc64582be21..496a4e538d7 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java
@@ -26,9 +26,9 @@ package jdk.tools.jlink.internal.plugins;
 
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 /**
@@ -45,16 +45,16 @@ public final class StripNativeCommandsPlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.FILTER);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.FILTER);
         return Collections.unmodifiableSet(set);
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
-        in.visit((file) -> {
-            return file.getType() == Pool.ModuleDataType.NATIVE_CMD ? null : file;
+    public void visit(ModulePool in, ModulePool out) {
+        in.transformAndCopy((file) -> {
+            return file.getType() == ModuleEntry.Type.NATIVE_CMD ? null : file;
         }, out);
     }
 
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java
index f4cba7607ea..b60fecb5d16 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java
@@ -36,6 +36,7 @@ import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -50,9 +51,10 @@ import jdk.internal.org.objectweb.asm.Opcodes;
 
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin.Builder.*;
+import jdk.tools.jlink.plugin.ModuleEntry;
 
 /**
  * Jlink plugin to reconstitute module descriptors for installed modules.
@@ -81,8 +83,8 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<PluginType> getType() {
-        return Collections.singleton(CATEGORY.TRANSFORMER);
+    public Set<Category> getType() {
+        return Collections.singleton(Category.TRANSFORMER);
     }
 
     @Override
@@ -96,9 +98,9 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<STATE> getState() {
-        return enabled ? EnumSet.of(STATE.AUTO_ENABLED, STATE.FUNCTIONAL)
-                       : EnumSet.of(STATE.DISABLED);
+    public Set<State> getState() {
+        return enabled ? EnumSet.of(State.AUTO_ENABLED, State.FUNCTIONAL)
+                       : EnumSet.of(State.DISABLED);
     }
 
     @Override
@@ -110,7 +112,7 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin {
 
 
     @Override
-    public void visit(Pool in, Pool out) {
+    public void visit(ModulePool in, ModulePool out) {
         if (!enabled) {
             throw new PluginException(NAME + " was set");
         }
@@ -119,13 +121,14 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin {
 
         // generate the byte code to create ModuleDescriptors
         // skip parsing module-info.class and skip name check
-        for (Pool.Module module : in.getModules()) {
-            Pool.ModuleData data = module.get("module-info.class");
-            if (data == null) {
+        in.modules().forEach(module -> {
+            Optional<ModuleEntry> optData = module.findEntry("module-info.class");
+            if (! optData.isPresent()) {
                 // automatic module not supported yet
                 throw new PluginException("module-info.class not found for " +
                                           module.getName() + " module");
             }
+            ModuleEntry data = optData.get();
             assert module.getName().equals(data.getModule());
             try {
                 ByteArrayInputStream bain = new ByteArrayInputStream(data.getBytes());
@@ -141,7 +144,7 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin {
                     ModuleInfoRewriter minfoWriter =
                         new ModuleInfoRewriter(bain, mbuilder.conceals());
                     // replace with the overridden version
-                    data = new Pool.ModuleData(data.getModule(),
+                    data = ModuleEntry.create(data.getModule(),
                                                data.getPath(),
                                                data.getType(),
                                                minfoWriter.stream(),
@@ -151,19 +154,17 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin {
             } catch (IOException e) {
                 throw new PluginException(e);
             }
-
-        }
+        });
 
         // Generate the new class
         ClassWriter cwriter = builder.build();
-        for (Pool.ModuleData data : in.getContent()) {
+        in.entries().forEach(data -> {
             if (data.getPath().endsWith("module-info.class"))
-                continue;
-
+                return;
             if (builder.isOverriddenClass(data.getPath())) {
                 byte[] bytes = cwriter.toByteArray();
-                Pool.ModuleData ndata =
-                    new Pool.ModuleData(data.getModule(),
+                ModuleEntry ndata =
+                    ModuleEntry.create(data.getModule(),
                                         data.getPath(),
                                         data.getType(),
                                         new ByteArrayInputStream(bytes),
@@ -172,7 +173,7 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin {
             } else {
                 out.add(data);
             }
-        }
+        });
     }
 
     /*
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java
index df66e300f5c..d3dd7bff210 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java
@@ -34,10 +34,9 @@ import java.util.Set;
 import java.util.function.Predicate;
 import java.util.zip.Deflater;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.internal.PoolImpl;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import jdk.tools.jlink.internal.Utils;
 
@@ -68,9 +67,9 @@ public final class ZipPlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.COMPRESSOR);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.COMPRESSOR);
         return Collections.unmodifiableSet(set);
     }
 
@@ -124,16 +123,16 @@ public final class ZipPlugin implements TransformerPlugin {
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
-        in.visit((resource) -> {
-            ModuleData res = resource;
-            if (resource.getType().equals(ModuleDataType.CLASS_OR_RESOURCE)
+    public void visit(ModulePool in, ModulePool out) {
+        in.transformAndCopy((resource) -> {
+            ModuleEntry res = resource;
+            if (resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)
                     && predicate.test(resource.getPath())) {
                 byte[] compressed;
                 compressed = compress(resource.getBytes());
-                res = PoolImpl.newCompressedResource(resource,
+                res = ModulePoolImpl.newCompressedResource(resource,
                         ByteBuffer.wrap(compressed), getName(), null,
-                        ((PoolImpl) in).getStringTable(), in.getByteOrder());
+                        ((ModulePoolImpl) in).getStringTable(), in.getByteOrder());
             }
             return res;
         }, out);
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java
index 9902959d059..52712172d5e 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java
@@ -26,9 +26,9 @@ package jdk.tools.jlink.internal.plugins.asm;
 
 import java.util.Objects;
 import jdk.tools.jlink.plugin.TransformerPlugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.internal.PoolImpl;
+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
@@ -41,17 +41,17 @@ public abstract class AsmPlugin implements TransformerPlugin {
     }
 
     @Override
-    public void visit(Pool allContent, Pool outResources) {
+    public void visit(ModulePool allContent, ModulePool outResources) {
         Objects.requireNonNull(allContent);
         Objects.requireNonNull(outResources);
-        PoolImpl resources = new PoolImpl(allContent.getByteOrder());
-        for(ModuleData md : allContent.getContent()) {
-            if(md.getType().equals(Pool.ModuleDataType.CLASS_OR_RESOURCE)) {
+        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);
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java
index 9184bb86257..aa5c1cb5ef5 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java
@@ -24,13 +24,12 @@
  */
 package jdk.tools.jlink.internal.plugins.asm;
 
-import java.io.InputStream;
-import java.nio.ByteBuffer;
 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.Pool;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 /**
  * A pool of ClassReader and other resource files.
@@ -138,14 +137,14 @@ public interface AsmPool {
          * @return The ClassReader or null if the class is not found.
          * @throws jdk.tools.jlink.plugin.PluginException
          */
-        public ClassReader getClassReader(Pool.ModuleData res);
+        public ClassReader getClassReader(ModuleEntry res);
 
         /**
          * Returns all the classes contained in the writable pool.
          *
          * @return The collection of classes.
          */
-        public Collection<Pool.ModuleData> getClasses();
+        public Collection<ModuleEntry> getClasses();
     }
 
     /**
@@ -185,14 +184,14 @@ public interface AsmPool {
          * @param res The java resource
          * @return The Resource or null if the resource is not found.
          */
-        public ResourceFile getResourceFile(Pool.ModuleData res);
+        public ResourceFile getResourceFile(ModuleEntry res);
 
         /**
          * Returns all the resources contained in the writable pool.
          *
          * @return The array of resources.
          */
-        public Collection<Pool.ModuleData> getResourceFiles();
+        public Collection<ModuleEntry> getResourceFiles();
     }
 
     /**
@@ -206,7 +205,7 @@ public interface AsmPool {
          * @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(Pool resources);
+        public List<String> sort(ModulePool resources);
     }
 
     /**
@@ -237,7 +236,7 @@ public interface AsmPool {
      *
      * @return The classes.
      */
-    public Collection<Pool.ModuleData> getClasses();
+    public Collection<ModuleEntry> getClasses();
 
     /**
      * Returns the resources contained in the pool. Resources are all the file
@@ -245,7 +244,7 @@ public interface AsmPool {
      *
      * @return The array of resource files.
      */
-    public Collection<Pool.ModuleData> getResourceFiles();
+    public Collection<ModuleEntry> getResourceFiles();
 
     /**
      * Retrieves a resource based on the binary name. This name doesn't contain
@@ -266,7 +265,7 @@ public interface AsmPool {
      * @param res The resource
      * @return The resource file or null if it doesn't exist.
      */
-    public ResourceFile getResourceFile(Pool.ModuleData res);
+    public ResourceFile getResourceFile(ModuleEntry res);
 
     /**
      * Retrieve a ClassReader from the pool.
@@ -284,7 +283,7 @@ public interface AsmPool {
      * @return A reader or null if the class is unknown
      * @throws jdk.tools.jlink.plugin.PluginException
      */
-    public ClassReader getClassReader(Pool.ModuleData res);
+    public ClassReader getClassReader(ModuleEntry res);
 
     /**
      * To visit the set of ClassReaders.
@@ -310,6 +309,6 @@ public interface AsmPool {
      * @param output The pool used to fill the jimage.
      * @throws jdk.tools.jlink.plugin.PluginException
      */
-    public void fillOutputResources(Pool output);
+    public void fillOutputResources(ModulePool output);
 
 }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java
index cb838d11efa..20c17c85b7b 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java
@@ -41,15 +41,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
-import java.util.Optional;
 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.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModulePool;
 
 /**
  * A pool of ClassReader and other resource files. This class allows to
@@ -94,7 +93,7 @@ final class AsmPoolImpl implements AsmModulePool {
             }
 
             byte[] content = writer.toByteArray();
-            ModuleData res = Pool.newResource(path,
+            ModuleEntry res = ModuleEntry.create(path,
                     new ByteArrayInputStream(content), content.length);
             transformedClasses.put(className, res);
         }
@@ -108,7 +107,7 @@ final class AsmPoolImpl implements AsmModulePool {
         public void forgetClass(String className) {
             Objects.requireNonNull(className);
             // do we have a resource?
-            ModuleData res = transformedClasses.get(className);
+            ModuleEntry res = transformedClasses.get(className);
             if (res == null) {
                 res = inputClasses.get(className);
                 if (res == null) {
@@ -130,7 +129,7 @@ final class AsmPoolImpl implements AsmModulePool {
         @Override
         public ClassReader getClassReader(String binaryName) {
             Objects.requireNonNull(binaryName);
-            ModuleData res = transformedClasses.get(binaryName);
+            ModuleEntry res = transformedClasses.get(binaryName);
             ClassReader reader = null;
             if (res != null) {
                 reader = getClassReader(res);
@@ -144,16 +143,16 @@ final class AsmPoolImpl implements AsmModulePool {
          * @return The array of transformed classes.
          */
         @Override
-        public Collection<ModuleData> getClasses() {
-            List<ModuleData> classes = new ArrayList<>();
-            for (Entry<String, ModuleData> entry : transformedClasses.entrySet()) {
+        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(ModuleData res) {
+        public ClassReader getClassReader(ModuleEntry res) {
             return newClassReader(res.getBytes());
         }
     }
@@ -176,7 +175,7 @@ final class AsmPoolImpl implements AsmModulePool {
         public void addResourceFile(ResourceFile resFile) {
             Objects.requireNonNull(resFile);
             String path = toResourceNamePath(resFile.getPath());
-            ModuleData res = Pool.newResource(path, resFile.getContent());
+            ModuleEntry res = ModuleEntry.create(path, resFile.getContent());
             transformedResources.put(resFile.getPath(), res);
         }
 
@@ -191,7 +190,7 @@ final class AsmPoolImpl implements AsmModulePool {
             Objects.requireNonNull(resourceName);
             String path = toResourceNamePath(resourceName);
             // do we have a resource?
-            ModuleData res = transformedResources.get(resourceName);
+            ModuleEntry res = transformedResources.get(resourceName);
             if (res == null) {
                 res = inputResources.get(resourceName);
                 if (res == null) {
@@ -212,7 +211,7 @@ final class AsmPoolImpl implements AsmModulePool {
         @Override
         public ResourceFile getResourceFile(String name) {
             Objects.requireNonNull(name);
-            ModuleData res = transformedResources.get(name);
+            ModuleEntry res = transformedResources.get(name);
             ResourceFile resFile = null;
             if (res != null) {
                 resFile = getResourceFile(res);
@@ -226,24 +225,24 @@ final class AsmPoolImpl implements AsmModulePool {
          * @return The array of transformed classes.
          */
         @Override
-        public Collection<ModuleData> getResourceFiles() {
-            List<ModuleData> resources = new ArrayList<>();
-            for (Entry<String, ModuleData> entry : transformedResources.entrySet()) {
+        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(ModuleData res) {
+        public ResourceFile getResourceFile(ModuleEntry res) {
             return new ResourceFile(toJavaBinaryResourceName(res.getPath()),
                     res.getBytes());
         }
     }
 
-    private final Pool jimageResources;
-    private final Map<String, ModuleData> inputClasses;
-    private final Map<String, ModuleData> inputResources;
+    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;
 
@@ -254,9 +253,9 @@ final class AsmPoolImpl implements AsmModulePool {
 
     private Sorter sorter;
 
-    private final Map<String, ModuleData> transformedClasses
+    private final Map<String, ModuleEntry> transformedClasses
             =            new LinkedHashMap<>();
-    private final Map<String, ModuleData> transformedResources
+    private final Map<String, ModuleEntry> transformedResources
             =            new LinkedHashMap<>();
     private final List<String> forgetResources = new ArrayList<>();
     private final Map<String, String> newPackageMapping = new HashMap<>();
@@ -274,7 +273,7 @@ final class AsmPoolImpl implements AsmModulePool {
      * @param pools The resource pools.
      * @param descriptor The module descriptor.
      */
-    AsmPoolImpl(Pool inputResources, String moduleName,
+    AsmPoolImpl(ModulePool inputResources, String moduleName,
             AsmPools pools,
             ModuleDescriptor descriptor) {
         Objects.requireNonNull(inputResources);
@@ -285,11 +284,11 @@ final class AsmPoolImpl implements AsmModulePool {
         this.moduleName = moduleName;
         this.pools = pools;
         this.descriptor = descriptor;
-        Map<String, ModuleData> classes = new LinkedHashMap<>();
-        Map<String, ModuleData> resources = new LinkedHashMap<>();
+        Map<String, ModuleEntry> classes = new LinkedHashMap<>();
+        Map<String, ModuleEntry> resources = new LinkedHashMap<>();
         Map<String, String> packageClassToModule = new HashMap<>();
         Map<String, String> packageOtherToModule = new HashMap<>();
-        for (ModuleData res : inputResources.getContent()) {
+        inputResources.entries().forEach(res -> {
             if (res.getPath().endsWith(".class")) {
                 classes.put(toJavaBinaryClassName(res.getPath()), res);
             } else {
@@ -305,7 +304,7 @@ final class AsmPoolImpl implements AsmModulePool {
                     packageOtherToModule.put(split[1], res.getModule());
                 }
             }
-        }
+        });
         this.inputClasses = Collections.unmodifiableMap(classes);
         this.inputResources = Collections.unmodifiableMap(resources);
 
@@ -356,7 +355,7 @@ final class AsmPoolImpl implements AsmModulePool {
      * @return The array of classes.
      */
     @Override
-    public Collection<ModuleData> getClasses() {
+    public Collection<ModuleEntry> getClasses() {
         return inputClasses.values();
     }
 
@@ -367,7 +366,7 @@ final class AsmPoolImpl implements AsmModulePool {
      * @return The array of classes.
      */
     @Override
-    public Collection<ModuleData> getResourceFiles() {
+    public Collection<ModuleEntry> getResourceFiles() {
         return inputResources.values();
     }
 
@@ -385,7 +384,7 @@ final class AsmPoolImpl implements AsmModulePool {
     @Override
     public ResourceFile getResourceFile(String binaryName) {
         Objects.requireNonNull(binaryName);
-        ModuleData res = inputResources.get(binaryName);
+        ModuleEntry res = inputResources.get(binaryName);
         ResourceFile resFile = null;
         if (res != null) {
             resFile = getResourceFile(res);
@@ -402,7 +401,7 @@ final class AsmPoolImpl implements AsmModulePool {
     @Override
     public ClassReader getClassReader(String binaryName) {
         Objects.requireNonNull(binaryName);
-        ModuleData res = inputClasses.get(binaryName);
+        ModuleEntry res = inputClasses.get(binaryName);
         ClassReader reader = null;
         if (res != null) {
             reader = getClassReader(res);
@@ -411,13 +410,13 @@ final class AsmPoolImpl implements AsmModulePool {
     }
 
     @Override
-    public ResourceFile getResourceFile(ModuleData res) {
+    public ResourceFile getResourceFile(ModuleEntry res) {
         return new ResourceFile(toJavaBinaryResourceName(res.getPath()),
                 res.getBytes());
     }
 
     @Override
-    public ClassReader getClassReader(ModuleData res) {
+    public ClassReader getClassReader(ModuleEntry res) {
         return newClassReader(res.getBytes());
     }
 
@@ -505,7 +504,7 @@ final class AsmPoolImpl implements AsmModulePool {
     @Override
     public void visitClassReaders(ClassReaderVisitor visitor) {
         Objects.requireNonNull(visitor);
-        for (ModuleData res : getClasses()) {
+        for (ModuleEntry res : getClasses()) {
             ClassReader reader = newClassReader(res.getBytes());
             ClassWriter writer = visitor.visit(reader);
             if (writer != null) {
@@ -523,7 +522,7 @@ final class AsmPoolImpl implements AsmModulePool {
     @Override
     public void visitResourceFiles(ResourceFileVisitor visitor) {
         Objects.requireNonNull(visitor);
-        for (ModuleData resource : getResourceFiles()) {
+        for (ModuleEntry resource : getResourceFiles()) {
             ResourceFile resFile
                     = new ResourceFile(toJavaBinaryResourceName(resource.getPath()),
                             resource.getBytes());
@@ -540,18 +539,18 @@ final class AsmPoolImpl implements AsmModulePool {
      * been set, it is used to sort the returned resources.     *
      */
     @Override
-    public void fillOutputResources(Pool outputResources) {
+    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
-        Pool output = new PoolImpl(outputResources.getByteOrder(),
-                ((PoolImpl)outputResources).getStringTable());
-        for (ModuleData inResource : jimageResources.getContent()) {
+        ModulePool output = new ModulePoolImpl(outputResources.getByteOrder(),
+                ((ModulePoolImpl)outputResources).getStringTable());
+        jimageResources.entries().forEach(inResource -> {
             if (!forgetResources.contains(inResource.getPath())) {
-                ModuleData resource = inResource;
+                ModuleEntry resource = inResource;
                 // Do we have a transformed class with the same name?
-                ModuleData res = transformedResources.
+                ModuleEntry res = transformedResources.
                         get(toJavaBinaryResourceName(inResource.getPath()));
                 if (res != null) {
                     resource = res;
@@ -565,10 +564,10 @@ final class AsmPoolImpl implements AsmModulePool {
                 output.add(resource);
                 added.add(resource.getPath());
             }
-        }
+        });
         // Then new resources
-        for (Map.Entry<String, ModuleData> entry : transformedResources.entrySet()) {
-            ModuleData resource = entry.getValue();
+        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);
@@ -576,8 +575,8 @@ final class AsmPoolImpl implements AsmModulePool {
             }
         }
         // And new classes
-        for (Map.Entry<String, ModuleData> entry : transformedClasses.entrySet()) {
-            ModuleData resource = entry.getValue();
+        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);
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java
index bbb2d5403f8..53742ee5ad7 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java
@@ -41,11 +41,11 @@ 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.PoolImpl;
+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.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModulePool;
 
 /**
  * A container for pools of ClassReader and other resource files. A pool of all
@@ -97,10 +97,10 @@ public final class AsmPools {
             }
 
             @Override
-            public Collection<Pool.ModuleData> getClasses() {
-                List<Pool.ModuleData> all = new ArrayList<>();
+            public Collection<ModuleEntry> getClasses() {
+                List<ModuleEntry> all = new ArrayList<>();
                 visitAllPools((AsmModulePool pool) -> {
-                    for (Pool.ModuleData rf : pool.getTransformedClasses().getClasses()) {
+                    for (ModuleEntry rf : pool.getTransformedClasses().getClasses()) {
                         all.add(rf);
                     }
                 });
@@ -108,7 +108,7 @@ public final class AsmPools {
             }
 
             @Override
-            public ClassReader getClassReader(Pool.ModuleData res) {
+            public ClassReader getClassReader(ModuleEntry res) {
                 return visitPools((AsmModulePool pool) -> {
                     return pool.getTransformedClasses().getClassReader(res);
                 });
@@ -140,10 +140,10 @@ public final class AsmPools {
             }
 
             @Override
-            public Collection<Pool.ModuleData> getResourceFiles() {
-                List<Pool.ModuleData> all = new ArrayList<>();
+            public Collection<ModuleEntry> getResourceFiles() {
+                List<ModuleEntry> all = new ArrayList<>();
                 visitAllPools((AsmModulePool pool) -> {
-                    for (Pool.ModuleData rf : pool.getTransformedResourceFiles().getResourceFiles()) {
+                    for (ModuleEntry rf : pool.getTransformedResourceFiles().getResourceFiles()) {
                         all.add(rf);
                     }
                 });
@@ -151,7 +151,7 @@ public final class AsmPools {
             }
 
             @Override
-            public ResourceFile getResourceFile(Pool.ModuleData res) {
+            public ResourceFile getResourceFile(ModuleEntry res) {
                 return visitPools((AsmModulePool pool) -> {
                     return pool.getTransformedResourceFiles().getResourceFile(res);
                 });
@@ -175,10 +175,10 @@ public final class AsmPools {
         }
 
         @Override
-        public Collection<Pool.ModuleData> getClasses() {
-            List<Pool.ModuleData> all = new ArrayList<>();
+        public Collection<ModuleEntry> getClasses() {
+            List<ModuleEntry> all = new ArrayList<>();
             visitAllPools((AsmModulePool pool) -> {
-                for (Pool.ModuleData rf : pool.getClasses()) {
+                for (ModuleEntry rf : pool.getClasses()) {
                     all.add(rf);
                 }
             });
@@ -186,10 +186,10 @@ public final class AsmPools {
         }
 
         @Override
-        public Collection<Pool.ModuleData> getResourceFiles() {
-            List<Pool.ModuleData> all = new ArrayList<>();
+        public Collection<ModuleEntry> getResourceFiles() {
+            List<ModuleEntry> all = new ArrayList<>();
             visitAllPools((AsmModulePool pool) -> {
-                for (Pool.ModuleData rf : pool.getResourceFiles()) {
+                for (ModuleEntry rf : pool.getResourceFiles()) {
                     all.add(rf);
                 }
             });
@@ -211,14 +211,14 @@ public final class AsmPools {
         }
 
         @Override
-        public ResourceFile getResourceFile(Pool.ModuleData res) {
+        public ResourceFile getResourceFile(ModuleEntry res) {
             return visitPools((AsmModulePool pool) -> {
                 return pool.getResourceFile(res);
             });
         }
 
         @Override
-        public ClassReader getClassReader(Pool.ModuleData res) {
+        public ClassReader getClassReader(ModuleEntry res) {
             return visitPoolsEx((AsmModulePool pool) -> {
                 return pool.getClassReader(res);
             });
@@ -239,7 +239,7 @@ public final class AsmPools {
         }
 
         @Override
-        public void fillOutputResources(Pool outputResources) {
+        public void fillOutputResources(ModulePool outputResources) {
             AsmPools.this.fillOutputResources(outputResources);
         }
 
@@ -324,15 +324,15 @@ public final class AsmPools {
      *
      * @param inputResources The raw resources to build the pool from.
      */
-    public AsmPools(Pool inputResources) {
+    public AsmPools(ModulePool inputResources) {
         Objects.requireNonNull(inputResources);
-        Map<String, Pool> resPools = new LinkedHashMap<>();
+        Map<String, ModulePool> resPools = new LinkedHashMap<>();
         Map<String, ModuleDescriptor> descriptors = new HashMap<>();
-        for (Pool.ModuleData res : inputResources.getContent()) {
-            Pool p = resPools.get(res.getModule());
+        inputResources.entries().forEach(res -> {
+            ModulePool p = resPools.get(res.getModule());
             if (p == null) {
-                p = new PoolImpl(inputResources.getByteOrder(),
-                        ((PoolImpl)inputResources).getStringTable());
+                p = new ModulePoolImpl(inputResources.getByteOrder(),
+                        ((ModulePoolImpl)inputResources).getStringTable());
                 resPools.put(res.getModule(), p);
             }
             if (res.getPath().endsWith("module-info.class")) {
@@ -341,11 +341,11 @@ public final class AsmPools {
                 descriptors.put(res.getModule(), descriptor);
             }
             p.add(res);
-        }
+        });
         poolsArray = new AsmModulePool[resPools.size()];
         int i = 0;
 
-        for (Entry<String, Pool> entry : resPools.entrySet()) {
+        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");
@@ -405,7 +405,7 @@ public final class AsmPools {
      *
      * @param outputResources The pool used to fill the jimage.
      */
-    public void fillOutputResources(Pool outputResources) {
+    public void fillOutputResources(ModulePool outputResources) {
         // First sort modules
         List<String> modules = new ArrayList<>();
         for (String k : pools.keySet()) {
@@ -414,8 +414,8 @@ public final class AsmPools {
         if (moduleSorter != null) {
             modules = moduleSorter.sort(modules);
         }
-        Pool output = new PoolImpl(outputResources.getByteOrder(),
-                ((PoolImpl)outputResources).getStringTable());
+        ModulePool output = new ModulePoolImpl(outputResources.getByteOrder(),
+                ((ModulePoolImpl)outputResources).getStringTable());
         for (String mn : modules) {
             AsmPool pool = pools.get(mn);
             pool.fillOutputResources(output);
@@ -423,17 +423,17 @@ public final class AsmPools {
         sort(outputResources, output, global.sorter);
     }
 
-    static void sort(Pool outputResources,
-            Pool transientOutput, Sorter 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.get(s));
+                outputResources.add(transientOutput.findEntry(s).get());
             }
         } else {
-            for (ModuleData res : transientOutput.getContent()) {
+            transientOutput.entries().forEach(res-> {
                 outputResources.add(res);
-            }
+            });
         }
     }
 
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ExecutableImage.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ExecutableImage.java
index d5e767cd553..499d23dd450 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ExecutableImage.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ExecutableImage.java
@@ -24,66 +24,41 @@
  */
 package jdk.tools.jlink.plugin;
 
-import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.Collections;
 import java.util.List;
-import java.util.Objects;
 import java.util.Set;
 
 /**
- * An executable runtime image. Instance of this class contains the information
- * needed to create image processes.
+ * An executable runtime image. Contains the information about the executable
+ * image created.
  */
-public abstract class ExecutableImage {
-
-    private final Path home;
-    private final List<String> args;
-    private final Set<String> modules;
-
-    protected ExecutableImage(Path home, Set<String> modules,
-            List<String> args) {
-        Objects.requireNonNull(home);
-        Objects.requireNonNull(args);
-        if (!Files.exists(home)) {
-            throw new IllegalArgumentException("Invalid image home");
-        }
-        this.home = home;
-        this.modules = Collections.unmodifiableSet(modules);
-        this.args = Collections.unmodifiableList(args);
-    }
+public interface ExecutableImage {
 
     /**
      * Image home directory,
      *
      * @return The home directory.
      */
-    public Path getHome() {
-        return home;
-    }
+    public Path getHome();
 
     /**
      * The names of the modules located in the image.
      *
      * @return The set of modules.
      */
-    public Set<String> getModules() {
-        return modules;
-    }
+    public Set<String> getModules();
 
     /**
      * The list of arguments required to execute the image.
      *
      * @return The list of arguments.
      */
-    public List<String> getExecutionArgs() {
-        return args;
-    }
+    public List<String> getExecutionArgs();
 
     /**
      * Store new arguments required to execute the image.
      *
      * @param args Additional arguments
      */
-    public abstract void storeLaunchArgs(List<String> args);
+    public void storeLaunchArgs(List<String> args);
 }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/LinkModule.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/LinkModule.java
new file mode 100644
index 00000000000..f516d8d0494
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/LinkModule.java
@@ -0,0 +1,87 @@
+/*
+ * 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.plugin;
+
+import java.lang.module.ModuleDescriptor;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+  * Link-time representation of a Java module.
+  */
+public interface LinkModule {
+
+    /**
+     * The module name.
+     *
+     * @return The name.
+     */
+    public String getName();
+
+    /**
+     * Retrieves a LinkModuleEntry from the given path (e.g:
+     * /mymodule/com.foo.bar/MyClass.class)
+     *
+     * @param path The piece of data path.
+     * @return A LinkModuleEntry of the given path, if found.
+     */
+    public Optional<ModuleEntry> findEntry(String path);
+
+    /**
+     * The module descriptor of this module.
+     *
+     * @return The module descriptor.
+     */
+    public ModuleDescriptor getDescriptor();
+
+    /**
+     * Add a LinkModuleEntry to this module.
+     *
+     * @param data The LinkModuleEntry to add.
+     */
+    public void add(ModuleEntry data);
+
+    /**
+     * Retrieves all the packages located in this module.
+     *
+     * @return The set of packages.
+     */
+    public Set<String> getAllPackages();
+
+    /**
+     * Retrieves the stream of LinkModuleEntry.
+     *
+     * @return The LinkModuleEntry stream.
+     */
+    public Stream<? extends ModuleEntry> entries();
+
+    /**
+     * Return the number of LinkModuleEntry count in this LinkModule.
+     *
+     * @return the entry count.
+     */
+    public int getEntryCount();
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java
new file mode 100644
index 00000000000..61f828fc914
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java
@@ -0,0 +1,155 @@
+/*
+ * 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.plugin;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Objects;
+import jdk.tools.jlink.internal.ImageFileCreator;
+import jdk.tools.jlink.internal.ModuleEntryImpl;
+
+/**
+ * A LinkModuleEntry is the elementary unit of data inside an image. It is
+ * generally a file. e.g.: a java class file, a resource file, a shared library,
+ * ...
+ * <br>
+ * A LinkModuleEntry is identified by a path of the form:
+ * <ul>
+ * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
+ * name}</li>
+ * <li>For other files (shared lib, launchers, config, ...):/{module name}/
+ * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}</li>
+ * </ul>
+ */
+public interface ModuleEntry {
+
+    /**
+     * Type of module data.
+     * <li>
+     * <ul>CLASS_OR_RESOURCE: A java class or resource file.</ul>
+     * <ul>CONFIG: A configuration file.</ul>
+     * <ul>NATIVE_CMD: A native process launcher.</ul>
+     * <ul>NATIVE_LIB: A native library.</ul>
+     * <ul>OTHER: Other kind of file.</ul>
+     * </li>
+     */
+    public enum Type {
+        CLASS_OR_RESOURCE,
+        CONFIG,
+        NATIVE_CMD,
+        NATIVE_LIB,
+        OTHER
+    }
+    /**
+     * The LinkModuleEntry module name.
+     *
+     * @return The module name.
+     */
+    public String getModule();
+
+    /**
+     * The LinkModuleEntry path.
+     *
+     * @return The module path.
+     */
+    public String getPath();
+
+    /**
+     * The LinkModuleEntry's type.
+     *
+     * @return The data type.
+     */
+    public Type getType();
+
+    /**
+     * The LinkModuleEntry content as an array of byte.
+     *
+     * @return An Array of bytes.
+     */
+    public byte[] getBytes();
+
+    /**
+     * The LinkModuleEntry content length.
+     *
+     * @return The length.
+     */
+    public long getLength();
+
+    /**
+     * The LinkModuleEntry stream.
+     *
+     * @return The module data stream.
+     */
+    public InputStream stream();
+
+
+    /**
+     * Create a LinkModuleEntry located inside a jimage file. Such
+     * LinkModuleEntry has a Type being equals to CLASS_OR_RESOURCE.
+     *
+     * @param path The complete resource path (contains the module radical).
+     * @param content The resource content.
+     * @param size The content size.
+     * @return A new LinkModuleEntry.
+     */
+    public static ModuleEntry create(String path, InputStream content, long size) {
+        Objects.requireNonNull(path);
+        Objects.requireNonNull(content);
+        String[] split = ImageFileCreator.splitPath(path);
+        String module = split[0];
+        return new ModuleEntryImpl(module, path, Type.CLASS_OR_RESOURCE, content, size);
+    }
+
+    /**
+     * Create a LinkModuleEntry for a file that will be located inside a jimage
+     * file.
+     *
+     * @param path The resource path.
+     * @param content The resource content.
+     * @return A new LinkModuleEntry.
+     */
+    public static ModuleEntry create(String path, byte[] content) {
+        return create(path, new ByteArrayInputStream(content),
+                content.length);
+    }
+
+    /**
+     * Create a LinkModuleEntry for a file that will be located outside a jimage
+     * file.
+     *
+     * @param module The module in which this files is located.
+     * @param path The file path locator (doesn't contain the module name).
+     * @param type The LinkModuleEntry type.
+     * @param content The file content.
+     * @param size The content size.
+     * @return A new LinkModuleEntry.
+     */
+    public static ModuleEntry create(String module, String path, ModuleEntry.Type type,
+            InputStream content, long size) {
+        Objects.requireNonNull(path);
+        Objects.requireNonNull(content);
+        return new ModuleEntryImpl(module, path, type, content, size);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModulePool.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModulePool.java
new file mode 100644
index 00000000000..4d0f230e1c6
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModulePool.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.nio.ByteOrder;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * Pool of module data.
+ */
+public interface ModulePool {
+/**
+     * Is this a read-only ModulePool?
+     *
+     * @return true if this is a read-only configuration.
+     */
+    public boolean isReadOnly();
+
+    /**
+     * Add a ModuleEntry.
+     *
+     * @param data The ModuleEntry to add.
+     */
+    public void add(ModuleEntry data);
+    /**
+     * Retrieves the module for the provided name.
+     *
+     * @param name The module name
+     * @return the module of matching name, if found
+     */
+    public Optional<LinkModule> findModule(String name);
+
+    /**
+     * The stream of modules contained in this ModulePool.
+     *
+     * @return The stream of modules.
+     */
+    public Stream<? extends LinkModule> modules();
+
+    /**
+     * Return the number of LinkModule count in this ModulePool.
+     *
+     * @return the module count.
+     */
+    public int getModuleCount();
+
+    /**
+     * Get all ModuleEntry contained in this ModulePool instance.
+     *
+     * @return The stream of LinkModuleEntries.
+     */
+    public Stream<? extends ModuleEntry> entries();
+
+    /**
+     * Return the number of ModuleEntry count in this ModulePool.
+     *
+     * @return the entry count.
+     */
+    public int getEntryCount();
+
+    /**
+     * Get the ModuleEntry for the passed path.
+     *
+     * @param path A data path
+     * @return A ModuleEntry instance or null if the data is not found
+     */
+   public Optional<ModuleEntry> findEntry(String path);
+
+    /**
+     * Check if the ModulePool contains the given ModuleEntry.
+     *
+     * @param data The module data to check existence for.
+     * @return The module data or null if not found.
+     */
+    public boolean contains(ModuleEntry data);
+
+    /**
+     * Check if the ModulePool contains some content at all.
+     *
+     * @return True, no content, false otherwise.
+     */
+    public boolean isEmpty();
+
+    /**
+     * Visit each ModuleEntry in this ModulePool to transform it and copy
+     * the transformed ModuleEntry to the output ModulePool.
+     *
+     * @param transform The function called for each ModuleEntry found in the
+     * ModulePool. The transform function should return a ModuleEntry
+     * instance which will be added to the output or it should return null if
+     * the passed ModuleEntry is to be ignored for the output.
+     *
+     * @param output The ModulePool to be filled with Visitor returned
+     * ModuleEntry.
+     */
+    public void transformAndCopy(Function<ModuleEntry, ModuleEntry> transform, ModulePool output);
+
+    /**
+     * The ByteOrder currently in use when generating the jimage file.
+     *
+     * @return The ByteOrder.
+     */
+    public ByteOrder getByteOrder();
+
+    /**
+     * Release properties such as OS, CPU name, version etc.
+     *
+     * @return the release properties
+     */
+    public Map<String, String> getReleaseProperties();
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java
index 56e51bc9bc5..30633b546d3 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java
@@ -26,7 +26,6 @@ package jdk.tools.jlink.plugin;
 
 import java.util.Collections;
 import java.util.EnumSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import jdk.tools.jlink.internal.plugins.PluginsResourceBundle;
@@ -36,14 +35,6 @@ import jdk.tools.jlink.internal.plugins.PluginsResourceBundle;
  */
 public interface Plugin {
 
-    /**
-     * Type of plugin.
-     */
-    public interface PluginType {
-
-        public String getName();
-    }
-
     /**
      * Order of categories:
      * <ol>
@@ -53,28 +44,29 @@ public interface Plugin {
      * <li>MODULEINFO_TRANSFORMER: Transform only module-info.class</li>
      * <li>SORTER: Sort resources within the resource container.</li>
      * <li>COMPRESSOR: Compress resource within the resouce containers.</li>
+     * <li>METAINFO_ADDER: Added meta info (like release, copyright etc.)</li>
      * <li>VERIFIER: Does some image verification.</li>
      * <li>PROCESSOR: Does some post processing on image.</li>
      * <li>PACKAGER: Final processing</li>
      * </ol>
      */
-    public enum CATEGORY implements PluginType {
+    public enum Category {
         FILTER("FILTER"),
         TRANSFORMER("TRANSFORMER"),
         MODULEINFO_TRANSFORMER("MODULEINFO_TRANSFORMER"),
         SORTER("SORTER"),
         COMPRESSOR("COMPRESSOR"),
+        METAINFO_ADDER("METAINFO_ADDER"),
         VERIFIER("VERIFIER"),
         PROCESSOR("PROCESSOR"),
         PACKAGER("PACKAGER");
 
         private final String name;
 
-        CATEGORY(String name) {
+        Category(String name) {
             this.name = name;
         }
 
-        @Override
         public String getName() {
             return name;
         }
@@ -91,7 +83,7 @@ public interface Plugin {
      * {@link #getStateDescription() getStateDescription} method</li>
      * </ul>
      */
-    public enum STATE {
+    public enum State {
         DISABLED,
         AUTO_ENABLED,
         FUNCTIONAL
@@ -101,7 +93,7 @@ public interface Plugin {
      * The Plugin set of types.
      * @return The set of types.
      */
-    public default Set<PluginType> getType() {
+    public default Set<Category> getType() {
         return Collections.emptySet();
     }
 
@@ -109,8 +101,8 @@ public interface Plugin {
      * The Plugin set of states.
      * @return The set of states.
      */
-    public default Set<STATE> getState() {
-        return EnumSet.of(STATE.FUNCTIONAL);
+    public default Set<State> getState() {
+        return EnumSet.of(State.FUNCTIONAL);
     }
 
     /**
@@ -191,7 +183,7 @@ public interface Plugin {
      * @return A status description.
      */
     public default String getStateDescription() {
-        return getState().contains(STATE.FUNCTIONAL)
+        return getState().contains(State.FUNCTIONAL)
                 ? PluginsResourceBundle.getMessage("main.status.ok")
                 : PluginsResourceBundle.getMessage("main.status.not.ok");
     }
@@ -206,18 +198,4 @@ public interface Plugin {
      */
     public default void configure(Map<String, String> config) {
     }
-
-    /**
-     * Configure the plugin based on the passed configuration.
-     * This method is called prior to invoke the plugin.
-     *
-     * @param config The plugin configuration.
-     * @param ctx The plugin context
-     * @throws IllegalArgumentException if a mandatory argument is missing or
-     * if an argument has invalid value.
-     *
-     */
-    public default void configure(Map<String, String> config, PluginContext ctx) {
-        configure(config);
-    }
 }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java
deleted file mode 100644
index 380ca41ac1a..00000000000
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.plugin;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.lang.module.ModuleDescriptor;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import jdk.tools.jlink.internal.ImageFileCreator;
-import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
-
-/**
- * Pool of module data.
- *
- */
-public abstract class Pool {
-
-    /**
-     * Interface to visit the content of a Pool.
-     */
-    public interface Visitor {
-
-        /**
-         * Called for each visited ModuleData.
-         *
-         * @param content A ModuleData
-         * @return A ModuleData instance or null if the passed ModuleData is to
-         * be removed from the image.
-         * @throws PluginException
-         */
-        public ModuleData visit(ModuleData content);
-    }
-
-    /**
-     * Type of module data.
-     * <li>
-     * <ul>CLASS_OR_RESOURCE: A java class or resource file.</ul>
-     * <ul>CONFIG: A configuration file.</ul>
-     * <ul>NATIVE_CMD: A native process launcher.</ul>
-     * <ul>NATIVE_LIB: A native library.</ul>
-     * <ul>OTHER: Other kind of file.</ul>
-     * </li>
-     */
-    public static enum ModuleDataType {
-
-        CLASS_OR_RESOURCE,
-        CONFIG,
-        NATIVE_CMD,
-        NATIVE_LIB,
-        OTHER;
-    }
-
-    /**
-     * A module in the pool.
-     */
-    public interface Module {
-
-        /**
-         * The module name.
-         *
-         * @return The name.
-         */
-        public String getName();
-
-        /**
-         * Retrieves a ModuleData from a path (e.g:
-         * /mymodule/com.foo.bar/MyClass.class)
-         *
-         * @param path The piece of data path.
-         * @return A ModuleData or null if the path doesn't identify a
-         * ModuleData.
-         */
-        public ModuleData get(String path);
-
-        /**
-         * The module descriptor of this module.
-         *
-         * @return The module descriptor.
-         */
-        public ModuleDescriptor getDescriptor();
-
-        /**
-         * Add a ModuleData to this module.
-         *
-         * @param data The ModuleData to add.
-         */
-        public void add(ModuleData data);
-
-        /**
-         * Retrieves all the packages located in this module.
-         *
-         * @return The set of packages.
-         */
-        public Set<String> getAllPackages();
-
-        /**
-         * Retrieves the collection of ModuleData.
-         *
-         * @return The ModuleData collection.
-         */
-        public Collection<ModuleData> getContent();
-
-    }
-
-    private class ModuleImpl implements Module {
-
-        private final Map<String, ModuleData> moduleContent = new LinkedHashMap<>();
-        private ModuleDescriptor descriptor;
-        private final String name;
-
-        private ModuleImpl(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public ModuleData get(String path) {
-            if (!path.startsWith("/")) {
-                path = "/" + path;
-            }
-            if (!path.startsWith("/" + name)) {
-                path = "/" + name + path;
-            }
-            return moduleContent.get(path);
-        }
-
-        @Override
-        public ModuleDescriptor getDescriptor() {
-            if (descriptor == null) {
-                String p = "/" + name + "/module-info.class";
-                ModuleData content = moduleContent.get(p);
-                if (content == null) {
-                    throw new PluginException("No module-info for " + name
-                            + " module");
-                }
-                ByteBuffer bb = ByteBuffer.wrap(content.getBytes());
-                descriptor = ModuleDescriptor.read(bb);
-            }
-            return descriptor;
-        }
-
-        @Override
-        public void add(ModuleData data) {
-            if (isReadOnly()) {
-                throw new PluginException("pool is readonly");
-            }
-            Objects.requireNonNull(data);
-            if (!data.getModule().equals(name)) {
-                throw new PluginException("Can't add resource " + data.getPath()
-                        + " to module " + name);
-            }
-            Pool.this.add(data);
-        }
-
-        @Override
-        public Set<String> getAllPackages() {
-            Set<String> pkgs = new HashSet<>();
-            moduleContent.values().stream().filter(m -> m.getType().
-                    equals(ModuleDataType.CLASS_OR_RESOURCE)).forEach((res) -> {
-                // Module metadata only contains packages with .class files
-                if (ImageFileCreator.isClassPackage(res.getPath())) {
-                    String[] split = ImageFileCreator.splitPath(res.getPath());
-                    String pkg = split[1];
-                    if (pkg != null && !pkg.isEmpty()) {
-                        pkgs.add(pkg);
-                    }
-                }
-            });
-            return pkgs;
-        }
-
-        @Override
-        public String toString() {
-            return getName();
-        }
-
-        @Override
-        public Collection<ModuleData> getContent() {
-            return Collections.unmodifiableCollection(moduleContent.values());
-        }
-    }
-
-    /**
-     * A ModuleData is the elementary unit of data inside an image. It is
-     * generally a file. e.g.: a java class file, a resource file, a shared
-     * library, ...
-     * <br>
-     * A ModuleData is identified by a path of the form:
-     * <ul>
-     * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
-     * name}</li>
-     * <li>For other files (shared lib, launchers, config, ...):/{module name}/
-     * {@literal bin|conf|native}/{dir1}/.../{dirN}/{file name}</li>
-     * </ul>
-     */
-    public static class ModuleData {
-
-        private final ModuleDataType type;
-        private final String path;
-        private final String module;
-        private final long length;
-        private final InputStream stream;
-        private byte[] buffer;
-
-        /**
-         * Create a new ModuleData.
-         *
-         * @param module The module name.
-         * @param path The data path identifier.
-         * @param type The data type.
-         * @param stream The data content stream.
-         * @param length The stream length.
-         */
-        public ModuleData(String module, String path, ModuleDataType type,
-                InputStream stream, long length) {
-            Objects.requireNonNull(module);
-            Objects.requireNonNull(path);
-            Objects.requireNonNull(type);
-            Objects.requireNonNull(stream);
-            this.path = path;
-            this.type = type;
-            this.module = module;
-            this.stream = stream;
-            this.length = length;
-        }
-
-        /**
-         * The ModuleData module name.
-         *
-         * @return The module name.
-         */
-        public final String getModule() {
-            return module;
-        }
-
-        /**
-         * The ModuleData path.
-         *
-         * @return The module path.
-         */
-        public final String getPath() {
-            return path;
-        }
-
-        /**
-         * The ModuleData type.
-         *
-         * @return The data type.
-         */
-        public final ModuleDataType getType() {
-            return type;
-        }
-
-        /**
-         * The ModuleData content as an array of byte.
-         *
-         * @return An Array of bytes.
-         */
-        public byte[] getBytes() {
-            if (buffer == null) {
-                try {
-                    buffer = stream.readAllBytes();
-                } catch (IOException ex) {
-                    throw new UncheckedIOException(ex);
-                }
-            }
-            return buffer;
-        }
-
-        /**
-         * The ModuleData content length.
-         *
-         * @return The length.
-         */
-        public long getLength() {
-            return length;
-        }
-
-        /**
-         * The ModuleData stream.
-         *
-         * @return The module data stream.
-         */
-        public InputStream stream() {
-            return stream;
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 7;
-            hash = 89 * hash + Objects.hashCode(this.path);
-            return hash;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof ModuleData)) {
-                return false;
-            }
-            ModuleData f = (ModuleData) other;
-            return f.path.equals(path);
-        }
-
-        @Override
-        public String toString() {
-            return getPath();
-        }
-    }
-
-    private final Map<String, ModuleData> resources = new LinkedHashMap<>();
-    private final Map<String, ModuleImpl> modules = new LinkedHashMap<>();
-    private final ModuleImpl fileCopierModule = new ModuleImpl(FileCopierPlugin.FAKE_MODULE);
-
-    private final ByteOrder order;
-
-    protected Pool() {
-        this(ByteOrder.nativeOrder());
-    }
-
-    protected Pool(ByteOrder order) {
-        Objects.requireNonNull(order);
-        this.order = order;
-    }
-
-    /**
-     * Read only state. No data can be added to a ReadOnly Pool.
-     *
-     * @return true if readonly false otherwise.
-     */
-    public abstract boolean isReadOnly();
-
-    /**
-     * Add a ModuleData.
-     *
-     * @param data The ModuleData to add.
-     */
-    public void add(ModuleData data) {
-        if (isReadOnly()) {
-            throw new PluginException("pool is readonly");
-        }
-        Objects.requireNonNull(data);
-        if (resources.get(data.getPath()) != null) {
-            throw new PluginException("Resource " + data.getPath()
-                    + " already present");
-        }
-        String modulename = data.getModule();
-        ModuleImpl m = modules.get(modulename);
-        // ## TODO: FileCopierPlugin should not add content to a module
-        // FAKE_MODULE is not really a module to be added in the image
-        if (FileCopierPlugin.FAKE_MODULE.equals(modulename)) {
-            m = fileCopierModule;
-        }
-        if (m == null) {
-            m = new ModuleImpl(modulename);
-            modules.put(modulename, m);
-        }
-        resources.put(data.getPath(), data);
-        m.moduleContent.put(data.getPath(), data);
-    }
-
-    /**
-     * Retrieves the module for the provided name.
-     *
-     * @param name The module name
-     * @return the module or null if the module doesn't exist.
-     */
-    public Module getModule(String name) {
-        Objects.requireNonNull(name);
-        return modules.get(name);
-    }
-
-    /**
-     * The collection of modules contained in this pool.
-     *
-     * @return The collection of modules.
-     */
-    public Collection<Module> getModules() {
-        return Collections.unmodifiableCollection(modules.values());
-    }
-
-    /**
-     * Get all ModuleData contained in this pool instance.
-     *
-     * @return The collection of resources;
-     */
-    public Collection<ModuleData> getContent() {
-        return Collections.unmodifiableCollection(resources.values());
-    }
-
-    /**
-     * Get the ModuleData for the passed path.
-     *
-     * @param path A data path
-     * @return A ModuleData instance or null if the data is not found
-     */
-    public ModuleData get(String path) {
-        Objects.requireNonNull(path);
-        return resources.get(path);
-    }
-
-    /**
-     * Check if the pool contains this data.
-     *
-     * @param data The module data to check existence for.
-     * @return The module data or null if not found.
-     */
-    public boolean contains(ModuleData data) {
-        Objects.requireNonNull(data);
-        return get(data.getPath()) != null;
-    }
-
-    /**
-     * Check if the Pool contains some content.
-     *
-     * @return True, no content, false otherwise.
-     */
-    public boolean isEmpty() {
-        return resources.isEmpty();
-    }
-
-    /**
-     * Visit the pool.
-     *
-     * @param visitor The Visitor called for each ModuleData found in the pool.
-     * @param output The pool to be filled with Visitor returned ModuleData.
-     */
-    public void visit(Visitor visitor, Pool output) {
-        for (ModuleData resource : getContent()) {
-            ModuleData res = visitor.visit(resource);
-            if (res != null) {
-                output.add(res);
-            }
-        }
-    }
-
-    /**
-     * The ByteOrder currently in use when generating the jimage file.
-     *
-     * @return The ByteOrder.
-     */
-    public ByteOrder getByteOrder() {
-        return order;
-    }
-
-    /**
-     * Create a ModuleData located inside a jimage file. Such ModuleData has a
-     * ModuleDataType being equals to CLASS_OR_RESOURCE.
-     *
-     * @param path The complete resource path (contains the module radical).
-     * @param content The resource content.
-     * @param size The content size.
-     * @return A new ModuleData.
-     */
-    public static ModuleData newResource(String path, InputStream content, long size) {
-        Objects.requireNonNull(path);
-        Objects.requireNonNull(content);
-        String[] split = ImageFileCreator.splitPath(path);
-        String module = split[0];
-        return new ModuleData(module, path, ModuleDataType.CLASS_OR_RESOURCE, content, size);
-    }
-
-    /**
-     * Create a ModuleData for a file that will be located inside a jimage file.
-     *
-     * @param path The resource path.
-     * @param content The resource content.
-     * @return A new ModuleData.
-     */
-    public static ModuleData newResource(String path, byte[] content) {
-        return newResource(path, new ByteArrayInputStream(content),
-                content.length);
-    }
-
-    /**
-     * Create a ModuleData for a file that will be located outside a jimage
-     * file.
-     *
-     * @param module The module in which this files is located.
-     * @param path The file path locator (doesn't contain the module name).
-     * @param type The ModuleData type.
-     * @param content The file content.
-     * @param size The content size.
-     * @return A new ModuleData.
-     */
-    public static ModuleData newImageFile(String module, String path, ModuleDataType type,
-            InputStream content, long size) {
-        Objects.requireNonNull(path);
-        Objects.requireNonNull(content);
-        return new ModuleData(module, path, type, content, size);
-    }
-
-}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/TransformerPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/TransformerPlugin.java
index 4af4897e636..15133221c43 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/TransformerPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/TransformerPlugin.java
@@ -40,5 +40,5 @@ public interface TransformerPlugin extends Plugin {
      *
      * @throws PluginException
      */
-    public void visit(Pool in, Pool out);
+    public void visit(ModulePool in, ModulePool out);
 }
diff --git a/jdk/src/jdk.jlink/share/classes/module-info.java b/jdk/src/jdk.jlink/share/classes/module-info.java
index 49e426fed12..c23116404ac 100644
--- a/jdk/src/jdk.jlink/share/classes/module-info.java
+++ b/jdk/src/jdk.jlink/share/classes/module-info.java
@@ -24,9 +24,7 @@
  */
 
 module jdk.jlink {
-    exports jdk.tools.jlink;
     exports jdk.tools.jlink.plugin;
-    exports jdk.tools.jlink.builder;
 
     requires jdk.internal.opt;
     requires jdk.jdeps;
@@ -46,5 +44,5 @@ module jdk.jlink {
     provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
     provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.IncludeLocalesPlugin;
     provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin;
-    provides jdk.tools.jlink.plugin.PostProcessorPlugin with jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin;
 }
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index de8331e3622..6e1cd7385d4 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -116,10 +116,8 @@
 
 # jdk_beans
 
-java/beans/XMLEncoder/Test4903007.java                          8060027 generic-all
-java/beans/XMLEncoder/java_awt_GridBagLayout.java               8060027 generic-all
-java/beans/XMLDecoder/8028054/TestConstructorFinder.java        8060027 generic-all
-java/beans/XMLDecoder/8028054/TestMethodFinder.java             8060027 generic-all
+java/beans/XMLDecoder/8028054/TestConstructorFinder.java        8156579 generic-all
+java/beans/XMLDecoder/8028054/TestMethodFinder.java             8156579 generic-all
 
 java/beans/Introspector/8132566/OverridePropertyInfoTest.java   8132565 generic-all
 java/beans/Introspector/8132566/OverrideUserDefPropertyInfoTest.java 8132565 generic-all
@@ -145,6 +143,12 @@ java/lang/management/MemoryMXBean/LowMemoryTest.java            8130339 generic-
 
 ############################################################################
 
+# jdk_io
+
+java/io/pathNames/GeneralWin32.java                             8156595 windows-all
+
+############################################################################
+
 # jdk_jmx
 
 com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java 8030957 aix-all
@@ -210,6 +214,10 @@ sun/security/krb5/auto/Unreachable.java                         7164518 macosx-a
 java/security/KeyPairGenerator/SolarisShortDSA.java             7041639 solaris-all
 sun/security/tools/keytool/standard.sh                          7041639 solaris-all
 
+sun/security/tools/keytool/ListKeychainStore.sh                 8156889 macosx-all
+
+sun/security/mscapi/ShortRSAKey1024.sh                          8153948 windows-all
+
 java/security/Security/ClassLoaderDeadlock/Deadlock2.sh         8062758 generic-all
 
 sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java      8026393 generic-all
@@ -224,6 +232,8 @@ sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java            8077138,8023434
 sun/security/pkcs11/KeyAgreement/TestDH.java                    8077138,8023434 windows-all
 sun/security/pkcs11/KeyAgreement/TestInterop.java               8077138,8023434 windows-all
 sun/security/pkcs11/KeyAgreement/TestShort.java                 8077138,8023434 windows-all
+sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java           8154910 windows-all
+sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java         8154910 windows-all
 sun/security/pkcs11/KeyGenerator/DESParity.java                 8077138,8023434 windows-all
 sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java          8077138,8023434 windows-all
 sun/security/pkcs11/KeyPairGenerator/TestDH2048.java            8077138,8023434 windows-all
@@ -288,7 +298,6 @@ sun/security/x509/URICertStore/ExtensionsWithLDAP.java          8134577 generic-
 
 # jdk_sound
 
-javax/sound/midi/Gervill/SoftProvider/GetDevice.java            8059743 generic-all
 javax/sound/sampled/DirectAudio/bug6400879.java                 8148915 linux-all
 
 ############################################################################
@@ -323,6 +332,8 @@ tools/launcher/FXLauncherTest.java                              8068049 linux-al
 
 tools/pack200/Pack200Props.java                                 8155857 generic-all
 
+tools/pack200/TestNormal.java                                   8156807 windows-all
+
 ############################################################################
 
 # jdk_jdi
diff --git a/jdk/test/com/oracle/security/ucrypto/TestDigest.java b/jdk/test/com/oracle/security/ucrypto/TestDigest.java
index 5bd6f412f29..5dabb55095e 100644
--- a/jdk/test/com/oracle/security/ucrypto/TestDigest.java
+++ b/jdk/test/com/oracle/security/ucrypto/TestDigest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug     7088989
+ * @bug     7088989 8000415
  * @summary Ensure the various message digests works correctly
  * @key randomness
  */
@@ -40,84 +40,106 @@ public class TestDigest extends UcryptoTest {
     private static final String[] MD_ALGOS = {
         "MD5",
         "SHA",
+        "SHA-224",
         "SHA-256",
         "SHA-384",
-        "SHA-512"
+        "SHA-512",
+        "SHA3-224",
+        "SHA3-256",
+        "SHA3-384",
+        "SHA3-512"
     };
 
     public static void main(String[] args) throws Exception {
         main(new TestDigest(), null);
     }
 
-    public void doTest(Provider p) {
+    public void doTest(Provider p) throws Exception {
         boolean testPassed = true;
         byte[] msg = new byte[200];
         (new SecureRandom()).nextBytes(msg);
         String interopProvName = "SUN";
 
+        MessageDigest md, md2;
+
         for (String a : MD_ALGOS) {
+            System.out.println("Testing " + a);
             try {
-                MessageDigest md, md2;
-                try {
-                    md = MessageDigest.getInstance(a, p);
-                } catch (NoSuchAlgorithmException nsae) {
-                    System.out.println("Skipping Unsupported MD algo: " + a);
-                    continue;
-                }
-                md2 = MessageDigest.getInstance(a, interopProvName);
-                // Test Interoperability for update+digest calls
-                for (int i = 0; i < 3; i++) {
-                    md.update(msg);
-                    byte[] digest = md.digest();
-                    md2.update(msg);
-                    byte[] digest2 = md2.digest();
-                    if (!Arrays.equals(digest, digest2)) {
-                        System.out.println("DIFF1 FAILED for: " + a + " at iter " + i);
-                        testPassed = false;
-                    }
-                }
-
-                // Test Interoperability for digest calls
                 md = MessageDigest.getInstance(a, p);
+            } catch (NoSuchAlgorithmException nsae) {
+                System.out.println("=> Skip, unsupported");
+                continue;
+            }
+            try {
                 md2 = MessageDigest.getInstance(a, interopProvName);
+            } catch (NoSuchAlgorithmException nsae) {
+                System.out.println("=> Skip, no interop provider found");
+                continue;
+            }
 
-                for (int i = 0; i < 3; i++) {
-                    byte[] digest = md.digest();
-                    byte[] digest2 = md2.digest();
-                    if (!Arrays.equals(digest, digest2)) {
-                        System.out.println("DIFF2 FAILED for: " + a + " at iter " + i);
-                        testPassed = false;
-                    }
+            // Test Interoperability for update+digest calls
+            for (int i = 0; i < 3; i++) {
+                md.update(msg);
+                byte[] digest = md.digest();
+                md2.update(msg);
+                byte[] digest2 = md2.digest();
+                if (!Arrays.equals(digest, digest2)) {
+                    System.out.println("DIFF1 FAILED at iter " + i);
+                    testPassed = false;
+                } else {
+                    System.out.println("...diff1 test passed");
                 }
+            }
 
-                // Test Cloning functionality
-                md = MessageDigest.getInstance(a, p);
-                md2 = (MessageDigest) md.clone(); // clone right after construction
+            // Test Interoperability for digest calls
+            md = MessageDigest.getInstance(a, p);
+            md2 = MessageDigest.getInstance(a, interopProvName);
+
+            for (int i = 0; i < 3; i++) {
                 byte[] digest = md.digest();
                 byte[] digest2 = md2.digest();
                 if (!Arrays.equals(digest, digest2)) {
-                    System.out.println("DIFF-3.1 FAILED for: " + a);
+                    System.out.println("DIFF2 FAILED at iter " + i);
                     testPassed = false;
+                } else {
+                    System.out.println("...diff2 test passed");
                 }
-                md.update(msg);
-                md2 = (MessageDigest) md.clone(); // clone again after update call
-                digest = md.digest();
-                digest2 = md2.digest();
-                if (!Arrays.equals(digest, digest2)) {
-                    System.out.println("DIFF-3.2 FAILED for: " + a);
-                    testPassed = false;
-                }
-                md2 = (MessageDigest) md.clone(); // clone after digest
-                digest = md.digest();
-                digest2 = md2.digest();
-                if (!Arrays.equals(digest, digest2)) {
-                    System.out.println("DIFF-3.3 FAILED for: " + a);
-                    testPassed = false;
-                }
-            } catch(Exception ex) {
-                System.out.println("Unexpected Exception: " + a);
-                ex.printStackTrace();
+            }
+
+            // Test Cloning functionality if supported
+            md = MessageDigest.getInstance(a, p);
+            try {
+                md2 = (MessageDigest) md.clone(); // clone right after construction
+            } catch (CloneNotSupportedException cnse) {
+                System.out.println("...no clone support");
+                continue;
+            }
+            byte[] digest = md.digest();
+            byte[] digest2 = md2.digest();
+            if (!Arrays.equals(digest, digest2)) {
+                System.out.println("DIFF-3.1 FAILED");
                 testPassed = false;
+            } else {
+                System.out.println("...diff3.1 tests passed");
+            }
+            md.update(msg);
+            md2 = (MessageDigest) md.clone(); // clone again after update call
+            digest = md.digest();
+            digest2 = md2.digest();
+            if (!Arrays.equals(digest, digest2)) {
+                System.out.println("DIFF-3.2 FAILED");
+                testPassed = false;
+            } else {
+                System.out.println("...diff3.2 tests passed");
+            }
+            md2 = (MessageDigest) md.clone(); // clone after digest
+            digest = md.digest();
+            digest2 = md2.digest();
+            if (!Arrays.equals(digest, digest2)) {
+                System.out.println("DIFF-3.3 FAILED");
+                testPassed = false;
+            } else {
+                System.out.println("...diff3.3 tests passed");
             }
         }
         if (!testPassed) {
diff --git a/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java b/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
index a162debb3f8..9052737aad5 100644
--- a/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
+++ b/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
@@ -228,12 +228,18 @@ public class FieldSetAccessibleTest {
     }
 
     static boolean test(String s, boolean addExports) {
+        String clsName = s.replace('/', '.').substring(0, s.length() - 6);
         try {
+            System.out.println("Loading " + clsName);
             final Class<?> c = Class.forName(
-                    s.replace('/', '.').substring(0, s.length() - 6),
+                    clsName,
                     false,
                     systemClassLoader);
             return test(c, addExports);
+        } catch (VerifyError ve) {
+            System.err.println("VerifyError for " + clsName);
+            ve.printStackTrace(System.err);
+            failed.add(s);
         } catch (Exception t) {
             t.printStackTrace(System.err);
             failed.add(s);
diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh
index 3872f813ffd..a00c14077d6 100644
--- a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh
+++ b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh
@@ -106,7 +106,7 @@ done
 # run test
 ${TESTJAVA}${FS}bin${FS}java \
         ${TESTVMOPTS} \
-        -verbose:class -Xlog:classload -cp . \
+        -verbose:class -Xlog:class+load -cp . \
         -Dtest.classes=${TESTCLASSES} \
         Starter cross
 # -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass \
diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh
index 198cd70827a..1289b4c861e 100644
--- a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh
+++ b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh
@@ -102,7 +102,7 @@ done
 # run test
 ${TESTJAVA}${FS}bin${FS}java \
         ${TESTVMOPTS} \
-        -verbose:class -Xlog:classload -cp . \
+        -verbose:class -Xlog:class+load -cp . \
         -Dtest.classes=${TESTCLASSES} \
         Starter one-way
 # -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass \
diff --git a/jdk/test/java/lang/StackWalker/CountLocalSlots.java b/jdk/test/java/lang/StackWalker/CountLocalSlots.java
new file mode 100644
index 00000000000..c78a4cb7bf4
--- /dev/null
+++ b/jdk/test/java/lang/StackWalker/CountLocalSlots.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8147039
+ * @summary Confirm locals[] always has expected length, even for "dead" locals
+ * @compile LocalsAndOperands.java
+ * @run testng/othervm -Xcomp CountLocalSlots
+ */
+
+import org.testng.annotations.Test;
+import java.lang.StackWalker.StackFrame;
+
+public class CountLocalSlots {
+    final static boolean debug = true;
+
+    @Test(dataProvider = "provider", dataProviderClass = LocalsAndOperands.class)
+    public void countLocalSlots(StackFrame... frames) {
+        for (StackFrame frame : frames) {
+            if (debug) {
+                System.out.println("Running countLocalSlots");
+                LocalsAndOperands.dumpStackWithLocals(frames);
+            }
+            // Confirm expected number of locals
+            String methodName = frame.getMethodName();
+            Integer expectedObj = (Integer) LocalsAndOperands.Tester.NUM_LOCALS.get(methodName);
+            if (expectedObj == null) {
+                if (!debug) { LocalsAndOperands.dumpStackWithLocals(frames); }
+                throw new RuntimeException("No NUM_LOCALS entry for " +
+                        methodName + "().  Update test?");
+            }
+            Object[] locals = (Object[]) LocalsAndOperands.invokeGetLocals(frame);
+            if (locals.length != expectedObj) {
+                if (!debug) { LocalsAndOperands.dumpStackWithLocals(frames); }
+                throw new RuntimeException(methodName + "(): number of locals (" +
+                        locals.length + ") did not match expected (" + expectedObj + ")");
+            }
+        }
+    }
+}
diff --git a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java b/jdk/test/java/lang/StackWalker/LocalsAndOperands.java
index 63a6731a164..b253ab27e81 100644
--- a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java
+++ b/jdk/test/java/lang/StackWalker/LocalsAndOperands.java
@@ -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
@@ -23,17 +23,20 @@
 
 /*
  * @test
- * @bug 8020968
- * @summary Sanity test for locals and operands
- * @run main LocalsAndOperands
+ * @bug 8020968 8147039
+ * @summary Tests for locals and operands
+ * @run testng LocalsAndOperands
  */
 
+import org.testng.annotations.*;
 import java.lang.StackWalker.StackFrame;
 import java.lang.reflect.*;
-import java.util.List;
-import java.util.stream.Collectors;
+import java.util.*;
+import java.util.stream.*;
 
 public class LocalsAndOperands {
+    static final boolean debug = true;
+
     static Class<?> liveStackFrameClass;
     static Class<?> primitiveValueClass;
     static StackWalker extendedWalker;
@@ -41,92 +44,319 @@ public class LocalsAndOperands {
     static Method getOperands;
     static Method getMonitors;
     static Method primitiveType;
-    public static void main(String... args) throws Exception {
-        liveStackFrameClass = Class.forName("java.lang.LiveStackFrame");
-        primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue");
 
-        getLocals = liveStackFrameClass.getDeclaredMethod("getLocals");
-        getLocals.setAccessible(true);
+    static {
+        try {
+            liveStackFrameClass = Class.forName("java.lang.LiveStackFrame");
+            primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue");
 
-        getOperands = liveStackFrameClass.getDeclaredMethod("getStack");
-        getOperands.setAccessible(true);
+            getLocals = liveStackFrameClass.getDeclaredMethod("getLocals");
+            getLocals.setAccessible(true);
 
-        getMonitors = liveStackFrameClass.getDeclaredMethod("getMonitors");
-        getMonitors.setAccessible(true);
+            getOperands = liveStackFrameClass.getDeclaredMethod("getStack");
+            getOperands.setAccessible(true);
 
-        primitiveType = primitiveValueClass.getDeclaredMethod("type");
-        primitiveType.setAccessible(true);
+            getMonitors = liveStackFrameClass.getDeclaredMethod("getMonitors");
+            getMonitors.setAccessible(true);
 
-        Method method = liveStackFrameClass.getMethod("getStackWalker");
-        method.setAccessible(true);
-        extendedWalker = (StackWalker) method.invoke(null);
-        new LocalsAndOperands(extendedWalker, true).test();
+            primitiveType = primitiveValueClass.getDeclaredMethod("type");
+            primitiveType.setAccessible(true);
 
-        // no access to local and operands.
-        new LocalsAndOperands(StackWalker.getInstance(), false).test();
+            Method method = liveStackFrameClass.getMethod("getStackWalker");
+            method.setAccessible(true);
+            extendedWalker = (StackWalker) method.invoke(null);
+        } catch (Throwable t) { throw new RuntimeException(t); }
     }
 
-    private final StackWalker walker;
-    private final boolean extended;
-    LocalsAndOperands(StackWalker walker, boolean extended) {
-        this.walker = walker;
-        this.extended = extended;
+    /** Helper method to return a StackFrame's locals */
+    static Object[] invokeGetLocals(StackFrame arg) {
+        try {
+            return (Object[]) getLocals.invoke(arg);
+        } catch (Exception e) { throw new RuntimeException(e); }
     }
 
-    synchronized void test() throws Exception {
-        int x = 10;
-        char c = 'z';
-        String hi = "himom";
-        long l = 1000000L;
-        double d =  3.1415926;
+    /*****************
+     * DataProviders *
+     *****************/
 
-        List<StackWalker.StackFrame> frames = walker.walk(s -> s.collect(Collectors.toList()));
-        if (extended) {
-            for (StackWalker.StackFrame f : frames) {
-                System.out.println("frame: " + f);
-                Object[] locals = (Object[]) getLocals.invoke(f);
+    /** Calls testLocals() and provides LiveStackFrames for testLocals* methods */
+    @DataProvider
+    public static StackFrame[][] provider() {
+        return new StackFrame[][] {
+            new Tester().testLocals()
+        };
+    }
+
+    /**
+     * Calls testLocalsKeepAlive() and provides LiveStackFrames for testLocals* methods.
+     * Local variables in testLocalsKeepAlive() are ensured to not become dead.
+     */
+    @DataProvider
+    public static StackFrame[][] keepAliveProvider() {
+        return new StackFrame[][] {
+            new Tester().testLocalsKeepAlive()
+        };
+    }
+
+    /**
+     * Provides StackFrames from a StackWalker without the LOCALS_AND_OPERANDS
+     * option.
+     */
+    @DataProvider
+    public static StackFrame[][] noLocalsProvider() {
+        // Use default StackWalker
+        return new StackFrame[][] {
+            new Tester(StackWalker.getInstance(), true).testLocals()
+        };
+    }
+
+    /**
+     * Calls testLocals() and provides LiveStackFrames for *all* called methods,
+     * including test infrastructure (jtreg, testng, etc)
+     *
+     */
+    @DataProvider
+    public static StackFrame[][] unfilteredProvider() {
+        return new StackFrame[][] {
+            new Tester(extendedWalker, false).testLocals()
+        };
+    }
+
+    /****************
+     * Test methods *
+     ****************/
+
+    /**
+     * Check for expected local values and types in the LiveStackFrame
+     */
+    @Test(dataProvider = "keepAliveProvider")
+    public static void checkLocalValues(StackFrame... frames) {
+        if (debug) {
+            System.out.println("Running checkLocalValues");
+            dumpStackWithLocals(frames);
+        }
+        Arrays.stream(frames).filter(f -> f.getMethodName()
+                                           .equals("testLocalsKeepAlive"))
+                                           .forEach(
+            f -> {
+                Object[] locals = invokeGetLocals(f);
                 for (int i = 0; i < locals.length; i++) {
-                    System.out.format("  local %d: %s type %s\n", i, locals[i], type(locals[i]));
+                    // Value
+                    String expected = Tester.LOCAL_VALUES[i];
+                    Object observed = locals[i];
+                    if (expected != null /* skip nulls in golden values */ &&
+                            !expected.equals(observed.toString())) {
+                        System.err.println("Local value mismatch:");
+                        if (!debug) { dumpStackWithLocals(frames); }
+                        throw new RuntimeException("local " + i + " value is " +
+                                observed + ", expected " + expected);
+                    }
 
-                    // check for non-null locals in LocalsAndOperands.test()
-                    if (f.getClassName().equals("LocalsAndOperands") &&
-                            f.getMethodName().equals("test")) {
-                        if (locals[i] == null) {
-                            throw new RuntimeException("kept-alive locals should not be null");
-                        }
+                    // Type
+                    expected = Tester.LOCAL_TYPES[i];
+                    observed = type(locals[i]);
+                    if (expected != null /* skip nulls in golden values */ &&
+                            !expected.equals(observed)) {
+                        System.err.println("Local type mismatch:");
+                        if (!debug) { dumpStackWithLocals(frames); }
+                        throw new RuntimeException("local " + i + " type is " +
+                                observed + ", expected " + expected);
                     }
                 }
-
-                Object[] operands = (Object[]) getOperands.invoke(f);
-                for (int i = 0; i < operands.length; i++) {
-                    System.out.format("  operand %d: %s type %s%n", i, operands[i],
-                                      type(operands[i]));
-                }
-
-                Object[] monitors = (Object[]) getMonitors.invoke(f);
-                for (int i = 0; i < monitors.length; i++) {
-                    System.out.format("  monitor %d: %s%n", i, monitors[i]);
-                }
             }
-        } else {
-            for (StackFrame f : frames) {
-                if (liveStackFrameClass.isInstance(f)) {
-                    throw new RuntimeException("should not be LiveStackFrame");
-                }
-            }
-        }
-        // Use local variables so they stay alive
-        System.out.println("Stayin' alive: "+x+" "+c+" "+hi+" "+l+" "+d);
+        );
     }
 
-    String type(Object o) throws Exception {
-        if (o == null) {
-            return "null";
-        } else if (primitiveValueClass.isInstance(o)) {
-            char c = (char)primitiveType.invoke(o);
-            return String.valueOf(c);
-        } else {
-            return o.getClass().getName();
+    /**
+     * Basic sanity check for locals and operands
+     */
+    @Test(dataProvider = "provider")
+    public static void sanityCheck(StackFrame... frames) {
+        if (debug) {
+            System.out.println("Running sanityCheck");
         }
+        try {
+            Stream<StackFrame> stream = Arrays.stream(frames);
+            if (debug) {
+                stream.forEach(LocalsAndOperands::printLocals);
+            } else {
+                System.out.println(stream.count() + " frames");
+            }
+        } catch (Throwable t) {
+            dumpStackWithLocals(frames);
+            throw t;
+        }
+    }
+
+    /**
+     * Sanity check for locals and operands, including testng/jtreg frames
+     */
+    @Test(dataProvider = "unfilteredProvider")
+    public static void unfilteredSanityCheck(StackFrame... frames) {
+        if (debug) {
+            System.out.println("Running unfilteredSanityCheck");
+        }
+        try {
+            Stream<StackFrame> stream = Arrays.stream(frames);
+            if (debug) {
+                stream.forEach(f -> { System.out.println(f + ": " +
+                        invokeGetLocals(f).length + " locals"); } );
+            } else {
+                System.out.println(stream.count() + " frames");
+            }
+        } catch (Throwable t) {
+            dumpStackWithLocals(frames);
+            throw t;
+        }
+    }
+
+    /**
+     * Test that LiveStackFrames are not provided with the default StackWalker
+     * options.
+     */
+    @Test(dataProvider = "noLocalsProvider")
+    public static void withoutLocalsAndOperands(StackFrame... frames) {
+        for (StackFrame frame : frames) {
+            if (liveStackFrameClass.isInstance(frame)) {
+                throw new RuntimeException("should not be LiveStackFrame");
+            }
+        }
+    }
+
+    static class Tester {
+        private StackWalker walker;
+        private boolean filter = true; // Filter out testng/jtreg/etc frames?
+
+        Tester() {
+            this.walker = extendedWalker;
+        }
+
+        Tester(StackWalker walker, boolean filter) {
+            this.walker = walker;
+            this.filter = filter;
+        }
+
+        /**
+         * Perform stackwalk without keeping local variables alive and return an
+         * array of the collected StackFrames
+         */
+        private synchronized StackFrame[] testLocals() {
+            // Unused local variables will become dead
+            int x = 10;
+            char c = 'z';
+            String hi = "himom";
+            long l = 1000000L;
+            double d =  3.1415926;
+
+            if (filter) {
+                return walker.walk(s -> s.filter(f -> TEST_METHODS.contains(f
+                        .getMethodName())).collect(Collectors.toList()))
+                        .toArray(new StackFrame[0]);
+            } else {
+                return walker.walk(s -> s.collect(Collectors.toList()))
+                        .toArray(new StackFrame[0]);
+            }
+        }
+
+        /**
+         * Perform stackwalk, keeping local variables alive, and return a list of
+         * the collected StackFrames
+         */
+        private synchronized StackFrame[] testLocalsKeepAlive() {
+            int x = 10;
+            char c = 'z';
+            String hi = "himom";
+            long l = 1000000L;
+            double d =  3.1415926;
+
+            List<StackWalker.StackFrame> frames;
+            if (filter) {
+                frames = walker.walk(s -> s.filter(f -> TEST_METHODS.contains(f
+                        .getMethodName())).collect(Collectors.toList()));
+            } else {
+                frames = walker.walk(s -> s.collect(Collectors.toList()));
+            }
+
+            // Use local variables so they stay alive
+            System.out.println("Stayin' alive: "+x+" "+c+" "+hi+" "+l+" "+d);
+            return frames.toArray(new StackFrame[0]); // FIXME: convert to Array here
+        }
+
+        // Expected values for locals in testLocals() & testLocalsKeepAlive()
+        // TODO: use real values instead of Strings, rebuild doubles & floats, etc
+        private final static String[] LOCAL_VALUES = new String[] {
+            null, // skip, LocalsAndOperands$Tester@XXX identity is different each run
+            "10",
+            "122",
+            "himom",
+            "0",
+            null, // skip, fix in 8156073
+            null, // skip, fix in 8156073
+            null, // skip, fix in 8156073
+            "0"
+        };
+
+        // Expected types for locals in testLocals() & testLocalsKeepAlive()
+        // TODO: use real types
+        private final static String[] LOCAL_TYPES = new String[] {
+            null, // skip
+            "I",
+            "I",
+            "java.lang.String",
+            "I",
+            "I",
+            "I",
+            "I",
+            "I"
+        };
+
+        final static Map NUM_LOCALS = Map.of("testLocals", 8,
+                                             "testLocalsKeepAlive",
+                                             LOCAL_VALUES.length);
+        private final static Collection<String> TEST_METHODS = NUM_LOCALS.keySet();
+    }
+
+    /**
+     * Print stack trace with locals
+     */
+    public static void dumpStackWithLocals(StackFrame...frames) {
+        Arrays.stream(frames).forEach(LocalsAndOperands::printLocals);
+    }
+
+    /**
+     * Print the StackFrame and an indexed list of its locals
+     */
+    public static void printLocals(StackWalker.StackFrame frame) {
+        try {
+            System.out.println(frame);
+            Object[] locals = (Object[]) getLocals.invoke(frame);
+            for (int i = 0; i < locals.length; i++) {
+                System.out.format("  local %d: %s type %s\n", i, locals[i], type(locals[i]));
+            }
+
+            Object[] operands = (Object[]) getOperands.invoke(frame);
+            for (int i = 0; i < operands.length; i++) {
+                System.out.format("  operand %d: %s type %s%n", i, operands[i],
+                                  type(operands[i]));
+            }
+
+            Object[] monitors = (Object[]) getMonitors.invoke(frame);
+            for (int i = 0; i < monitors.length; i++) {
+                System.out.format("  monitor %d: %s%n", i, monitors[i]);
+            }
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
+
+    private static String type(Object o) {
+        try {
+            if (o == null) {
+                return "null";
+            } else if (primitiveValueClass.isInstance(o)) {
+                char c = (char)primitiveType.invoke(o);
+                return String.valueOf(c);
+            } else {
+                return o.getClass().getName();
+            }
+        } catch(Exception e) { throw new RuntimeException(e); }
     }
 }
diff --git a/jdk/test/java/lang/StackWalker/LocalsCrash.java b/jdk/test/java/lang/StackWalker/LocalsCrash.java
new file mode 100644
index 00000000000..b50dd263f00
--- /dev/null
+++ b/jdk/test/java/lang/StackWalker/LocalsCrash.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8147039
+ * @summary Test for -Xcomp crash that happened before 8147039 fix
+ * @run testng/othervm -Xcomp LocalsCrash
+ */
+
+import org.testng.annotations.*;
+import java.lang.reflect.*;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class LocalsCrash {
+    static Class<?> liveStackFrameClass;
+    static Method getStackWalker;
+
+    static {
+        try {
+            liveStackFrameClass = Class.forName("java.lang.LiveStackFrame");
+            getStackWalker = liveStackFrameClass.getMethod("getStackWalker");
+            getStackWalker.setAccessible(true);
+        } catch (Throwable t) { throw new RuntimeException(t); }
+    }
+
+    private StackWalker walker;
+
+    LocalsCrash() {
+        try {
+            walker = (StackWalker) getStackWalker.invoke(null);
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
+
+    @Test
+    public void test00() { doStackWalk(); }
+
+    @Test
+    public void test01() { doStackWalk(); }
+
+    private synchronized List<StackWalker.StackFrame> doStackWalk() {
+        try {
+            // Unused local variables will become dead
+            int x = 10;
+            char c = 'z';
+            String hi = "himom";
+            long l = 1000000L;
+            double d =  3.1415926;
+
+            return walker.walk(s -> s.collect(Collectors.toList()));
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
+}
diff --git a/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh b/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh
index f5bb3b83179..b428a59bb28 100644
--- a/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh
+++ b/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh
@@ -80,5 +80,5 @@ $JAR ${TESTTOOLVMOPTS} -cfm "${TESTCLASSES}"/ClassUnloadTest.jar "${MANIFEST}" \
 
 # Finally we run the test
 (cd "${TESTCLASSES}"; \
-  $JAVA ${TESTVMOPTS} -Xverify:none -Xlog:classunload \
+  $JAVA ${TESTVMOPTS} -Xverify:none -Xlog:class+unload \
     -javaagent:ClassUnloadTest.jar ClassUnloadTest "${OTHERDIR}" Bar.jar)
diff --git a/jdk/test/java/lang/invoke/ArrayLengthTest.java b/jdk/test/java/lang/invoke/ArrayLengthTest.java
new file mode 100644
index 00000000000..3eabf9789c2
--- /dev/null
+++ b/jdk/test/java/lang/invoke/ArrayLengthTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @run testng/othervm -ea -esa test.java.lang.invoke.ArrayLengthTest
+ */
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+public class ArrayLengthTest {
+
+    @DataProvider
+    Object[][] arrayClasses() {
+        return new Object[][] {
+                {int[].class},
+                {long[].class},
+                {float[].class},
+                {double[].class},
+                {boolean[].class},
+                {byte[].class},
+                {short[].class},
+                {char[].class},
+                {Object[].class},
+                {StringBuffer[].class}
+        };
+    }
+
+    @Test(dataProvider = "arrayClasses")
+    public void testArrayLength(Class<?> arrayClass) throws Throwable {
+        MethodHandle arrayLength = MethodHandles.arrayLength(arrayClass);
+        assertEquals(int.class, arrayLength.type().returnType());
+        assertEquals(arrayClass, arrayLength.type().parameterType(0));
+        Object array = MethodHandles.arrayConstructor(arrayClass).invoke(10);
+        assertEquals(10, arrayLength.invoke(array));
+    }
+
+    @Test(dataProvider = "arrayClasses", expectedExceptions = NullPointerException.class)
+    public void testArrayLengthInvokeNPE(Class<?> arrayClass) throws Throwable {
+        MethodHandle arrayLength = MethodHandles.arrayLength(arrayClass);
+        arrayLength.invoke(null);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testArrayLengthNoArray() {
+        MethodHandles.arrayLength(String.class);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testArrayLengthNPE() {
+        MethodHandles.arrayLength(null);
+    }
+
+}
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java
index 59737dbeb7b..b8cbc17784d 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java
@@ -40,6 +40,7 @@ import static org.testng.Assert.*;
 
 abstract class VarHandleBaseTest {
     static final int ITERS = Integer.getInteger("iters", 1);
+    static final int WEAK_ATTEMPTS = Integer.getInteger("weakAttempts", 10);
 
     interface ThrowingRunnable {
         void run() throws Throwable;
@@ -211,7 +212,6 @@ abstract class VarHandleBaseTest {
     }
 
     static MethodHandle findVirtual(VarHandle vh, TestAccessMode tam, MethodType mt) {
-        mt = vh.accessModeType(tam.toAccessMode());
         MethodHandle mh;
         try {
             mh = MethodHandles.publicLookup().
@@ -221,36 +221,26 @@ abstract class VarHandleBaseTest {
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
-        return bind(vh, tam, mh, mt);
+        return bind(vh, mh, mt);
     }
 
-    static MethodHandle varHandleInvokerWithAccessModeType(VarHandle vh, TestAccessMode tam, MethodType mt) {
-        mt = vh.accessModeType(tam.toAccessMode());
+    static MethodHandle varHandleInvoker(VarHandle vh, TestAccessMode tam, MethodType mt) {
         MethodHandle mh = MethodHandles.varHandleInvoker(
                 tam.toAccessMode(),
                 mt);
 
-        return bind(vh, tam, mh, mt);
+        return bind(vh, mh, mt);
     }
 
-    static MethodHandle varHandleInvokerWithSymbolicTypeDescriptor(VarHandle vh, TestAccessMode tam, MethodType mt) {
-        MethodHandle mh = MethodHandles.varHandleInvoker(
-                tam.toAccessMode(),
-                mt);
-
-        return bind(vh, tam, mh, mt);
-    }
-
-    static MethodHandle varHandleExactInvokerWithAccessModeType(VarHandle vh, TestAccessMode tam, MethodType mt) {
-        mt = vh.accessModeType(tam.toAccessMode());
+    static MethodHandle varHandleExactInvoker(VarHandle vh, TestAccessMode tam, MethodType mt) {
         MethodHandle mh = MethodHandles.varHandleExactInvoker(
                 tam.toAccessMode(),
                 mt);
 
-        return bind(vh, tam, mh, mt);
+        return bind(vh, mh, mt);
     }
 
-    private static MethodHandle bind(VarHandle vh, TestAccessMode testAccessMode, MethodHandle mh, MethodType emt) {
+    private static MethodHandle bind(VarHandle vh, MethodHandle mh, MethodType emt) {
         assertEquals(mh.type(), emt.insertParameterTypes(0, VarHandle.class),
                      "MethodHandle type differs from access mode type");
 
@@ -268,33 +258,30 @@ abstract class VarHandleBaseTest {
     enum VarHandleToMethodHandle {
         VAR_HANDLE_TO_METHOD_HANDLE(
                 "VarHandle.toMethodHandle",
+                true,
                 VarHandleBaseTest::toMethodHandle),
         METHOD_HANDLES_LOOKUP_FIND_VIRTUAL(
                 "Lookup.findVirtual",
+                false,
                 VarHandleBaseTest::findVirtual),
-        METHOD_HANDLES_VAR_HANDLE_INVOKER_WITH_ACCESS_MODE_TYPE(
-                "MethodHandles.varHandleInvoker(accessModeType)",
-                VarHandleBaseTest::varHandleInvokerWithAccessModeType),
-        METHOD_HANDLES_VAR_HANDLE_INVOKER_WITH_SYMBOLIC_TYPE_DESCRIPTOR(
-                "MethodHandles.varHandleInvoker(symbolicTypeDescriptor)",
-                VarHandleBaseTest::varHandleInvokerWithSymbolicTypeDescriptor),
-        METHOD_HANDLES_VAR_HANDLE_EXACT_INVOKER_WITH_ACCESS_MODE_TYPE(
-                "MethodHandles.varHandleExactInvoker(accessModeType)",
-                VarHandleBaseTest::varHandleExactInvokerWithAccessModeType);
+        METHOD_HANDLES_VAR_HANDLE_INVOKER(
+                "MethodHandles.varHandleInvoker",
+                false,
+                VarHandleBaseTest::varHandleInvoker),
+        METHOD_HANDLES_VAR_HANDLE_EXACT_INVOKER(
+                "MethodHandles.varHandleExactInvoker",
+                true,
+                VarHandleBaseTest::varHandleExactInvoker);
 
         final String desc;
+        final boolean isExact;
         final TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f;
-        final boolean exact;
 
-        VarHandleToMethodHandle(String desc, TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f) {
-            this(desc, f, false);
-        }
-
-        VarHandleToMethodHandle(String desc, TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f,
-                                boolean exact) {
+        VarHandleToMethodHandle(String desc, boolean isExact,
+                                TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f) {
             this.desc = desc;
             this.f = f;
-            this.exact = exact;
+            this.isExact = isExact;
         }
 
         MethodHandle apply(VarHandle vh, TestAccessMode am, MethodType mt) {
@@ -363,6 +350,15 @@ abstract class VarHandleBaseTest {
             return amToHandle.computeIfAbsent(
                     amt, k -> f.apply(vh, am, mt));
         }
+
+        Class<? extends Throwable> getWMTEOOrOther(Class<? extends Throwable> c) {
+            return f.isExact ? WrongMethodTypeException.class : c;
+        }
+
+        void checkWMTEOrCCE(ThrowingRunnable r) {
+            checkWithThrowable(getWMTEOOrOther(ClassCastException.class), null, r);
+        }
+
     }
 
     interface AccessTestAction<T> {
@@ -475,4 +471,4 @@ abstract class VarHandleBaseTest {
             assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
         }
     }
-}
\ No newline at end of file
+}
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java
index 021091484e6..06d2a65b1dd 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessBoolean
  * @run testng/othervm -Diters=20000                         VarHandleTestAccessBoolean
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessBoolean
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestAccessBoolean
  */
 
 import org.testng.annotations.BeforeClass;
@@ -292,6 +293,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(recv, true, false);
         });
 
+        checkUOE(() -> {
+            boolean r = (boolean) vh.getAndSet(recv, true);
+        });
+
         checkUOE(() -> {
             boolean o = (boolean) vh.getAndAdd(recv, true);
         });
@@ -378,6 +383,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(true, false);
         });
 
+        checkUOE(() -> {
+            boolean r = (boolean) vh.getAndSet(true);
+        });
+
         checkUOE(() -> {
             boolean o = (boolean) vh.getAndAdd(true);
         });
@@ -454,6 +463,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(recv, true, false);
         });
 
+        checkUOE(() -> {
+            boolean r = (boolean) vh.getAndSet(recv, true);
+        });
+
         checkUOE(() -> {
             boolean o = (boolean) vh.getAndAdd(recv, true);
         });
@@ -530,6 +543,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(true, false);
         });
 
+        checkUOE(() -> {
+            boolean r = (boolean) vh.getAndSet(true);
+        });
+
         checkUOE(() -> {
             boolean o = (boolean) vh.getAndAdd(true);
         });
@@ -613,6 +630,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest {
             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);
         });
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java
index e550815156c..2ba0afbef2d 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessByte
  * @run testng/othervm -Diters=20000                         VarHandleTestAccessByte
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessByte
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestAccessByte
  */
 
 import org.testng.annotations.BeforeClass;
@@ -292,6 +293,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest {
             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);
         });
@@ -378,6 +383,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2);
         });
 
+        checkUOE(() -> {
+            byte r = (byte) vh.getAndSet((byte)1);
+        });
+
         checkUOE(() -> {
             byte o = (byte) vh.getAndAdd((byte)1);
         });
@@ -454,6 +463,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest {
             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);
         });
@@ -530,6 +543,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2);
         });
 
+        checkUOE(() -> {
+            byte r = (byte) vh.getAndSet((byte)1);
+        });
+
         checkUOE(() -> {
             byte o = (byte) vh.getAndAdd((byte)1);
         });
@@ -613,6 +630,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest {
             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);
         });
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java
index 5c13c6d6677..bcc42a3c335 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessChar
  * @run testng/othervm -Diters=20000                         VarHandleTestAccessChar
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessChar
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestAccessChar
  */
 
 import org.testng.annotations.BeforeClass;
@@ -292,6 +293,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b');
         });
 
+        checkUOE(() -> {
+            char r = (char) vh.getAndSet(recv, 'a');
+        });
+
         checkUOE(() -> {
             char o = (char) vh.getAndAdd(recv, 'a');
         });
@@ -378,6 +383,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease('a', 'b');
         });
 
+        checkUOE(() -> {
+            char r = (char) vh.getAndSet('a');
+        });
+
         checkUOE(() -> {
             char o = (char) vh.getAndAdd('a');
         });
@@ -454,6 +463,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b');
         });
 
+        checkUOE(() -> {
+            char r = (char) vh.getAndSet(recv, 'a');
+        });
+
         checkUOE(() -> {
             char o = (char) vh.getAndAdd(recv, 'a');
         });
@@ -530,6 +543,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease('a', 'b');
         });
 
+        checkUOE(() -> {
+            char r = (char) vh.getAndSet('a');
+        });
+
         checkUOE(() -> {
             char o = (char) vh.getAndAdd('a');
         });
@@ -613,6 +630,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest {
             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');
         });
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java
index 65125e3f62e..74f0765f709 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessDouble
  * @run testng/othervm -Diters=20000                         VarHandleTestAccessDouble
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessDouble
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestAccessDouble
  */
 
 import org.testng.annotations.BeforeClass;
@@ -292,6 +293,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest {
             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);
         });
@@ -378,6 +383,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(1.0d, 2.0d);
         });
 
+        checkUOE(() -> {
+            double r = (double) vh.getAndSet(1.0d);
+        });
+
         checkUOE(() -> {
             double o = (double) vh.getAndAdd(1.0d);
         });
@@ -454,6 +463,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest {
             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);
         });
@@ -530,6 +543,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(1.0d, 2.0d);
         });
 
+        checkUOE(() -> {
+            double r = (double) vh.getAndSet(1.0d);
+        });
+
         checkUOE(() -> {
             double o = (double) vh.getAndAdd(1.0d);
         });
@@ -613,6 +630,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(array, i, 1.0d, 2.0d);
         });
 
+        checkUOE(() -> {
+            double r = (double) vh.getAndSet(array, i, 1.0d);
+        });
+
         checkUOE(() -> {
             double o = (double) vh.getAndAdd(array, i, 1.0d);
         });
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java
index 8e7491ad45a..241e0897414 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessFloat
  * @run testng/othervm -Diters=20000                         VarHandleTestAccessFloat
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessFloat
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestAccessFloat
  */
 
 import org.testng.annotations.BeforeClass;
@@ -292,6 +293,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(recv, 1.0f, 2.0f);
         });
 
+        checkUOE(() -> {
+            float r = (float) vh.getAndSet(recv, 1.0f);
+        });
+
         checkUOE(() -> {
             float o = (float) vh.getAndAdd(recv, 1.0f);
         });
@@ -378,6 +383,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(1.0f, 2.0f);
         });
 
+        checkUOE(() -> {
+            float r = (float) vh.getAndSet(1.0f);
+        });
+
         checkUOE(() -> {
             float o = (float) vh.getAndAdd(1.0f);
         });
@@ -454,6 +463,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(recv, 1.0f, 2.0f);
         });
 
+        checkUOE(() -> {
+            float r = (float) vh.getAndSet(recv, 1.0f);
+        });
+
         checkUOE(() -> {
             float o = (float) vh.getAndAdd(recv, 1.0f);
         });
@@ -530,6 +543,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(1.0f, 2.0f);
         });
 
+        checkUOE(() -> {
+            float r = (float) vh.getAndSet(1.0f);
+        });
+
         checkUOE(() -> {
             float o = (float) vh.getAndAdd(1.0f);
         });
@@ -613,6 +630,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(array, i, 1.0f, 2.0f);
         });
 
+        checkUOE(() -> {
+            float r = (float) vh.getAndSet(array, i, 1.0f);
+        });
+
         checkUOE(() -> {
             float o = (float) vh.getAndAdd(array, i, 1.0f);
         });
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java
index bfcb5feec4c..3adb9b83fa7 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessInt
  * @run testng/othervm -Diters=20000                         VarHandleTestAccessInt
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessInt
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestAccessInt
  */
 
 import org.testng.annotations.BeforeClass;
@@ -402,29 +403,41 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest {
         }
 
         {
-            boolean r = vh.weakCompareAndSet(recv, 1, 2);
-            assertEquals(r, true, "weakCompareAndSet int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, 1, 2);
+            }
+            assertEquals(success, true, "weakCompareAndSet int");
             int x = (int) vh.get(recv);
             assertEquals(x, 2, "weakCompareAndSet int value");
         }
 
         {
-            boolean r = vh.weakCompareAndSetAcquire(recv, 2, 1);
-            assertEquals(r, true, "weakCompareAndSetAcquire int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, 2, 1);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire int");
             int x = (int) vh.get(recv);
             assertEquals(x, 1, "weakCompareAndSetAcquire int");
         }
 
         {
-            boolean r = vh.weakCompareAndSetRelease(recv, 1, 2);
-            assertEquals(r, true, "weakCompareAndSetRelease int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, 1, 2);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease int");
             int x = (int) vh.get(recv);
             assertEquals(x, 2, "weakCompareAndSetRelease int");
         }
 
         {
-            boolean r = vh.weakCompareAndSetVolatile(recv, 2, 1);
-            assertEquals(r, true, "weakCompareAndSetVolatile int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetVolatile(recv, 2, 1);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile int");
             int x = (int) vh.get(recv);
             assertEquals(x, 1, "weakCompareAndSetVolatile int value");
         }
@@ -543,36 +556,48 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSet(1, 2);
-            assertEquals(r, true, "weakCompareAndSet int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(1, 2);
+            }
+            assertEquals(success, true, "weakCompareAndSet int");
             int x = (int) vh.get();
             assertEquals(x, 2, "weakCompareAndSet int value");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetAcquire(2, 1);
-            assertEquals(r, true, "weakCompareAndSetAcquire int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(2, 1);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire int");
             int x = (int) vh.get();
             assertEquals(x, 1, "weakCompareAndSetAcquire int");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetRelease(1, 2);
-            assertEquals(r, true, "weakCompareAndSetRelease int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(1, 2);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease int");
             int x = (int) vh.get();
             assertEquals(x, 2, "weakCompareAndSetRelease int");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetVolatile(2, 1);
-            assertEquals(r, true, "weakCompareAndSetVolatile int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(2, 1);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile int");
             int x = (int) vh.get();
-            assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+            assertEquals(x, 1, "weakCompareAndSetVolatile int");
         }
 
         // Compare set and get
         {
-            int o = (int) vh.getAndSet( 2);
+            int o = (int) vh.getAndSet(2);
             assertEquals(o, 1, "getAndSet int");
             int x = (int) vh.get();
             assertEquals(x, 2, "getAndSet int value");
@@ -687,31 +712,43 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest {
             }
 
             {
-                boolean r = vh.weakCompareAndSet(array, i, 1, 2);
-                assertEquals(r, true, "weakCompareAndSet int");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, 1, 2);
+                }
+                assertEquals(success, true, "weakCompareAndSet int");
                 int x = (int) vh.get(array, i);
                 assertEquals(x, 2, "weakCompareAndSet int value");
             }
 
             {
-                boolean r = vh.weakCompareAndSetAcquire(array, i, 2, 1);
-                assertEquals(r, true, "weakCompareAndSetAcquire int");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, 2, 1);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire int");
                 int x = (int) vh.get(array, i);
                 assertEquals(x, 1, "weakCompareAndSetAcquire int");
             }
 
             {
-                boolean r = vh.weakCompareAndSetRelease(array, i, 1, 2);
-                assertEquals(r, true, "weakCompareAndSetRelease int");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, 1, 2);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease int");
                 int x = (int) vh.get(array, i);
                 assertEquals(x, 2, "weakCompareAndSetRelease int");
             }
 
             {
-                boolean r = vh.weakCompareAndSetVolatile(array, i, 2, 1);
-                assertEquals(r, true, "weakCompareAndSetVolatile int");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetVolatile(array, i, 2, 1);
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile int");
                 int x = (int) vh.get(array, i);
-                assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+                assertEquals(x, 1, "weakCompareAndSetVolatile int");
             }
 
             // Compare set and get
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java
index 1f02bed9045..9afb2de8320 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessLong
  * @run testng/othervm -Diters=20000                         VarHandleTestAccessLong
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessLong
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestAccessLong
  */
 
 import org.testng.annotations.BeforeClass;
@@ -402,29 +403,41 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest {
         }
 
         {
-            boolean r = vh.weakCompareAndSet(recv, 1L, 2L);
-            assertEquals(r, true, "weakCompareAndSet long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, 1L, 2L);
+            }
+            assertEquals(success, true, "weakCompareAndSet long");
             long x = (long) vh.get(recv);
             assertEquals(x, 2L, "weakCompareAndSet long value");
         }
 
         {
-            boolean r = vh.weakCompareAndSetAcquire(recv, 2L, 1L);
-            assertEquals(r, true, "weakCompareAndSetAcquire long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, 2L, 1L);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire long");
             long x = (long) vh.get(recv);
             assertEquals(x, 1L, "weakCompareAndSetAcquire long");
         }
 
         {
-            boolean r = vh.weakCompareAndSetRelease(recv, 1L, 2L);
-            assertEquals(r, true, "weakCompareAndSetRelease long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, 1L, 2L);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease long");
             long x = (long) vh.get(recv);
             assertEquals(x, 2L, "weakCompareAndSetRelease long");
         }
 
         {
-            boolean r = vh.weakCompareAndSetVolatile(recv, 2L, 1L);
-            assertEquals(r, true, "weakCompareAndSetVolatile long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetVolatile(recv, 2L, 1L);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile long");
             long x = (long) vh.get(recv);
             assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
         }
@@ -543,36 +556,48 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSet(1L, 2L);
-            assertEquals(r, true, "weakCompareAndSet long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(1L, 2L);
+            }
+            assertEquals(success, true, "weakCompareAndSet long");
             long x = (long) vh.get();
             assertEquals(x, 2L, "weakCompareAndSet long value");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetAcquire(2L, 1L);
-            assertEquals(r, true, "weakCompareAndSetAcquire long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(2L, 1L);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire long");
             long x = (long) vh.get();
             assertEquals(x, 1L, "weakCompareAndSetAcquire long");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetRelease(1L, 2L);
-            assertEquals(r, true, "weakCompareAndSetRelease long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(1L, 2L);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease long");
             long x = (long) vh.get();
             assertEquals(x, 2L, "weakCompareAndSetRelease long");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetVolatile(2L, 1L);
-            assertEquals(r, true, "weakCompareAndSetVolatile long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(2L, 1L);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile long");
             long x = (long) vh.get();
-            assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+            assertEquals(x, 1L, "weakCompareAndSetVolatile long");
         }
 
         // Compare set and get
         {
-            long o = (long) vh.getAndSet( 2L);
+            long o = (long) vh.getAndSet(2L);
             assertEquals(o, 1L, "getAndSet long");
             long x = (long) vh.get();
             assertEquals(x, 2L, "getAndSet long value");
@@ -687,31 +712,43 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest {
             }
 
             {
-                boolean r = vh.weakCompareAndSet(array, i, 1L, 2L);
-                assertEquals(r, true, "weakCompareAndSet long");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, 1L, 2L);
+                }
+                assertEquals(success, true, "weakCompareAndSet long");
                 long x = (long) vh.get(array, i);
                 assertEquals(x, 2L, "weakCompareAndSet long value");
             }
 
             {
-                boolean r = vh.weakCompareAndSetAcquire(array, i, 2L, 1L);
-                assertEquals(r, true, "weakCompareAndSetAcquire long");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, 2L, 1L);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire long");
                 long x = (long) vh.get(array, i);
                 assertEquals(x, 1L, "weakCompareAndSetAcquire long");
             }
 
             {
-                boolean r = vh.weakCompareAndSetRelease(array, i, 1L, 2L);
-                assertEquals(r, true, "weakCompareAndSetRelease long");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, 1L, 2L);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease long");
                 long x = (long) vh.get(array, i);
                 assertEquals(x, 2L, "weakCompareAndSetRelease long");
             }
 
             {
-                boolean r = vh.weakCompareAndSetVolatile(array, i, 2L, 1L);
-                assertEquals(r, true, "weakCompareAndSetVolatile long");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetVolatile(array, i, 2L, 1L);
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile long");
                 long x = (long) vh.get(array, i);
-                assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+                assertEquals(x, 1L, "weakCompareAndSetVolatile long");
             }
 
             // Compare set and get
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java
index 822252f7a7d..a64ed990cb9 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessShort
  * @run testng/othervm -Diters=20000                         VarHandleTestAccessShort
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessShort
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestAccessShort
  */
 
 import org.testng.annotations.BeforeClass;
@@ -292,6 +293,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(recv, (short)1, (short)2);
         });
 
+        checkUOE(() -> {
+            short r = (short) vh.getAndSet(recv, (short)1);
+        });
+
         checkUOE(() -> {
             short o = (short) vh.getAndAdd(recv, (short)1);
         });
@@ -378,6 +383,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease((short)1, (short)2);
         });
 
+        checkUOE(() -> {
+            short r = (short) vh.getAndSet((short)1);
+        });
+
         checkUOE(() -> {
             short o = (short) vh.getAndAdd((short)1);
         });
@@ -454,6 +463,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(recv, (short)1, (short)2);
         });
 
+        checkUOE(() -> {
+            short r = (short) vh.getAndSet(recv, (short)1);
+        });
+
         checkUOE(() -> {
             short o = (short) vh.getAndAdd(recv, (short)1);
         });
@@ -530,6 +543,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease((short)1, (short)2);
         });
 
+        checkUOE(() -> {
+            short r = (short) vh.getAndSet((short)1);
+        });
+
         checkUOE(() -> {
             short o = (short) vh.getAndAdd((short)1);
         });
@@ -613,6 +630,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest {
             boolean r = vh.weakCompareAndSetRelease(array, i, (short)1, (short)2);
         });
 
+        checkUOE(() -> {
+            short r = (short) vh.getAndSet(array, i, (short)1);
+        });
+
         checkUOE(() -> {
             short o = (short) vh.getAndAdd(array, i, (short)1);
         });
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java
index 9e4ec77768b..74f08bda535 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessString
  * @run testng/othervm -Diters=20000                         VarHandleTestAccessString
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessString
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestAccessString
  */
 
 import org.testng.annotations.BeforeClass;
@@ -416,29 +417,41 @@ public class VarHandleTestAccessString extends VarHandleBaseTest {
         }
 
         {
-            boolean r = vh.weakCompareAndSet(recv, "foo", "bar");
-            assertEquals(r, true, "weakCompareAndSet String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, "foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSet String");
             String x = (String) vh.get(recv);
             assertEquals(x, "bar", "weakCompareAndSet String value");
         }
 
         {
-            boolean r = vh.weakCompareAndSetAcquire(recv, "bar", "foo");
-            assertEquals(r, true, "weakCompareAndSetAcquire String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, "bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire String");
             String x = (String) vh.get(recv);
             assertEquals(x, "foo", "weakCompareAndSetAcquire String");
         }
 
         {
-            boolean r = vh.weakCompareAndSetRelease(recv, "foo", "bar");
-            assertEquals(r, true, "weakCompareAndSetRelease String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, "foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease String");
             String x = (String) vh.get(recv);
             assertEquals(x, "bar", "weakCompareAndSetRelease String");
         }
 
         {
-            boolean r = vh.weakCompareAndSetVolatile(recv, "bar", "foo");
-            assertEquals(r, true, "weakCompareAndSetVolatile String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetVolatile(recv, "bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile String");
             String x = (String) vh.get(recv);
             assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
         }
@@ -555,36 +568,48 @@ public class VarHandleTestAccessString extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSet("foo", "bar");
-            assertEquals(r, true, "weakCompareAndSet String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet("foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSet String");
             String x = (String) vh.get();
             assertEquals(x, "bar", "weakCompareAndSet String value");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetAcquire("bar", "foo");
-            assertEquals(r, true, "weakCompareAndSetAcquire String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire("bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire String");
             String x = (String) vh.get();
             assertEquals(x, "foo", "weakCompareAndSetAcquire String");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetRelease("foo", "bar");
-            assertEquals(r, true, "weakCompareAndSetRelease String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease("foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease String");
             String x = (String) vh.get();
             assertEquals(x, "bar", "weakCompareAndSetRelease String");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetVolatile("bar", "foo");
-            assertEquals(r, true, "weakCompareAndSetVolatile String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease("bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile String");
             String x = (String) vh.get();
-            assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+            assertEquals(x, "foo", "weakCompareAndSetVolatile String");
         }
 
         // Compare set and get
         {
-            String o = (String) vh.getAndSet( "bar");
+            String o = (String) vh.getAndSet("bar");
             assertEquals(o, "foo", "getAndSet String");
             String x = (String) vh.get();
             assertEquals(x, "bar", "getAndSet String value");
@@ -697,31 +722,43 @@ public class VarHandleTestAccessString extends VarHandleBaseTest {
             }
 
             {
-                boolean r = vh.weakCompareAndSet(array, i, "foo", "bar");
-                assertEquals(r, true, "weakCompareAndSet String");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, "foo", "bar");
+                }
+                assertEquals(success, true, "weakCompareAndSet String");
                 String x = (String) vh.get(array, i);
                 assertEquals(x, "bar", "weakCompareAndSet String value");
             }
 
             {
-                boolean r = vh.weakCompareAndSetAcquire(array, i, "bar", "foo");
-                assertEquals(r, true, "weakCompareAndSetAcquire String");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, "bar", "foo");
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire String");
                 String x = (String) vh.get(array, i);
                 assertEquals(x, "foo", "weakCompareAndSetAcquire String");
             }
 
             {
-                boolean r = vh.weakCompareAndSetRelease(array, i, "foo", "bar");
-                assertEquals(r, true, "weakCompareAndSetRelease String");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, "foo", "bar");
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease String");
                 String x = (String) vh.get(array, i);
                 assertEquals(x, "bar", "weakCompareAndSetRelease String");
             }
 
             {
-                boolean r = vh.weakCompareAndSetVolatile(array, i, "bar", "foo");
-                assertEquals(r, true, "weakCompareAndSetVolatile String");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetVolatile(array, i, "bar", "foo");
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile String");
                 String x = (String) vh.get(array, i);
-                assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+                assertEquals(x, "foo", "weakCompareAndSetVolatile String");
             }
 
             // Compare set and get
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java
index 8159e16ff62..a2221b50a20 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsChar
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsChar
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsChar
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestByteArrayAsChar
  */
 
 import org.testng.annotations.DataProvider;
@@ -50,7 +51,7 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest {
 
     static final char VALUE_2 = (char)0x1112;
 
-    static final char VALUE_3 = (char)0x2122;
+    static final char VALUE_3 = (char)0xFFFE;
 
 
     @Override
@@ -253,6 +254,10 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest {
             checkROBE(() -> {
                 vh.setOpaque(array, ci, VALUE_1);
             });
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
             checkUOE(() -> {
                 char r = (char) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
             });
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java
index a327b00fb77..79305710ce2 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsDouble
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsDouble
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsDouble
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestByteArrayAsDouble
  */
 
 import org.testng.annotations.DataProvider;
@@ -50,7 +51,7 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest {
 
     static final double VALUE_2 = 0x1112131415161718L;
 
-    static final double VALUE_3 = 0x2122232425262728L;
+    static final double VALUE_3 = 0xFFFEFDFCFBFAF9F8L;
 
 
     @Override
@@ -254,9 +255,7 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest {
             checkROBE(() -> {
                 double o = (double) vh.getAndSet(array, ci, VALUE_1);
             });
-            checkUOE(() -> {
-                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
-            });
+
 
             checkUOE(() -> {
                 double o = (double) vh.getAndAdd(array, ci, VALUE_1);
@@ -700,22 +699,31 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest {
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSet double");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet double");
                     double x = (double) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSet double value");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
-                    assertEquals(r, true, "weakCompareAndSetAcquire double");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire double");
                     double x = (double) vh.get(array, i);
                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSetRelease double");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease double");
                     double x = (double) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
                 }
@@ -840,22 +848,31 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest {
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSet double");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet double");
                     double x = (double) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSet double value");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
-                    assertEquals(r, true, "weakCompareAndSetAcquire double");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire double");
                     double x = (double) vh.get(array, i);
                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSetRelease double");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease double");
                     double x = (double) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
                 }
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java
index 196c8101723..b3545b4f69c 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsFloat
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsFloat
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsFloat
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestByteArrayAsFloat
  */
 
 import org.testng.annotations.DataProvider;
@@ -50,7 +51,7 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest {
 
     static final float VALUE_2 = 0x11121314;
 
-    static final float VALUE_3 = 0x21222324;
+    static final float VALUE_3 = 0xFFFEFDFC;
 
 
     @Override
@@ -254,9 +255,7 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest {
             checkROBE(() -> {
                 float o = (float) vh.getAndSet(array, ci, VALUE_1);
             });
-            checkUOE(() -> {
-                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
-            });
+
 
             checkUOE(() -> {
                 float o = (float) vh.getAndAdd(array, ci, VALUE_1);
@@ -700,22 +699,31 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest {
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSet float");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet float");
                     float x = (float) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSet float value");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
-                    assertEquals(r, true, "weakCompareAndSetAcquire float");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire float");
                     float x = (float) vh.get(array, i);
                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSetRelease float");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease float");
                     float x = (float) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
                 }
@@ -840,22 +848,31 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest {
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSet float");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet float");
                     float x = (float) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSet float value");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
-                    assertEquals(r, true, "weakCompareAndSetAcquire float");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire float");
                     float x = (float) vh.get(array, i);
                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSetRelease float");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease float");
                     float x = (float) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
                 }
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java
index 400c20605c5..b733bb34054 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsInt
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsInt
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsInt
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestByteArrayAsInt
  */
 
 import org.testng.annotations.DataProvider;
@@ -50,7 +51,7 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest {
 
     static final int VALUE_2 = 0x11121314;
 
-    static final int VALUE_3 = 0x21222324;
+    static final int VALUE_3 = 0xFFFEFDFC;
 
 
     @Override
@@ -247,9 +248,7 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest {
             checkROBE(() -> {
                 int o = (int) vh.getAndSet(array, ci, VALUE_1);
             });
-            checkUOE(() -> {
-                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
-            });
+
 
             checkROBE(() -> {
                 int o = (int) vh.getAndAdd(array, ci, VALUE_1);
@@ -714,22 +713,31 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest {
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSet int");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet int");
                     int x = (int) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSet int value");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
-                    assertEquals(r, true, "weakCompareAndSetAcquire int");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire int");
                     int x = (int) vh.get(array, i);
                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSetRelease int");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease int");
                     int x = (int) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
                 }
@@ -863,22 +871,31 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest {
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSet int");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet int");
                     int x = (int) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSet int value");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
-                    assertEquals(r, true, "weakCompareAndSetAcquire int");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire int");
                     int x = (int) vh.get(array, i);
                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSetRelease int");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease int");
                     int x = (int) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
                 }
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java
index a0cabc8653a..88bf198272b 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsLong
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsLong
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsLong
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestByteArrayAsLong
  */
 
 import org.testng.annotations.DataProvider;
@@ -50,7 +51,7 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest {
 
     static final long VALUE_2 = 0x1112131415161718L;
 
-    static final long VALUE_3 = 0x2122232425262728L;
+    static final long VALUE_3 = 0xFFFEFDFCFBFAF9F8L;
 
 
     @Override
@@ -247,9 +248,7 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest {
             checkROBE(() -> {
                 long o = (long) vh.getAndSet(array, ci, VALUE_1);
             });
-            checkUOE(() -> {
-                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
-            });
+
 
             checkROBE(() -> {
                 long o = (long) vh.getAndAdd(array, ci, VALUE_1);
@@ -714,22 +713,31 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest {
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSet long");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet long");
                     long x = (long) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSet long value");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
-                    assertEquals(r, true, "weakCompareAndSetAcquire long");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire long");
                     long x = (long) vh.get(array, i);
                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSetRelease long");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease long");
                     long x = (long) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
                 }
@@ -863,22 +871,31 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest {
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSet long");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet long");
                     long x = (long) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSet long value");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
-                    assertEquals(r, true, "weakCompareAndSetAcquire long");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire long");
                     long x = (long) vh.get(array, i);
                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSetRelease long");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease long");
                     long x = (long) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
                 }
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java
index 2632b00bd23..5ed9d6099f7 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsShort
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsShort
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsShort
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestByteArrayAsShort
  */
 
 import org.testng.annotations.DataProvider;
@@ -50,7 +51,7 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest {
 
     static final short VALUE_2 = (short)0x1112;
 
-    static final short VALUE_3 = (short)0x2122;
+    static final short VALUE_3 = (short)0xFFFE;
 
 
     @Override
@@ -253,6 +254,10 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest {
             checkROBE(() -> {
                 vh.setOpaque(array, ci, VALUE_1);
             });
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
             checkUOE(() -> {
                 short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
             });
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java
index 32761fe0e3f..f43fcc1b82c 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessBoolean
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodHandleAccessBoolean
  */
 
 import org.testng.annotations.BeforeClass;
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java
index 8c36eb861c5..3d5c27e8bfd 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessByte
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodHandleAccessByte
  */
 
 import org.testng.annotations.BeforeClass;
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java
index fb1f3877342..bde76a69c05 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessChar
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodHandleAccessChar
  */
 
 import org.testng.annotations.BeforeClass;
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java
index cd2c15d04d3..de683ce6997 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessDouble
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodHandleAccessDouble
  */
 
 import org.testng.annotations.BeforeClass;
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java
index 58d9e295298..99309e5081f 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessFloat
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodHandleAccessFloat
  */
 
 import org.testng.annotations.BeforeClass;
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java
index 8ccf7983056..fc0e8f214f9 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessInt
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodHandleAccessInt
  */
 
 import org.testng.annotations.BeforeClass;
@@ -208,31 +209,43 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1, 2);
-            assertEquals(r, true, "weakCompareAndSet int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1, 2);
+            }
+            assertEquals(success, true, "weakCompareAndSet int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, 2, "weakCompareAndSet int value");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2, 1);
-            assertEquals(r, true, "weakCompareAndSetAcquire int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2, 1);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, 1, "weakCompareAndSetAcquire int");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1, 2);
-            assertEquals(r, true, "weakCompareAndSetRelease int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1, 2);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, 2, "weakCompareAndSetRelease int");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2, 1);
-            assertEquals(r, true, "weakCompareAndSetVolatile int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2, 1);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
-            assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+            assertEquals(x, 1, "weakCompareAndSetVolatile int");
         }
 
         // Compare set and get
@@ -349,36 +362,48 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1, 2);
-            assertEquals(r, true, "weakCompareAndSet int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1, 2);
+            }
+            assertEquals(success, true, "weakCompareAndSet int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, 2, "weakCompareAndSet int value");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2, 1);
-            assertEquals(r, true, "weakCompareAndSetAcquire int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2, 1);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, 1, "weakCompareAndSetAcquire int");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1, 2);
-            assertEquals(r, true, "weakCompareAndSetRelease int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1, 2);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, 2, "weakCompareAndSetRelease int");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2, 1);
-            assertEquals(r, true, "weakCompareAndSetVolatile int");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2, 1);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact();
-            assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+            assertEquals(x, 1, "weakCompareAndSetVolatile int");
         }
 
         // Compare set and get
         {
-            int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2);
+            int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact( 2);
             assertEquals(o, 1, "getAndSet int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, 2, "getAndSet int value");
@@ -493,31 +518,43 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest {
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1, 2);
-                assertEquals(r, true, "weakCompareAndSet int");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1, 2);
+                }
+                assertEquals(success, true, "weakCompareAndSet int");
                 int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, 2, "weakCompareAndSet int value");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2, 1);
-                assertEquals(r, true, "weakCompareAndSetAcquire int");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2, 1);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire int");
                 int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, 1, "weakCompareAndSetAcquire int");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1, 2);
-                assertEquals(r, true, "weakCompareAndSetRelease int");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1, 2);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease int");
                 int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, 2, "weakCompareAndSetRelease int");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2, 1);
-                assertEquals(r, true, "weakCompareAndSetVolatile int");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2, 1);
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile int");
                 int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
-                assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+                assertEquals(x, 1, "weakCompareAndSetVolatile int");
             }
 
             // Compare set and get
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java
index 65493ec2b49..0f265da3f2e 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessLong
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodHandleAccessLong
  */
 
 import org.testng.annotations.BeforeClass;
@@ -208,31 +209,43 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1L, 2L);
-            assertEquals(r, true, "weakCompareAndSet long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1L, 2L);
+            }
+            assertEquals(success, true, "weakCompareAndSet long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, 2L, "weakCompareAndSet long value");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2L, 1L);
-            assertEquals(r, true, "weakCompareAndSetAcquire long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2L, 1L);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, 1L, "weakCompareAndSetAcquire long");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1L, 2L);
-            assertEquals(r, true, "weakCompareAndSetRelease long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1L, 2L);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, 2L, "weakCompareAndSetRelease long");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2L, 1L);
-            assertEquals(r, true, "weakCompareAndSetVolatile long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2L, 1L);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
-            assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+            assertEquals(x, 1L, "weakCompareAndSetVolatile long");
         }
 
         // Compare set and get
@@ -349,36 +362,48 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1L, 2L);
-            assertEquals(r, true, "weakCompareAndSet long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1L, 2L);
+            }
+            assertEquals(success, true, "weakCompareAndSet long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, 2L, "weakCompareAndSet long value");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2L, 1L);
-            assertEquals(r, true, "weakCompareAndSetAcquire long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2L, 1L);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, 1L, "weakCompareAndSetAcquire long");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1L, 2L);
-            assertEquals(r, true, "weakCompareAndSetRelease long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1L, 2L);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, 2L, "weakCompareAndSetRelease long");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2L, 1L);
-            assertEquals(r, true, "weakCompareAndSetVolatile long");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2L, 1L);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact();
-            assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+            assertEquals(x, 1L, "weakCompareAndSetVolatile long");
         }
 
         // Compare set and get
         {
-            long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2L);
+            long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact( 2L);
             assertEquals(o, 1L, "getAndSet long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, 2L, "getAndSet long value");
@@ -493,31 +518,43 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest {
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1L, 2L);
-                assertEquals(r, true, "weakCompareAndSet long");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1L, 2L);
+                }
+                assertEquals(success, true, "weakCompareAndSet long");
                 long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, 2L, "weakCompareAndSet long value");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2L, 1L);
-                assertEquals(r, true, "weakCompareAndSetAcquire long");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2L, 1L);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire long");
                 long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, 1L, "weakCompareAndSetAcquire long");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1L, 2L);
-                assertEquals(r, true, "weakCompareAndSetRelease long");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1L, 2L);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease long");
                 long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, 2L, "weakCompareAndSetRelease long");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2L, 1L);
-                assertEquals(r, true, "weakCompareAndSetVolatile long");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2L, 1L);
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile long");
                 long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
-                assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+                assertEquals(x, 1L, "weakCompareAndSetVolatile long");
             }
 
             // Compare set and get
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java
index 6edc9b19b68..51b51e73747 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessShort
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodHandleAccessShort
  */
 
 import org.testng.annotations.BeforeClass;
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java
index 5ae7c877854..ce5167a0b91 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessString
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodHandleAccessString
  */
 
 import org.testng.annotations.BeforeClass;
@@ -208,31 +209,43 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "foo", "bar");
-            assertEquals(r, true, "weakCompareAndSet String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSet String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, "bar", "weakCompareAndSet String value");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "foo");
-            assertEquals(r, true, "weakCompareAndSetAcquire String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, "foo", "weakCompareAndSetAcquire String");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "bar");
-            assertEquals(r, true, "weakCompareAndSetRelease String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, "bar", "weakCompareAndSetRelease String");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, "bar", "foo");
-            assertEquals(r, true, "weakCompareAndSetVolatile String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, "bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
-            assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+            assertEquals(x, "foo", "weakCompareAndSetVolatile String");
         }
 
         // Compare set and get
@@ -345,36 +358,48 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("foo", "bar");
-            assertEquals(r, true, "weakCompareAndSet String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSet String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, "bar", "weakCompareAndSet String value");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact("bar", "foo");
-            assertEquals(r, true, "weakCompareAndSetAcquire String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact("bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, "foo", "weakCompareAndSetAcquire String");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "bar");
-            assertEquals(r, true, "weakCompareAndSetRelease String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, "bar", "weakCompareAndSetRelease String");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact("bar", "foo");
-            assertEquals(r, true, "weakCompareAndSetVolatile String");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact("bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
-            assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+            assertEquals(x, "foo", "weakCompareAndSetVolatile String");
         }
 
         // Compare set and get
         {
-            String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact("bar");
+            String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact( "bar");
             assertEquals(o, "foo", "getAndSet String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, "bar", "getAndSet String value");
@@ -485,31 +510,43 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest {
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "foo", "bar");
-                assertEquals(r, true, "weakCompareAndSet String");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "foo", "bar");
+                }
+                assertEquals(success, true, "weakCompareAndSet String");
                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, "bar", "weakCompareAndSet String value");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "foo");
-                assertEquals(r, true, "weakCompareAndSetAcquire String");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "foo");
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire String");
                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, "foo", "weakCompareAndSetAcquire String");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, "foo", "bar");
-                assertEquals(r, true, "weakCompareAndSetRelease String");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, "foo", "bar");
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease String");
                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, "bar", "weakCompareAndSetRelease String");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, "bar", "foo");
-                assertEquals(r, true, "weakCompareAndSetVolatile String");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, "bar", "foo");
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile String");
                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
-                assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+                assertEquals(x, "foo", "weakCompareAndSetVolatile String");
             }
 
             // Compare set and get
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java
index 75ba7ae3dc2..df680146374 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8156486
  * @run testng/othervm VarHandleTestMethodTypeBoolean
  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeBoolean
  */
@@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest {
     public Object[][] accessTestCaseProvider() throws Exception {
         List<AccessTestCase<?>> cases = new ArrayList<>();
 
-        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Instance field",
                                               vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Static field",
                                               vhStaticField, VarHandleTestMethodTypeBoolean::testStaticFieldWrongMethodType,
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+        cases.add(new VarHandleAccessTestCase("Array",
                                               vhArray, VarHandleTestMethodTypeBoolean::testArrayWrongMethodType,
                                               false));
+
         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
-            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Instance field",
                                                      vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Static field",
                                                      vhStaticField, f, VarHandleTestMethodTypeBoolean::testStaticFieldWrongMethodType,
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Array",
                                                      vhArray, f, VarHandleTestMethodTypeBoolean::testArrayWrongMethodType,
                                                      false));
         }
@@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                boolean x = (boolean) hs.get(am, methodType(boolean.class, Void.class)).
-                    invoke(null);
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class)).
+                    invokeExact((VarHandleTestMethodTypeBoolean) null);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
-                    invoke(0);
+                    invokeExact(0);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
-                Void x = (Void) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class)).
-                    invoke(recv);
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeBoolean.class)).
+                    invokeExact(recv);
             });
             checkWMTE(() -> { // primitive class
                 int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeBoolean.class)).
-                    invoke(recv);
+                    invokeExact(recv);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean x = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                hs.get(am, methodType(void.class, Void.class, boolean.class)).
-                    invoke(null, true);
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, boolean.class)).
+                    invokeExact((VarHandleTestMethodTypeBoolean) null, true);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 hs.get(am, methodType(void.class, Class.class, boolean.class)).
-                    invoke(Void.class, true);
+                    invokeExact(Void.class, true);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, boolean.class)).
-                    invoke(0, true);
+                    invokeExact(0, true);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, boolean.class, Class.class)).
-                    invoke(recv, true, Void.class);
+                    invokeExact(recv, true, Void.class);
             });
         }
 
@@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest {
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // primitive class
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             // Incorrect arity
             checkWMTE(() -> { // >
                 boolean x = (boolean) hs.get(am, methodType(Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, boolean.class, Class.class)).
-                    invoke(true, Void.class);
+                    invokeExact(true, Void.class);
             });
         }
 
@@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                boolean x = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class)).
-                    invoke(null, 0);
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class)).
+                    invokeExact((boolean[]) null, 0);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class)).
-                    invoke(Void.class, 0);
+                    invokeExact(Void.class, 0);
             });
             checkWMTE(() -> { // array primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class)).
-                    invoke(0, 0);
+                    invokeExact(0, 0);
             });
             checkWMTE(() -> { // index reference class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, Class.class)).
-                    invoke(array, Void.class);
+                    invokeExact(array, Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class, boolean[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             checkWMTE(() -> { // primitive class
                 int x = (int) hs.get(am, methodType(int.class, boolean[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean x = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                hs.get(am, methodType(void.class, Void.class, int.class, boolean.class)).
-                    invoke(null, 0, true);
+                hs.get(am, methodType(void.class, boolean[].class, int.class, boolean.class)).
+                    invokeExact((boolean[]) null, 0, true);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 hs.get(am, methodType(void.class, Class.class, int.class, boolean.class)).
-                    invoke(Void.class, 0, true);
+                    invokeExact(Void.class, 0, true);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, boolean[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class, boolean.class)).
-                    invoke(0, 0, true);
+                    invokeExact(0, 0, true);
             });
             checkWMTE(() -> { // index reference class
                 hs.get(am, methodType(void.class, boolean[].class, Class.class, boolean.class)).
-                    invoke(array, Void.class, true);
+                    invokeExact(array, Void.class, true);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, boolean[].class, int.class, Class.class)).
-                    invoke(array, 0, true, Void.class);
+                    invokeExact(array, 0, true, Void.class);
             });
         }
 
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java
index b212bfc9d7d..0bfddc7ad27 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8156486
  * @run testng/othervm VarHandleTestMethodTypeByte
  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeByte
  */
@@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeByte extends VarHandleBaseTest {
     public Object[][] accessTestCaseProvider() throws Exception {
         List<AccessTestCase<?>> cases = new ArrayList<>();
 
-        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Instance field",
                                               vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Static field",
                                               vhStaticField, VarHandleTestMethodTypeByte::testStaticFieldWrongMethodType,
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+        cases.add(new VarHandleAccessTestCase("Array",
                                               vhArray, VarHandleTestMethodTypeByte::testArrayWrongMethodType,
                                               false));
+
         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
-            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Instance field",
                                                      vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Static field",
                                                      vhStaticField, f, VarHandleTestMethodTypeByte::testStaticFieldWrongMethodType,
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Array",
                                                      vhArray, f, VarHandleTestMethodTypeByte::testArrayWrongMethodType,
                                                      false));
         }
@@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeByte extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                byte x = (byte) hs.get(am, methodType(byte.class, Void.class)).
-                    invoke(null);
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class)).
+                    invokeExact((VarHandleTestMethodTypeByte) null);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 byte x = (byte) hs.get(am, methodType(byte.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 byte x = (byte) hs.get(am, methodType(byte.class, int.class)).
-                    invoke(0);
+                    invokeExact(0);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
-                Void x = (Void) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class)).
-                    invoke(recv);
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeByte.class)).
+                    invokeExact(recv);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class)).
-                    invoke(recv);
+                    invokeExact(recv);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 byte x = (byte) hs.get(am, methodType(byte.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                hs.get(am, methodType(void.class, Void.class, byte.class)).
-                    invoke(null, (byte)1);
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact((VarHandleTestMethodTypeByte) null, (byte)1);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 hs.get(am, methodType(void.class, Class.class, byte.class)).
-                    invoke(Void.class, (byte)1);
+                    invokeExact(Void.class, (byte)1);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, byte.class)).
-                    invoke(0, (byte)1);
+                    invokeExact(0, (byte)1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, byte.class, Class.class)).
-                    invoke(recv, (byte)1, Void.class);
+                    invokeExact(recv, (byte)1, Void.class);
             });
         }
 
@@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeByte extends VarHandleBaseTest {
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             // Incorrect arity
             checkWMTE(() -> { // >
                 byte x = (byte) hs.get(am, methodType(Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, byte.class, Class.class)).
-                    invoke((byte)1, Void.class);
+                    invokeExact((byte)1, Void.class);
             });
         }
 
@@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeByte extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                byte x = (byte) hs.get(am, methodType(byte.class, Void.class, int.class)).
-                    invoke(null, 0);
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class)).
+                    invokeExact((byte[]) null, 0);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 byte x = (byte) hs.get(am, methodType(byte.class, Class.class, int.class)).
-                    invoke(Void.class, 0);
+                    invokeExact(Void.class, 0);
             });
             checkWMTE(() -> { // array primitive class
                 byte x = (byte) hs.get(am, methodType(byte.class, int.class, int.class)).
-                    invoke(0, 0);
+                    invokeExact(0, 0);
             });
             checkWMTE(() -> { // index reference class
                 byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, Class.class)).
-                    invoke(array, Void.class);
+                    invokeExact(array, Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class, byte[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 byte x = (byte) hs.get(am, methodType(byte.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                hs.get(am, methodType(void.class, Void.class, int.class, byte.class)).
-                    invoke(null, 0, (byte)1);
+                hs.get(am, methodType(void.class, byte[].class, int.class, byte.class)).
+                    invokeExact((byte[]) null, 0, (byte)1);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 hs.get(am, methodType(void.class, Class.class, int.class, byte.class)).
-                    invoke(Void.class, 0, (byte)1);
+                    invokeExact(Void.class, 0, (byte)1);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, byte[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class, byte.class)).
-                    invoke(0, 0, (byte)1);
+                    invokeExact(0, 0, (byte)1);
             });
             checkWMTE(() -> { // index reference class
                 hs.get(am, methodType(void.class, byte[].class, Class.class, byte.class)).
-                    invoke(array, Void.class, (byte)1);
+                    invokeExact(array, Void.class, (byte)1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, byte[].class, int.class, Class.class)).
-                    invoke(array, 0, (byte)1, Void.class);
+                    invokeExact(array, 0, (byte)1, Void.class);
             });
         }
 
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java
index 6ac8a0fed70..8d5166d8644 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8156486
  * @run testng/othervm VarHandleTestMethodTypeChar
  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeChar
  */
@@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeChar extends VarHandleBaseTest {
     public Object[][] accessTestCaseProvider() throws Exception {
         List<AccessTestCase<?>> cases = new ArrayList<>();
 
-        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Instance field",
                                               vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Static field",
                                               vhStaticField, VarHandleTestMethodTypeChar::testStaticFieldWrongMethodType,
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+        cases.add(new VarHandleAccessTestCase("Array",
                                               vhArray, VarHandleTestMethodTypeChar::testArrayWrongMethodType,
                                               false));
+
         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
-            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Instance field",
                                                      vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Static field",
                                                      vhStaticField, f, VarHandleTestMethodTypeChar::testStaticFieldWrongMethodType,
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Array",
                                                      vhArray, f, VarHandleTestMethodTypeChar::testArrayWrongMethodType,
                                                      false));
         }
@@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeChar extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                char x = (char) hs.get(am, methodType(char.class, Void.class)).
-                    invoke(null);
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class)).
+                    invokeExact((VarHandleTestMethodTypeChar) null);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 char x = (char) hs.get(am, methodType(char.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 char x = (char) hs.get(am, methodType(char.class, int.class)).
-                    invoke(0);
+                    invokeExact(0);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
-                Void x = (Void) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class)).
-                    invoke(recv);
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeChar.class)).
+                    invokeExact(recv);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class)).
-                    invoke(recv);
+                    invokeExact(recv);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 char x = (char) hs.get(am, methodType(char.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                hs.get(am, methodType(void.class, Void.class, char.class)).
-                    invoke(null, 'a');
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact((VarHandleTestMethodTypeChar) null, 'a');
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 hs.get(am, methodType(void.class, Class.class, char.class)).
-                    invoke(Void.class, 'a');
+                    invokeExact(Void.class, 'a');
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, char.class)).
-                    invoke(0, 'a');
+                    invokeExact(0, 'a');
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, char.class, Class.class)).
-                    invoke(recv, 'a', Void.class);
+                    invokeExact(recv, 'a', Void.class);
             });
         }
 
@@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeChar extends VarHandleBaseTest {
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             // Incorrect arity
             checkWMTE(() -> { // >
                 char x = (char) hs.get(am, methodType(Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, char.class, Class.class)).
-                    invoke('a', Void.class);
+                    invokeExact('a', Void.class);
             });
         }
 
@@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeChar extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                char x = (char) hs.get(am, methodType(char.class, Void.class, int.class)).
-                    invoke(null, 0);
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class)).
+                    invokeExact((char[]) null, 0);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 char x = (char) hs.get(am, methodType(char.class, Class.class, int.class)).
-                    invoke(Void.class, 0);
+                    invokeExact(Void.class, 0);
             });
             checkWMTE(() -> { // array primitive class
                 char x = (char) hs.get(am, methodType(char.class, int.class, int.class)).
-                    invoke(0, 0);
+                    invokeExact(0, 0);
             });
             checkWMTE(() -> { // index reference class
                 char x = (char) hs.get(am, methodType(char.class, char[].class, Class.class)).
-                    invoke(array, Void.class);
+                    invokeExact(array, Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class, char[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 char x = (char) hs.get(am, methodType(char.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                hs.get(am, methodType(void.class, Void.class, int.class, char.class)).
-                    invoke(null, 0, 'a');
+                hs.get(am, methodType(void.class, char[].class, int.class, char.class)).
+                    invokeExact((char[]) null, 0, 'a');
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 hs.get(am, methodType(void.class, Class.class, int.class, char.class)).
-                    invoke(Void.class, 0, 'a');
+                    invokeExact(Void.class, 0, 'a');
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, char[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class, char.class)).
-                    invoke(0, 0, 'a');
+                    invokeExact(0, 0, 'a');
             });
             checkWMTE(() -> { // index reference class
                 hs.get(am, methodType(void.class, char[].class, Class.class, char.class)).
-                    invoke(array, Void.class, 'a');
+                    invokeExact(array, Void.class, 'a');
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, char[].class, int.class, Class.class)).
-                    invoke(array, 0, 'a', Void.class);
+                    invokeExact(array, 0, 'a', Void.class);
             });
         }
 
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java
index e5fc073d191..f3531016262 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8156486
  * @run testng/othervm VarHandleTestMethodTypeDouble
  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeDouble
  */
@@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest {
     public Object[][] accessTestCaseProvider() throws Exception {
         List<AccessTestCase<?>> cases = new ArrayList<>();
 
-        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Instance field",
                                               vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Static field",
                                               vhStaticField, VarHandleTestMethodTypeDouble::testStaticFieldWrongMethodType,
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+        cases.add(new VarHandleAccessTestCase("Array",
                                               vhArray, VarHandleTestMethodTypeDouble::testArrayWrongMethodType,
                                               false));
+
         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
-            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Instance field",
                                                      vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Static field",
                                                      vhStaticField, f, VarHandleTestMethodTypeDouble::testStaticFieldWrongMethodType,
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Array",
                                                      vhArray, f, VarHandleTestMethodTypeDouble::testArrayWrongMethodType,
                                                      false));
         }
@@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                double x = (double) hs.get(am, methodType(double.class, Void.class)).
-                    invoke(null);
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class)).
+                    invokeExact((VarHandleTestMethodTypeDouble) null);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 double x = (double) hs.get(am, methodType(double.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 double x = (double) hs.get(am, methodType(double.class, int.class)).
-                    invoke(0);
+                    invokeExact(0);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
-                Void x = (Void) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class)).
-                    invoke(recv);
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeDouble.class)).
+                    invokeExact(recv);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class)).
-                    invoke(recv);
+                    invokeExact(recv);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 double x = (double) hs.get(am, methodType(double.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                hs.get(am, methodType(void.class, Void.class, double.class)).
-                    invoke(null, 1.0d);
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, double.class)).
+                    invokeExact((VarHandleTestMethodTypeDouble) null, 1.0d);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 hs.get(am, methodType(void.class, Class.class, double.class)).
-                    invoke(Void.class, 1.0d);
+                    invokeExact(Void.class, 1.0d);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, double.class)).
-                    invoke(0, 1.0d);
+                    invokeExact(0, 1.0d);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, double.class, Class.class)).
-                    invoke(recv, 1.0d, Void.class);
+                    invokeExact(recv, 1.0d, Void.class);
             });
         }
 
@@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest {
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             // Incorrect arity
             checkWMTE(() -> { // >
                 double x = (double) hs.get(am, methodType(Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, double.class, Class.class)).
-                    invoke(1.0d, Void.class);
+                    invokeExact(1.0d, Void.class);
             });
         }
 
@@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                double x = (double) hs.get(am, methodType(double.class, Void.class, int.class)).
-                    invoke(null, 0);
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class)).
+                    invokeExact((double[]) null, 0);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 double x = (double) hs.get(am, methodType(double.class, Class.class, int.class)).
-                    invoke(Void.class, 0);
+                    invokeExact(Void.class, 0);
             });
             checkWMTE(() -> { // array primitive class
                 double x = (double) hs.get(am, methodType(double.class, int.class, int.class)).
-                    invoke(0, 0);
+                    invokeExact(0, 0);
             });
             checkWMTE(() -> { // index reference class
                 double x = (double) hs.get(am, methodType(double.class, double[].class, Class.class)).
-                    invoke(array, Void.class);
+                    invokeExact(array, Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class, double[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 double x = (double) hs.get(am, methodType(double.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                hs.get(am, methodType(void.class, Void.class, int.class, double.class)).
-                    invoke(null, 0, 1.0d);
+                hs.get(am, methodType(void.class, double[].class, int.class, double.class)).
+                    invokeExact((double[]) null, 0, 1.0d);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 hs.get(am, methodType(void.class, Class.class, int.class, double.class)).
-                    invoke(Void.class, 0, 1.0d);
+                    invokeExact(Void.class, 0, 1.0d);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, double[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class, double.class)).
-                    invoke(0, 0, 1.0d);
+                    invokeExact(0, 0, 1.0d);
             });
             checkWMTE(() -> { // index reference class
                 hs.get(am, methodType(void.class, double[].class, Class.class, double.class)).
-                    invoke(array, Void.class, 1.0d);
+                    invokeExact(array, Void.class, 1.0d);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, double[].class, int.class, Class.class)).
-                    invoke(array, 0, 1.0d, Void.class);
+                    invokeExact(array, 0, 1.0d, Void.class);
             });
         }
 
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java
index c1bee039b73..b07049d64b0 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8156486
  * @run testng/othervm VarHandleTestMethodTypeFloat
  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeFloat
  */
@@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest {
     public Object[][] accessTestCaseProvider() throws Exception {
         List<AccessTestCase<?>> cases = new ArrayList<>();
 
-        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Instance field",
                                               vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Static field",
                                               vhStaticField, VarHandleTestMethodTypeFloat::testStaticFieldWrongMethodType,
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+        cases.add(new VarHandleAccessTestCase("Array",
                                               vhArray, VarHandleTestMethodTypeFloat::testArrayWrongMethodType,
                                               false));
+
         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
-            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Instance field",
                                                      vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Static field",
                                                      vhStaticField, f, VarHandleTestMethodTypeFloat::testStaticFieldWrongMethodType,
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Array",
                                                      vhArray, f, VarHandleTestMethodTypeFloat::testArrayWrongMethodType,
                                                      false));
         }
@@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                float x = (float) hs.get(am, methodType(float.class, Void.class)).
-                    invoke(null);
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class)).
+                    invokeExact((VarHandleTestMethodTypeFloat) null);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 float x = (float) hs.get(am, methodType(float.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 float x = (float) hs.get(am, methodType(float.class, int.class)).
-                    invoke(0);
+                    invokeExact(0);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
-                Void x = (Void) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class)).
-                    invoke(recv);
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeFloat.class)).
+                    invokeExact(recv);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class)).
-                    invoke(recv);
+                    invokeExact(recv);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 float x = (float) hs.get(am, methodType(float.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                hs.get(am, methodType(void.class, Void.class, float.class)).
-                    invoke(null, 1.0f);
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, float.class)).
+                    invokeExact((VarHandleTestMethodTypeFloat) null, 1.0f);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 hs.get(am, methodType(void.class, Class.class, float.class)).
-                    invoke(Void.class, 1.0f);
+                    invokeExact(Void.class, 1.0f);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, float.class)).
-                    invoke(0, 1.0f);
+                    invokeExact(0, 1.0f);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, float.class, Class.class)).
-                    invoke(recv, 1.0f, Void.class);
+                    invokeExact(recv, 1.0f, Void.class);
             });
         }
 
@@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest {
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             // Incorrect arity
             checkWMTE(() -> { // >
                 float x = (float) hs.get(am, methodType(Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, float.class, Class.class)).
-                    invoke(1.0f, Void.class);
+                    invokeExact(1.0f, Void.class);
             });
         }
 
@@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                float x = (float) hs.get(am, methodType(float.class, Void.class, int.class)).
-                    invoke(null, 0);
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class)).
+                    invokeExact((float[]) null, 0);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 float x = (float) hs.get(am, methodType(float.class, Class.class, int.class)).
-                    invoke(Void.class, 0);
+                    invokeExact(Void.class, 0);
             });
             checkWMTE(() -> { // array primitive class
                 float x = (float) hs.get(am, methodType(float.class, int.class, int.class)).
-                    invoke(0, 0);
+                    invokeExact(0, 0);
             });
             checkWMTE(() -> { // index reference class
                 float x = (float) hs.get(am, methodType(float.class, float[].class, Class.class)).
-                    invoke(array, Void.class);
+                    invokeExact(array, Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class, float[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 float x = (float) hs.get(am, methodType(float.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                hs.get(am, methodType(void.class, Void.class, int.class, float.class)).
-                    invoke(null, 0, 1.0f);
+                hs.get(am, methodType(void.class, float[].class, int.class, float.class)).
+                    invokeExact((float[]) null, 0, 1.0f);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 hs.get(am, methodType(void.class, Class.class, int.class, float.class)).
-                    invoke(Void.class, 0, 1.0f);
+                    invokeExact(Void.class, 0, 1.0f);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, float[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class, float.class)).
-                    invoke(0, 0, 1.0f);
+                    invokeExact(0, 0, 1.0f);
             });
             checkWMTE(() -> { // index reference class
                 hs.get(am, methodType(void.class, float[].class, Class.class, float.class)).
-                    invoke(array, Void.class, 1.0f);
+                    invokeExact(array, Void.class, 1.0f);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, float[].class, int.class, Class.class)).
-                    invoke(array, 0, 1.0f, Void.class);
+                    invokeExact(array, 0, 1.0f, Void.class);
             });
         }
 
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java
index 13b6b0607b0..67fca94c49a 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8156486
  * @run testng/othervm VarHandleTestMethodTypeInt
  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeInt
  */
@@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest {
     public Object[][] accessTestCaseProvider() throws Exception {
         List<AccessTestCase<?>> cases = new ArrayList<>();
 
-        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Instance field",
                                               vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Static field",
                                               vhStaticField, VarHandleTestMethodTypeInt::testStaticFieldWrongMethodType,
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+        cases.add(new VarHandleAccessTestCase("Array",
                                               vhArray, VarHandleTestMethodTypeInt::testArrayWrongMethodType,
                                               false));
+
         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
-            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Instance field",
                                                      vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Static field",
                                                      vhStaticField, f, VarHandleTestMethodTypeInt::testStaticFieldWrongMethodType,
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Array",
                                                      vhArray, f, VarHandleTestMethodTypeInt::testArrayWrongMethodType,
                                                      false));
         }
@@ -644,211 +646,211 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                int x = (int) hs.get(am, methodType(int.class, Void.class)).
-                    invoke(null);
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 int x = (int) hs.get(am, methodType(int.class, int.class)).
-                    invoke(0);
+                    invokeExact(0);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
-                Void x = (Void) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class)).
-                    invoke(recv);
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class)).
+                    invokeExact(recv);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class)).
-                    invoke(recv);
+                    invokeExact(recv);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                hs.get(am, methodType(void.class, Void.class, int.class)).
-                    invoke(null, 1);
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 1);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 hs.get(am, methodType(void.class, Class.class, int.class)).
-                    invoke(Void.class, 1);
+                    invokeExact(Void.class, 1);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class)).
-                    invoke(0, 1);
+                    invokeExact(0, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)).
-                    invoke(recv, 1, Void.class);
+                    invokeExact(recv, 1, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, int.class)).
-                    invoke(null, 1, 1);
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 1, 1);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, int.class)).
-                    invoke(Void.class, 1, 1);
+                    invokeExact(Void.class, 1, 1);
             });
             checkWMTE(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, Class.class, int.class)).
-                    invoke(recv, Void.class, 1);
+                    invokeExact(recv, Void.class, 1);
             });
             checkWMTE(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)).
-                    invoke(recv, 1, Void.class);
+                    invokeExact(recv, 1, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , int.class, int.class)).
-                    invoke(0, 1, 1);
+                    invokeExact(0, 1, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, int.class, Class.class)).
-                    invoke(recv, 1, 1, Void.class);
+                    invokeExact(recv, 1, 1, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
             checkNPE(() -> { // null receiver
-                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class)).
-                    invoke(null, 1, 1);
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 1, 1);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)).
-                    invoke(Void.class, 1, 1);
+                    invokeExact(Void.class, 1, 1);
             });
             checkWMTE(() -> { // expected reference class
                 int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class, int.class)).
-                    invoke(recv, Void.class, 1);
+                    invokeExact(recv, Void.class, 1);
             });
             checkWMTE(() -> { // actual reference class
                 int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)).
-                    invoke(recv, 1, Void.class);
+                    invokeExact(recv, 1, Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 int x = (int) hs.get(am, methodType(int.class, int.class , int.class, int.class)).
-                    invoke(0, 1, 1);
+                    invokeExact(0, 1, 1);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class , int.class, int.class)).
-                    invoke(recv, 1, 1);
+                    invokeExact(recv, 1, 1);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class , int.class, int.class)).
-                    invoke(recv, 1, 1);
+                    invokeExact(recv, 1, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, int.class, Class.class)).
-                    invoke(recv, 1, 1, Void.class);
+                    invokeExact(recv, 1, 1, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
             checkNPE(() -> { // null receiver
-                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class)).
-                    invoke(null, 1);
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 1);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
-                    invoke(Void.class, 1);
+                    invokeExact(Void.class, 1);
             });
             checkWMTE(() -> { // value reference class
                 int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 int x = (int) hs.get(am, methodType(int.class, int.class, int.class)).
-                    invoke(0, 1);
+                    invokeExact(0, 1);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class, int.class)).
-                    invoke(recv, 1);
+                    invokeExact(recv, 1);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class)).
-                    invoke(recv, 1);
+                    invokeExact(recv, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
-                    invoke(recv, 1, Void.class);
+                    invokeExact(recv, 1, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
             checkNPE(() -> { // null receiver
-                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class)).
-                    invoke(null, 1);
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 1);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
-                    invoke(Void.class, 1);
+                    invokeExact(Void.class, 1);
             });
             checkWMTE(() -> { // value reference class
                 int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 int x = (int) hs.get(am, methodType(int.class, int.class, int.class)).
-                    invoke(0, 1);
+                    invokeExact(0, 1);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class, int.class)).
-                    invoke(recv, 1);
+                    invokeExact(recv, 1);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class)).
-                    invoke(recv, 1);
+                    invokeExact(recv, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
-                    invoke(recv, 1, Void.class);
+                    invokeExact(recv, 1, Void.class);
             });
         }
     }
@@ -1190,52 +1192,52 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest {
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             // Incorrect arity
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, int.class, Class.class)).
-                    invoke(1, Void.class);
+                    invokeExact(1, Void.class);
             });
         }
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
             checkWMTE(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class)).
-                    invoke(Void.class, 1);
+                    invokeExact(Void.class, 1);
             });
             checkWMTE(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, Class.class)).
-                    invoke(1, Void.class);
+                    invokeExact(1, Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, Class.class)).
-                    invoke(1, 1, Void.class);
+                    invokeExact(1, 1, Void.class);
             });
         }
 
@@ -1243,29 +1245,29 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest {
             // Incorrect argument types
             checkWMTE(() -> { // expected reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
-                    invoke(Void.class, 1);
+                    invokeExact(Void.class, 1);
             });
             checkWMTE(() -> { // actual reference class
                 int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)).
-                    invoke(1, Void.class);
+                    invokeExact(1, Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, int.class, int.class)).
-                    invoke(1, 1);
+                    invokeExact(1, 1);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class)).
-                    invoke(1, 1);
+                    invokeExact(1, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, int.class, int.class, Class.class)).
-                    invoke(1, 1, Void.class);
+                    invokeExact(1, 1, Void.class);
             });
         }
 
@@ -1273,25 +1275,25 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest {
             // Incorrect argument types
             checkWMTE(() -> { // value reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, int.class)).
-                    invoke(1);
+                    invokeExact(1);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
-                    invoke(1);
+                    invokeExact(1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)).
-                    invoke(1, Void.class);
+                    invokeExact(1, Void.class);
             });
         }
 
@@ -1299,25 +1301,25 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest {
             // Incorrect argument types
             checkWMTE(() -> { // value reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, int.class)).
-                    invoke(1);
+                    invokeExact(1);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
-                    invoke(1);
+                    invokeExact(1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)).
-                    invoke(1, Void.class);
+                    invokeExact(1, Void.class);
             });
         }
     }
@@ -1909,237 +1911,237 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class)).
-                    invoke(null, 0);
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class)).
+                    invokeExact((int[]) null, 0);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
-                    invoke(Void.class, 0);
+                    invokeExact(Void.class, 0);
             });
             checkWMTE(() -> { // array primitive class
                 int x = (int) hs.get(am, methodType(int.class, int.class, int.class)).
-                    invoke(0, 0);
+                    invokeExact(0, 0);
             });
             checkWMTE(() -> { // index reference class
                 int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class)).
-                    invoke(array, Void.class);
+                    invokeExact(array, Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class, int[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                hs.get(am, methodType(void.class, Void.class, int.class, int.class)).
-                    invoke(null, 0, 1);
+                hs.get(am, methodType(void.class, int[].class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 1);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 hs.get(am, methodType(void.class, Class.class, int.class, int.class)).
-                    invoke(Void.class, 0, 1);
+                    invokeExact(Void.class, 0, 1);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, int[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class, int.class)).
-                    invoke(0, 0, 1);
+                    invokeExact(0, 0, 1);
             });
             checkWMTE(() -> { // index reference class
                 hs.get(am, methodType(void.class, int[].class, Class.class, int.class)).
-                    invoke(array, Void.class, 1);
+                    invokeExact(array, Void.class, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, int[].class, int.class, Class.class)).
-                    invoke(array, 0, 1, Void.class);
+                    invokeExact(array, 0, 1, Void.class);
             });
         }
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, int.class, int.class)).
-                    invoke(null, 0, 1, 1);
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 1, 1);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, int.class, int.class)).
-                    invoke(Void.class, 0, 1, 1);
+                    invokeExact(Void.class, 0, 1, 1);
             });
             checkWMTE(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, Class.class, int.class)).
-                    invoke(array, 0, Void.class, 1);
+                    invokeExact(array, 0, Void.class, 1);
             });
             checkWMTE(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, Class.class)).
-                    invoke(array, 0, 1, Void.class);
+                    invokeExact(array, 0, 1, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, int.class, int.class)).
-                    invoke(0, 0, 1, 1);
+                    invokeExact(0, 0, 1, 1);
             });
             checkWMTE(() -> { // index reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, Class.class, int.class, int.class)).
-                    invoke(array, Void.class, 1, 1);
+                    invokeExact(array, Void.class, 1, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class, Class.class)).
-                    invoke(array, 0, 1, 1, Void.class);
+                    invokeExact(array, 0, 1, 1, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class, int.class)).
-                    invoke(null, 0, 1, 1);
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 1, 1);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class, int.class)).
-                    invoke(Void.class, 0, 1, 1);
+                    invokeExact(Void.class, 0, 1, 1);
             });
             checkWMTE(() -> { // expected reference class
                 int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class, int.class)).
-                    invoke(array, 0, Void.class, 1);
+                    invokeExact(array, 0, Void.class, 1);
             });
             checkWMTE(() -> { // actual reference class
                 int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)).
-                    invoke(array, 0, 1, Void.class);
+                    invokeExact(array, 0, 1, Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class, int.class)).
-                    invoke(0, 0, 1, 1);
+                    invokeExact(0, 0, 1, 1);
             });
             checkWMTE(() -> { // index reference class
                 int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class, int.class)).
-                    invoke(array, Void.class, 1, 1);
+                    invokeExact(array, Void.class, 1, 1);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class, int.class)).
-                    invoke(array, 0, 1, 1);
+                    invokeExact(array, 0, 1, 1);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class)).
-                    invoke(array, 0, 1, 1);
+                    invokeExact(array, 0, 1, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, int.class, Class.class)).
-                    invoke(array, 0, 1, 1, Void.class);
+                    invokeExact(array, 0, 1, 1, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class)).
-                    invoke(null, 0, 1);
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 1);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)).
-                    invoke(Void.class, 0, 1);
+                    invokeExact(Void.class, 0, 1);
             });
             checkWMTE(() -> { // value reference class
                 int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class)).
-                    invoke(0, 0, 1);
+                    invokeExact(0, 0, 1);
             });
             checkWMTE(() -> { // index reference class
                 int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class)).
-                    invoke(array, Void.class, 1);
+                    invokeExact(array, Void.class, 1);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class)).
-                    invoke(array, 0, 1);
+                    invokeExact(array, 0, 1);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class)).
-                    invoke(array, 0, 1);
+                    invokeExact(array, 0, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)).
-                    invoke(array, 0, 1, Void.class);
+                    invokeExact(array, 0, 1, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class)).
-                    invoke(null, 0, 1);
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 1);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)).
-                    invoke(Void.class, 0, 1);
+                    invokeExact(Void.class, 0, 1);
             });
             checkWMTE(() -> { // value reference class
                 int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class)).
-                    invoke(0, 0, 1);
+                    invokeExact(0, 0, 1);
             });
             checkWMTE(() -> { // index reference class
                 int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class)).
-                    invoke(array, Void.class, 1);
+                    invokeExact(array, Void.class, 1);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class)).
-                    invoke(array, 0, 1);
+                    invokeExact(array, 0, 1);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class)).
-                    invoke(array, 0, 1);
+                    invokeExact(array, 0, 1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 int x = (int) hs.get(am, methodType(int.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)).
-                    invoke(array, 0, 1, Void.class);
+                    invokeExact(array, 0, 1, Void.class);
             });
         }
     }
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java
index 44151683133..0972e663cc7 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8156486
  * @run testng/othervm VarHandleTestMethodTypeLong
  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeLong
  */
@@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest {
     public Object[][] accessTestCaseProvider() throws Exception {
         List<AccessTestCase<?>> cases = new ArrayList<>();
 
-        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Instance field",
                                               vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Static field",
                                               vhStaticField, VarHandleTestMethodTypeLong::testStaticFieldWrongMethodType,
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+        cases.add(new VarHandleAccessTestCase("Array",
                                               vhArray, VarHandleTestMethodTypeLong::testArrayWrongMethodType,
                                               false));
+
         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
-            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Instance field",
                                                      vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Static field",
                                                      vhStaticField, f, VarHandleTestMethodTypeLong::testStaticFieldWrongMethodType,
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Array",
                                                      vhArray, f, VarHandleTestMethodTypeLong::testArrayWrongMethodType,
                                                      false));
         }
@@ -644,211 +646,211 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                long x = (long) hs.get(am, methodType(long.class, Void.class)).
-                    invoke(null);
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 long x = (long) hs.get(am, methodType(long.class, int.class)).
-                    invoke(0);
+                    invokeExact(0);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
-                Void x = (Void) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class)).
-                    invoke(recv);
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class)).
+                    invokeExact(recv);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class)).
-                    invoke(recv);
+                    invokeExact(recv);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                hs.get(am, methodType(void.class, Void.class, long.class)).
-                    invoke(null, 1L);
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 1L);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 hs.get(am, methodType(void.class, Class.class, long.class)).
-                    invoke(Void.class, 1L);
+                    invokeExact(Void.class, 1L);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, long.class)).
-                    invoke(0, 1L);
+                    invokeExact(0, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)).
-                    invoke(recv, 1L, Void.class);
+                    invokeExact(recv, 1L, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, long.class, long.class)).
-                    invoke(null, 1L, 1L);
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 1L, 1L);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, long.class, long.class)).
-                    invoke(Void.class, 1L, 1L);
+                    invokeExact(Void.class, 1L, 1L);
             });
             checkWMTE(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, Class.class, long.class)).
-                    invoke(recv, Void.class, 1L);
+                    invokeExact(recv, Void.class, 1L);
             });
             checkWMTE(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)).
-                    invoke(recv, 1L, Void.class);
+                    invokeExact(recv, 1L, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , long.class, long.class)).
-                    invoke(0, 1L, 1L);
+                    invokeExact(0, 1L, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, long.class, Class.class)).
-                    invoke(recv, 1L, 1L, Void.class);
+                    invokeExact(recv, 1L, 1L, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
             checkNPE(() -> { // null receiver
-                long x = (long) hs.get(am, methodType(long.class, Void.class, long.class, long.class)).
-                    invoke(null, 1L, 1L);
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 1L, 1L);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class, long.class, long.class)).
-                    invoke(Void.class, 1L, 1L);
+                    invokeExact(Void.class, 1L, 1L);
             });
             checkWMTE(() -> { // expected reference class
                 long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class, long.class)).
-                    invoke(recv, Void.class, 1L);
+                    invokeExact(recv, Void.class, 1L);
             });
             checkWMTE(() -> { // actual reference class
                 long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)).
-                    invoke(recv, 1L, Void.class);
+                    invokeExact(recv, 1L, Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 long x = (long) hs.get(am, methodType(long.class, int.class , long.class, long.class)).
-                    invoke(0, 1L, 1L);
+                    invokeExact(0, 1L, 1L);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class , long.class, long.class)).
-                    invoke(recv, 1L, 1L);
+                    invokeExact(recv, 1L, 1L);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class , long.class, long.class)).
-                    invoke(recv, 1L, 1L);
+                    invokeExact(recv, 1L, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, long.class, Class.class)).
-                    invoke(recv, 1L, 1L, Void.class);
+                    invokeExact(recv, 1L, 1L, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
             checkNPE(() -> { // null receiver
-                long x = (long) hs.get(am, methodType(long.class, Void.class, long.class)).
-                    invoke(null, 1L);
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 1L);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)).
-                    invoke(Void.class, 1L);
+                    invokeExact(Void.class, 1L);
             });
             checkWMTE(() -> { // value reference class
                 long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 long x = (long) hs.get(am, methodType(long.class, int.class, long.class)).
-                    invoke(0, 1L);
+                    invokeExact(0, 1L);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class, long.class)).
-                    invoke(recv, 1L);
+                    invokeExact(recv, 1L);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class)).
-                    invoke(recv, 1L);
+                    invokeExact(recv, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
-                    invoke(recv, 1L, Void.class);
+                    invokeExact(recv, 1L, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
             checkNPE(() -> { // null receiver
-                long x = (long) hs.get(am, methodType(long.class, Void.class, long.class)).
-                    invoke(null, 1L);
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 1L);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)).
-                    invoke(Void.class, 1L);
+                    invokeExact(Void.class, 1L);
             });
             checkWMTE(() -> { // value reference class
                 long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 long x = (long) hs.get(am, methodType(long.class, int.class, long.class)).
-                    invoke(0, 1L);
+                    invokeExact(0, 1L);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class, long.class)).
-                    invoke(recv, 1L);
+                    invokeExact(recv, 1L);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class)).
-                    invoke(recv, 1L);
+                    invokeExact(recv, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
-                    invoke(recv, 1L, Void.class);
+                    invokeExact(recv, 1L, Void.class);
             });
         }
     }
@@ -1190,52 +1192,52 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest {
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             // Incorrect arity
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, long.class, Class.class)).
-                    invoke(1L, Void.class);
+                    invokeExact(1L, Void.class);
             });
         }
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
             checkWMTE(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, long.class)).
-                    invoke(Void.class, 1L);
+                    invokeExact(Void.class, 1L);
             });
             checkWMTE(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, long.class, Class.class)).
-                    invoke(1L, Void.class);
+                    invokeExact(1L, Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, long.class, long.class, Class.class)).
-                    invoke(1L, 1L, Void.class);
+                    invokeExact(1L, 1L, Void.class);
             });
         }
 
@@ -1243,29 +1245,29 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest {
             // Incorrect argument types
             checkWMTE(() -> { // expected reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)).
-                    invoke(Void.class, 1L);
+                    invokeExact(Void.class, 1L);
             });
             checkWMTE(() -> { // actual reference class
                 long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)).
-                    invoke(1L, Void.class);
+                    invokeExact(1L, Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, long.class, long.class)).
-                    invoke(1L, 1L);
+                    invokeExact(1L, 1L);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class, long.class)).
-                    invoke(1L, 1L);
+                    invokeExact(1L, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, long.class, long.class, Class.class)).
-                    invoke(1L, 1L, Void.class);
+                    invokeExact(1L, 1L, Void.class);
             });
         }
 
@@ -1273,25 +1275,25 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest {
             // Incorrect argument types
             checkWMTE(() -> { // value reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, long.class)).
-                    invoke(1L);
+                    invokeExact(1L);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class)).
-                    invoke(1L);
+                    invokeExact(1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)).
-                    invoke(1L, Void.class);
+                    invokeExact(1L, Void.class);
             });
         }
 
@@ -1299,25 +1301,25 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest {
             // Incorrect argument types
             checkWMTE(() -> { // value reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, long.class)).
-                    invoke(1L);
+                    invokeExact(1L);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class)).
-                    invoke(1L);
+                    invokeExact(1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)).
-                    invoke(1L, Void.class);
+                    invokeExact(1L, Void.class);
             });
         }
     }
@@ -1909,237 +1911,237 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                long x = (long) hs.get(am, methodType(long.class, Void.class, int.class)).
-                    invoke(null, 0);
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class)).
+                    invokeExact((long[]) null, 0);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class, int.class)).
-                    invoke(Void.class, 0);
+                    invokeExact(Void.class, 0);
             });
             checkWMTE(() -> { // array primitive class
                 long x = (long) hs.get(am, methodType(long.class, int.class, int.class)).
-                    invoke(0, 0);
+                    invokeExact(0, 0);
             });
             checkWMTE(() -> { // index reference class
                 long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class)).
-                    invoke(array, Void.class);
+                    invokeExact(array, Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class, long[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                hs.get(am, methodType(void.class, Void.class, int.class, long.class)).
-                    invoke(null, 0, 1L);
+                hs.get(am, methodType(void.class, long[].class, int.class, long.class)).
+                    invokeExact((long[]) null, 0, 1L);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 hs.get(am, methodType(void.class, Class.class, int.class, long.class)).
-                    invoke(Void.class, 0, 1L);
+                    invokeExact(Void.class, 0, 1L);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, long[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class, long.class)).
-                    invoke(0, 0, 1L);
+                    invokeExact(0, 0, 1L);
             });
             checkWMTE(() -> { // index reference class
                 hs.get(am, methodType(void.class, long[].class, Class.class, long.class)).
-                    invoke(array, Void.class, 1L);
+                    invokeExact(array, Void.class, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, long[].class, int.class, Class.class)).
-                    invoke(array, 0, 1L, Void.class);
+                    invokeExact(array, 0, 1L, Void.class);
             });
         }
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, long.class, long.class)).
-                    invoke(null, 0, 1L, 1L);
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class)).
+                    invokeExact((long[]) null, 0, 1L, 1L);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, long.class, long.class)).
-                    invoke(Void.class, 0, 1L, 1L);
+                    invokeExact(Void.class, 0, 1L, 1L);
             });
             checkWMTE(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, Class.class, long.class)).
-                    invoke(array, 0, Void.class, 1L);
+                    invokeExact(array, 0, Void.class, 1L);
             });
             checkWMTE(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, Class.class)).
-                    invoke(array, 0, 1L, Void.class);
+                    invokeExact(array, 0, 1L, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, long.class, long.class)).
-                    invoke(0, 0, 1L, 1L);
+                    invokeExact(0, 0, 1L, 1L);
             });
             checkWMTE(() -> { // index reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, Class.class, long.class, long.class)).
-                    invoke(array, Void.class, 1L, 1L);
+                    invokeExact(array, Void.class, 1L, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class, Class.class)).
-                    invoke(array, 0, 1L, 1L, Void.class);
+                    invokeExact(array, 0, 1L, 1L, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                long x = (long) hs.get(am, methodType(long.class, Void.class, int.class, long.class, long.class)).
-                    invoke(null, 0, 1L, 1L);
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, long.class)).
+                    invokeExact((long[]) null, 0, 1L, 1L);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class, long.class)).
-                    invoke(Void.class, 0, 1L, 1L);
+                    invokeExact(Void.class, 0, 1L, 1L);
             });
             checkWMTE(() -> { // expected reference class
                 long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class, long.class)).
-                    invoke(array, 0, Void.class, 1L);
+                    invokeExact(array, 0, Void.class, 1L);
             });
             checkWMTE(() -> { // actual reference class
                 long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)).
-                    invoke(array, 0, 1L, Void.class);
+                    invokeExact(array, 0, 1L, Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class, long.class)).
-                    invoke(0, 0, 1L, 1L);
+                    invokeExact(0, 0, 1L, 1L);
             });
             checkWMTE(() -> { // index reference class
                 long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class, long.class)).
-                    invoke(array, Void.class, 1L, 1L);
+                    invokeExact(array, Void.class, 1L, 1L);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class, long.class)).
-                    invoke(array, 0, 1L, 1L);
+                    invokeExact(array, 0, 1L, 1L);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class)).
-                    invoke(array, 0, 1L, 1L);
+                    invokeExact(array, 0, 1L, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, long.class, Class.class)).
-                    invoke(array, 0, 1L, 1L, Void.class);
+                    invokeExact(array, 0, 1L, 1L, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                long x = (long) hs.get(am, methodType(long.class, Void.class, int.class, long.class)).
-                    invoke(null, 0, 1L);
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class)).
+                    invokeExact((long[]) null, 0, 1L);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class)).
-                    invoke(Void.class, 0, 1L);
+                    invokeExact(Void.class, 0, 1L);
             });
             checkWMTE(() -> { // value reference class
                 long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class)).
-                    invoke(0, 0, 1L);
+                    invokeExact(0, 0, 1L);
             });
             checkWMTE(() -> { // index reference class
                 long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class)).
-                    invoke(array, Void.class, 1L);
+                    invokeExact(array, Void.class, 1L);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class)).
-                    invoke(array, 0, 1L);
+                    invokeExact(array, 0, 1L);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class)).
-                    invoke(array, 0, 1L);
+                    invokeExact(array, 0, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)).
-                    invoke(array, 0, 1L, Void.class);
+                    invokeExact(array, 0, 1L, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                long x = (long) hs.get(am, methodType(long.class, Void.class, int.class, long.class)).
-                    invoke(null, 0, 1L);
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class)).
+                    invokeExact((long[]) null, 0, 1L);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class)).
-                    invoke(Void.class, 0, 1L);
+                    invokeExact(Void.class, 0, 1L);
             });
             checkWMTE(() -> { // value reference class
                 long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class)).
-                    invoke(0, 0, 1L);
+                    invokeExact(0, 0, 1L);
             });
             checkWMTE(() -> { // index reference class
                 long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class)).
-                    invoke(array, Void.class, 1L);
+                    invokeExact(array, Void.class, 1L);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class)).
-                    invoke(array, 0, 1L);
+                    invokeExact(array, 0, 1L);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class)).
-                    invoke(array, 0, 1L);
+                    invokeExact(array, 0, 1L);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 long x = (long) hs.get(am, methodType(long.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)).
-                    invoke(array, 0, 1L, Void.class);
+                    invokeExact(array, 0, 1L, Void.class);
             });
         }
     }
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java
index 634646e78c1..16efabe0917 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8156486
  * @run testng/othervm VarHandleTestMethodTypeShort
  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeShort
  */
@@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeShort extends VarHandleBaseTest {
     public Object[][] accessTestCaseProvider() throws Exception {
         List<AccessTestCase<?>> cases = new ArrayList<>();
 
-        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Instance field",
                                               vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Static field",
                                               vhStaticField, VarHandleTestMethodTypeShort::testStaticFieldWrongMethodType,
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+        cases.add(new VarHandleAccessTestCase("Array",
                                               vhArray, VarHandleTestMethodTypeShort::testArrayWrongMethodType,
                                               false));
+
         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
-            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Instance field",
                                                      vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Static field",
                                                      vhStaticField, f, VarHandleTestMethodTypeShort::testStaticFieldWrongMethodType,
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Array",
                                                      vhArray, f, VarHandleTestMethodTypeShort::testArrayWrongMethodType,
                                                      false));
         }
@@ -329,63 +331,63 @@ public class VarHandleTestMethodTypeShort extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                short x = (short) hs.get(am, methodType(short.class, Void.class)).
-                    invoke(null);
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class)).
+                    invokeExact((VarHandleTestMethodTypeShort) null);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 short x = (short) hs.get(am, methodType(short.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 short x = (short) hs.get(am, methodType(short.class, int.class)).
-                    invoke(0);
+                    invokeExact(0);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
-                Void x = (Void) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class)).
-                    invoke(recv);
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeShort.class)).
+                    invokeExact(recv);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class)).
-                    invoke(recv);
+                    invokeExact(recv);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 short x = (short) hs.get(am, methodType(short.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                hs.get(am, methodType(void.class, Void.class, short.class)).
-                    invoke(null, (short)1);
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact((VarHandleTestMethodTypeShort) null, (short)1);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 hs.get(am, methodType(void.class, Class.class, short.class)).
-                    invoke(Void.class, (short)1);
+                    invokeExact(Void.class, (short)1);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, short.class)).
-                    invoke(0, (short)1);
+                    invokeExact(0, (short)1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, short.class, Class.class)).
-                    invoke(recv, (short)1, Void.class);
+                    invokeExact(recv, (short)1, Void.class);
             });
         }
 
@@ -513,32 +515,32 @@ public class VarHandleTestMethodTypeShort extends VarHandleBaseTest {
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             // Incorrect arity
             checkWMTE(() -> { // >
                 short x = (short) hs.get(am, methodType(Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, short.class, Class.class)).
-                    invoke((short)1, Void.class);
+                    invokeExact((short)1, Void.class);
             });
         }
 
@@ -783,71 +785,71 @@ public class VarHandleTestMethodTypeShort extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                short x = (short) hs.get(am, methodType(short.class, Void.class, int.class)).
-                    invoke(null, 0);
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class)).
+                    invokeExact((short[]) null, 0);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 short x = (short) hs.get(am, methodType(short.class, Class.class, int.class)).
-                    invoke(Void.class, 0);
+                    invokeExact(Void.class, 0);
             });
             checkWMTE(() -> { // array primitive class
                 short x = (short) hs.get(am, methodType(short.class, int.class, int.class)).
-                    invoke(0, 0);
+                    invokeExact(0, 0);
             });
             checkWMTE(() -> { // index reference class
                 short x = (short) hs.get(am, methodType(short.class, short[].class, Class.class)).
-                    invoke(array, Void.class);
+                    invokeExact(array, Void.class);
             });
             // Incorrect return type
             checkWMTE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class, short[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 short x = (short) hs.get(am, methodType(short.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                hs.get(am, methodType(void.class, Void.class, int.class, short.class)).
-                    invoke(null, 0, (short)1);
+                hs.get(am, methodType(void.class, short[].class, int.class, short.class)).
+                    invokeExact((short[]) null, 0, (short)1);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 hs.get(am, methodType(void.class, Class.class, int.class, short.class)).
-                    invoke(Void.class, 0, (short)1);
+                    invokeExact(Void.class, 0, (short)1);
             });
             checkWMTE(() -> { // value reference class
                 hs.get(am, methodType(void.class, short[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class, short.class)).
-                    invoke(0, 0, (short)1);
+                    invokeExact(0, 0, (short)1);
             });
             checkWMTE(() -> { // index reference class
                 hs.get(am, methodType(void.class, short[].class, Class.class, short.class)).
-                    invoke(array, Void.class, (short)1);
+                    invokeExact(array, Void.class, (short)1);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, short[].class, int.class, Class.class)).
-                    invoke(array, 0, (short)1, Void.class);
+                    invokeExact(array, 0, (short)1, Void.class);
             });
         }
 
diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java
index f3b58c9e2f9..2cc853349ce 100644
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8156486
  * @run testng/othervm VarHandleTestMethodTypeString
  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeString
  */
@@ -81,27 +82,28 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest {
     public Object[][] accessTestCaseProvider() throws Exception {
         List<AccessTestCase<?>> cases = new ArrayList<>();
 
-        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Instance field",
                                               vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Static field",
                                               vhStaticField, VarHandleTestMethodTypeString::testStaticFieldWrongMethodType,
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+        cases.add(new VarHandleAccessTestCase("Array",
                                               vhArray, VarHandleTestMethodTypeString::testArrayWrongMethodType,
                                               false));
+
         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
-            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Instance field",
                                                      vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Static field",
                                                      vhStaticField, f, VarHandleTestMethodTypeString::testStaticFieldWrongMethodType,
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Array",
                                                      vhArray, f, VarHandleTestMethodTypeString::testArrayWrongMethodType,
                                                      false));
         }
@@ -586,174 +588,174 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                String x = (String) hs.get(am, methodType(String.class, Void.class)).
-                    invoke(null);
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class)).
+                    invokeExact((VarHandleTestMethodTypeString) null);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 String x = (String) hs.get(am, methodType(String.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 String x = (String) hs.get(am, methodType(String.class, int.class)).
-                    invoke(0);
+                    invokeExact(0);
             });
             // Incorrect return type
-            checkCCE(() -> { // reference class
-                Void x = (Void) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class)).
-                    invoke(recv);
+            hs.checkWMTEOrCCE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class)).
+                    invokeExact(recv);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class)).
-                    invoke(recv);
+                    invokeExact(recv);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 String x = (String) hs.get(am, methodType(String.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                hs.get(am, methodType(void.class, Void.class, String.class)).
-                    invoke(null, "foo");
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, String.class)).
+                    invokeExact((VarHandleTestMethodTypeString) null, "foo");
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 hs.get(am, methodType(void.class, Class.class, String.class)).
-                    invoke(Void.class, "foo");
+                    invokeExact(Void.class, "foo");
             });
-            checkCCE(() -> { // value reference class
+            hs.checkWMTEOrCCE(() -> { // value reference class
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, String.class)).
-                    invoke(0, "foo");
+                    invokeExact(0, "foo");
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, String.class, Class.class)).
-                    invoke(recv, "foo", Void.class);
+                    invokeExact(recv, "foo", Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, String.class, String.class)).
-                    invoke(null, "foo", "foo");
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, String.class)).
+                    invokeExact((VarHandleTestMethodTypeString) null, "foo", "foo");
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, String.class, String.class)).
-                    invoke(Void.class, "foo", "foo");
+                    invokeExact(Void.class, "foo", "foo");
             });
-            checkCCE(() -> { // expected reference class
+            hs.checkWMTEOrCCE(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, Class.class, String.class)).
-                    invoke(recv, Void.class, "foo");
+                    invokeExact(recv, Void.class, "foo");
             });
-            checkCCE(() -> { // actual reference class
+            hs.checkWMTEOrCCE(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, Class.class)).
-                    invoke(recv, "foo", Void.class);
+                    invokeExact(recv, "foo", Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , String.class, String.class)).
-                    invoke(0, "foo", "foo");
+                    invokeExact(0, "foo", "foo");
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, String.class, Class.class)).
-                    invoke(recv, "foo", "foo", Void.class);
+                    invokeExact(recv, "foo", "foo", Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
             checkNPE(() -> { // null receiver
-                String x = (String) hs.get(am, methodType(String.class, Void.class, String.class, String.class)).
-                    invoke(null, "foo", "foo");
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, String.class)).
+                    invokeExact((VarHandleTestMethodTypeString) null, "foo", "foo");
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 String x = (String) hs.get(am, methodType(String.class, Class.class, String.class, String.class)).
-                    invoke(Void.class, "foo", "foo");
+                    invokeExact(Void.class, "foo", "foo");
             });
-            checkCCE(() -> { // expected reference class
+            hs.checkWMTEOrCCE(() -> { // expected reference class
                 String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class, String.class)).
-                    invoke(recv, Void.class, "foo");
+                    invokeExact(recv, Void.class, "foo");
             });
-            checkCCE(() -> { // actual reference class
+            hs.checkWMTEOrCCE(() -> { // actual reference class
                 String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, Class.class)).
-                    invoke(recv, "foo", Void.class);
+                    invokeExact(recv, "foo", Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 String x = (String) hs.get(am, methodType(String.class, int.class , String.class, String.class)).
-                    invoke(0, "foo", "foo");
+                    invokeExact(0, "foo", "foo");
             });
             // Incorrect return type
-            checkCCE(() -> { // reference class
+            hs.checkWMTEOrCCE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class , String.class, String.class)).
-                    invoke(recv, "foo", "foo");
+                    invokeExact(recv, "foo", "foo");
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class , String.class, String.class)).
-                    invoke(recv, "foo", "foo");
+                    invokeExact(recv, "foo", "foo");
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 String x = (String) hs.get(am, methodType(String.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, String.class, Class.class)).
-                    invoke(recv, "foo", "foo", Void.class);
+                    invokeExact(recv, "foo", "foo", Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
             checkNPE(() -> { // null receiver
-                String x = (String) hs.get(am, methodType(String.class, Void.class, String.class)).
-                    invoke(null, "foo");
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class)).
+                    invokeExact((VarHandleTestMethodTypeString) null, "foo");
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 String x = (String) hs.get(am, methodType(String.class, Class.class, String.class)).
-                    invoke(Void.class, "foo");
+                    invokeExact(Void.class, "foo");
             });
-            checkCCE(() -> { // value reference class
+            hs.checkWMTEOrCCE(() -> { // value reference class
                 String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 String x = (String) hs.get(am, methodType(String.class, int.class, String.class)).
-                    invoke(0, "foo");
+                    invokeExact(0, "foo");
             });
             // Incorrect return type
-            checkCCE(() -> { // reference class
+            hs.checkWMTEOrCCE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class, String.class)).
-                    invoke(recv, "foo");
+                    invokeExact(recv, "foo");
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class)).
-                    invoke(recv, "foo");
+                    invokeExact(recv, "foo");
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 String x = (String) hs.get(am, methodType(String.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class)).
-                    invoke(recv, "foo", Void.class);
+                    invokeExact(recv, "foo", Void.class);
             });
         }
 
@@ -1054,110 +1056,110 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest {
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect return type
-            checkCCE(() -> { // reference class
+            hs.checkWMTEOrCCE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             // Incorrect arity
             checkWMTE(() -> { // >
                 String x = (String) hs.get(am, methodType(Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
-            checkCCE(() -> { // value reference class
+            hs.checkWMTEOrCCE(() -> { // value reference class
                 hs.get(am, methodType(void.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, String.class, Class.class)).
-                    invoke("foo", Void.class);
+                    invokeExact("foo", Void.class);
             });
         }
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
-            checkCCE(() -> { // expected reference class
+            hs.checkWMTEOrCCE(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, String.class)).
-                    invoke(Void.class, "foo");
+                    invokeExact(Void.class, "foo");
             });
-            checkCCE(() -> { // actual reference class
+            hs.checkWMTEOrCCE(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, String.class, Class.class)).
-                    invoke("foo", Void.class);
+                    invokeExact("foo", Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, String.class, String.class, Class.class)).
-                    invoke("foo", "foo", Void.class);
+                    invokeExact("foo", "foo", Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
             // Incorrect argument types
-            checkCCE(() -> { // expected reference class
+            hs.checkWMTEOrCCE(() -> { // expected reference class
                 String x = (String) hs.get(am, methodType(String.class, Class.class, String.class)).
-                    invoke(Void.class, "foo");
+                    invokeExact(Void.class, "foo");
             });
-            checkCCE(() -> { // actual reference class
+            hs.checkWMTEOrCCE(() -> { // actual reference class
                 String x = (String) hs.get(am, methodType(String.class, String.class, Class.class)).
-                    invoke("foo", Void.class);
+                    invokeExact("foo", Void.class);
             });
             // Incorrect return type
-            checkCCE(() -> { // reference class
+            hs.checkWMTEOrCCE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, String.class, String.class)).
-                    invoke("foo", "foo");
+                    invokeExact("foo", "foo");
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, String.class, String.class)).
-                    invoke("foo", "foo");
+                    invokeExact("foo", "foo");
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 String x = (String) hs.get(am, methodType(String.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 String x = (String) hs.get(am, methodType(String.class, String.class, String.class, Class.class)).
-                    invoke("foo", "foo", Void.class);
+                    invokeExact("foo", "foo", Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
             // Incorrect argument types
-            checkCCE(() -> { // value reference class
+            hs.checkWMTEOrCCE(() -> { // value reference class
                 String x = (String) hs.get(am, methodType(String.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect return type
-            checkCCE(() -> { // reference class
+            hs.checkWMTEOrCCE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, String.class)).
-                    invoke("foo");
+                    invokeExact("foo");
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, String.class)).
-                    invoke("foo");
+                    invokeExact("foo");
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 String x = (String) hs.get(am, methodType(String.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 String x = (String) hs.get(am, methodType(String.class, String.class, Class.class)).
-                    invoke("foo", Void.class);
+                    invokeExact("foo", Void.class);
             });
         }
 
@@ -1686,195 +1688,195 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                String x = (String) hs.get(am, methodType(String.class, Void.class, int.class)).
-                    invoke(null, 0);
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class)).
+                    invokeExact((String[]) null, 0);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 String x = (String) hs.get(am, methodType(String.class, Class.class, int.class)).
-                    invoke(Void.class, 0);
+                    invokeExact(Void.class, 0);
             });
             checkWMTE(() -> { // array primitive class
                 String x = (String) hs.get(am, methodType(String.class, int.class, int.class)).
-                    invoke(0, 0);
+                    invokeExact(0, 0);
             });
             checkWMTE(() -> { // index reference class
                 String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class)).
-                    invoke(array, Void.class);
+                    invokeExact(array, Void.class);
             });
             // Incorrect return type
-            checkCCE(() -> { // reference class
+            hs.checkWMTEOrCCE(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class, String[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 String x = (String) hs.get(am, methodType(String.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                hs.get(am, methodType(void.class, Void.class, int.class, String.class)).
-                    invoke(null, 0, "foo");
+                hs.get(am, methodType(void.class, String[].class, int.class, String.class)).
+                    invokeExact((String[]) null, 0, "foo");
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 hs.get(am, methodType(void.class, Class.class, int.class, String.class)).
-                    invoke(Void.class, 0, "foo");
+                    invokeExact(Void.class, 0, "foo");
             });
-            checkCCE(() -> { // value reference class
+            hs.checkWMTEOrCCE(() -> { // value reference class
                 hs.get(am, methodType(void.class, String[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class, String.class)).
-                    invoke(0, 0, "foo");
+                    invokeExact(0, 0, "foo");
             });
             checkWMTE(() -> { // index reference class
                 hs.get(am, methodType(void.class, String[].class, Class.class, String.class)).
-                    invoke(array, Void.class, "foo");
+                    invokeExact(array, Void.class, "foo");
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, String[].class, int.class, Class.class)).
-                    invoke(array, 0, "foo", Void.class);
+                    invokeExact(array, 0, "foo", Void.class);
             });
         }
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, String.class, String.class)).
-                    invoke(null, 0, "foo", "foo");
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class)).
+                    invokeExact((String[]) null, 0, "foo", "foo");
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, String.class, String.class)).
-                    invoke(Void.class, 0, "foo", "foo");
+                    invokeExact(Void.class, 0, "foo", "foo");
             });
-            checkCCE(() -> { // expected reference class
+            hs.checkWMTEOrCCE(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, Class.class, String.class)).
-                    invoke(array, 0, Void.class, "foo");
+                    invokeExact(array, 0, Void.class, "foo");
             });
-            checkCCE(() -> { // actual reference class
+            hs.checkWMTEOrCCE(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, Class.class)).
-                    invoke(array, 0, "foo", Void.class);
+                    invokeExact(array, 0, "foo", Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, String.class, String.class)).
-                    invoke(0, 0, "foo", "foo");
+                    invokeExact(0, 0, "foo", "foo");
             });
             checkWMTE(() -> { // index reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, Class.class, String.class, String.class)).
-                    invoke(array, Void.class, "foo", "foo");
+                    invokeExact(array, Void.class, "foo", "foo");
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class, Class.class)).
-                    invoke(array, 0, "foo", "foo", Void.class);
+                    invokeExact(array, 0, "foo", "foo", Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                String x = (String) hs.get(am, methodType(String.class, Void.class, int.class, String.class, String.class)).
-                    invoke(null, 0, "foo", "foo");
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, String.class)).
+                    invokeExact((String[]) null, 0, "foo", "foo");
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 String x = (String) hs.get(am, methodType(String.class, Class.class, int.class, String.class, String.class)).
-                    invoke(Void.class, 0, "foo", "foo");
+                    invokeExact(Void.class, 0, "foo", "foo");
             });
-            checkCCE(() -> { // expected reference class
+            hs.checkWMTEOrCCE(() -> { // expected reference class
                 String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class, String.class)).
-                    invoke(array, 0, Void.class, "foo");
+                    invokeExact(array, 0, Void.class, "foo");
             });
-            checkCCE(() -> { // actual reference class
+            hs.checkWMTEOrCCE(() -> { // actual reference class
                 String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, Class.class)).
-                    invoke(array, 0, "foo", Void.class);
+                    invokeExact(array, 0, "foo", Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 String x = (String) hs.get(am, methodType(String.class, int.class, int.class, String.class, String.class)).
-                    invoke(0, 0, "foo", "foo");
+                    invokeExact(0, 0, "foo", "foo");
             });
             checkWMTE(() -> { // index reference class
                 String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class, String.class, String.class)).
-                    invoke(array, Void.class, "foo", "foo");
+                    invokeExact(array, Void.class, "foo", "foo");
             });
             // Incorrect return type
-            checkCCE(() -> { // reference class
+            hs.checkWMTEOrCCE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, String[].class, int.class, String.class, String.class)).
-                    invoke(array, 0, "foo", "foo");
+                    invokeExact(array, 0, "foo", "foo");
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class)).
-                    invoke(array, 0, "foo", "foo");
+                    invokeExact(array, 0, "foo", "foo");
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 String x = (String) hs.get(am, methodType(String.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, String.class, Class.class)).
-                    invoke(array, 0, "foo", "foo", Void.class);
+                    invokeExact(array, 0, "foo", "foo", Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                String x = (String) hs.get(am, methodType(String.class, Void.class, int.class, String.class)).
-                    invoke(null, 0, "foo");
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class)).
+                    invokeExact((String[]) null, 0, "foo");
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 String x = (String) hs.get(am, methodType(String.class, Class.class, int.class, String.class)).
-                    invoke(Void.class, 0, "foo");
+                    invokeExact(Void.class, 0, "foo");
             });
-            checkCCE(() -> { // value reference class
+            hs.checkWMTEOrCCE(() -> { // value reference class
                 String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 String x = (String) hs.get(am, methodType(String.class, int.class, int.class, String.class)).
-                    invoke(0, 0, "foo");
+                    invokeExact(0, 0, "foo");
             });
             checkWMTE(() -> { // index reference class
                 String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class, String.class)).
-                    invoke(array, Void.class, "foo");
+                    invokeExact(array, Void.class, "foo");
             });
             // Incorrect return type
-            checkCCE(() -> { // reference class
+            hs.checkWMTEOrCCE(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, String[].class, int.class, String.class)).
-                    invoke(array, 0, "foo");
+                    invokeExact(array, 0, "foo");
             });
             checkWMTE(() -> { // primitive class
                 boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class)).
-                    invoke(array, 0, "foo");
+                    invokeExact(array, 0, "foo");
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 String x = (String) hs.get(am, methodType(String.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, Class.class)).
-                    invoke(array, 0, "foo", Void.class);
+                    invokeExact(array, 0, "foo", Void.class);
             });
         }
 
diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template
index 391dc1a5197..cb33f8ff070 100644
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccess$Type$
  * @run testng/othervm -Diters=20000                         VarHandleTestAccess$Type$
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccess$Type$
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestAccess$Type$
  */
 
 import org.testng.annotations.BeforeClass;
@@ -309,6 +310,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest {
         checkUOE(() -> {
             boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$);
         });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSet(recv, $value1$);
+        });
 #end[CAS]
 
 #if[!AtomicAdd]
@@ -399,6 +404,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest {
         checkUOE(() -> {
             boolean r = vh.weakCompareAndSetRelease($value1$, $value2$);
         });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSet($value1$);
+        });
 #end[CAS]
 
 #if[!AtomicAdd]
@@ -504,29 +513,41 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest {
         }
 
         {
-            boolean r = vh.weakCompareAndSet(recv, $value1$, $value2$);
-            assertEquals(r, true, "weakCompareAndSet $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, $value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSet $type$");
             $type$ x = ($type$) vh.get(recv);
             assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
         }
 
         {
-            boolean r = vh.weakCompareAndSetAcquire(recv, $value2$, $value1$);
-            assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, $value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire $type$");
             $type$ x = ($type$) vh.get(recv);
             assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
         }
 
         {
-            boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$);
-            assertEquals(r, true, "weakCompareAndSetRelease $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, $value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease $type$");
             $type$ x = ($type$) vh.get(recv);
             assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
         }
 
         {
-            boolean r = vh.weakCompareAndSetVolatile(recv, $value2$, $value1$);
-            assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetVolatile(recv, $value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile $type$");
             $type$ x = ($type$) vh.get(recv);
             assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
         }
@@ -586,6 +607,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest {
         checkUOE(() -> {
             boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$);
         });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSet(recv, $value1$);
+        });
 #end[CAS]
 
 #if[!AtomicAdd]
@@ -691,36 +716,48 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSet($value1$, $value2$);
-            assertEquals(r, true, "weakCompareAndSet $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet($value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSet $type$");
             $type$ x = ($type$) vh.get();
             assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetAcquire($value2$, $value1$);
-            assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire($value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire $type$");
             $type$ x = ($type$) vh.get();
             assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetRelease($value1$, $value2$);
-            assertEquals(r, true, "weakCompareAndSetRelease $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease($value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease $type$");
             $type$ x = ($type$) vh.get();
             assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetVolatile($value2$, $value1$);
-            assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease($value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile $type$");
             $type$ x = ($type$) vh.get();
-            assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+            assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$");
         }
 
         // Compare set and get
         {
-            $type$ o = ($type$) vh.getAndSet( $value2$);
+            $type$ o = ($type$) vh.getAndSet($value2$);
             assertEquals(o, $value1$, "getAndSet $type$");
             $type$ x = ($type$) vh.get();
             assertEquals(x, $value2$, "getAndSet $type$ value");
@@ -773,6 +810,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest {
         checkUOE(() -> {
             boolean r = vh.weakCompareAndSetRelease($value1$, $value2$);
         });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSet($value1$);
+        });
 #end[CAS]
 
 #if[!AtomicAdd]
@@ -881,31 +922,43 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest {
             }
 
             {
-                boolean r = vh.weakCompareAndSet(array, i, $value1$, $value2$);
-                assertEquals(r, true, "weakCompareAndSet $type$");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, $value1$, $value2$);
+                }
+                assertEquals(success, true, "weakCompareAndSet $type$");
                 $type$ x = ($type$) vh.get(array, i);
                 assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
             }
 
             {
-                boolean r = vh.weakCompareAndSetAcquire(array, i, $value2$, $value1$);
-                assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, $value2$, $value1$);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire $type$");
                 $type$ x = ($type$) vh.get(array, i);
                 assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
             }
 
             {
-                boolean r = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$);
-                assertEquals(r, true, "weakCompareAndSetRelease $type$");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease $type$");
                 $type$ x = ($type$) vh.get(array, i);
                 assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
             }
 
             {
-                boolean r = vh.weakCompareAndSetVolatile(array, i, $value2$, $value1$);
-                assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetVolatile(array, i, $value2$, $value1$);
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile $type$");
                 $type$ x = ($type$) vh.get(array, i);
-                assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+                assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$");
             }
 
             // Compare set and get
@@ -967,6 +1020,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest {
         checkUOE(() -> {
             boolean r = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$);
         });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSet(array, i, $value1$);
+        });
 #end[CAS]
 
 #if[!AtomicAdd]
diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template
index e433789f8cd..1cb19b7893e 100644
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template
@@ -27,6 +27,7 @@
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAs$Type$
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAs$Type$
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAs$Type$
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestByteArrayAs$Type$
  */
 
 import org.testng.annotations.DataProvider;
@@ -311,10 +312,12 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
             checkROBE(() -> {
                 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
             });
+
+#else[CAS]
             checkUOE(() -> {
                 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
             });
-#else[CAS]
+
             checkUOE(() -> {
                 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
             });
@@ -884,22 +887,31 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSet $type$");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet $type$");
                     $type$ x = ($type$) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
-                    assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire $type$");
                     $type$ x = ($type$) vh.get(array, i);
                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSetRelease $type$");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease $type$");
                     $type$ x = ($type$) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
                 }
@@ -1037,22 +1049,31 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSet $type$");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet $type$");
                     $type$ x = ($type$) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
-                    assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire $type$");
                     $type$ x = ($type$) vh.get(array, i);
                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$");
                 }
 
                 {
-                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
-                    assertEquals(r, true, "weakCompareAndSetRelease $type$");
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease $type$");
                     $type$ x = ($type$) vh.get(array, i);
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
                 }
diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template
index f56d9a641a7..f943bf2611b 100644
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template
@@ -24,6 +24,7 @@
 /*
  * @test
  * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccess$Type$
+ * @run testng/othervm -Diters=20000 -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodHandleAccess$Type$
  */
 
 import org.testng.annotations.BeforeClass;
@@ -209,31 +210,43 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, $value1$, $value2$);
-            assertEquals(r, true, "weakCompareAndSet $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, $value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSet $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, $value2$, $value1$);
-            assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, $value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, $value1$, $value2$);
-            assertEquals(r, true, "weakCompareAndSetRelease $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, $value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
             assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, $value2$, $value1$);
-            assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, $value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
-            assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+            assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$");
         }
 
         // Compare set and get
@@ -380,36 +393,48 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest {
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact($value1$, $value2$);
-            assertEquals(r, true, "weakCompareAndSet $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact($value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSet $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact($value2$, $value1$);
-            assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact($value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value2$);
-            assertEquals(r, true, "weakCompareAndSetRelease $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact($value2$, $value1$);
-            assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact($value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetVolatile $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
-            assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+            assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$");
         }
 
         // Compare set and get
         {
-            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact($value2$);
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact( $value2$);
             assertEquals(o, $value1$, "getAndSet $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, $value2$, "getAndSet $type$ value");
@@ -554,31 +579,43 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest {
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, $value1$, $value2$);
-                assertEquals(r, true, "weakCompareAndSet $type$");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, $value1$, $value2$);
+                }
+                assertEquals(success, true, "weakCompareAndSet $type$");
                 $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value2$, $value1$);
-                assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value2$, $value1$);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire $type$");
                 $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, $value1$, $value2$);
-                assertEquals(r, true, "weakCompareAndSetRelease $type$");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, $value1$, $value2$);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease $type$");
                 $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
                 assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
             }
 
             {
-                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, $value2$, $value1$);
-                assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, $value2$, $value1$);
+                }
+                assertEquals(success, true, "weakCompareAndSetVolatile $type$");
                 $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
-                assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+                assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$");
             }
 
             // Compare set and get
diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template
index fe504902f10..5bec8b46a10 100644
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8156486
  * @run testng/othervm VarHandleTestMethodType$Type$
  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodType$Type$
  */
@@ -81,27 +82,28 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest {
     public Object[][] accessTestCaseProvider() throws Exception {
         List<AccessTestCase<?>> cases = new ArrayList<>();
 
-        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Instance field",
                                               vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+        cases.add(new VarHandleAccessTestCase("Static field",
                                               vhStaticField, VarHandleTestMethodType$Type$::testStaticFieldWrongMethodType,
                                               false));
 
-        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+        cases.add(new VarHandleAccessTestCase("Array",
                                               vhArray, VarHandleTestMethodType$Type$::testArrayWrongMethodType,
                                               false));
+
         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
-            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Instance field",
                                                      vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Static field",
                                                      vhStaticField, f, VarHandleTestMethodType$Type$::testStaticFieldWrongMethodType,
                                                      false));
 
-            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+            cases.add(new MethodHandleAccessTestCase("Array",
                                                      vhArray, f, VarHandleTestMethodType$Type$::testArrayWrongMethodType,
                                                      false));
         }
@@ -648,63 +650,63 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class)).
-                    invoke(null);
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class)).
-                    invoke(0);
+                    invokeExact(0);
             });
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
-                Void x = (Void) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class)).
-                    invoke(recv);
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class)).
+                    invokeExact(recv);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class)).
-                    invoke(recv);
+                    invokeExact(recv);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                hs.get(am, methodType(void.class, Void.class, $type$.class)).
-                    invoke(null, $value1$);
+                hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 hs.get(am, methodType(void.class, Class.class, $type$.class)).
-                    invoke(Void.class, $value1$);
+                    invokeExact(Void.class, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
                 hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, $type$.class)).
-                    invoke(0, $value1$);
+                    invokeExact(0, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)).
-                    invoke(recv, $value1$, Void.class);
+                    invokeExact(recv, $value1$, Void.class);
             });
         }
 
@@ -712,111 +714,111 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, $type$.class, $type$.class)).
-                    invoke(null, $value1$, $value1$);
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$, $value1$);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, $type$.class, $type$.class)).
-                    invoke(Void.class, $value1$, $value1$);
+                    invokeExact(Void.class, $value1$, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, Class.class, $type$.class)).
-                    invoke(recv, Void.class, $value1$);
+                    invokeExact(recv, Void.class, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)).
-                    invoke(recv, $value1$, Void.class);
+                    invokeExact(recv, $value1$, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , $type$.class, $type$.class)).
-                    invoke(0, $value1$, $value1$);
+                    invokeExact(0, $value1$, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class, Class.class)).
-                    invoke(recv, $value1$, $value1$, Void.class);
+                    invokeExact(recv, $value1$, $value1$, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
             checkNPE(() -> { // null receiver
-                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, $type$.class, $type$.class)).
-                    invoke(null, $value1$, $value1$);
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$, $value1$);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class, $type$.class)).
-                    invoke(Void.class, $value1$, $value1$);
+                    invokeExact(Void.class, $value1$, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class, $type$.class)).
-                    invoke(recv, Void.class, $value1$);
+                    invokeExact(recv, Void.class, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)).
-                    invoke(recv, $value1$, Void.class);
+                    invokeExact(recv, $value1$, Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class , $type$.class, $type$.class)).
-                    invoke(0, $value1$, $value1$);
+                    invokeExact(0, $value1$, $value1$);
             });
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class , $type$.class, $type$.class)).
-                    invoke(recv, $value1$, $value1$);
+                    invokeExact(recv, $value1$, $value1$);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class , $type$.class, $type$.class)).
-                    invoke(recv, $value1$, $value1$);
+                    invokeExact(recv, $value1$, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class, Class.class)).
-                    invoke(recv, $value1$, $value1$, Void.class);
+                    invokeExact(recv, $value1$, $value1$, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
             checkNPE(() -> { // null receiver
-                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, $type$.class)).
-                    invoke(null, $value1$);
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)).
-                    invoke(Void.class, $value1$);
+                    invokeExact(Void.class, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)).
-                    invoke(0, $value1$);
+                    invokeExact(0, $value1$);
             });
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class, $type$.class)).
-                    invoke(recv, $value1$);
+                    invokeExact(recv, $value1$);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
-                    invoke(recv, $value1$);
+                    invokeExact(recv, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
-                    invoke(recv, $value1$, Void.class);
+                    invokeExact(recv, $value1$, Void.class);
             });
         }
 #end[CAS]
@@ -824,38 +826,38 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest {
 #if[AtomicAdd]
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
             checkNPE(() -> { // null receiver
-                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, $type$.class)).
-                    invoke(null, $value1$);
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)).
-                    invoke(Void.class, $value1$);
+                    invokeExact(Void.class, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)).
-                    invoke(recv, Void.class);
+                    invokeExact(recv, Void.class);
             });
             checkWMTE(() -> { // reciever primitive class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)).
-                    invoke(0, $value1$);
+                    invokeExact(0, $value1$);
             });
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class, $type$.class)).
-                    invoke(recv, $value1$);
+                    invokeExact(recv, $value1$);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
-                    invoke(recv, $value1$);
+                    invokeExact(recv, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
-                    invoke(recv, $value1$, Void.class);
+                    invokeExact(recv, $value1$, Void.class);
             });
         }
 #end[AtomicAdd]
@@ -1200,111 +1202,111 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest {
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class)).
-                    invoke();
+                    invokeExact();
             });
             // Incorrect arity
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType(Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
-            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
                 hs.get(am, methodType(void.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, $type$.class, Class.class)).
-                    invoke($value1$, Void.class);
+                    invokeExact($value1$, Void.class);
             });
         }
 #if[CAS]
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
-            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, $type$.class)).
-                    invoke(Void.class, $value1$);
+                    invokeExact(Void.class, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$.class, Class.class)).
-                    invoke($value1$, Void.class);
+                    invokeExact($value1$, Void.class);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$.class, $type$.class, Class.class)).
-                    invoke($value1$, $value1$, Void.class);
+                    invokeExact($value1$, $value1$, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
             // Incorrect argument types
-            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)).
-                    invoke(Void.class, $value1$);
+                    invokeExact(Void.class, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)).
-                    invoke($value1$, Void.class);
+                    invokeExact($value1$, Void.class);
             });
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, $type$.class, $type$.class)).
-                    invoke($value1$, $value1$);
+                    invokeExact($value1$, $value1$);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class, $type$.class)).
-                    invoke($value1$, $value1$);
+                    invokeExact($value1$, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, $type$.class, Class.class)).
-                    invoke($value1$, $value1$, Void.class);
+                    invokeExact($value1$, $value1$, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
             // Incorrect argument types
-            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, $type$.class)).
-                    invoke($value1$);
+                    invokeExact($value1$);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class)).
-                    invoke($value1$);
+                    invokeExact($value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)).
-                    invoke($value1$, Void.class);
+                    invokeExact($value1$, Void.class);
             });
         }
 #end[CAS]
@@ -1314,25 +1316,25 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest {
             // Incorrect argument types
             check{#if[String]?CCE:WMTE}(() -> { // value reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)).
-                    invoke(Void.class);
+                    invokeExact(Void.class);
             });
             // Incorrect return type
             check{#if[String]?CCE:WMTE}(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, $type$.class)).
-                    invoke($value1$);
+                    invokeExact($value1$);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class)).
-                    invoke($value1$);
+                    invokeExact($value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)).
-                    invoke($value1$, Void.class);
+                    invokeExact($value1$, Void.class);
             });
         }
 #end[AtomicAdd]
@@ -1929,196 +1931,196 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class)).
-                    invoke(null, 0);
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class)).
+                    invokeExact(($type$[]) null, 0);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class)).
-                    invoke(Void.class, 0);
+                    invokeExact(Void.class, 0);
             });
             checkWMTE(() -> { // array primitive class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class)).
-                    invoke(0, 0);
+                    invokeExact(0, 0);
             });
             checkWMTE(() -> { // index reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class)).
-                    invoke(array, Void.class);
+                    invokeExact(array, Void.class);
             });
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
                 Void x = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class)).
-                    invoke(array, 0);
+                    invokeExact(array, 0);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                hs.get(am, methodType(void.class, Void.class, int.class, $type$.class)).
-                    invoke(null, 0, $value1$);
+                hs.get(am, methodType(void.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 hs.get(am, methodType(void.class, Class.class, int.class, $type$.class)).
-                    invoke(Void.class, 0, $value1$);
+                    invokeExact(Void.class, 0, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
                 hs.get(am, methodType(void.class, $type$[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 hs.get(am, methodType(void.class, int.class, int.class, $type$.class)).
-                    invoke(0, 0, $value1$);
+                    invokeExact(0, 0, $value1$);
             });
             checkWMTE(() -> { // index reference class
                 hs.get(am, methodType(void.class, $type$[].class, Class.class, $type$.class)).
-                    invoke(array, Void.class, $value1$);
+                    invokeExact(array, Void.class, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 hs.get(am, methodType(void.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 hs.get(am, methodType(void.class, $type$[].class, int.class, Class.class)).
-                    invoke(array, 0, $value1$, Void.class);
+                    invokeExact(array, 0, $value1$, Void.class);
             });
         }
 #if[CAS]
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, $type$.class, $type$.class)).
-                    invoke(null, 0, $value1$, $value1$);
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$, $value1$);
             });
-            checkCCE(() -> { // receiver reference class
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, $type$.class, $type$.class)).
-                    invoke(Void.class, 0, $value1$, $value1$);
+                    invokeExact(Void.class, 0, $value1$, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, Class.class, $type$.class)).
-                    invoke(array, 0, Void.class, $value1$);
+                    invokeExact(array, 0, Void.class, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, Class.class)).
-                    invoke(array, 0, $value1$, Void.class);
+                    invokeExact(array, 0, $value1$, Void.class);
             });
             checkWMTE(() -> { // receiver primitive class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, $type$.class, $type$.class)).
-                    invoke(0, 0, $value1$, $value1$);
+                    invokeExact(0, 0, $value1$, $value1$);
             });
             checkWMTE(() -> { // index reference class
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, Class.class, $type$.class, $type$.class)).
-                    invoke(array, Void.class, $value1$, $value1$);
+                    invokeExact(array, Void.class, $value1$, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 boolean r = (boolean) hs.get(am, methodType(boolean.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, $type$.class, Class.class)).
-                    invoke(array, 0, $value1$, $value1$, Void.class);
+                    invokeExact(array, 0, $value1$, $value1$, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
             // Incorrect argument types
             checkNPE(() -> { // null receiver
-                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class, $type$.class, $type$.class)).
-                    invoke(null, 0, $value1$, $value1$);
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$, $value1$);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class, $type$.class)).
-                    invoke(Void.class, 0, $value1$, $value1$);
+                    invokeExact(Void.class, 0, $value1$, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class, $type$.class)).
-                    invoke(array, 0, Void.class, $value1$);
+                    invokeExact(array, 0, Void.class, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)).
-                    invoke(array, 0, $value1$, Void.class);
+                    invokeExact(array, 0, $value1$, Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class, $type$.class)).
-                    invoke(0, 0, $value1$, $value1$);
+                    invokeExact(0, 0, $value1$, $value1$);
             });
             checkWMTE(() -> { // index reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class, $type$.class)).
-                    invoke(array, Void.class, $value1$, $value1$);
+                    invokeExact(array, Void.class, $value1$, $value1$);
             });
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class, $type$.class)).
-                    invoke(array, 0, $value1$, $value1$);
+                    invokeExact(array, 0, $value1$, $value1$);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class, $type$.class)).
-                    invoke(array, 0, $value1$, $value1$);
+                    invokeExact(array, 0, $value1$, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, $type$.class, Class.class)).
-                    invoke(array, 0, $value1$, $value1$, Void.class);
+                    invokeExact(array, 0, $value1$, $value1$, Void.class);
             });
         }
 
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class, $type$.class)).
-                    invoke(null, 0, $value1$);
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class)).
-                    invoke(Void.class, 0, $value1$);
+                    invokeExact(Void.class, 0, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class)).
-                    invoke(0, 0, $value1$);
+                    invokeExact(0, 0, $value1$);
             });
             checkWMTE(() -> { // index reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class)).
-                    invoke(array, Void.class, $value1$);
+                    invokeExact(array, Void.class, $value1$);
             });
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class)).
-                    invoke(array, 0, $value1$);
+                    invokeExact(array, 0, $value1$);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class)).
-                    invoke(array, 0, $value1$);
+                    invokeExact(array, 0, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)).
-                    invoke(array, 0, $value1$, Void.class);
+                    invokeExact(array, 0, $value1$, Void.class);
             });
         }
 #end[CAS]
@@ -2127,42 +2129,42 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest {
         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
             // Incorrect argument types
             checkNPE(() -> { // null array
-                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class, $type$.class)).
-                    invoke(null, 0, $value1$);
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$);
             });
-            checkCCE(() -> { // array reference class
+            hs.checkWMTEOrCCE(() -> { // array reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class)).
-                    invoke(Void.class, 0, $value1$);
+                    invokeExact(Void.class, 0, $value1$);
             });
-            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)).
-                    invoke(array, 0, Void.class);
+                    invokeExact(array, 0, Void.class);
             });
             checkWMTE(() -> { // array primitive class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class)).
-                    invoke(0, 0, $value1$);
+                    invokeExact(0, 0, $value1$);
             });
             checkWMTE(() -> { // index reference class
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class)).
-                    invoke(array, Void.class, $value1$);
+                    invokeExact(array, Void.class, $value1$);
             });
             // Incorrect return type
-            check{#if[String]?CCE:WMTE}(() -> { // reference class
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
                 Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class)).
-                    invoke(array, 0, $value1$);
+                    invokeExact(array, 0, $value1$);
             });
             checkWMTE(() -> { // primitive class
                 $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class)).
-                    invoke(array, 0, $value1$);
+                    invokeExact(array, 0, $value1$);
             });
             // Incorrect arity
             checkWMTE(() -> { // 0
                 $type$ x = ($type$) hs.get(am, methodType($type$.class)).
-                    invoke();
+                    invokeExact();
             });
             checkWMTE(() -> { // >
                 $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)).
-                    invoke(array, 0, $value1$, Void.class);
+                    invokeExact(array, 0, $value1$, Void.class);
             });
         }
 #end[AtomicAdd]
diff --git a/jdk/test/java/lang/invoke/VarHandles/generate-vh-tests.sh b/jdk/test/java/lang/invoke/VarHandles/generate-vh-tests.sh
index 7d6afc7b206..436d2d371d9 100644
--- a/jdk/test/java/lang/invoke/VarHandles/generate-vh-tests.sh
+++ b/jdk/test/java/lang/invoke/VarHandles/generate-vh-tests.sh
@@ -113,36 +113,40 @@ do
       ;;
   esac
 
+  # The value of `value3` is chosen such that when added to `value1` or `value2`
+  # it will result in carrying of bits over to the next byte, thereby detecting
+  # possible errors in endianness conversion e.g. if say for atomic addition the
+  # augend is incorrectly processed
   case $type in
     short)
       value1=(short)0x0102
       value2=(short)0x1112
-      value3=(short)0x2122
+      value3=(short)0xFFFE
       ;;
     char)
       value1=(char)0x0102
       value2=(char)0x1112
-      value3=(char)0x2122
+      value3=(char)0xFFFE
       ;;
     int)
       value1=0x01020304
       value2=0x11121314
-      value3=0x21222324
+      value3=0xFFFEFDFC
       ;;
     long)
       value1=0x0102030405060708L
       value2=0x1112131415161718L
-      value3=0x2122232425262728L
+      value3=0xFFFEFDFCFBFAF9F8L
       ;;
     float)
       value1=0x01020304
       value2=0x11121314
-      value3=0x21222324
+      value3=0xFFFEFDFC
       ;;
     double)
       value1=0x0102030405060708L
       value2=0x1112131415161718L
-      value3=0x2122232425262728L
+      value3=0xFFFEFDFCFBFAF9F8L
       ;;
   esac
 
diff --git a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java
index 195cb3a2fd8..2d52eeb4299 100644
--- a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java
+++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java
@@ -36,9 +36,13 @@
  * @modules jdk.management
  * @build jdk.testlibrary.* ResetPeakMemoryUsage MemoryUtil RunUtil
  * @run main ResetPeakMemoryUsage
+ * @requires vm.opt.ExplicitGCInvokesConcurrent != "true"
+ * @requires vm.opt.ExplicitGCInvokesConcurrentAndUnloadsClasses != "true"
+ * @requires vm.opt.DisableExplicitGC != "true"
  */
 
 import java.lang.management.*;
+import java.lang.ref.WeakReference;
 import java.util.*;
 
 public class ResetPeakMemoryUsage {
@@ -100,6 +104,7 @@ public class ResetPeakMemoryUsage {
         printMemoryUsage(usage0, peak0);
 
         obj = new Object[largeArraySize];
+        WeakReference<Object> weakRef = new WeakReference<>(obj);
 
         MemoryUsage usage1 = mpool.getUsage();
         MemoryUsage peak1 = mpool.getPeakUsage();
@@ -124,7 +129,11 @@ public class ResetPeakMemoryUsage {
         // The object is now garbage and do a GC
         // memory usage should drop
         obj = null;
-        mbean.gc();
+
+        //This will cause sure shot GC unlike Runtime.gc() invoked by mbean.gc()
+        while(weakRef.get() != null) {
+            mbean.gc();
+        }
 
         MemoryUsage usage2 = mpool.getUsage();
         MemoryUsage peak2 = mpool.getPeakUsage();
diff --git a/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java b/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java
index ac0bc89f98c..63f5c5fbc31 100644
--- a/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java
+++ b/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java
@@ -270,8 +270,7 @@ public class PlatformLoggingMXBeanTest
         // Calling getMBeanInfo will throw exception if not found.
         platformMBS.getMBeanInfo(objName);
 
-        if (!platformMBS.isInstanceOf(objName, "java.lang.management.PlatformLoggingMXBean") ||
-            !platformMBS.isInstanceOf(objName, "java.util.logging.LoggingMXBean")) {
+        if (!platformMBS.isInstanceOf(objName, "java.lang.management.PlatformLoggingMXBean")) {
             throw new RuntimeException(objName + " is of unexpected type");
         }
 
diff --git a/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java b/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java
index b37813fd290..6a0cd78a241 100644
--- a/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java
+++ b/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java
@@ -24,6 +24,7 @@
 /**
  * @test
  * @library /lib/testlibrary
+ * @modules jdk.compiler
  * @build LayerAndLoadersTest CompilerUtils ModuleUtils
  * @run testng LayerAndLoadersTest
  * @summary Tests for java.lang.reflect.Layer@createWithXXX methods
diff --git a/jdk/test/java/net/httpclient/http2/TLSConnection.java b/jdk/test/java/net/httpclient/http2/TLSConnection.java
new file mode 100644
index 00000000000..f2721eb268e
--- /dev/null
+++ b/jdk/test/java/net/httpclient/http2/TLSConnection.java
@@ -0,0 +1,247 @@
+/*
+ * 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.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.Http2Handler;
+import java.net.http.Http2TestExchange;
+import java.net.http.Http2TestServer;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSession;
+
+/*
+ * @test
+ * @bug 8150769 8157107
+ * @summary Checks that SSL parameters can be set for HTTP/2 connection
+ * @modules java.httpclient
+ * @compile/module=java.httpclient java/net/http/Http2Handler.java
+ * @compile/module=java.httpclient java/net/http/Http2TestExchange.java
+ * @compile/module=java.httpclient java/net/http/Http2TestServer.java
+ * @run main/othervm TLSConnection
+ */
+public class TLSConnection {
+
+    private static final String KEYSTORE = System.getProperty("test.src")
+            + File.separator + "keystore.p12";
+   private static final String PASSWORD = "password";
+
+    public static void main(String[] args) throws Exception {
+
+        // enable all logging
+        System.setProperty("java.net.http.HttpClient.log", "all,frames:all");
+
+        // initialize JSSE
+        System.setProperty("javax.net.ssl.keyStore", KEYSTORE);
+        System.setProperty("javax.net.ssl.keyStorePassword", PASSWORD);
+        System.setProperty("javax.net.ssl.trustStore", KEYSTORE);
+        System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD);
+
+        Handler handler = new Handler();
+
+        try (Http2TestServer server = new Http2TestServer(true, 0, handler)) {
+            server.start();
+
+            int port = server.getAddress().getPort();
+            String uriString = "https://127.0.0.1:" + Integer.toString(port);
+
+            // run test cases
+            boolean success = true;
+
+            SSLParameters parameters = null;
+            success &= expectFailure(
+                    "Test #1: SSL parameters is null, expect NPE",
+                    () -> connect(uriString, parameters),
+                    NullPointerException.class);
+
+            success &= expectSuccess(
+                    "Test #2: default SSL parameters, "
+                            + "expect successful connection",
+                    () -> connect(uriString, new SSLParameters()));
+            success &= checkProtocol(handler.getSSLSession(), "TLSv1.2");
+
+            // set SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA cipher suite
+            // which has less priority in default cipher suite list
+            success &= expectSuccess(
+                    "Test #3: SSL parameters with "
+                            + "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA cipher suite, "
+                            + "expect successful connection",
+                    () -> connect(uriString, new SSLParameters(
+                            new String[] { "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA" })));
+            success &= checkProtocol(handler.getSSLSession(), "TLSv1.2");
+            success &= checkCipherSuite(handler.getSSLSession(),
+                    "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
+
+            // set TLS_RSA_WITH_AES_128_CBC_SHA cipher suite
+            // which has less priority in default cipher suite list
+            // also set TLSv11 protocol
+            success &= expectSuccess(
+                    "Test #4: SSL parameters with "
+                            + "TLS_RSA_WITH_AES_128_CBC_SHA cipher suite,"
+                            + " expect successful connection",
+                    () -> connect(uriString, new SSLParameters(
+                            new String[] { "TLS_RSA_WITH_AES_128_CBC_SHA" },
+                            new String[] { "TLSv1.1" })));
+            success &= checkProtocol(handler.getSSLSession(), "TLSv1.1");
+            success &= checkCipherSuite(handler.getSSLSession(),
+                    "TLS_RSA_WITH_AES_128_CBC_SHA");
+
+            if (success) {
+                System.out.println("Test passed");
+            } else {
+                throw new RuntimeException("At least one test case failed");
+            }
+        }
+    }
+
+    private static interface Test {
+
+        public void run() throws Exception;
+    }
+
+    private static class Handler implements Http2Handler {
+
+        private static final byte[] BODY = "Test response".getBytes();
+
+        private volatile SSLSession sslSession;
+
+        @Override
+        public void handle(Http2TestExchange t) throws IOException {
+            System.out.println("Handler: received request to "
+                    + t.getRequestURI());
+
+            try (InputStream is = t.getRequestBody()) {
+                byte[] body = is.readAllBytes();
+                System.out.println("Handler: read " + body.length
+                        + " bytes of body: ");
+                System.out.println(new String(body));
+            }
+
+            try (OutputStream os = t.getResponseBody()) {
+                t.sendResponseHeaders(200, BODY.length);
+                os.write(BODY);
+            }
+
+            sslSession = t.getSSLSession();
+        }
+
+        SSLSession getSSLSession() {
+            return sslSession;
+        }
+    }
+
+    private static void connect(String uriString, SSLParameters sslParameters)
+            throws URISyntaxException, IOException, InterruptedException {
+
+        String body = HttpClient.create()
+                .sslParameters(sslParameters)
+                .version(HttpClient.Version.HTTP_2)
+                .build()
+                .request(new URI(uriString))
+                .body(HttpRequest.fromString("body"))
+                .GET()
+                .response()
+                .body(HttpResponse.asString());
+
+        System.out.println("Response: " + body);
+    }
+
+    private static boolean checkProtocol(SSLSession session, String protocol) {
+        if (session == null) {
+            System.out.println("Check protocol: no session provided");
+            return false;
+        }
+
+        System.out.println("Check protocol: negotiated protocol: "
+                + session.getProtocol());
+        System.out.println("Check protocol: expected protocol: "
+                + protocol);
+        if (!protocol.equals(session.getProtocol())) {
+            System.out.println("Check protocol: unexpected negotiated protocol");
+            return false;
+        }
+
+        return true;
+    }
+
+    private static boolean checkCipherSuite(SSLSession session, String ciphersuite) {
+        if (session == null) {
+            System.out.println("Check protocol: no session provided");
+            return false;
+        }
+
+        System.out.println("Check protocol: negotiated ciphersuite: "
+                + session.getCipherSuite());
+        System.out.println("Check protocol: expected ciphersuite: "
+                + ciphersuite);
+        if (!ciphersuite.equals(session.getCipherSuite())) {
+            System.out.println("Check protocol: unexpected negotiated ciphersuite");
+            return false;
+        }
+
+        return true;
+    }
+
+    private static boolean expectSuccess(String message, Test test) {
+        System.out.println(message);
+        try {
+            test.run();
+            System.out.println("Passed");
+            return true;
+        } catch (Exception e) {
+            System.out.println("Failed: unexpected exception:");
+            e.printStackTrace(System.out);
+            return false;
+        }
+    }
+
+    private static boolean expectFailure(String message, Test test,
+            Class<? extends Throwable> expectedException) {
+
+        System.out.println(message);
+        try {
+            test.run();
+            System.out.println("Failed: unexpected successful connection");
+            return false;
+        } catch (Exception e) {
+            System.out.println("Got an exception:");
+            e.printStackTrace(System.out);
+            if (expectedException != null
+                    && !expectedException.isAssignableFrom(e.getClass())) {
+                System.out.printf("Failed: expected %s, but got %s%n",
+                        expectedException.getName(),
+                        e.getClass().getName());
+                return false;
+            }
+            System.out.println("Passed: expected exception");
+            return true;
+        }
+    }
+
+}
diff --git a/jdk/test/java/net/httpclient/http2/Timeout.java b/jdk/test/java/net/httpclient/http2/Timeout.java
new file mode 100644
index 00000000000..5418d127a97
--- /dev/null
+++ b/jdk/test/java/net/httpclient/http2/Timeout.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpTimeoutException;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+
+/*
+ * @test
+ * @bug 8156710
+ * @summary Check if HttpTimeoutException is thrown if a server doesn't reply
+ * @run main/othervm Timeout
+ */
+public class Timeout {
+
+    private static final int RANDOM_PORT = 0;
+    private static final int TIMEOUT = 3 * 1000; // in millis
+    private static final String KEYSTORE = System.getProperty("test.src")
+            + File.separator + "keystore.p12";
+    private static final String PASSWORD = "password";
+
+    // indicates if server is ready to accept connections
+    private static volatile boolean ready = false;
+
+    public static void main(String[] args) throws Exception {
+        System.setProperty("javax.net.ssl.keyStore", KEYSTORE);
+        System.setProperty("javax.net.ssl.keyStorePassword", PASSWORD);
+        System.setProperty("javax.net.ssl.trustStore", KEYSTORE);
+        System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD);
+
+        SSLServerSocketFactory factory =
+                (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+
+        try (SSLServerSocket ssocket =
+                (SSLServerSocket) factory.createServerSocket(RANDOM_PORT)) {
+
+            // start server
+            Thread server = new Thread(() -> {
+                while (true) {
+                    System.out.println("server: ready");
+                    ready = true;
+                    try (SSLSocket socket = (SSLSocket) ssocket.accept()) {
+
+                        // just read forever
+                        System.out.println("server: accepted");
+                        while (true) {
+                            socket.getInputStream().read();
+                        }
+                    } catch (IOException e) {
+                        // ignore exceptions on server side
+                        System.out.println("server: exception: " + e);
+                    }
+                }
+            });
+            server.setDaemon(true);
+            server.start();
+
+            // wait for server is ready
+            do {
+                Thread.sleep(1000);
+            } while (!ready);
+
+            String uri = "https://localhost:" + ssocket.getLocalPort();
+            connect(uri);
+        }
+    }
+
+    private static void connect(String server) throws Exception {
+        try {
+            HttpClient.create()
+                    .version(HttpClient.Version.HTTP_2)
+                    .build()
+                    .request(new URI(server))
+                    .timeout(TimeUnit.MILLISECONDS, TIMEOUT)
+                    .body(HttpRequest.fromString("body"))
+                    .GET()
+                    .response()
+                    .body(HttpResponse.asString());
+
+            throw new RuntimeException("unexpected successful connection");
+        } catch (HttpTimeoutException e) {
+            System.out.println("expected exception: " + e);
+        }
+    }
+
+}
diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java
index 667a1d6ec55..3baefe142bb 100644
--- a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java
@@ -42,7 +42,7 @@ import javax.net.ssl.SSLServerSocketFactory;
  * Http2Handler on additional threads. All threads
  * obtained from the supplied ExecutorService.
  */
-public class Http2TestServer {
+public class Http2TestServer implements AutoCloseable {
     final ServerSocket server;
     boolean secure;
     SettingsFrame serverSettings, clientSettings;
@@ -156,4 +156,9 @@ public class Http2TestServer {
         });
     }
 
+    @Override
+    public void close() throws Exception {
+        stop();
+    }
+
 }
diff --git a/jdk/test/java/net/httpclient/http2/keystore.p12 b/jdk/test/java/net/httpclient/http2/keystore.p12
new file mode 100644
index 00000000000..a635533d086
Binary files /dev/null and b/jdk/test/java/net/httpclient/http2/keystore.p12 differ
diff --git a/jdk/test/java/nio/Buffer/Basic-X.java.template b/jdk/test/java/nio/Buffer/Basic-X.java.template
index 5e96b454b1b..d578b1366d3 100644
--- a/jdk/test/java/nio/Buffer/Basic-X.java.template
+++ b/jdk/test/java/nio/Buffer/Basic-X.java.template
@@ -31,7 +31,6 @@
 #warn This file is preprocessed before being compiled
 
 import java.nio.*;
-import java.lang.reflect.Method;
 
 
 public class Basic$Type$
@@ -60,7 +59,6 @@ public class Basic$Type$
 
     private static void relGet($Type$Buffer b) {
         int n = b.capacity();
-        $type$ v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)(($type$)ic(i)));
         b.rewind();
@@ -68,7 +66,6 @@ public class Basic$Type$
 
     private static void relGet($Type$Buffer b, int start) {
         int n = b.remaining();
-        $type$ v;
         for (int i = start; i < n; i++)
             ck(b, (long)b.get(), (long)(($type$)ic(i)));
         b.rewind();
@@ -76,7 +73,6 @@ public class Basic$Type$
 
     private static void absGet($Type$Buffer b) {
         int n = b.capacity();
-        $type$ v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)(($type$)ic(i)));
         b.rewind();
@@ -86,8 +82,9 @@ public class Basic$Type$
         int n = b.capacity();
         $type$[] a = new $type$[n + 7];
         b.get(a, 7, n);
-        for (int i = 0; i < n; i++)
+        for (int i = 0; i < n; i++) {
             ck(b, (long)a[i + 7], (long)(($type$)ic(i)));
+        }
     }
 
     private static void relPut($Type$Buffer b) {
@@ -178,7 +175,7 @@ public class Basic$Type$
     private static void bulkPutString($Type$Buffer b) {
         int n = b.capacity();
         b.clear();
-        StringBuffer sb = new StringBuffer(n + 7);
+        StringBuilder sb = new StringBuilder(n + 7);
         sb.append("1234567");
         for (int i = 0; i < n; i++)
             sb.append((char)ic(i));
@@ -203,13 +200,14 @@ public class Basic$Type$
     private static void checkBytes(ByteBuffer b, byte[] bs) {
         int n = bs.length;
         int p = b.position();
-        byte v;
         if (b.order() == ByteOrder.BIG_ENDIAN) {
-            for (int i = 0; i < n; i++)
+            for (int i = 0; i < n; i++) {
                 ck(b, b.get(), bs[i]);
+            }
         } else {
-            for (int i = n - 1; i >= 0; i--)
+            for (int i = n - 1; i >= 0; i--) {
                 ck(b, b.get(), bs[i]);
+            }
         }
         b.position(p);
     }
@@ -217,7 +215,7 @@ public class Basic$Type$
     private static void compact(Buffer b) {
         try {
             Class<?> cl = b.getClass();
-            Method m = cl.getDeclaredMethod("compact");
+            java.lang.reflect.Method m = cl.getDeclaredMethod("compact");
             m.setAccessible(true);
             m.invoke(b);
         } catch (Exception e) {
@@ -226,12 +224,11 @@ public class Basic$Type$
     }
 
     private static void checkInvalidMarkException(final Buffer b) {
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-            public void run() {
+        tryCatch(b, InvalidMarkException.class, () -> {
                 b.mark();
                 compact(b);
                 b.reset();
-            }});
+            });
     }
 
     private static void testViews(int level, ByteBuffer b, boolean direct) {
@@ -338,41 +335,50 @@ public class Basic$Type$
 
     private static void testAlign(final ByteBuffer b, boolean direct) {
         // index out-of bounds
-        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(-1, (short) 1));
+        catchIllegalArgument(b, () -> b.alignmentOffset(-1, (short) 1));
 
         // unit size values
-        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, (short) 0));
+        catchIllegalArgument(b, () -> b.alignmentOffset(0, (short) 0));
         for (int us = 1; us < 65; us++) {
             int _us = us;
             if ((us & (us - 1)) != 0) {
                 // unit size not a power of two
-                tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, _us));
+                catchIllegalArgument(b, () -> b.alignmentOffset(0, _us));
             } else {
                 if (direct || us <= 8) {
                     b.alignmentOffset(0, us);
                 } else {
                     // unit size > 8 with non-direct buffer
-                    tryCatch(b, UnsupportedOperationException.class, () -> b.alignmentOffset(0, _us));
+                    tryCatch(b, UnsupportedOperationException.class,
+                            () -> b.alignmentOffset(0, _us));
                 }
             }
         }
 
         // Probe for long misalignment at index zero for a newly created buffer
-        ByteBuffer empty = direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
+        ByteBuffer empty =
+                direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
         int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
 
         if (direct) {
             // Freshly created direct byte buffers should be aligned at index 0
             // for ref and primitive values (see Unsafe.allocateMemory)
-            if (longMisalignmentAtZero != 0)
-                fail("Direct byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+            if (longMisalignmentAtZero != 0) {
+                fail("Direct byte buffer misaligned at index 0"
+                        + " for ref and primitive values "
+                        + longMisalignmentAtZero);
+            }
         } else {
             // For heap byte buffers misalignment may occur on 32-bit systems
             // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
             // Note the GC will preserve alignment of the base address of the
             // array
-            if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 != longMisalignmentAtZero)
-                fail("Heap byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+            if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8
+                    != longMisalignmentAtZero) {
+                fail("Heap byte buffer misaligned at index 0"
+                        + " for ref and primitive values "
+                        + longMisalignmentAtZero);
+            }
         }
 
         // Ensure test buffer is correctly aligned at index 0
@@ -385,8 +391,10 @@ public class Basic$Type$
                 int am = b.alignmentOffset(i, us);
                 int expectedAm = (longMisalignmentAtZero + i) % us;
 
-                if (am != expectedAm)
-                    fail(String.format("b.alignmentOffset(%d, %d) == %d incorrect, expected %d", i, us, am, expectedAm));
+                if (am != expectedAm) {
+                    String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d";
+                    fail(String.format(f, i, us, am, expectedAm));
+                }
             }
         }
 
@@ -395,8 +403,10 @@ public class Basic$Type$
         int al = b.limit() - b.alignmentOffset(b.limit(), 8);
         ByteBuffer ab = b.position(ap).limit(al).
                 slice();
-        if (ab.limit() == 0)
-            fail("Test input buffer not sufficiently sized to cover an aligned region for all values", b);
+        if (ab.limit() == 0) {
+            fail("Test input buffer not sufficiently sized to cover" +
+                    " an aligned region for all values", b);
+        }
         if (ab.alignmentOffset(0, 8) != 0)
             fail("Aligned test input buffer not correctly aligned at index 0", ab);
 
@@ -428,8 +438,9 @@ public class Basic$Type$
                 l = l - l_mod;
 
                 int ec = l - p;
-                if (as.limit() != ec)
+                if (as.limit() != ec) {
                     fail("Buffer capacity incorrect, expected: " + ec, as);
+                }
             }
         }
     }
@@ -441,6 +452,22 @@ public class Basic$Type$
         fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
     }
 
+    private static void catchIllegalArgument(Buffer b, Runnable thunk) {
+        tryCatch(b, IllegalArgumentException.class, thunk);
+    }
+
+    private static void catchReadOnlyBuffer(Buffer b, Runnable thunk) {
+        tryCatch(b, ReadOnlyBufferException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(Buffer b, Runnable thunk) {
+        tryCatch(b, IndexOutOfBoundsException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds($type$[] t, Runnable thunk) {
+        tryCatch(t, IndexOutOfBoundsException.class, thunk);
+    }
+
     private static void tryCatch(Buffer b, Class<?> ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -452,11 +479,12 @@ public class Basic$Type$
                 fail(x.getMessage() + " not expected");
             }
         }
-        if (!caught)
+        if (!caught) {
             fail(ex.getName() + " not thrown", b);
+        }
     }
 
-    private static void tryCatch($type$ [] t, Class<?> ex, Runnable thunk) {
+    private static void tryCatch($type$[] t, Class<?> ex, Runnable thunk) {
         tryCatch($Type$Buffer.wrap(t), ex, thunk);
     }
 
@@ -513,11 +541,9 @@ public class Basic$Type$
         // 7190219
         b.clear();
         int pos = b.position();
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-            public void run() {
-                b.put(String.valueOf(new char[b.capacity() + 1]), 0,
-                        b.capacity() + 1);
-            }});
+        tryCatch(b, BufferOverflowException.class, () ->
+                b.put(String.valueOf(new char[b.capacity() + 1]), 0, b.capacity() + 1)
+            );
         ck(b, b.position(), pos);
         relGet(b);
 
@@ -537,38 +563,14 @@ public class Basic$Type$
         b.limit(b.capacity() / 2);
         b.position(b.limit());
 
-        tryCatch(b, BufferUnderflowException.class, new Runnable() {
-                public void run() {
-                    b.get();
-                }});
-
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-                public void run() {
-                    b.put(($type$)42);
-                }});
-
-        // The index must be non-negative and lesss than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.put(b.limit(), ($type$)42);
-                }});
-
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-                public void run() {
-                    b.position(0);
-                    b.mark();
-                    b.compact();
-                    b.reset();
-                }});
+        tryCatch(b, BufferUnderflowException.class, () -> b.get());
+        tryCatch(b, BufferOverflowException.class, () -> b.put(($type$)42));
+        // The index must be non-negative and less than the buffer's limit.
+        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
+        catchIndexOutOfBounds(b, () -> b.get(-1));
+        catchIndexOutOfBounds(b, () -> b.put(b.limit(), ($type$)42));
+        tryCatch(b, InvalidMarkException.class,
+                () -> b.position(0).mark().compact().reset());
 
         try {
             b.position(b.limit() + 1);
@@ -635,7 +637,6 @@ public class Basic$Type$
         b.put(0.5121609353879392);      // Changes value if incorrectly swapped
 #end[double]
 
-        $type$ v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), ($type$)-1);
@@ -644,23 +645,27 @@ public class Basic$Type$
         ck(b, b.get(), $Fulltype$.MIN_VALUE);
 
 #if[float]
+        $type$ v;
         ck(b, b.get(), -Float.MAX_VALUE);
         ck(b, b.get(), -Float.MIN_VALUE);
         ck(b, b.get(), Float.NEGATIVE_INFINITY);
         ck(b, b.get(), Float.POSITIVE_INFINITY);
         if (Float.floatToRawIntBits(v = b.get()) !=
-            Float.floatToRawIntBits(Float.NaN))
+            Float.floatToRawIntBits(Float.NaN)) {
             fail(b, (long)Float.NaN, (long)v);
+        }
         ck(b, b.get(), 0.91697687f);
 #end[float]
 #if[double]
+        $type$ v;
         ck(b, b.get(), -Double.MAX_VALUE);
         ck(b, b.get(), -Double.MIN_VALUE);
         ck(b, b.get(), Double.NEGATIVE_INFINITY);
         ck(b, b.get(), Double.POSITIVE_INFINITY);
         if (Double.doubleToRawLongBits(v = b.get())
-            != Double.doubleToRawLongBits(Double.NaN))
+            != Double.doubleToRawLongBits(Double.NaN)) {
             fail(b, (long)Double.NaN, (long)v);
+        }
         ck(b, b.get(), 0.5121609353879392);
 #end[double]
 
@@ -683,14 +688,15 @@ public class Basic$Type$
 #if[float]
                     || Float.compare(x, y) != 0
 #end[float]
-                    )
+                    ) {
                     out.println("[" + i + "] " + x + " != " + y);
+                }
             }
             fail("Identical buffers not equal", b, b2);
         }
-        if (b.compareTo(b2) != 0)
+        if (b.compareTo(b2) != 0) {
             fail("Comparison to identical buffer != 0", b, b2);
-
+        }
         b.limit(b.limit() + 1);
         b.position(b.limit() - 1);
         b.put(($type$)99);
@@ -714,7 +720,7 @@ public class Basic$Type$
             if (xb.compareTo(xb) != 0) {
                 fail("compareTo not reflexive", xb, xb, x, x);
             }
-            if (! xb.equals(xb)) {
+            if (!xb.equals(xb)) {
                 fail("equals not reflexive", xb, xb, x, x);
             }
             for ($type$ y : VALUES) {
@@ -765,9 +771,10 @@ public class Basic$Type$
 
         if (!sb.equals(sb2))
             fail("Sliced slices do not match", sb, sb2);
-        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
+        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) {
             fail("Array offsets do not match: "
                  + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
+        }
 
 #if[byte]
 
@@ -808,129 +815,49 @@ public class Basic$Type$
             fail("Buffer not equal to read-only view", b, rb);
         show(level + 1, rb);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    relPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    absPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutArray(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutBuffer(rb);
-                }});
+        catchReadOnlyBuffer(b, () -> relPut(rb));
+        catchReadOnlyBuffer(b, () -> absPut(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutArray(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutBuffer(rb));
 
         // put($Type$Buffer) should not change source position
         final $Type$Buffer src = $Type$Buffer.allocate(1);
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.put(src);
-                 }});
+        catchReadOnlyBuffer(b, () -> rb.put(src));
         ck(src, src.position(), 0);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.compact();
-                }});
+        catchReadOnlyBuffer(b, () -> rb.compact());
 
 #if[byte]
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putChar((char)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putChar(0, (char)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putShort((short)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putShort(0, (short)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putInt(1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putInt(0, 1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putLong((long)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putLong(0, (long)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putFloat((float)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putFloat(0, (float)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putDouble((double)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putDouble(0, (double)1);
-                }});
+        catchReadOnlyBuffer(b, () -> rb.putChar((char)1));
+        catchReadOnlyBuffer(b, () -> rb.putChar(0, (char)1));
+        catchReadOnlyBuffer(b, () -> rb.putShort((short)1));
+        catchReadOnlyBuffer(b, () -> rb.putShort(0, (short)1));
+        catchReadOnlyBuffer(b, () -> rb.putInt(1));
+        catchReadOnlyBuffer(b, () -> rb.putInt(0, 1));
+        catchReadOnlyBuffer(b, () -> rb.putLong((long)1));
+        catchReadOnlyBuffer(b, () -> rb.putLong(0, (long)1));
+        catchReadOnlyBuffer(b, () -> rb.putFloat((float)1));
+        catchReadOnlyBuffer(b, () -> rb.putFloat(0, (float)1));
+        catchReadOnlyBuffer(b, () -> rb.putDouble((double)1));
+        catchReadOnlyBuffer(b, () -> rb.putDouble(0, (double)1));
 
 #end[byte]
 
 #if[char]
 
         // 7199551
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-            public void run() {
-                String s = new String(new char[rb.remaining() + 1]);
-                rb.put(s);
-            }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-            public void run() {
-                String s = new String(new char[rb.remaining() + 1]);
-                rb.append(s);
-            }});
+        catchReadOnlyBuffer(b, () -> rb.put(new String(new char[rb.remaining() + 1])));
+        catchReadOnlyBuffer(b, () -> rb.append(new String(new char[rb.remaining() + 1])));
 
 #end[char]
 
         if (rb.getClass().getName().startsWith("java.nio.Heap")) {
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.array();
-                    }});
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.arrayOffset();
-                    }});
-
-            if (rb.hasArray())
-                fail("Read-only heap buffer's backing array is accessible",
-                     rb);
-
+            catchReadOnlyBuffer(b, () -> rb.array());
+            catchReadOnlyBuffer(b, () -> rb.arrayOffset());
+            if (rb.hasArray()) {
+                fail("Read-only heap buffer's backing array is accessible", rb);
+            }
         }
 
         // Bulk puts from read-only buffers
@@ -969,10 +896,7 @@ public class Basic$Type$
         ck(b, b.toString().equals(s.substring(start, end)));
         ck(b, b.toString().equals("defghi"));
         ck(b, b.isReadOnly());
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    b.put('x');
-                }});
+        catchReadOnlyBuffer(b, () -> b.put('x'));
         ck(b, start, b.position());
         ck(b, end, b.limit());
         ck(b, s.length(), b.capacity());
@@ -981,63 +905,25 @@ public class Basic$Type$
 
         // The index, relative to the position, must be non-negative and
         // smaller than remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.charAt(-1);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.charAt(b.remaining());
-                }});
-
+        catchIndexOutOfBounds(b, () -> b.charAt(-1));
+        catchIndexOutOfBounds(b, () -> b.charAt(b.remaining()));
         // The index must be non-negative and less than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
+        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
+        catchIndexOutOfBounds(b, () -> b.get(-1));
         // The start must be non-negative and no larger than remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(-1, b.remaining());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(b.remaining() + 1, b.remaining());
-                }});
+        catchIndexOutOfBounds(b, () -> b.subSequence(-1, b.remaining()));
+        catchIndexOutOfBounds(b, () -> b.subSequence(b.remaining() + 1, b.remaining()));
 
         // The end must be no smaller than start and no larger than
         // remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(2, 1);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(0, b.remaining() + 1);
-                }});
+        catchIndexOutOfBounds(b, () -> b.subSequence(2, 1));
+        catchIndexOutOfBounds(b, () -> b.subSequence(0, b.remaining() + 1));
 
         // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, -1, s.length());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, s.length() + 1, s.length());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, 1, 0);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, 0, s.length() + 1);
-                }});
+        catchIndexOutOfBounds(b, () -> $Type$Buffer.wrap(s, -1, s.length()));
+        catchIndexOutOfBounds(b, () -> $Type$Buffer.wrap(s, s.length() + 1, s.length()));
+        catchIndexOutOfBounds(b, () -> $Type$Buffer.wrap(s, 1, 0));
+        catchIndexOutOfBounds(b, () -> $Type$Buffer.wrap(s, 0, s.length() + 1));
     }
 
 #end[char]
@@ -1052,40 +938,21 @@ public class Basic$Type$
         ck(b, b.limit(), offset + length);
 
         // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, -1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, ba.length + 1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, 0, -1);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, 0, ba.length + 1);
-                }});
+        catchIndexOutOfBounds(ba, () -> $Type$Buffer.wrap(ba, -1, ba.length));
+        catchIndexOutOfBounds(ba, () -> $Type$Buffer.wrap(ba, ba.length + 1, ba.length));
+        catchIndexOutOfBounds(ba, () -> $Type$Buffer.wrap(ba, 0, -1));
+        catchIndexOutOfBounds(ba, () -> $Type$Buffer.wrap(ba, 0, ba.length + 1));
 
         // A NullPointerException will be thrown if the array is null.
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(($type$ []) null, 0, 5);
-                }});
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(($type$ []) null);
-                }});
+        tryCatch(ba, NullPointerException.class,
+                () -> $Type$Buffer.wrap(($type$ []) null, 0, 5));
+        tryCatch(ba, NullPointerException.class,
+                () -> $Type$Buffer.wrap(($type$ []) null));
     }
 
     private static void testAllocate() {
         // An IllegalArgumentException will be thrown for negative capacities.
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.allocate(-1);
-                }});
+        catchIllegalArgument((Buffer) null, () -> $Type$Buffer.allocate(-1));
         try {
             $Type$Buffer.allocate(-1);
         } catch (IllegalArgumentException e) {
@@ -1095,10 +962,7 @@ public class Basic$Type$
             }
         }
 #if[byte]
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.allocateDirect(-1);
-                }});
+        catchIllegalArgument((Buffer) null, () -> $Type$Buffer.allocateDirect(-1));
         try {
             $Type$Buffer.allocateDirect(-1);
         } catch (IllegalArgumentException e) {
diff --git a/jdk/test/java/nio/Buffer/BasicByte.java b/jdk/test/java/nio/Buffer/BasicByte.java
index 2d165449fa6..039dde39eb0 100644
--- a/jdk/test/java/nio/Buffer/BasicByte.java
+++ b/jdk/test/java/nio/Buffer/BasicByte.java
@@ -31,7 +31,6 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
-import java.lang.reflect.Method;
 
 
 public class BasicByte
@@ -60,7 +59,6 @@ public class BasicByte
 
     private static void relGet(ByteBuffer b) {
         int n = b.capacity();
-        byte v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((byte)ic(i)));
         b.rewind();
@@ -68,7 +66,6 @@ public class BasicByte
 
     private static void relGet(ByteBuffer b, int start) {
         int n = b.remaining();
-        byte v;
         for (int i = start; i < n; i++)
             ck(b, (long)b.get(), (long)((byte)ic(i)));
         b.rewind();
@@ -76,7 +73,6 @@ public class BasicByte
 
     private static void absGet(ByteBuffer b) {
         int n = b.capacity();
-        byte v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((byte)ic(i)));
         b.rewind();
@@ -86,8 +82,9 @@ public class BasicByte
         int n = b.capacity();
         byte[] a = new byte[n + 7];
         b.get(a, 7, n);
-        for (int i = 0; i < n; i++)
+        for (int i = 0; i < n; i++) {
             ck(b, (long)a[i + 7], (long)((byte)ic(i)));
+        }
     }
 
     private static void relPut(ByteBuffer b) {
@@ -203,13 +200,14 @@ public class BasicByte
     private static void checkBytes(ByteBuffer b, byte[] bs) {
         int n = bs.length;
         int p = b.position();
-        byte v;
         if (b.order() == ByteOrder.BIG_ENDIAN) {
-            for (int i = 0; i < n; i++)
+            for (int i = 0; i < n; i++) {
                 ck(b, b.get(), bs[i]);
+            }
         } else {
-            for (int i = n - 1; i >= 0; i--)
+            for (int i = n - 1; i >= 0; i--) {
                 ck(b, b.get(), bs[i]);
+            }
         }
         b.position(p);
     }
@@ -217,7 +215,7 @@ public class BasicByte
     private static void compact(Buffer b) {
         try {
             Class<?> cl = b.getClass();
-            Method m = cl.getDeclaredMethod("compact");
+            java.lang.reflect.Method m = cl.getDeclaredMethod("compact");
             m.setAccessible(true);
             m.invoke(b);
         } catch (Exception e) {
@@ -226,12 +224,11 @@ public class BasicByte
     }
 
     private static void checkInvalidMarkException(final Buffer b) {
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-            public void run() {
+        tryCatch(b, InvalidMarkException.class, () -> {
                 b.mark();
                 compact(b);
                 b.reset();
-            }});
+            });
     }
 
     private static void testViews(int level, ByteBuffer b, boolean direct) {
@@ -338,41 +335,50 @@ public class BasicByte
 
     private static void testAlign(final ByteBuffer b, boolean direct) {
         // index out-of bounds
-        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(-1, (short) 1));
+        catchIllegalArgument(b, () -> b.alignmentOffset(-1, (short) 1));
 
         // unit size values
-        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, (short) 0));
+        catchIllegalArgument(b, () -> b.alignmentOffset(0, (short) 0));
         for (int us = 1; us < 65; us++) {
             int _us = us;
             if ((us & (us - 1)) != 0) {
                 // unit size not a power of two
-                tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, _us));
+                catchIllegalArgument(b, () -> b.alignmentOffset(0, _us));
             } else {
                 if (direct || us <= 8) {
                     b.alignmentOffset(0, us);
                 } else {
                     // unit size > 8 with non-direct buffer
-                    tryCatch(b, UnsupportedOperationException.class, () -> b.alignmentOffset(0, _us));
+                    tryCatch(b, UnsupportedOperationException.class,
+                            () -> b.alignmentOffset(0, _us));
                 }
             }
         }
 
         // Probe for long misalignment at index zero for a newly created buffer
-        ByteBuffer empty = direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
+        ByteBuffer empty =
+                direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
         int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
 
         if (direct) {
             // Freshly created direct byte buffers should be aligned at index 0
             // for ref and primitive values (see Unsafe.allocateMemory)
-            if (longMisalignmentAtZero != 0)
-                fail("Direct byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+            if (longMisalignmentAtZero != 0) {
+                fail("Direct byte buffer misaligned at index 0"
+                        + " for ref and primitive values "
+                        + longMisalignmentAtZero);
+            }
         } else {
             // For heap byte buffers misalignment may occur on 32-bit systems
             // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
             // Note the GC will preserve alignment of the base address of the
             // array
-            if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 != longMisalignmentAtZero)
-                fail("Heap byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+            if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8
+                    != longMisalignmentAtZero) {
+                fail("Heap byte buffer misaligned at index 0"
+                        + " for ref and primitive values "
+                        + longMisalignmentAtZero);
+            }
         }
 
         // Ensure test buffer is correctly aligned at index 0
@@ -385,8 +391,10 @@ public class BasicByte
                 int am = b.alignmentOffset(i, us);
                 int expectedAm = (longMisalignmentAtZero + i) % us;
 
-                if (am != expectedAm)
-                    fail(String.format("b.alignmentOffset(%d, %d) == %d incorrect, expected %d", i, us, am, expectedAm));
+                if (am != expectedAm) {
+                    String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d";
+                    fail(String.format(f, i, us, am, expectedAm));
+                }
             }
         }
 
@@ -395,8 +403,10 @@ public class BasicByte
         int al = b.limit() - b.alignmentOffset(b.limit(), 8);
         ByteBuffer ab = b.position(ap).limit(al).
                 slice();
-        if (ab.limit() == 0)
-            fail("Test input buffer not sufficiently sized to cover an aligned region for all values", b);
+        if (ab.limit() == 0) {
+            fail("Test input buffer not sufficiently sized to cover" +
+                    " an aligned region for all values", b);
+        }
         if (ab.alignmentOffset(0, 8) != 0)
             fail("Aligned test input buffer not correctly aligned at index 0", ab);
 
@@ -428,8 +438,9 @@ public class BasicByte
                 l = l - l_mod;
 
                 int ec = l - p;
-                if (as.limit() != ec)
+                if (as.limit() != ec) {
                     fail("Buffer capacity incorrect, expected: " + ec, as);
+                }
             }
         }
     }
@@ -441,6 +452,22 @@ public class BasicByte
         fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
     }
 
+    private static void catchIllegalArgument(Buffer b, Runnable thunk) {
+        tryCatch(b, IllegalArgumentException.class, thunk);
+    }
+
+    private static void catchReadOnlyBuffer(Buffer b, Runnable thunk) {
+        tryCatch(b, ReadOnlyBufferException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(Buffer b, Runnable thunk) {
+        tryCatch(b, IndexOutOfBoundsException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(byte[] t, Runnable thunk) {
+        tryCatch(t, IndexOutOfBoundsException.class, thunk);
+    }
+
     private static void tryCatch(Buffer b, Class<?> ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -452,11 +479,12 @@ public class BasicByte
                 fail(x.getMessage() + " not expected");
             }
         }
-        if (!caught)
+        if (!caught) {
             fail(ex.getName() + " not thrown", b);
+        }
     }
 
-    private static void tryCatch(byte [] t, Class<?> ex, Runnable thunk) {
+    private static void tryCatch(byte[] t, Class<?> ex, Runnable thunk) {
         tryCatch(ByteBuffer.wrap(t), ex, thunk);
     }
 
@@ -518,8 +546,6 @@ public class BasicByte
 
 
 
-
-
 
 
 
@@ -537,38 +563,14 @@ public class BasicByte
         b.limit(b.capacity() / 2);
         b.position(b.limit());
 
-        tryCatch(b, BufferUnderflowException.class, new Runnable() {
-                public void run() {
-                    b.get();
-                }});
-
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-                public void run() {
-                    b.put((byte)42);
-                }});
-
-        // The index must be non-negative and lesss than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.put(b.limit(), (byte)42);
-                }});
-
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-                public void run() {
-                    b.position(0);
-                    b.mark();
-                    b.compact();
-                    b.reset();
-                }});
+        tryCatch(b, BufferUnderflowException.class, () -> b.get());
+        tryCatch(b, BufferOverflowException.class, () -> b.put((byte)42));
+        // The index must be non-negative and less than the buffer's limit.
+        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
+        catchIndexOutOfBounds(b, () -> b.get(-1));
+        catchIndexOutOfBounds(b, () -> b.put(b.limit(), (byte)42));
+        tryCatch(b, InvalidMarkException.class,
+                () -> b.position(0).mark().compact().reset());
 
         try {
             b.position(b.limit() + 1);
@@ -635,7 +637,6 @@ public class BasicByte
 
 
 
-        byte v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (byte)-1);
@@ -660,6 +661,10 @@ public class BasicByte
 
 
 
+
+
+
+
 
 
 
@@ -683,14 +688,15 @@ public class BasicByte
 
 
 
-                    )
+                    ) {
                     out.println("[" + i + "] " + x + " != " + y);
+                }
             }
             fail("Identical buffers not equal", b, b2);
         }
-        if (b.compareTo(b2) != 0)
+        if (b.compareTo(b2) != 0) {
             fail("Comparison to identical buffer != 0", b, b2);
-
+        }
         b.limit(b.limit() + 1);
         b.position(b.limit() - 1);
         b.put((byte)99);
@@ -714,7 +720,7 @@ public class BasicByte
             if (xb.compareTo(xb) != 0) {
                 fail("compareTo not reflexive", xb, xb, x, x);
             }
-            if (! xb.equals(xb)) {
+            if (!xb.equals(xb)) {
                 fail("equals not reflexive", xb, xb, x, x);
             }
             for (byte y : VALUES) {
@@ -765,9 +771,10 @@ public class BasicByte
 
         if (!sb.equals(sb2))
             fail("Sliced slices do not match", sb, sb2);
-        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
+        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) {
             fail("Array offsets do not match: "
                  + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
+        }
 
 
 
@@ -808,102 +815,32 @@ public class BasicByte
             fail("Buffer not equal to read-only view", b, rb);
         show(level + 1, rb);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    relPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    absPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutArray(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutBuffer(rb);
-                }});
+        catchReadOnlyBuffer(b, () -> relPut(rb));
+        catchReadOnlyBuffer(b, () -> absPut(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutArray(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutBuffer(rb));
 
         // put(ByteBuffer) should not change source position
         final ByteBuffer src = ByteBuffer.allocate(1);
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.put(src);
-                 }});
+        catchReadOnlyBuffer(b, () -> rb.put(src));
         ck(src, src.position(), 0);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.compact();
-                }});
-
-
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putChar((char)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putChar(0, (char)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putShort((short)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putShort(0, (short)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putInt(1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putInt(0, 1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putLong((long)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putLong(0, (long)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putFloat((float)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putFloat(0, (float)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putDouble((double)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putDouble(0, (double)1);
-                }});
-
-
-
-
-
+        catchReadOnlyBuffer(b, () -> rb.compact());
 
 
 
+        catchReadOnlyBuffer(b, () -> rb.putChar((char)1));
+        catchReadOnlyBuffer(b, () -> rb.putChar(0, (char)1));
+        catchReadOnlyBuffer(b, () -> rb.putShort((short)1));
+        catchReadOnlyBuffer(b, () -> rb.putShort(0, (short)1));
+        catchReadOnlyBuffer(b, () -> rb.putInt(1));
+        catchReadOnlyBuffer(b, () -> rb.putInt(0, 1));
+        catchReadOnlyBuffer(b, () -> rb.putLong((long)1));
+        catchReadOnlyBuffer(b, () -> rb.putLong(0, (long)1));
+        catchReadOnlyBuffer(b, () -> rb.putFloat((float)1));
+        catchReadOnlyBuffer(b, () -> rb.putFloat(0, (float)1));
+        catchReadOnlyBuffer(b, () -> rb.putDouble((double)1));
+        catchReadOnlyBuffer(b, () -> rb.putDouble(0, (double)1));
 
 
 
@@ -916,21 +853,11 @@ public class BasicByte
 
 
         if (rb.getClass().getName().startsWith("java.nio.Heap")) {
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.array();
-                    }});
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.arrayOffset();
-                    }});
-
-            if (rb.hasArray())
-                fail("Read-only heap buffer's backing array is accessible",
-                     rb);
-
+            catchReadOnlyBuffer(b, () -> rb.array());
+            catchReadOnlyBuffer(b, () -> rb.arrayOffset());
+            if (rb.hasArray()) {
+                fail("Read-only heap buffer's backing array is accessible", rb);
+            }
         }
 
         // Bulk puts from read-only buffers
@@ -980,47 +907,6 @@ public class BasicByte
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
@@ -1052,40 +938,21 @@ public class BasicByte
         ck(b, b.limit(), offset + length);
 
         // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    ByteBuffer.wrap(ba, -1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    ByteBuffer.wrap(ba, ba.length + 1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    ByteBuffer.wrap(ba, 0, -1);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    ByteBuffer.wrap(ba, 0, ba.length + 1);
-                }});
+        catchIndexOutOfBounds(ba, () -> ByteBuffer.wrap(ba, -1, ba.length));
+        catchIndexOutOfBounds(ba, () -> ByteBuffer.wrap(ba, ba.length + 1, ba.length));
+        catchIndexOutOfBounds(ba, () -> ByteBuffer.wrap(ba, 0, -1));
+        catchIndexOutOfBounds(ba, () -> ByteBuffer.wrap(ba, 0, ba.length + 1));
 
         // A NullPointerException will be thrown if the array is null.
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    ByteBuffer.wrap((byte []) null, 0, 5);
-                }});
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    ByteBuffer.wrap((byte []) null);
-                }});
+        tryCatch(ba, NullPointerException.class,
+                () -> ByteBuffer.wrap((byte []) null, 0, 5));
+        tryCatch(ba, NullPointerException.class,
+                () -> ByteBuffer.wrap((byte []) null));
     }
 
     private static void testAllocate() {
         // An IllegalArgumentException will be thrown for negative capacities.
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    ByteBuffer.allocate(-1);
-                }});
+        catchIllegalArgument((Buffer) null, () -> ByteBuffer.allocate(-1));
         try {
             ByteBuffer.allocate(-1);
         } catch (IllegalArgumentException e) {
@@ -1095,10 +962,7 @@ public class BasicByte
             }
         }
 
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    ByteBuffer.allocateDirect(-1);
-                }});
+        catchIllegalArgument((Buffer) null, () -> ByteBuffer.allocateDirect(-1));
         try {
             ByteBuffer.allocateDirect(-1);
         } catch (IllegalArgumentException e) {
diff --git a/jdk/test/java/nio/Buffer/BasicChar.java b/jdk/test/java/nio/Buffer/BasicChar.java
index b8dc950b68c..a059aa9c3bb 100644
--- a/jdk/test/java/nio/Buffer/BasicChar.java
+++ b/jdk/test/java/nio/Buffer/BasicChar.java
@@ -31,7 +31,6 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
-import java.lang.reflect.Method;
 
 
 public class BasicChar
@@ -60,7 +59,6 @@ public class BasicChar
 
     private static void relGet(CharBuffer b) {
         int n = b.capacity();
-        char v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((char)ic(i)));
         b.rewind();
@@ -68,7 +66,6 @@ public class BasicChar
 
     private static void relGet(CharBuffer b, int start) {
         int n = b.remaining();
-        char v;
         for (int i = start; i < n; i++)
             ck(b, (long)b.get(), (long)((char)ic(i)));
         b.rewind();
@@ -76,7 +73,6 @@ public class BasicChar
 
     private static void absGet(CharBuffer b) {
         int n = b.capacity();
-        char v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((char)ic(i)));
         b.rewind();
@@ -86,8 +82,9 @@ public class BasicChar
         int n = b.capacity();
         char[] a = new char[n + 7];
         b.get(a, 7, n);
-        for (int i = 0; i < n; i++)
+        for (int i = 0; i < n; i++) {
             ck(b, (long)a[i + 7], (long)((char)ic(i)));
+        }
     }
 
     private static void relPut(CharBuffer b) {
@@ -178,7 +175,7 @@ public class BasicChar
     private static void bulkPutString(CharBuffer b) {
         int n = b.capacity();
         b.clear();
-        StringBuffer sb = new StringBuffer(n + 7);
+        StringBuilder sb = new StringBuilder(n + 7);
         sb.append("1234567");
         for (int i = 0; i < n; i++)
             sb.append((char)ic(i));
@@ -420,6 +417,20 @@ public class BasicChar
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -441,6 +452,22 @@ public class BasicChar
         fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
     }
 
+    private static void catchIllegalArgument(Buffer b, Runnable thunk) {
+        tryCatch(b, IllegalArgumentException.class, thunk);
+    }
+
+    private static void catchReadOnlyBuffer(Buffer b, Runnable thunk) {
+        tryCatch(b, ReadOnlyBufferException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(Buffer b, Runnable thunk) {
+        tryCatch(b, IndexOutOfBoundsException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(char[] t, Runnable thunk) {
+        tryCatch(t, IndexOutOfBoundsException.class, thunk);
+    }
+
     private static void tryCatch(Buffer b, Class<?> ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -452,11 +479,12 @@ public class BasicChar
                 fail(x.getMessage() + " not expected");
             }
         }
-        if (!caught)
+        if (!caught) {
             fail(ex.getName() + " not thrown", b);
+        }
     }
 
-    private static void tryCatch(char [] t, Class<?> ex, Runnable thunk) {
+    private static void tryCatch(char[] t, Class<?> ex, Runnable thunk) {
         tryCatch(CharBuffer.wrap(t), ex, thunk);
     }
 
@@ -513,11 +541,9 @@ public class BasicChar
         // 7190219
         b.clear();
         int pos = b.position();
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-            public void run() {
-                b.put(String.valueOf(new char[b.capacity() + 1]), 0,
-                        b.capacity() + 1);
-            }});
+        tryCatch(b, BufferOverflowException.class, () ->
+                b.put(String.valueOf(new char[b.capacity() + 1]), 0, b.capacity() + 1)
+            );
         ck(b, b.position(), pos);
         relGet(b);
 
@@ -537,38 +563,14 @@ public class BasicChar
         b.limit(b.capacity() / 2);
         b.position(b.limit());
 
-        tryCatch(b, BufferUnderflowException.class, new Runnable() {
-                public void run() {
-                    b.get();
-                }});
-
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-                public void run() {
-                    b.put((char)42);
-                }});
-
-        // The index must be non-negative and lesss than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.put(b.limit(), (char)42);
-                }});
-
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-                public void run() {
-                    b.position(0);
-                    b.mark();
-                    b.compact();
-                    b.reset();
-                }});
+        tryCatch(b, BufferUnderflowException.class, () -> b.get());
+        tryCatch(b, BufferOverflowException.class, () -> b.put((char)42));
+        // The index must be non-negative and less than the buffer's limit.
+        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
+        catchIndexOutOfBounds(b, () -> b.get(-1));
+        catchIndexOutOfBounds(b, () -> b.put(b.limit(), (char)42));
+        tryCatch(b, InvalidMarkException.class,
+                () -> b.position(0).mark().compact().reset());
 
         try {
             b.position(b.limit() + 1);
@@ -635,7 +637,6 @@ public class BasicChar
 
 
 
-        char v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (char)-1);
@@ -660,6 +661,10 @@ public class BasicChar
 
 
 
+
+
+
+
 
 
 
@@ -683,14 +688,15 @@ public class BasicChar
 
 
 
-                    )
+                    ) {
                     out.println("[" + i + "] " + x + " != " + y);
+                }
             }
             fail("Identical buffers not equal", b, b2);
         }
-        if (b.compareTo(b2) != 0)
+        if (b.compareTo(b2) != 0) {
             fail("Comparison to identical buffer != 0", b, b2);
-
+        }
         b.limit(b.limit() + 1);
         b.position(b.limit() - 1);
         b.put((char)99);
@@ -714,7 +720,7 @@ public class BasicChar
             if (xb.compareTo(xb) != 0) {
                 fail("compareTo not reflexive", xb, xb, x, x);
             }
-            if (! xb.equals(xb)) {
+            if (!xb.equals(xb)) {
                 fail("equals not reflexive", xb, xb, x, x);
             }
             for (char y : VALUES) {
@@ -765,9 +771,10 @@ public class BasicChar
 
         if (!sb.equals(sb2))
             fail("Sliced slices do not match", sb, sb2);
-        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
+        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) {
             fail("Array offsets do not match: "
                  + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
+        }
 
 
 
@@ -808,79 +815,17 @@ public class BasicChar
             fail("Buffer not equal to read-only view", b, rb);
         show(level + 1, rb);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    relPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    absPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutArray(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutBuffer(rb);
-                }});
+        catchReadOnlyBuffer(b, () -> relPut(rb));
+        catchReadOnlyBuffer(b, () -> absPut(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutArray(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutBuffer(rb));
 
         // put(CharBuffer) should not change source position
         final CharBuffer src = CharBuffer.allocate(1);
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.put(src);
-                 }});
+        catchReadOnlyBuffer(b, () -> rb.put(src));
         ck(src, src.position(), 0);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.compact();
-                }});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+        catchReadOnlyBuffer(b, () -> rb.compact());
 
 
 
@@ -902,35 +847,17 @@ public class BasicChar
 
 
         // 7199551
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-            public void run() {
-                String s = new String(new char[rb.remaining() + 1]);
-                rb.put(s);
-            }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-            public void run() {
-                String s = new String(new char[rb.remaining() + 1]);
-                rb.append(s);
-            }});
+        catchReadOnlyBuffer(b, () -> rb.put(new String(new char[rb.remaining() + 1])));
+        catchReadOnlyBuffer(b, () -> rb.append(new String(new char[rb.remaining() + 1])));
 
 
 
         if (rb.getClass().getName().startsWith("java.nio.Heap")) {
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.array();
-                    }});
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.arrayOffset();
-                    }});
-
-            if (rb.hasArray())
-                fail("Read-only heap buffer's backing array is accessible",
-                     rb);
-
+            catchReadOnlyBuffer(b, () -> rb.array());
+            catchReadOnlyBuffer(b, () -> rb.arrayOffset());
+            if (rb.hasArray()) {
+                fail("Read-only heap buffer's backing array is accessible", rb);
+            }
         }
 
         // Bulk puts from read-only buffers
@@ -969,10 +896,7 @@ public class BasicChar
         ck(b, b.toString().equals(s.substring(start, end)));
         ck(b, b.toString().equals("defghi"));
         ck(b, b.isReadOnly());
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    b.put('x');
-                }});
+        catchReadOnlyBuffer(b, () -> b.put('x'));
         ck(b, start, b.position());
         ck(b, end, b.limit());
         ck(b, s.length(), b.capacity());
@@ -981,63 +905,25 @@ public class BasicChar
 
         // The index, relative to the position, must be non-negative and
         // smaller than remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.charAt(-1);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.charAt(b.remaining());
-                }});
-
+        catchIndexOutOfBounds(b, () -> b.charAt(-1));
+        catchIndexOutOfBounds(b, () -> b.charAt(b.remaining()));
         // The index must be non-negative and less than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
+        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
+        catchIndexOutOfBounds(b, () -> b.get(-1));
         // The start must be non-negative and no larger than remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(-1, b.remaining());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(b.remaining() + 1, b.remaining());
-                }});
+        catchIndexOutOfBounds(b, () -> b.subSequence(-1, b.remaining()));
+        catchIndexOutOfBounds(b, () -> b.subSequence(b.remaining() + 1, b.remaining()));
 
         // The end must be no smaller than start and no larger than
         // remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(2, 1);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(0, b.remaining() + 1);
-                }});
+        catchIndexOutOfBounds(b, () -> b.subSequence(2, 1));
+        catchIndexOutOfBounds(b, () -> b.subSequence(0, b.remaining() + 1));
 
         // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.wrap(s, -1, s.length());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.wrap(s, s.length() + 1, s.length());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.wrap(s, 1, 0);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.wrap(s, 0, s.length() + 1);
-                }});
+        catchIndexOutOfBounds(b, () -> CharBuffer.wrap(s, -1, s.length()));
+        catchIndexOutOfBounds(b, () -> CharBuffer.wrap(s, s.length() + 1, s.length()));
+        catchIndexOutOfBounds(b, () -> CharBuffer.wrap(s, 1, 0));
+        catchIndexOutOfBounds(b, () -> CharBuffer.wrap(s, 0, s.length() + 1));
     }
 
 
@@ -1052,40 +938,21 @@ public class BasicChar
         ck(b, b.limit(), offset + length);
 
         // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.wrap(ba, -1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.wrap(ba, ba.length + 1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.wrap(ba, 0, -1);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.wrap(ba, 0, ba.length + 1);
-                }});
+        catchIndexOutOfBounds(ba, () -> CharBuffer.wrap(ba, -1, ba.length));
+        catchIndexOutOfBounds(ba, () -> CharBuffer.wrap(ba, ba.length + 1, ba.length));
+        catchIndexOutOfBounds(ba, () -> CharBuffer.wrap(ba, 0, -1));
+        catchIndexOutOfBounds(ba, () -> CharBuffer.wrap(ba, 0, ba.length + 1));
 
         // A NullPointerException will be thrown if the array is null.
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.wrap((char []) null, 0, 5);
-                }});
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.wrap((char []) null);
-                }});
+        tryCatch(ba, NullPointerException.class,
+                () -> CharBuffer.wrap((char []) null, 0, 5));
+        tryCatch(ba, NullPointerException.class,
+                () -> CharBuffer.wrap((char []) null));
     }
 
     private static void testAllocate() {
         // An IllegalArgumentException will be thrown for negative capacities.
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    CharBuffer.allocate(-1);
-                }});
+        catchIllegalArgument((Buffer) null, () -> CharBuffer.allocate(-1));
         try {
             CharBuffer.allocate(-1);
         } catch (IllegalArgumentException e) {
@@ -1105,9 +972,6 @@ public class BasicChar
 
 
 
-
-
-
     }
 
     public static void test() {
diff --git a/jdk/test/java/nio/Buffer/BasicDouble.java b/jdk/test/java/nio/Buffer/BasicDouble.java
index b25fe15aa52..41dc5379057 100644
--- a/jdk/test/java/nio/Buffer/BasicDouble.java
+++ b/jdk/test/java/nio/Buffer/BasicDouble.java
@@ -31,7 +31,6 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
-import java.lang.reflect.Method;
 
 
 public class BasicDouble
@@ -60,7 +59,6 @@ public class BasicDouble
 
     private static void relGet(DoubleBuffer b) {
         int n = b.capacity();
-        double v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((double)ic(i)));
         b.rewind();
@@ -68,7 +66,6 @@ public class BasicDouble
 
     private static void relGet(DoubleBuffer b, int start) {
         int n = b.remaining();
-        double v;
         for (int i = start; i < n; i++)
             ck(b, (long)b.get(), (long)((double)ic(i)));
         b.rewind();
@@ -76,7 +73,6 @@ public class BasicDouble
 
     private static void absGet(DoubleBuffer b) {
         int n = b.capacity();
-        double v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((double)ic(i)));
         b.rewind();
@@ -86,8 +82,9 @@ public class BasicDouble
         int n = b.capacity();
         double[] a = new double[n + 7];
         b.get(a, 7, n);
-        for (int i = 0; i < n; i++)
+        for (int i = 0; i < n; i++) {
             ck(b, (long)a[i + 7], (long)((double)ic(i)));
+        }
     }
 
     private static void relPut(DoubleBuffer b) {
@@ -420,6 +417,20 @@ public class BasicDouble
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -441,6 +452,22 @@ public class BasicDouble
         fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
     }
 
+    private static void catchIllegalArgument(Buffer b, Runnable thunk) {
+        tryCatch(b, IllegalArgumentException.class, thunk);
+    }
+
+    private static void catchReadOnlyBuffer(Buffer b, Runnable thunk) {
+        tryCatch(b, ReadOnlyBufferException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(Buffer b, Runnable thunk) {
+        tryCatch(b, IndexOutOfBoundsException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(double[] t, Runnable thunk) {
+        tryCatch(t, IndexOutOfBoundsException.class, thunk);
+    }
+
     private static void tryCatch(Buffer b, Class<?> ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -452,11 +479,12 @@ public class BasicDouble
                 fail(x.getMessage() + " not expected");
             }
         }
-        if (!caught)
+        if (!caught) {
             fail(ex.getName() + " not thrown", b);
+        }
     }
 
-    private static void tryCatch(double [] t, Class<?> ex, Runnable thunk) {
+    private static void tryCatch(double[] t, Class<?> ex, Runnable thunk) {
         tryCatch(DoubleBuffer.wrap(t), ex, thunk);
     }
 
@@ -518,8 +546,6 @@ public class BasicDouble
 
 
 
-
-
 
 
 
@@ -537,38 +563,14 @@ public class BasicDouble
         b.limit(b.capacity() / 2);
         b.position(b.limit());
 
-        tryCatch(b, BufferUnderflowException.class, new Runnable() {
-                public void run() {
-                    b.get();
-                }});
-
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-                public void run() {
-                    b.put((double)42);
-                }});
-
-        // The index must be non-negative and lesss than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.put(b.limit(), (double)42);
-                }});
-
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-                public void run() {
-                    b.position(0);
-                    b.mark();
-                    b.compact();
-                    b.reset();
-                }});
+        tryCatch(b, BufferUnderflowException.class, () -> b.get());
+        tryCatch(b, BufferOverflowException.class, () -> b.put((double)42));
+        // The index must be non-negative and less than the buffer's limit.
+        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
+        catchIndexOutOfBounds(b, () -> b.get(-1));
+        catchIndexOutOfBounds(b, () -> b.put(b.limit(), (double)42));
+        tryCatch(b, InvalidMarkException.class,
+                () -> b.position(0).mark().compact().reset());
 
         try {
             b.position(b.limit() + 1);
@@ -635,7 +637,6 @@ public class BasicDouble
         b.put(0.5121609353879392);      // Changes value if incorrectly swapped
 
 
-        double v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (double)-1);
@@ -654,13 +655,17 @@ public class BasicDouble
 
 
 
+
+
+        double v;
         ck(b, b.get(), -Double.MAX_VALUE);
         ck(b, b.get(), -Double.MIN_VALUE);
         ck(b, b.get(), Double.NEGATIVE_INFINITY);
         ck(b, b.get(), Double.POSITIVE_INFINITY);
         if (Double.doubleToRawLongBits(v = b.get())
-            != Double.doubleToRawLongBits(Double.NaN))
+            != Double.doubleToRawLongBits(Double.NaN)) {
             fail(b, (long)Double.NaN, (long)v);
+        }
         ck(b, b.get(), 0.5121609353879392);
 
 
@@ -683,14 +688,15 @@ public class BasicDouble
 
 
 
-                    )
+                    ) {
                     out.println("[" + i + "] " + x + " != " + y);
+                }
             }
             fail("Identical buffers not equal", b, b2);
         }
-        if (b.compareTo(b2) != 0)
+        if (b.compareTo(b2) != 0) {
             fail("Comparison to identical buffer != 0", b, b2);
-
+        }
         b.limit(b.limit() + 1);
         b.position(b.limit() - 1);
         b.put((double)99);
@@ -714,7 +720,7 @@ public class BasicDouble
             if (xb.compareTo(xb) != 0) {
                 fail("compareTo not reflexive", xb, xb, x, x);
             }
-            if (! xb.equals(xb)) {
+            if (!xb.equals(xb)) {
                 fail("equals not reflexive", xb, xb, x, x);
             }
             for (double y : VALUES) {
@@ -765,9 +771,10 @@ public class BasicDouble
 
         if (!sb.equals(sb2))
             fail("Sliced slices do not match", sb, sb2);
-        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
+        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) {
             fail("Array offsets do not match: "
                  + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
+        }
 
 
 
@@ -808,87 +815,17 @@ public class BasicDouble
             fail("Buffer not equal to read-only view", b, rb);
         show(level + 1, rb);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    relPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    absPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutArray(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutBuffer(rb);
-                }});
+        catchReadOnlyBuffer(b, () -> relPut(rb));
+        catchReadOnlyBuffer(b, () -> absPut(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutArray(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutBuffer(rb));
 
         // put(DoubleBuffer) should not change source position
         final DoubleBuffer src = DoubleBuffer.allocate(1);
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.put(src);
-                 }});
+        catchReadOnlyBuffer(b, () -> rb.put(src));
         ck(src, src.position(), 0);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.compact();
-                }});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+        catchReadOnlyBuffer(b, () -> rb.compact());
 
 
 
@@ -916,21 +853,11 @@ public class BasicDouble
 
 
         if (rb.getClass().getName().startsWith("java.nio.Heap")) {
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.array();
-                    }});
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.arrayOffset();
-                    }});
-
-            if (rb.hasArray())
-                fail("Read-only heap buffer's backing array is accessible",
-                     rb);
-
+            catchReadOnlyBuffer(b, () -> rb.array());
+            catchReadOnlyBuffer(b, () -> rb.arrayOffset());
+            if (rb.hasArray()) {
+                fail("Read-only heap buffer's backing array is accessible", rb);
+            }
         }
 
         // Bulk puts from read-only buffers
@@ -980,47 +907,6 @@ public class BasicDouble
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
@@ -1052,40 +938,21 @@ public class BasicDouble
         ck(b, b.limit(), offset + length);
 
         // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    DoubleBuffer.wrap(ba, -1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    DoubleBuffer.wrap(ba, ba.length + 1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    DoubleBuffer.wrap(ba, 0, -1);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    DoubleBuffer.wrap(ba, 0, ba.length + 1);
-                }});
+        catchIndexOutOfBounds(ba, () -> DoubleBuffer.wrap(ba, -1, ba.length));
+        catchIndexOutOfBounds(ba, () -> DoubleBuffer.wrap(ba, ba.length + 1, ba.length));
+        catchIndexOutOfBounds(ba, () -> DoubleBuffer.wrap(ba, 0, -1));
+        catchIndexOutOfBounds(ba, () -> DoubleBuffer.wrap(ba, 0, ba.length + 1));
 
         // A NullPointerException will be thrown if the array is null.
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    DoubleBuffer.wrap((double []) null, 0, 5);
-                }});
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    DoubleBuffer.wrap((double []) null);
-                }});
+        tryCatch(ba, NullPointerException.class,
+                () -> DoubleBuffer.wrap((double []) null, 0, 5));
+        tryCatch(ba, NullPointerException.class,
+                () -> DoubleBuffer.wrap((double []) null));
     }
 
     private static void testAllocate() {
         // An IllegalArgumentException will be thrown for negative capacities.
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    DoubleBuffer.allocate(-1);
-                }});
+        catchIllegalArgument((Buffer) null, () -> DoubleBuffer.allocate(-1));
         try {
             DoubleBuffer.allocate(-1);
         } catch (IllegalArgumentException e) {
@@ -1105,9 +972,6 @@ public class BasicDouble
 
 
 
-
-
-
     }
 
     public static void test() {
diff --git a/jdk/test/java/nio/Buffer/BasicFloat.java b/jdk/test/java/nio/Buffer/BasicFloat.java
index c4d42867b2b..8f1d950d19c 100644
--- a/jdk/test/java/nio/Buffer/BasicFloat.java
+++ b/jdk/test/java/nio/Buffer/BasicFloat.java
@@ -31,7 +31,6 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
-import java.lang.reflect.Method;
 
 
 public class BasicFloat
@@ -60,7 +59,6 @@ public class BasicFloat
 
     private static void relGet(FloatBuffer b) {
         int n = b.capacity();
-        float v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((float)ic(i)));
         b.rewind();
@@ -68,7 +66,6 @@ public class BasicFloat
 
     private static void relGet(FloatBuffer b, int start) {
         int n = b.remaining();
-        float v;
         for (int i = start; i < n; i++)
             ck(b, (long)b.get(), (long)((float)ic(i)));
         b.rewind();
@@ -76,7 +73,6 @@ public class BasicFloat
 
     private static void absGet(FloatBuffer b) {
         int n = b.capacity();
-        float v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((float)ic(i)));
         b.rewind();
@@ -86,8 +82,9 @@ public class BasicFloat
         int n = b.capacity();
         float[] a = new float[n + 7];
         b.get(a, 7, n);
-        for (int i = 0; i < n; i++)
+        for (int i = 0; i < n; i++) {
             ck(b, (long)a[i + 7], (long)((float)ic(i)));
+        }
     }
 
     private static void relPut(FloatBuffer b) {
@@ -420,6 +417,20 @@ public class BasicFloat
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -441,6 +452,22 @@ public class BasicFloat
         fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
     }
 
+    private static void catchIllegalArgument(Buffer b, Runnable thunk) {
+        tryCatch(b, IllegalArgumentException.class, thunk);
+    }
+
+    private static void catchReadOnlyBuffer(Buffer b, Runnable thunk) {
+        tryCatch(b, ReadOnlyBufferException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(Buffer b, Runnable thunk) {
+        tryCatch(b, IndexOutOfBoundsException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(float[] t, Runnable thunk) {
+        tryCatch(t, IndexOutOfBoundsException.class, thunk);
+    }
+
     private static void tryCatch(Buffer b, Class<?> ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -452,11 +479,12 @@ public class BasicFloat
                 fail(x.getMessage() + " not expected");
             }
         }
-        if (!caught)
+        if (!caught) {
             fail(ex.getName() + " not thrown", b);
+        }
     }
 
-    private static void tryCatch(float [] t, Class<?> ex, Runnable thunk) {
+    private static void tryCatch(float[] t, Class<?> ex, Runnable thunk) {
         tryCatch(FloatBuffer.wrap(t), ex, thunk);
     }
 
@@ -518,8 +546,6 @@ public class BasicFloat
 
 
 
-
-
 
 
 
@@ -537,38 +563,14 @@ public class BasicFloat
         b.limit(b.capacity() / 2);
         b.position(b.limit());
 
-        tryCatch(b, BufferUnderflowException.class, new Runnable() {
-                public void run() {
-                    b.get();
-                }});
-
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-                public void run() {
-                    b.put((float)42);
-                }});
-
-        // The index must be non-negative and lesss than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.put(b.limit(), (float)42);
-                }});
-
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-                public void run() {
-                    b.position(0);
-                    b.mark();
-                    b.compact();
-                    b.reset();
-                }});
+        tryCatch(b, BufferUnderflowException.class, () -> b.get());
+        tryCatch(b, BufferOverflowException.class, () -> b.put((float)42));
+        // The index must be non-negative and less than the buffer's limit.
+        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
+        catchIndexOutOfBounds(b, () -> b.get(-1));
+        catchIndexOutOfBounds(b, () -> b.put(b.limit(), (float)42));
+        tryCatch(b, InvalidMarkException.class,
+                () -> b.position(0).mark().compact().reset());
 
         try {
             b.position(b.limit() + 1);
@@ -635,7 +637,6 @@ public class BasicFloat
 
 
 
-        float v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (float)-1);
@@ -644,13 +645,15 @@ public class BasicFloat
         ck(b, b.get(), Float.MIN_VALUE);
 
 
+        float v;
         ck(b, b.get(), -Float.MAX_VALUE);
         ck(b, b.get(), -Float.MIN_VALUE);
         ck(b, b.get(), Float.NEGATIVE_INFINITY);
         ck(b, b.get(), Float.POSITIVE_INFINITY);
         if (Float.floatToRawIntBits(v = b.get()) !=
-            Float.floatToRawIntBits(Float.NaN))
+            Float.floatToRawIntBits(Float.NaN)) {
             fail(b, (long)Float.NaN, (long)v);
+        }
         ck(b, b.get(), 0.91697687f);
 
 
@@ -665,6 +668,8 @@ public class BasicFloat
 
 
 
+
+
         // Comparison
         b.rewind();
         FloatBuffer b2 = FloatBuffer.allocate(b.capacity());
@@ -683,14 +688,15 @@ public class BasicFloat
 
                     || Float.compare(x, y) != 0
 
-                    )
+                    ) {
                     out.println("[" + i + "] " + x + " != " + y);
+                }
             }
             fail("Identical buffers not equal", b, b2);
         }
-        if (b.compareTo(b2) != 0)
+        if (b.compareTo(b2) != 0) {
             fail("Comparison to identical buffer != 0", b, b2);
-
+        }
         b.limit(b.limit() + 1);
         b.position(b.limit() - 1);
         b.put((float)99);
@@ -714,7 +720,7 @@ public class BasicFloat
             if (xb.compareTo(xb) != 0) {
                 fail("compareTo not reflexive", xb, xb, x, x);
             }
-            if (! xb.equals(xb)) {
+            if (!xb.equals(xb)) {
                 fail("equals not reflexive", xb, xb, x, x);
             }
             for (float y : VALUES) {
@@ -765,9 +771,10 @@ public class BasicFloat
 
         if (!sb.equals(sb2))
             fail("Sliced slices do not match", sb, sb2);
-        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
+        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) {
             fail("Array offsets do not match: "
                  + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
+        }
 
 
 
@@ -808,87 +815,17 @@ public class BasicFloat
             fail("Buffer not equal to read-only view", b, rb);
         show(level + 1, rb);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    relPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    absPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutArray(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutBuffer(rb);
-                }});
+        catchReadOnlyBuffer(b, () -> relPut(rb));
+        catchReadOnlyBuffer(b, () -> absPut(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutArray(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutBuffer(rb));
 
         // put(FloatBuffer) should not change source position
         final FloatBuffer src = FloatBuffer.allocate(1);
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.put(src);
-                 }});
+        catchReadOnlyBuffer(b, () -> rb.put(src));
         ck(src, src.position(), 0);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.compact();
-                }});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+        catchReadOnlyBuffer(b, () -> rb.compact());
 
 
 
@@ -916,21 +853,11 @@ public class BasicFloat
 
 
         if (rb.getClass().getName().startsWith("java.nio.Heap")) {
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.array();
-                    }});
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.arrayOffset();
-                    }});
-
-            if (rb.hasArray())
-                fail("Read-only heap buffer's backing array is accessible",
-                     rb);
-
+            catchReadOnlyBuffer(b, () -> rb.array());
+            catchReadOnlyBuffer(b, () -> rb.arrayOffset());
+            if (rb.hasArray()) {
+                fail("Read-only heap buffer's backing array is accessible", rb);
+            }
         }
 
         // Bulk puts from read-only buffers
@@ -980,47 +907,6 @@ public class BasicFloat
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
@@ -1052,40 +938,21 @@ public class BasicFloat
         ck(b, b.limit(), offset + length);
 
         // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    FloatBuffer.wrap(ba, -1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    FloatBuffer.wrap(ba, ba.length + 1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    FloatBuffer.wrap(ba, 0, -1);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    FloatBuffer.wrap(ba, 0, ba.length + 1);
-                }});
+        catchIndexOutOfBounds(ba, () -> FloatBuffer.wrap(ba, -1, ba.length));
+        catchIndexOutOfBounds(ba, () -> FloatBuffer.wrap(ba, ba.length + 1, ba.length));
+        catchIndexOutOfBounds(ba, () -> FloatBuffer.wrap(ba, 0, -1));
+        catchIndexOutOfBounds(ba, () -> FloatBuffer.wrap(ba, 0, ba.length + 1));
 
         // A NullPointerException will be thrown if the array is null.
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    FloatBuffer.wrap((float []) null, 0, 5);
-                }});
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    FloatBuffer.wrap((float []) null);
-                }});
+        tryCatch(ba, NullPointerException.class,
+                () -> FloatBuffer.wrap((float []) null, 0, 5));
+        tryCatch(ba, NullPointerException.class,
+                () -> FloatBuffer.wrap((float []) null));
     }
 
     private static void testAllocate() {
         // An IllegalArgumentException will be thrown for negative capacities.
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    FloatBuffer.allocate(-1);
-                }});
+        catchIllegalArgument((Buffer) null, () -> FloatBuffer.allocate(-1));
         try {
             FloatBuffer.allocate(-1);
         } catch (IllegalArgumentException e) {
@@ -1105,9 +972,6 @@ public class BasicFloat
 
 
 
-
-
-
     }
 
     public static void test() {
diff --git a/jdk/test/java/nio/Buffer/BasicInt.java b/jdk/test/java/nio/Buffer/BasicInt.java
index 46ad7578d24..71632f407ef 100644
--- a/jdk/test/java/nio/Buffer/BasicInt.java
+++ b/jdk/test/java/nio/Buffer/BasicInt.java
@@ -31,7 +31,6 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
-import java.lang.reflect.Method;
 
 
 public class BasicInt
@@ -60,7 +59,6 @@ public class BasicInt
 
     private static void relGet(IntBuffer b) {
         int n = b.capacity();
-        int v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((int)ic(i)));
         b.rewind();
@@ -68,7 +66,6 @@ public class BasicInt
 
     private static void relGet(IntBuffer b, int start) {
         int n = b.remaining();
-        int v;
         for (int i = start; i < n; i++)
             ck(b, (long)b.get(), (long)((int)ic(i)));
         b.rewind();
@@ -76,7 +73,6 @@ public class BasicInt
 
     private static void absGet(IntBuffer b) {
         int n = b.capacity();
-        int v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((int)ic(i)));
         b.rewind();
@@ -86,8 +82,9 @@ public class BasicInt
         int n = b.capacity();
         int[] a = new int[n + 7];
         b.get(a, 7, n);
-        for (int i = 0; i < n; i++)
+        for (int i = 0; i < n; i++) {
             ck(b, (long)a[i + 7], (long)((int)ic(i)));
+        }
     }
 
     private static void relPut(IntBuffer b) {
@@ -420,6 +417,20 @@ public class BasicInt
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -441,6 +452,22 @@ public class BasicInt
         fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
     }
 
+    private static void catchIllegalArgument(Buffer b, Runnable thunk) {
+        tryCatch(b, IllegalArgumentException.class, thunk);
+    }
+
+    private static void catchReadOnlyBuffer(Buffer b, Runnable thunk) {
+        tryCatch(b, ReadOnlyBufferException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(Buffer b, Runnable thunk) {
+        tryCatch(b, IndexOutOfBoundsException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(int[] t, Runnable thunk) {
+        tryCatch(t, IndexOutOfBoundsException.class, thunk);
+    }
+
     private static void tryCatch(Buffer b, Class<?> ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -452,11 +479,12 @@ public class BasicInt
                 fail(x.getMessage() + " not expected");
             }
         }
-        if (!caught)
+        if (!caught) {
             fail(ex.getName() + " not thrown", b);
+        }
     }
 
-    private static void tryCatch(int [] t, Class<?> ex, Runnable thunk) {
+    private static void tryCatch(int[] t, Class<?> ex, Runnable thunk) {
         tryCatch(IntBuffer.wrap(t), ex, thunk);
     }
 
@@ -518,8 +546,6 @@ public class BasicInt
 
 
 
-
-
 
 
 
@@ -537,38 +563,14 @@ public class BasicInt
         b.limit(b.capacity() / 2);
         b.position(b.limit());
 
-        tryCatch(b, BufferUnderflowException.class, new Runnable() {
-                public void run() {
-                    b.get();
-                }});
-
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-                public void run() {
-                    b.put((int)42);
-                }});
-
-        // The index must be non-negative and lesss than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.put(b.limit(), (int)42);
-                }});
-
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-                public void run() {
-                    b.position(0);
-                    b.mark();
-                    b.compact();
-                    b.reset();
-                }});
+        tryCatch(b, BufferUnderflowException.class, () -> b.get());
+        tryCatch(b, BufferOverflowException.class, () -> b.put((int)42));
+        // The index must be non-negative and less than the buffer's limit.
+        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
+        catchIndexOutOfBounds(b, () -> b.get(-1));
+        catchIndexOutOfBounds(b, () -> b.put(b.limit(), (int)42));
+        tryCatch(b, InvalidMarkException.class,
+                () -> b.position(0).mark().compact().reset());
 
         try {
             b.position(b.limit() + 1);
@@ -635,7 +637,6 @@ public class BasicInt
 
 
 
-        int v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (int)-1);
@@ -660,6 +661,10 @@ public class BasicInt
 
 
 
+
+
+
+
 
 
 
@@ -683,14 +688,15 @@ public class BasicInt
 
 
 
-                    )
+                    ) {
                     out.println("[" + i + "] " + x + " != " + y);
+                }
             }
             fail("Identical buffers not equal", b, b2);
         }
-        if (b.compareTo(b2) != 0)
+        if (b.compareTo(b2) != 0) {
             fail("Comparison to identical buffer != 0", b, b2);
-
+        }
         b.limit(b.limit() + 1);
         b.position(b.limit() - 1);
         b.put((int)99);
@@ -714,7 +720,7 @@ public class BasicInt
             if (xb.compareTo(xb) != 0) {
                 fail("compareTo not reflexive", xb, xb, x, x);
             }
-            if (! xb.equals(xb)) {
+            if (!xb.equals(xb)) {
                 fail("equals not reflexive", xb, xb, x, x);
             }
             for (int y : VALUES) {
@@ -765,9 +771,10 @@ public class BasicInt
 
         if (!sb.equals(sb2))
             fail("Sliced slices do not match", sb, sb2);
-        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
+        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) {
             fail("Array offsets do not match: "
                  + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
+        }
 
 
 
@@ -808,87 +815,17 @@ public class BasicInt
             fail("Buffer not equal to read-only view", b, rb);
         show(level + 1, rb);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    relPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    absPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutArray(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutBuffer(rb);
-                }});
+        catchReadOnlyBuffer(b, () -> relPut(rb));
+        catchReadOnlyBuffer(b, () -> absPut(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutArray(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutBuffer(rb));
 
         // put(IntBuffer) should not change source position
         final IntBuffer src = IntBuffer.allocate(1);
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.put(src);
-                 }});
+        catchReadOnlyBuffer(b, () -> rb.put(src));
         ck(src, src.position(), 0);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.compact();
-                }});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+        catchReadOnlyBuffer(b, () -> rb.compact());
 
 
 
@@ -916,21 +853,11 @@ public class BasicInt
 
 
         if (rb.getClass().getName().startsWith("java.nio.Heap")) {
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.array();
-                    }});
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.arrayOffset();
-                    }});
-
-            if (rb.hasArray())
-                fail("Read-only heap buffer's backing array is accessible",
-                     rb);
-
+            catchReadOnlyBuffer(b, () -> rb.array());
+            catchReadOnlyBuffer(b, () -> rb.arrayOffset());
+            if (rb.hasArray()) {
+                fail("Read-only heap buffer's backing array is accessible", rb);
+            }
         }
 
         // Bulk puts from read-only buffers
@@ -980,47 +907,6 @@ public class BasicInt
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
@@ -1052,40 +938,21 @@ public class BasicInt
         ck(b, b.limit(), offset + length);
 
         // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    IntBuffer.wrap(ba, -1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    IntBuffer.wrap(ba, ba.length + 1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    IntBuffer.wrap(ba, 0, -1);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    IntBuffer.wrap(ba, 0, ba.length + 1);
-                }});
+        catchIndexOutOfBounds(ba, () -> IntBuffer.wrap(ba, -1, ba.length));
+        catchIndexOutOfBounds(ba, () -> IntBuffer.wrap(ba, ba.length + 1, ba.length));
+        catchIndexOutOfBounds(ba, () -> IntBuffer.wrap(ba, 0, -1));
+        catchIndexOutOfBounds(ba, () -> IntBuffer.wrap(ba, 0, ba.length + 1));
 
         // A NullPointerException will be thrown if the array is null.
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    IntBuffer.wrap((int []) null, 0, 5);
-                }});
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    IntBuffer.wrap((int []) null);
-                }});
+        tryCatch(ba, NullPointerException.class,
+                () -> IntBuffer.wrap((int []) null, 0, 5));
+        tryCatch(ba, NullPointerException.class,
+                () -> IntBuffer.wrap((int []) null));
     }
 
     private static void testAllocate() {
         // An IllegalArgumentException will be thrown for negative capacities.
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    IntBuffer.allocate(-1);
-                }});
+        catchIllegalArgument((Buffer) null, () -> IntBuffer.allocate(-1));
         try {
             IntBuffer.allocate(-1);
         } catch (IllegalArgumentException e) {
@@ -1105,9 +972,6 @@ public class BasicInt
 
 
 
-
-
-
     }
 
     public static void test() {
diff --git a/jdk/test/java/nio/Buffer/BasicLong.java b/jdk/test/java/nio/Buffer/BasicLong.java
index d3a0ff98c10..a7310c3c66d 100644
--- a/jdk/test/java/nio/Buffer/BasicLong.java
+++ b/jdk/test/java/nio/Buffer/BasicLong.java
@@ -31,7 +31,6 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
-import java.lang.reflect.Method;
 
 
 public class BasicLong
@@ -60,7 +59,6 @@ public class BasicLong
 
     private static void relGet(LongBuffer b) {
         int n = b.capacity();
-        long v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((long)ic(i)));
         b.rewind();
@@ -68,7 +66,6 @@ public class BasicLong
 
     private static void relGet(LongBuffer b, int start) {
         int n = b.remaining();
-        long v;
         for (int i = start; i < n; i++)
             ck(b, (long)b.get(), (long)((long)ic(i)));
         b.rewind();
@@ -76,7 +73,6 @@ public class BasicLong
 
     private static void absGet(LongBuffer b) {
         int n = b.capacity();
-        long v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((long)ic(i)));
         b.rewind();
@@ -86,8 +82,9 @@ public class BasicLong
         int n = b.capacity();
         long[] a = new long[n + 7];
         b.get(a, 7, n);
-        for (int i = 0; i < n; i++)
+        for (int i = 0; i < n; i++) {
             ck(b, (long)a[i + 7], (long)((long)ic(i)));
+        }
     }
 
     private static void relPut(LongBuffer b) {
@@ -420,6 +417,20 @@ public class BasicLong
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -441,6 +452,22 @@ public class BasicLong
         fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
     }
 
+    private static void catchIllegalArgument(Buffer b, Runnable thunk) {
+        tryCatch(b, IllegalArgumentException.class, thunk);
+    }
+
+    private static void catchReadOnlyBuffer(Buffer b, Runnable thunk) {
+        tryCatch(b, ReadOnlyBufferException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(Buffer b, Runnable thunk) {
+        tryCatch(b, IndexOutOfBoundsException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(long[] t, Runnable thunk) {
+        tryCatch(t, IndexOutOfBoundsException.class, thunk);
+    }
+
     private static void tryCatch(Buffer b, Class<?> ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -452,11 +479,12 @@ public class BasicLong
                 fail(x.getMessage() + " not expected");
             }
         }
-        if (!caught)
+        if (!caught) {
             fail(ex.getName() + " not thrown", b);
+        }
     }
 
-    private static void tryCatch(long [] t, Class<?> ex, Runnable thunk) {
+    private static void tryCatch(long[] t, Class<?> ex, Runnable thunk) {
         tryCatch(LongBuffer.wrap(t), ex, thunk);
     }
 
@@ -518,8 +546,6 @@ public class BasicLong
 
 
 
-
-
 
 
 
@@ -537,38 +563,14 @@ public class BasicLong
         b.limit(b.capacity() / 2);
         b.position(b.limit());
 
-        tryCatch(b, BufferUnderflowException.class, new Runnable() {
-                public void run() {
-                    b.get();
-                }});
-
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-                public void run() {
-                    b.put((long)42);
-                }});
-
-        // The index must be non-negative and lesss than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.put(b.limit(), (long)42);
-                }});
-
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-                public void run() {
-                    b.position(0);
-                    b.mark();
-                    b.compact();
-                    b.reset();
-                }});
+        tryCatch(b, BufferUnderflowException.class, () -> b.get());
+        tryCatch(b, BufferOverflowException.class, () -> b.put((long)42));
+        // The index must be non-negative and less than the buffer's limit.
+        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
+        catchIndexOutOfBounds(b, () -> b.get(-1));
+        catchIndexOutOfBounds(b, () -> b.put(b.limit(), (long)42));
+        tryCatch(b, InvalidMarkException.class,
+                () -> b.position(0).mark().compact().reset());
 
         try {
             b.position(b.limit() + 1);
@@ -635,7 +637,6 @@ public class BasicLong
 
 
 
-        long v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (long)-1);
@@ -660,6 +661,10 @@ public class BasicLong
 
 
 
+
+
+
+
 
 
 
@@ -683,14 +688,15 @@ public class BasicLong
 
 
 
-                    )
+                    ) {
                     out.println("[" + i + "] " + x + " != " + y);
+                }
             }
             fail("Identical buffers not equal", b, b2);
         }
-        if (b.compareTo(b2) != 0)
+        if (b.compareTo(b2) != 0) {
             fail("Comparison to identical buffer != 0", b, b2);
-
+        }
         b.limit(b.limit() + 1);
         b.position(b.limit() - 1);
         b.put((long)99);
@@ -714,7 +720,7 @@ public class BasicLong
             if (xb.compareTo(xb) != 0) {
                 fail("compareTo not reflexive", xb, xb, x, x);
             }
-            if (! xb.equals(xb)) {
+            if (!xb.equals(xb)) {
                 fail("equals not reflexive", xb, xb, x, x);
             }
             for (long y : VALUES) {
@@ -765,9 +771,10 @@ public class BasicLong
 
         if (!sb.equals(sb2))
             fail("Sliced slices do not match", sb, sb2);
-        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
+        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) {
             fail("Array offsets do not match: "
                  + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
+        }
 
 
 
@@ -808,87 +815,17 @@ public class BasicLong
             fail("Buffer not equal to read-only view", b, rb);
         show(level + 1, rb);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    relPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    absPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutArray(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutBuffer(rb);
-                }});
+        catchReadOnlyBuffer(b, () -> relPut(rb));
+        catchReadOnlyBuffer(b, () -> absPut(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutArray(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutBuffer(rb));
 
         // put(LongBuffer) should not change source position
         final LongBuffer src = LongBuffer.allocate(1);
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.put(src);
-                 }});
+        catchReadOnlyBuffer(b, () -> rb.put(src));
         ck(src, src.position(), 0);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.compact();
-                }});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+        catchReadOnlyBuffer(b, () -> rb.compact());
 
 
 
@@ -916,21 +853,11 @@ public class BasicLong
 
 
         if (rb.getClass().getName().startsWith("java.nio.Heap")) {
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.array();
-                    }});
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.arrayOffset();
-                    }});
-
-            if (rb.hasArray())
-                fail("Read-only heap buffer's backing array is accessible",
-                     rb);
-
+            catchReadOnlyBuffer(b, () -> rb.array());
+            catchReadOnlyBuffer(b, () -> rb.arrayOffset());
+            if (rb.hasArray()) {
+                fail("Read-only heap buffer's backing array is accessible", rb);
+            }
         }
 
         // Bulk puts from read-only buffers
@@ -980,47 +907,6 @@ public class BasicLong
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
@@ -1052,40 +938,21 @@ public class BasicLong
         ck(b, b.limit(), offset + length);
 
         // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    LongBuffer.wrap(ba, -1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    LongBuffer.wrap(ba, ba.length + 1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    LongBuffer.wrap(ba, 0, -1);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    LongBuffer.wrap(ba, 0, ba.length + 1);
-                }});
+        catchIndexOutOfBounds(ba, () -> LongBuffer.wrap(ba, -1, ba.length));
+        catchIndexOutOfBounds(ba, () -> LongBuffer.wrap(ba, ba.length + 1, ba.length));
+        catchIndexOutOfBounds(ba, () -> LongBuffer.wrap(ba, 0, -1));
+        catchIndexOutOfBounds(ba, () -> LongBuffer.wrap(ba, 0, ba.length + 1));
 
         // A NullPointerException will be thrown if the array is null.
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    LongBuffer.wrap((long []) null, 0, 5);
-                }});
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    LongBuffer.wrap((long []) null);
-                }});
+        tryCatch(ba, NullPointerException.class,
+                () -> LongBuffer.wrap((long []) null, 0, 5));
+        tryCatch(ba, NullPointerException.class,
+                () -> LongBuffer.wrap((long []) null));
     }
 
     private static void testAllocate() {
         // An IllegalArgumentException will be thrown for negative capacities.
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    LongBuffer.allocate(-1);
-                }});
+        catchIllegalArgument((Buffer) null, () -> LongBuffer.allocate(-1));
         try {
             LongBuffer.allocate(-1);
         } catch (IllegalArgumentException e) {
@@ -1105,9 +972,6 @@ public class BasicLong
 
 
 
-
-
-
     }
 
     public static void test() {
diff --git a/jdk/test/java/nio/Buffer/BasicShort.java b/jdk/test/java/nio/Buffer/BasicShort.java
index eef47f23e21..5d94bf2b15f 100644
--- a/jdk/test/java/nio/Buffer/BasicShort.java
+++ b/jdk/test/java/nio/Buffer/BasicShort.java
@@ -31,7 +31,6 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
-import java.lang.reflect.Method;
 
 
 public class BasicShort
@@ -60,7 +59,6 @@ public class BasicShort
 
     private static void relGet(ShortBuffer b) {
         int n = b.capacity();
-        short v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((short)ic(i)));
         b.rewind();
@@ -68,7 +66,6 @@ public class BasicShort
 
     private static void relGet(ShortBuffer b, int start) {
         int n = b.remaining();
-        short v;
         for (int i = start; i < n; i++)
             ck(b, (long)b.get(), (long)((short)ic(i)));
         b.rewind();
@@ -76,7 +73,6 @@ public class BasicShort
 
     private static void absGet(ShortBuffer b) {
         int n = b.capacity();
-        short v;
         for (int i = 0; i < n; i++)
             ck(b, (long)b.get(), (long)((short)ic(i)));
         b.rewind();
@@ -86,8 +82,9 @@ public class BasicShort
         int n = b.capacity();
         short[] a = new short[n + 7];
         b.get(a, 7, n);
-        for (int i = 0; i < n; i++)
+        for (int i = 0; i < n; i++) {
             ck(b, (long)a[i + 7], (long)((short)ic(i)));
+        }
     }
 
     private static void relPut(ShortBuffer b) {
@@ -420,6 +417,20 @@ public class BasicShort
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -441,6 +452,22 @@ public class BasicShort
         fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
     }
 
+    private static void catchIllegalArgument(Buffer b, Runnable thunk) {
+        tryCatch(b, IllegalArgumentException.class, thunk);
+    }
+
+    private static void catchReadOnlyBuffer(Buffer b, Runnable thunk) {
+        tryCatch(b, ReadOnlyBufferException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(Buffer b, Runnable thunk) {
+        tryCatch(b, IndexOutOfBoundsException.class, thunk);
+    }
+
+    private static void catchIndexOutOfBounds(short[] t, Runnable thunk) {
+        tryCatch(t, IndexOutOfBoundsException.class, thunk);
+    }
+
     private static void tryCatch(Buffer b, Class<?> ex, Runnable thunk) {
         boolean caught = false;
         try {
@@ -452,11 +479,12 @@ public class BasicShort
                 fail(x.getMessage() + " not expected");
             }
         }
-        if (!caught)
+        if (!caught) {
             fail(ex.getName() + " not thrown", b);
+        }
     }
 
-    private static void tryCatch(short [] t, Class<?> ex, Runnable thunk) {
+    private static void tryCatch(short[] t, Class<?> ex, Runnable thunk) {
         tryCatch(ShortBuffer.wrap(t), ex, thunk);
     }
 
@@ -518,8 +546,6 @@ public class BasicShort
 
 
 
-
-
 
 
 
@@ -537,38 +563,14 @@ public class BasicShort
         b.limit(b.capacity() / 2);
         b.position(b.limit());
 
-        tryCatch(b, BufferUnderflowException.class, new Runnable() {
-                public void run() {
-                    b.get();
-                }});
-
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-                public void run() {
-                    b.put((short)42);
-                }});
-
-        // The index must be non-negative and lesss than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.put(b.limit(), (short)42);
-                }});
-
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-                public void run() {
-                    b.position(0);
-                    b.mark();
-                    b.compact();
-                    b.reset();
-                }});
+        tryCatch(b, BufferUnderflowException.class, () -> b.get());
+        tryCatch(b, BufferOverflowException.class, () -> b.put((short)42));
+        // The index must be non-negative and less than the buffer's limit.
+        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
+        catchIndexOutOfBounds(b, () -> b.get(-1));
+        catchIndexOutOfBounds(b, () -> b.put(b.limit(), (short)42));
+        tryCatch(b, InvalidMarkException.class,
+                () -> b.position(0).mark().compact().reset());
 
         try {
             b.position(b.limit() + 1);
@@ -635,7 +637,6 @@ public class BasicShort
 
 
 
-        short v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (short)-1);
@@ -660,6 +661,10 @@ public class BasicShort
 
 
 
+
+
+
+
 
 
 
@@ -683,14 +688,15 @@ public class BasicShort
 
 
 
-                    )
+                    ) {
                     out.println("[" + i + "] " + x + " != " + y);
+                }
             }
             fail("Identical buffers not equal", b, b2);
         }
-        if (b.compareTo(b2) != 0)
+        if (b.compareTo(b2) != 0) {
             fail("Comparison to identical buffer != 0", b, b2);
-
+        }
         b.limit(b.limit() + 1);
         b.position(b.limit() - 1);
         b.put((short)99);
@@ -714,7 +720,7 @@ public class BasicShort
             if (xb.compareTo(xb) != 0) {
                 fail("compareTo not reflexive", xb, xb, x, x);
             }
-            if (! xb.equals(xb)) {
+            if (!xb.equals(xb)) {
                 fail("equals not reflexive", xb, xb, x, x);
             }
             for (short y : VALUES) {
@@ -765,9 +771,10 @@ public class BasicShort
 
         if (!sb.equals(sb2))
             fail("Sliced slices do not match", sb, sb2);
-        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
+        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) {
             fail("Array offsets do not match: "
                  + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
+        }
 
 
 
@@ -808,87 +815,17 @@ public class BasicShort
             fail("Buffer not equal to read-only view", b, rb);
         show(level + 1, rb);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    relPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    absPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutArray(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutBuffer(rb);
-                }});
+        catchReadOnlyBuffer(b, () -> relPut(rb));
+        catchReadOnlyBuffer(b, () -> absPut(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutArray(rb));
+        catchReadOnlyBuffer(b, () -> bulkPutBuffer(rb));
 
         // put(ShortBuffer) should not change source position
         final ShortBuffer src = ShortBuffer.allocate(1);
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.put(src);
-                 }});
+        catchReadOnlyBuffer(b, () -> rb.put(src));
         ck(src, src.position(), 0);
 
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.compact();
-                }});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+        catchReadOnlyBuffer(b, () -> rb.compact());
 
 
 
@@ -916,21 +853,11 @@ public class BasicShort
 
 
         if (rb.getClass().getName().startsWith("java.nio.Heap")) {
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.array();
-                    }});
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.arrayOffset();
-                    }});
-
-            if (rb.hasArray())
-                fail("Read-only heap buffer's backing array is accessible",
-                     rb);
-
+            catchReadOnlyBuffer(b, () -> rb.array());
+            catchReadOnlyBuffer(b, () -> rb.arrayOffset());
+            if (rb.hasArray()) {
+                fail("Read-only heap buffer's backing array is accessible", rb);
+            }
         }
 
         // Bulk puts from read-only buffers
@@ -980,47 +907,6 @@ public class BasicShort
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
@@ -1052,40 +938,21 @@ public class BasicShort
         ck(b, b.limit(), offset + length);
 
         // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    ShortBuffer.wrap(ba, -1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    ShortBuffer.wrap(ba, ba.length + 1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    ShortBuffer.wrap(ba, 0, -1);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    ShortBuffer.wrap(ba, 0, ba.length + 1);
-                }});
+        catchIndexOutOfBounds(ba, () -> ShortBuffer.wrap(ba, -1, ba.length));
+        catchIndexOutOfBounds(ba, () -> ShortBuffer.wrap(ba, ba.length + 1, ba.length));
+        catchIndexOutOfBounds(ba, () -> ShortBuffer.wrap(ba, 0, -1));
+        catchIndexOutOfBounds(ba, () -> ShortBuffer.wrap(ba, 0, ba.length + 1));
 
         // A NullPointerException will be thrown if the array is null.
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    ShortBuffer.wrap((short []) null, 0, 5);
-                }});
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    ShortBuffer.wrap((short []) null);
-                }});
+        tryCatch(ba, NullPointerException.class,
+                () -> ShortBuffer.wrap((short []) null, 0, 5));
+        tryCatch(ba, NullPointerException.class,
+                () -> ShortBuffer.wrap((short []) null));
     }
 
     private static void testAllocate() {
         // An IllegalArgumentException will be thrown for negative capacities.
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    ShortBuffer.allocate(-1);
-                }});
+        catchIllegalArgument((Buffer) null, () -> ShortBuffer.allocate(-1));
         try {
             ShortBuffer.allocate(-1);
         } catch (IllegalArgumentException e) {
@@ -1105,9 +972,6 @@ public class BasicShort
 
 
 
-
-
-
     }
 
     public static void test() {
diff --git a/jdk/test/java/nio/Buffer/LimitDirectMemory.java b/jdk/test/java/nio/Buffer/LimitDirectMemory.java
index 597e4d9c093..e8a22b4b89c 100644
--- a/jdk/test/java/nio/Buffer/LimitDirectMemory.java
+++ b/jdk/test/java/nio/Buffer/LimitDirectMemory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2010, 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
@@ -25,7 +25,7 @@ import java.nio.ByteBuffer;
 import java.util.Properties;
 
 public class LimitDirectMemory {
-    private static int K = 1024;
+    private static final int K = 1024;
 
     public static void main(String [] args) throws Exception {
         if (args.length < 2)
@@ -83,7 +83,7 @@ public class LimitDirectMemory {
 
         int idx = 0, len = size.length();
 
-        int result = 1;
+
         for (int i = 0; i < len; i++) {
             if (Character.isDigit(size.charAt(i))) idx++;
             else break;
@@ -92,7 +92,7 @@ public class LimitDirectMemory {
         if (idx == 0)
             throw new RuntimeException("No digits detected: " + size);
 
-        result = Integer.parseInt(size.substring(0, idx));
+        int result = Integer.parseInt(size.substring(0, idx));
 
         if (idx < len) {
             for (int i = idx; i < len; i++) {
diff --git a/jdk/test/java/nio/Buffer/Order-X.java.template b/jdk/test/java/nio/Buffer/Order-X.java.template
index a8753a5f8a9..97313a841f6 100644
--- a/jdk/test/java/nio/Buffer/Order-X.java.template
+++ b/jdk/test/java/nio/Buffer/Order-X.java.template
@@ -52,8 +52,5 @@ public class Order$Type$ extends Order {
         buf = $Type$Buffer.allocate(LENGTH);
         ck(buf.order(), nord);
         ck$Type$Buffer(buf, nord);
-
-        ck$Type$Buffer(ByteBuffer.allocate(LENGTH).as$Type$Buffer(), be);
-        ck$Type$Buffer(ByteBuffer.allocateDirect(LENGTH).as$Type$Buffer(), be);
     }
 }
diff --git a/jdk/test/java/nio/Buffer/Order.java b/jdk/test/java/nio/Buffer/Order.java
index 768fecb8b8a..33ae418bb56 100644
--- a/jdk/test/java/nio/Buffer/Order.java
+++ b/jdk/test/java/nio/Buffer/Order.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,41 +39,49 @@ public class Order {
 
     static void ck(ByteOrder ord, ByteOrder expected) {
         if (ord != expected)
-            throw new RuntimeException("Got " + ord
-                                       + ", expected " + expected);
+            throw new RuntimeException("Got " + ord + ", expected " + expected);
     }
 
-    static void ckViews(ByteBuffer bb, ByteOrder ord) {
+    private static void ckViews(ByteBuffer bb) {
         ck(bb.asCharBuffer().order(), bb.order());
+        ck(bb.asShortBuffer().order(), bb.order());
         ck(bb.asIntBuffer().order(), bb.order());
         ck(bb.asLongBuffer().order(), bb.order());
         ck(bb.asFloatBuffer().order(), bb.order());
         ck(bb.asDoubleBuffer().order(), bb.order());
     }
 
-    static void ckByteBuffer(ByteBuffer bb) {
-        ckViews(bb, bb.order());
-        bb.order(be);
-        ckViews(bb, be);
-        bb.order(le);
-        ckViews(bb, le);
+    private static void ckCopyViews(ByteBuffer bb) {
+        ck(bb.asReadOnlyBuffer().order(), be);
+        ck(bb.duplicate().order(), be);
+        ck(bb.slice().order(), be);
+    }
 
-        if (bb.hasArray()) {
-            byte[] array = bb.array();
-            ck(ByteBuffer.wrap(array, LENGTH/2, LENGTH/2).order(), be);
-            ck(ByteBuffer.wrap(array).order(), be);
-            ck(bb.asReadOnlyBuffer().order(), be);
-            ck(bb.duplicate().order(), be);
-            ck(bb.slice().order(), be);
-        }
+    private static void ckByteBuffer(ByteBuffer bb) {
+        ckViews(bb);
+        ckCopyViews(bb);
+        bb.order(be);
+        ckViews(bb);
+        ckCopyViews(bb);
+        bb.order(le);
+        ckViews(bb);
+        ckCopyViews(bb);
     }
 
     public static void main(String args[]) throws Exception {
 
+        ck(ByteBuffer.wrap(new byte[LENGTH], LENGTH/2, LENGTH/2).order(), be);
+        ck(ByteBuffer.wrap(new byte[LENGTH]).order(), be);
+        ck(ByteBuffer.wrap(new byte[LENGTH], LENGTH/2, LENGTH/2).order(be).order(), be);
+        ck(ByteBuffer.wrap(new byte[LENGTH]).order(be).order(), be);
+        ck(ByteBuffer.wrap(new byte[LENGTH], LENGTH/2, LENGTH/2).order(le).order(), le);
+        ck(ByteBuffer.wrap(new byte[LENGTH]).order(le).order(), le);
         ck(ByteBuffer.allocate(LENGTH).order(), be);
         ck(ByteBuffer.allocateDirect(LENGTH).order(), be);
         ck(ByteBuffer.allocate(LENGTH).order(be).order(), be);
         ck(ByteBuffer.allocate(LENGTH).order(le).order(), le);
+        ck(ByteBuffer.allocateDirect(LENGTH).order(be).order(), be);
+        ck(ByteBuffer.allocateDirect(LENGTH).order(le).order(), le);
 
         ckByteBuffer(ByteBuffer.allocate(LENGTH));
         ckByteBuffer(ByteBuffer.allocateDirect(LENGTH));
@@ -85,5 +93,4 @@ public class Order {
         OrderFloat.ckFloatBuffer();
         OrderDouble.ckDoubleBuffer();
     }
-
 }
diff --git a/jdk/test/java/nio/Buffer/OrderChar.java b/jdk/test/java/nio/Buffer/OrderChar.java
index ebf9faad79c..f72828bd0de 100644
--- a/jdk/test/java/nio/Buffer/OrderChar.java
+++ b/jdk/test/java/nio/Buffer/OrderChar.java
@@ -52,8 +52,5 @@ public class OrderChar extends Order {
         buf = CharBuffer.allocate(LENGTH);
         ck(buf.order(), nord);
         ckCharBuffer(buf, nord);
-
-        ckCharBuffer(ByteBuffer.allocate(LENGTH).asCharBuffer(), be);
-        ckCharBuffer(ByteBuffer.allocateDirect(LENGTH).asCharBuffer(), be);
     }
 }
diff --git a/jdk/test/java/nio/Buffer/OrderDouble.java b/jdk/test/java/nio/Buffer/OrderDouble.java
index deaa6a3eb27..4100695cab5 100644
--- a/jdk/test/java/nio/Buffer/OrderDouble.java
+++ b/jdk/test/java/nio/Buffer/OrderDouble.java
@@ -52,8 +52,5 @@ public class OrderDouble extends Order {
         buf = DoubleBuffer.allocate(LENGTH);
         ck(buf.order(), nord);
         ckDoubleBuffer(buf, nord);
-
-        ckDoubleBuffer(ByteBuffer.allocate(LENGTH).asDoubleBuffer(), be);
-        ckDoubleBuffer(ByteBuffer.allocateDirect(LENGTH).asDoubleBuffer(), be);
     }
 }
diff --git a/jdk/test/java/nio/Buffer/OrderFloat.java b/jdk/test/java/nio/Buffer/OrderFloat.java
index 6a65eaa8e4f..905d531d434 100644
--- a/jdk/test/java/nio/Buffer/OrderFloat.java
+++ b/jdk/test/java/nio/Buffer/OrderFloat.java
@@ -52,8 +52,5 @@ public class OrderFloat extends Order {
         buf = FloatBuffer.allocate(LENGTH);
         ck(buf.order(), nord);
         ckFloatBuffer(buf, nord);
-
-        ckFloatBuffer(ByteBuffer.allocate(LENGTH).asFloatBuffer(), be);
-        ckFloatBuffer(ByteBuffer.allocateDirect(LENGTH).asFloatBuffer(), be);
     }
 }
diff --git a/jdk/test/java/nio/Buffer/OrderInt.java b/jdk/test/java/nio/Buffer/OrderInt.java
index 5d3843ffec7..700fc07110a 100644
--- a/jdk/test/java/nio/Buffer/OrderInt.java
+++ b/jdk/test/java/nio/Buffer/OrderInt.java
@@ -52,8 +52,5 @@ public class OrderInt extends Order {
         buf = IntBuffer.allocate(LENGTH);
         ck(buf.order(), nord);
         ckIntBuffer(buf, nord);
-
-        ckIntBuffer(ByteBuffer.allocate(LENGTH).asIntBuffer(), be);
-        ckIntBuffer(ByteBuffer.allocateDirect(LENGTH).asIntBuffer(), be);
     }
 }
diff --git a/jdk/test/java/nio/Buffer/OrderLong.java b/jdk/test/java/nio/Buffer/OrderLong.java
index abda8b22932..9e507ffc18e 100644
--- a/jdk/test/java/nio/Buffer/OrderLong.java
+++ b/jdk/test/java/nio/Buffer/OrderLong.java
@@ -52,8 +52,5 @@ public class OrderLong extends Order {
         buf = LongBuffer.allocate(LENGTH);
         ck(buf.order(), nord);
         ckLongBuffer(buf, nord);
-
-        ckLongBuffer(ByteBuffer.allocate(LENGTH).asLongBuffer(), be);
-        ckLongBuffer(ByteBuffer.allocateDirect(LENGTH).asLongBuffer(), be);
     }
 }
diff --git a/jdk/test/java/nio/Buffer/OrderShort.java b/jdk/test/java/nio/Buffer/OrderShort.java
index d19b43a1b60..f385b62d6dd 100644
--- a/jdk/test/java/nio/Buffer/OrderShort.java
+++ b/jdk/test/java/nio/Buffer/OrderShort.java
@@ -52,8 +52,5 @@ public class OrderShort extends Order {
         buf = ShortBuffer.allocate(LENGTH);
         ck(buf.order(), nord);
         ckShortBuffer(buf, nord);
-
-        ckShortBuffer(ByteBuffer.allocate(LENGTH).asShortBuffer(), be);
-        ckShortBuffer(ByteBuffer.allocateDirect(LENGTH).asShortBuffer(), be);
     }
 }
diff --git a/jdk/test/java/nio/Buffer/SwapMicroBenchmark.java b/jdk/test/java/nio/Buffer/SwapMicroBenchmark.java
index 1942639a460..31bbe908c20 100644
--- a/jdk/test/java/nio/Buffer/SwapMicroBenchmark.java
+++ b/jdk/test/java/nio/Buffer/SwapMicroBenchmark.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,6 @@
 
 import java.util.*;
 import java.nio.*;
-import java.util.concurrent.*;
 import java.util.regex.Pattern;
 
 public class SwapMicroBenchmark {
diff --git a/jdk/test/java/sql/TEST.properties b/jdk/test/java/sql/TEST.properties
new file mode 100644
index 00000000000..878b05fc591
--- /dev/null
+++ b/jdk/test/java/sql/TEST.properties
@@ -0,0 +1,2 @@
+modules = java.sql
+
diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java
index db19675f97b..d0d380cd815 100644
--- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java
+++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java
@@ -73,7 +73,10 @@ import java.text.ParsePosition;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
+import java.time.Month;
 import java.time.YearMonth;
+import java.time.ZonedDateTime;
+import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
@@ -459,6 +462,98 @@ public class TCKDateTimeFormatterBuilder {
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
+    @DataProvider(name = "formatGenericTimeZonePatterns")
+    Object[][] data_formatGenericNonLocationPatterns() {
+        return new Object[][] {
+                {"v", "America/Los_Angeles", "PT"},
+                {"vvvv", "America/Los_Angeles", "Pacific Time"},
+                {"v", "America/New_York", "ET"},
+                {"vvvv", "America/New_York", "Eastern Time"},
+        };
+    }
+
+    @Test(dataProvider = "formatGenericTimeZonePatterns")
+    public void test_appendZoneText_formatGenericTimeZonePatterns(String pattern, String input, String expected) {
+        ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of(input));
+        DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
+        assertEquals(zdt.format(df), expected);
+    }
+
+    @DataProvider(name = "parseGenericTimeZonePatterns")
+    Object[][]  data_parseGenericTimeZonePatterns() {
+        return new Object[][] {
+                {"yyyy DDD HH mm v", LocalDateTime.of(2015, Month.MARCH, 10, 12, 13), ZoneId.of("America/Los_Angeles"),
+                 "2015 069 12 13 PT"},
+                {"yyyy DDD HH mm vvvv", LocalDateTime.of(2015, Month.MARCH, 10, 12, 13), ZoneId.of("America/Los_Angeles"),
+                 "2015 069 12 13 Pacific Time"},
+                {"yyyy DDD HH mm v", LocalDateTime.of(2015, Month.NOVEMBER, 10, 12, 13), ZoneId.of("America/Los_Angeles"),
+                 "2015 314 12 13 PT"},
+                {"yyyy DDD HH mm vvvv", LocalDateTime.of(2015, Month.NOVEMBER, 10, 12, 13), ZoneId.of("America/Los_Angeles"),
+                 "2015 314 12 13 Pacific Time"},
+        };
+    }
+
+    @Test(dataProvider = "parseGenericTimeZonePatterns")
+    public void test_appendZoneText_parseGenericTimeZonePatterns(String pattern, LocalDateTime ldt, ZoneId zId, String input) {
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
+        ZonedDateTime expected = ZonedDateTime.parse(input, df);
+        ZonedDateTime actual = ZonedDateTime.of(ldt, zId);
+        assertEquals(actual, expected);
+    }
+
+    @DataProvider(name = "formatNonGenericTimeZonePatterns_1")
+    Object[][]  data_formatNonGenericTimeZonePatterns_1() {
+        return new Object[][] {
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30),
+                 "2015-11-01 00:30:00 PDT"},
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30),
+                 "2015-11-01 01:30:00 PDT"},
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30),
+                 "2015-11-01 02:30:00 PST"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30),
+                 "2015-11-01 00:30:00 Pacific Daylight Time"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30),
+                 "2015-11-01 01:30:00 Pacific Daylight Time"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30),
+                 "2015-11-01 02:30:00 Pacific Standard Time"},
+        };
+    }
+
+    @Test(dataProvider = "formatNonGenericTimeZonePatterns_1")
+    public void test_appendZoneText_parseNonGenricTimeZonePatterns_1(String pattern, LocalDateTime ldt, String expected) {
+        ZoneId  zId = ZoneId.of("America/Los_Angeles");
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
+        ZonedDateTime zdt = ZonedDateTime.of(ldt, zId);
+        String actual = df.format(zdt);
+        assertEquals(actual, expected);
+    }
+
+    @DataProvider(name = "formatNonGenericTimeZonePatterns_2")
+    Object[][]  data_formatNonGenericTimeZonePatterns_2() {
+        return new Object[][] {
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30),
+                 "2015-11-01 00:30:00 PDT"},
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30),
+                 "2015-11-01 01:30:00 PT"},
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30),
+                 "2015-11-01 02:30:00 PST"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30),
+                 "2015-11-01 00:30:00 Pacific Daylight Time"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30),
+                 "2015-11-01 01:30:00 Pacific Time"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30),
+                 "2015-11-01 02:30:00 Pacific Standard Time"},
+        };
+    }
+
+    @Test(dataProvider = "formatNonGenericTimeZonePatterns_2")
+    public void test_appendZoneText_parseNonGenricTimeZonePatterns_2(String pattern, LocalDateTime ldt, String expected) {
+        ZoneId  zId = ZoneId.of("America/Los_Angeles");
+        DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern).withZone(zId);
+        String actual = df.format(ldt);
+        assertEquals(actual, expected);
+    }
+
     @Test(expectedExceptions=NullPointerException.class)
     public void test_appendZoneText_1arg_nullText() throws Exception {
         builder.appendZoneText(null);
@@ -734,6 +829,9 @@ public class TCKDateTimeFormatterBuilder {
 
             {"www"},
             {"WW"},
+
+            {"vv"},
+            {"vvv"},
         };
     }
 
diff --git a/jdk/test/java/util/Arrays/SortingNearlySortedPrimitive.java b/jdk/test/java/util/Arrays/SortingNearlySortedPrimitive.java
index 99bd4cf04d2..b2c8d6ec45b 100644
--- a/jdk/test/java/util/Arrays/SortingNearlySortedPrimitive.java
+++ b/jdk/test/java/util/Arrays/SortingNearlySortedPrimitive.java
@@ -1,6 +1,6 @@
 /*
  * Copyright 2015 Goldman Sachs.
- * 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
@@ -23,6 +23,7 @@
  */
 /*
  * @test
+ * @bug 8154049
  * @summary Tests the sorting of a large array of sorted primitive values,
  *          predominently for cases where the array is nearly sorted. This tests
  *          code that detects patterns in the array to determine if it is nearly
@@ -32,32 +33,117 @@
  * @run testng SortingNearlySortedPrimitive
  */
 
-import org.testng.Assert;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.function.Supplier;
+import java.util.List;
+import java.util.StringJoiner;
+import java.util.function.IntFunction;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
 
 public class SortingNearlySortedPrimitive {
-    private static final int ARRAY_SIZE = 1_000_000;
 
-    @DataProvider(name = "arrays")
-    public Object[][] createData() {
-        return new Object[][]{
-                {"hiZeroLowTest", (Supplier<int[]>) this::hiZeroLowData},
-                {"endLessThanTest", (Supplier<int[]>) this::endLessThanData},
-                {"highFlatLowTest", (Supplier<int[]>) this::highFlatLowData},
-                {"identicalTest", (Supplier<int[]>) this::identicalData},
-                {"sortedReversedSortedTest", (Supplier<int[]>) this::sortedReversedSortedData},
-                {"pairFlipTest", (Supplier<int[]>) this::pairFlipData},
-                {"zeroHiTest", (Supplier<int[]>) this::zeroHiData},
-        };
+    static final int BASE = 3;
+    static final int WIDTH = 4;
+    // Should be > DualPivotQuicksort.QUICKSORT_THRESHOLD
+    static final int PAD = 300;
+
+    Stream<int[]> createCombinations() {
+        // Create all combinations for the BASE value and double the WIDTH
+        // elements
+        // This is create various combinations of ascending, descending and
+        // equal runs to exercise the nearly sorted code paths
+        return IntStream.range(0, (int) Math.pow(BASE, 2 * WIDTH)).
+                mapToObj(this::createArray);
     }
 
-    @Test(dataProvider = "arrays")
-    public void runTests(String testName, Supplier<int[]> dataMethod) throws Exception {
-        int[] intSourceArray = dataMethod.get();
+    // Create an array which at either end is filled with -ve and +ve elements
+    // according to the base value and padded with zeros in between
+    int[] createArray(int v) {
+        int[] a = new int[WIDTH + PAD + WIDTH];
+
+        // Fill head of array
+        for (int j = 0; j < WIDTH; j++) {
+            a[j] = (v % BASE) - (BASE / 2);
+            v /= BASE;
+        }
+        // Fill tail of array
+        for (int j = 0; j < WIDTH; j++) {
+            a[WIDTH + PAD + j] = (v % BASE) - (BASE / 2);
+            v /= BASE;
+        }
+        return a;
+    }
+
+    @Test
+    public void testCombination() {
+        createCombinations().forEach(a -> {
+            try {
+                // Clone source array to ensure it is not modified
+                this.sortAndAssert(a.clone());
+                this.sortAndAssert(floatCopyFromInt(a));
+                this.sortAndAssert(doubleCopyFromInt(a));
+                this.sortAndAssert(longCopyFromInt(a));
+                this.sortAndAssert(shortCopyFromInt(a));
+                this.sortAndAssert(charCopyFromInt(a));
+            } catch (AssertionError sae) {
+                AssertionError ae = new AssertionError("Sort failed for " + arrayToString(a));
+                ae.addSuppressed(sae);
+                throw ae;
+            }
+        });
+    }
+
+    String arrayToString(int[] a) {
+        int[] l = Arrays.copyOfRange(a, 0, WIDTH + 2);
+        int[] r = Arrays.copyOfRange(a, a.length - (WIDTH + 2), a.length);
+        StringJoiner sj = new StringJoiner(",", "[", "]");
+        for (int i : l) {
+            sj.add(Integer.toString(i));
+        }
+        sj.add("...");
+        for (int i : r) {
+            sj.add(Integer.toString(i));
+        }
+        return sj.toString();
+    }
+
+
+    @DataProvider(name = "shapes")
+    public Object[][] createShapes() {
+        Stream<List<Object>> baseCases = Stream.of(
+                List.of("hiZeroLowTest", (IntFunction<int[]>) this::hiZeroLowData),
+                List.of("endLessThanTest", (IntFunction<int[]>) this::endLessThanData),
+                List.of("highFlatLowTest", (IntFunction<int[]>) this::highFlatLowData),
+                List.of("identicalTest", (IntFunction<int[]>) this::identicalData),
+                List.of("sortedReversedSortedTest", (IntFunction<int[]>) this::sortedReversedSortedData),
+                List.of("pairFlipTest", (IntFunction<int[]>) this::pairFlipData),
+                List.of("zeroHiTest", (IntFunction<int[]>) this::zeroHiData)
+        );
+
+        // Ensure the following inequality holds for certain sizes
+        // DualPivotQuicksort.QUICKSORT_THRESHOLD <= size - 1
+        //   < DualPivotQuicksort.COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
+        // This guarantees that code paths are taken for checking nearly sorted
+        // arrays for all primitive types
+        List<Integer> sizes = List.of(100, 1_000, 10_000, 1_000_000);
+        return baseCases.
+                flatMap(l -> sizes.stream().map(s -> append(l, s))).
+                toArray(Object[][]::new);
+    }
+
+    Object[] append(List<Object> l, Object value) {
+        List<Object> nl = new ArrayList<>(l);
+        nl.add(value);
+        return nl.toArray();
+    }
+
+    @Test(dataProvider = "shapes")
+    public void testShapes(String testName, IntFunction<int[]> dataMethod, int size) {
+        int[] intSourceArray = dataMethod.apply(size);
 
         // Clone source array to ensure it is not modified
         this.sortAndAssert(intSourceArray.clone());
@@ -110,73 +196,67 @@ public class SortingNearlySortedPrimitive {
 
     private void sortAndAssert(int[] array) {
         Arrays.sort(array);
-        for (int i = 1; i < ARRAY_SIZE; i++) {
+        for (int i = 1; i < array.length; i++) {
             if (array[i] < array[i - 1]) {
                 throw new AssertionError("not sorted");
             }
         }
-        Assert.assertEquals(ARRAY_SIZE, array.length);
     }
 
     private void sortAndAssert(char[] array) {
         Arrays.sort(array);
-        for (int i = 1; i < ARRAY_SIZE; i++) {
+        for (int i = 1; i < array.length; i++) {
             if (array[i] < array[i - 1]) {
                 throw new AssertionError("not sorted");
             }
         }
-        Assert.assertEquals(ARRAY_SIZE, array.length);
     }
 
     private void sortAndAssert(short[] array) {
         Arrays.sort(array);
-        for (int i = 1; i < ARRAY_SIZE; i++) {
+        for (int i = 1; i < array.length; i++) {
             if (array[i] < array[i - 1]) {
                 throw new AssertionError("not sorted");
             }
         }
-        Assert.assertEquals(ARRAY_SIZE, array.length);
     }
 
     private void sortAndAssert(double[] array) {
         Arrays.sort(array);
-        for (int i = 1; i < ARRAY_SIZE; i++) {
+        for (int i = 1; i < array.length; i++) {
             if (array[i] < array[i - 1]) {
                 throw new AssertionError("not sorted");
             }
         }
-        Assert.assertEquals(ARRAY_SIZE, array.length);
     }
 
     private void sortAndAssert(float[] array) {
         Arrays.sort(array);
-        for (int i = 1; i < ARRAY_SIZE; i++) {
+        for (int i = 1; i < array.length; i++) {
             if (array[i] < array[i - 1]) {
                 throw new AssertionError("not sorted");
             }
         }
-        Assert.assertEquals(ARRAY_SIZE, array.length);
     }
 
     private void sortAndAssert(long[] array) {
         Arrays.sort(array);
-        for (int i = 1; i < ARRAY_SIZE; i++) {
+        for (int i = 1; i < array.length; i++) {
             if (array[i] < array[i - 1]) {
                 throw new AssertionError("not sorted");
             }
         }
-        Assert.assertEquals(ARRAY_SIZE, array.length);
     }
 
-    private int[] zeroHiData() {
-        int[] array = new int[ARRAY_SIZE];
+    private int[] zeroHiData(int size) {
+        int[] array = new int[size];
 
-        int threeQuarters = (int) (ARRAY_SIZE * 0.75);
+        int threeQuarters = (int) (size * 0.75);
         for (int i = 0; i < threeQuarters; i++) {
             array[i] = 0;
         }
         int k = 1;
-        for (int i = threeQuarters; i < ARRAY_SIZE; i++) {
+        for (int i = threeQuarters; i < size; i++) {
             array[i] = k;
             k++;
         }
@@ -184,10 +264,10 @@ public class SortingNearlySortedPrimitive {
         return array;
     }
 
-    private int[] hiZeroLowData() {
-        int[] array = new int[ARRAY_SIZE];
+    private int[] hiZeroLowData(int size) {
+        int[] array = new int[size];
 
-        int oneThird = ARRAY_SIZE / 3;
+        int oneThird = size / 3;
         for (int i = 0; i < oneThird; i++) {
             array[i] = i;
         }
@@ -195,16 +275,16 @@ public class SortingNearlySortedPrimitive {
         for (int i = oneThird; i < twoThirds; i++) {
             array[i] = 0;
         }
-        for (int i = twoThirds; i < ARRAY_SIZE; i++) {
+        for (int i = twoThirds; i < size; i++) {
             array[i] = oneThird - i + twoThirds;
         }
         return array;
     }
 
-    private int[] highFlatLowData() {
-        int[] array = new int[ARRAY_SIZE];
+    private int[] highFlatLowData(int size) {
+        int[] array = new int[size];
 
-        int oneThird = ARRAY_SIZE / 3;
+        int oneThird = size / 3;
         for (int i = 0; i < oneThird; i++) {
             array[i] = i;
         }
@@ -213,57 +293,57 @@ public class SortingNearlySortedPrimitive {
         for (int i = oneThird; i < twoThirds; i++) {
             array[i] = constant;
         }
-        for (int i = twoThirds; i < ARRAY_SIZE; i++) {
+        for (int i = twoThirds; i < size; i++) {
             array[i] = constant - i + twoThirds;
         }
 
         return array;
     }
 
-    private int[] identicalData() {
-        int[] array = new int[ARRAY_SIZE];
+    private int[] identicalData(int size) {
+        int[] array = new int[size];
         int listNumber = 24;
 
-        for (int i = 0; i < ARRAY_SIZE; i++) {
+        for (int i = 0; i < size; i++) {
             array[i] = listNumber;
         }
 
         return array;
     }
 
-    private int[] endLessThanData() {
-        int[] array = new int[ARRAY_SIZE];
+    private int[] endLessThanData(int size) {
+        int[] array = new int[size];
 
-        for (int i = 0; i < ARRAY_SIZE - 1; i++) {
+        for (int i = 0; i < size - 1; i++) {
             array[i] = 3;
         }
-        array[ARRAY_SIZE - 1] = 1;
+        array[size - 1] = 1;
 
         return array;
     }
 
-    private int[] sortedReversedSortedData() {
-        int[] array = new int[ARRAY_SIZE];
+    private int[] sortedReversedSortedData(int size) {
+        int[] array = new int[size];
 
-        for (int i = 0; i < ARRAY_SIZE / 2; i++) {
+        for (int i = 0; i < size / 2; i++) {
             array[i] = i;
         }
         int num = 0;
-        for (int i = ARRAY_SIZE / 2; i < ARRAY_SIZE; i++) {
-            array[i] = ARRAY_SIZE - num;
+        for (int i = size / 2; i < size; i++) {
+            array[i] = size - num;
             num++;
         }
 
         return array;
     }
 
-    private int[] pairFlipData() {
-        int[] array = new int[ARRAY_SIZE];
+    private int[] pairFlipData(int size) {
+        int[] array = new int[size];
 
-        for (int i = 0; i < ARRAY_SIZE; i++) {
+        for (int i = 0; i < size; i++) {
             array[i] = i;
         }
-        for (int i = 0; i < ARRAY_SIZE; i += 2) {
+        for (int i = 0; i < size; i += 2) {
             int temp = array[i];
             array[i] = array[i + 1];
             array[i + 1] = temp;
diff --git a/jdk/test/java/util/Objects/CheckIndex.java b/jdk/test/java/util/Objects/CheckIndex.java
index c4efdb1c253..bcfa1d5b23d 100644
--- a/jdk/test/java/util/Objects/CheckIndex.java
+++ b/jdk/test/java/util/Objects/CheckIndex.java
@@ -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
@@ -23,11 +23,13 @@
 
 /**
  * @test
- * @summary IndexOutOfBoundsException check index tests
+ * @summary Objects.checkIndex/jdk.internal.util.Preconditions.checkIndex tests
  * @run testng CheckIndex
- * @bug 8135248 8142493
+ * @bug 8135248 8142493 8155794
+ * @modules java.base/jdk.internal.util
  */
 
+import jdk.internal.util.Preconditions;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
@@ -95,7 +97,7 @@ public class CheckIndex {
     public void testCheckIndex(int index, int length, boolean withinBounds) {
         String expectedMessage = withinBounds
                                  ? null
-                                 : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
+                                 : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
                 apply("checkIndex", List.of(index, length)).getMessage();
 
         BiConsumer<Class<? extends RuntimeException>, IntSupplier> checker = (ec, s) -> {
@@ -117,21 +119,21 @@ public class CheckIndex {
         };
 
         checker.accept(AssertingOutOfBoundsException.class,
-                     () -> Objects.checkIndex(index, length,
-                                              assertingOutOfBounds(expectedMessage, "checkIndex", index, length)));
+                     () -> Preconditions.checkIndex(index, length,
+                                                    assertingOutOfBounds(expectedMessage, "checkIndex", index, length)));
         checker.accept(IndexOutOfBoundsException.class,
-                     () -> Objects.checkIndex(index, length,
-                                              assertingOutOfBoundsReturnNull("checkIndex", index, length)));
+                     () -> Preconditions.checkIndex(index, length,
+                                                    assertingOutOfBoundsReturnNull("checkIndex", index, length)));
         checker.accept(IndexOutOfBoundsException.class,
-                     () -> Objects.checkIndex(index, length, null));
+                     () -> Preconditions.checkIndex(index, length, null));
         checker.accept(IndexOutOfBoundsException.class,
                      () -> Objects.checkIndex(index, length));
         checker.accept(ArrayIndexOutOfBoundsException.class,
-                     () -> Objects.checkIndex(index, length,
-                                              Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
+                     () -> Preconditions.checkIndex(index, length,
+                                                    Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
         checker.accept(StringIndexOutOfBoundsException.class,
-                     () -> Objects.checkIndex(index, length,
-                                              Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
+                     () -> Preconditions.checkIndex(index, length,
+                                                    Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
     }
 
 
@@ -157,7 +159,7 @@ public class CheckIndex {
     public void testCheckFromToIndex(int fromIndex, int toIndex, int length, boolean withinBounds) {
         String expectedMessage = withinBounds
                                  ? null
-                                 : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
+                                 : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
                 apply("checkFromToIndex", List.of(fromIndex, toIndex, length)).getMessage();
 
         BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {
@@ -179,21 +181,21 @@ public class CheckIndex {
         };
 
         check.accept(AssertingOutOfBoundsException.class,
-                     () -> Objects.checkFromToIndex(fromIndex, toIndex, length,
-                                                    assertingOutOfBounds(expectedMessage, "checkFromToIndex", fromIndex, toIndex, length)));
+                     () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,
+                                                          assertingOutOfBounds(expectedMessage, "checkFromToIndex", fromIndex, toIndex, length)));
         check.accept(IndexOutOfBoundsException.class,
-                     () -> Objects.checkFromToIndex(fromIndex, toIndex, length,
-                                                    assertingOutOfBoundsReturnNull("checkFromToIndex", fromIndex, toIndex, length)));
+                     () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,
+                                                          assertingOutOfBoundsReturnNull("checkFromToIndex", fromIndex, toIndex, length)));
         check.accept(IndexOutOfBoundsException.class,
-                     () -> Objects.checkFromToIndex(fromIndex, toIndex, length, null));
+                     () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, null));
         check.accept(IndexOutOfBoundsException.class,
                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length));
         check.accept(ArrayIndexOutOfBoundsException.class,
-                     () -> Objects.checkFromToIndex(fromIndex, toIndex, length,
-                                              Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
+                     () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,
+                                                          Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
         check.accept(StringIndexOutOfBoundsException.class,
-                     () -> Objects.checkFromToIndex(fromIndex, toIndex, length,
-                                              Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
+                     () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,
+                                                          Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
     }
 
 
@@ -226,7 +228,7 @@ public class CheckIndex {
     public void testCheckFromIndexSize(int fromIndex, int size, int length, boolean withinBounds) {
         String expectedMessage = withinBounds
                                  ? null
-                                 : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
+                                 : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
                 apply("checkFromIndexSize", List.of(fromIndex, size, length)).getMessage();
 
         BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {
@@ -248,27 +250,27 @@ public class CheckIndex {
         };
 
         check.accept(AssertingOutOfBoundsException.class,
-                     () -> Objects.checkFromIndexSize(fromIndex, size, length,
-                                                      assertingOutOfBounds(expectedMessage, "checkFromIndexSize", fromIndex, size, length)));
+                     () -> Preconditions.checkFromIndexSize(fromIndex, size, length,
+                                                            assertingOutOfBounds(expectedMessage, "checkFromIndexSize", fromIndex, size, length)));
         check.accept(IndexOutOfBoundsException.class,
-                     () -> Objects.checkFromIndexSize(fromIndex, size, length,
-                                                      assertingOutOfBoundsReturnNull("checkFromIndexSize", fromIndex, size, length)));
+                     () -> Preconditions.checkFromIndexSize(fromIndex, size, length,
+                                                            assertingOutOfBoundsReturnNull("checkFromIndexSize", fromIndex, size, length)));
         check.accept(IndexOutOfBoundsException.class,
-                     () -> Objects.checkFromIndexSize(fromIndex, size, length, null));
+                     () -> Preconditions.checkFromIndexSize(fromIndex, size, length, null));
         check.accept(IndexOutOfBoundsException.class,
                      () -> Objects.checkFromIndexSize(fromIndex, size, length));
         check.accept(ArrayIndexOutOfBoundsException.class,
-                     () -> Objects.checkFromIndexSize(fromIndex, size, length,
-                                                    Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
+                     () -> Preconditions.checkFromIndexSize(fromIndex, size, length,
+                                                            Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
         check.accept(StringIndexOutOfBoundsException.class,
-                     () -> Objects.checkFromIndexSize(fromIndex, size, length,
-                                                    Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
+                     () -> Preconditions.checkFromIndexSize(fromIndex, size, length,
+                                                            Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
     }
 
     @Test
     public void uniqueMessagesForCheckKinds() {
         BiFunction<String, List<Integer>, IndexOutOfBoundsException> f =
-                Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new);
+                Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new);
 
         List<String> messages = new ArrayList<>();
         // Exact arguments
diff --git a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java
index 7d6da0b255e..630f3796b8c 100644
--- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java
+++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -167,7 +167,7 @@ public class TimedAcquireLeak {
                             final String childPid,
                             final String className) {
         final String regex =
-            "(?m)^ *[0-9]+: +([0-9]+) +[0-9]+ +\\Q"+className+"\\E$";
+            "(?m)^ *[0-9]+: +([0-9]+) +[0-9]+ +\\Q"+className+"\\E(?:$| )";
         final Callable<Integer> objectsInUse =
             new Callable<Integer>() { public Integer call() {
                 Integer i = Integer.parseInt(
diff --git a/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java b/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java
index 0a482f31b90..0e40e52ce9b 100644
--- a/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java
+++ b/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /**
  * @test
  * @library /lib/testlibrary
+ * @modules jdk.httpserver
  * @build jdk.testlibrary.SimpleSSLContext
  * @run main Equals
  * @bug 8055299
diff --git a/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java b/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java
index ba3e5f10e50..bda0710f61e 100644
--- a/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java
+++ b/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java
@@ -34,9 +34,6 @@
  */
 
 import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.util.*;
 import java.net.*;
 import javax.net.ssl.*;
 
@@ -197,6 +194,7 @@ public class BestEffortOnLazyConnected {
                 hostname);
         // Ignore the test if the hostname does not sound like a domain name.
         if ((hostname == null) || hostname.isEmpty() ||
+                !hostname.contains(".") || hostname.endsWith(".") ||
                 hostname.startsWith("localhost") ||
                 Character.isDigit(hostname.charAt(hostname.length() - 1))) {
 
diff --git a/jdk/test/javax/net/ssl/etc/README b/jdk/test/javax/net/ssl/etc/README
new file mode 100644
index 00000000000..0ac6a844a86
--- /dev/null
+++ b/jdk/test/javax/net/ssl/etc/README
@@ -0,0 +1,94 @@
+Keystores used for the JSSE regression test suite.
+
+keystore
+truststore
+==========
+
+These are the primary two keystores and contain entries for testing most
+of the JSSE regression test files.  There are three entries, one RSA-based,
+one DSA-based and one EC-based.  If they expire, simply recreate them
+using keytool and most of the test cases should work.
+
+The password on both files is:
+
+    passphrase
+
+There are no individual key entry passwords at this time.
+
+
+keystore entries
+================
+
+Alias name: dummy
+-----------------
+Creation date: May 16, 2016
+Entry type: PrivateKeyEntry
+Certificate chain length: 1
+Certificate[1]:
+Owner: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US
+Issuer: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US
+Serial number: 57399b87
+Valid from: Mon May 16 10:06:38 UTC 2016 until: Sat May 16 10:06:38 UTC 2026
+Signature algorithm name: SHA256withRSA
+Version: 1
+
+This can be generated using hacked (update the keytool source code so that
+it can be used for version 1 X.509 certificate) keytool command:
+% keytool -genkeypair -alias dummy -keyalg RSA -keysize 2048 \
+  -sigalg SHA256withRSA \
+  -dname "CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US" \
+  -validity 3652 -keypass passphrase -keystore keystore -storepass passphrase
+
+
+Alias name: dummyecdsa
+----------------------
+Creation date: May 16, 2016
+Entry type: PrivateKeyEntry
+Certificate chain length: 1
+Certificate[1]:
+Owner: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US
+Issuer: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US
+Serial number: 57399c1d
+Valid from: Mon May 16 10:09:01 UTC 2016 until: Sat May 16 10:09:01 UTC 2026
+Signature algorithm name: SHA256withECDSA
+Version: 1
+
+This can be generated using hacked (update the keytool source code so that
+it can be used for version 1 X.509 certificate) keytool command:
+% keytool -genkeypair -alias dummy -keyalg EC -keysize 256 \
+  -sigalg SHA256withECDSA \
+  -dname "CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US" \
+  -validity 3652 -keypass passphrase -keystore keystore -storepass passphrase
+
+Alias name: dummydsa
+--------------------
+Creation date: Mar 11, 2007
+Entry type: PrivateKeyEntry
+Certificate chain length: 1
+Certificate[1]:
+Owner: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US
+Issuer: CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US
+Serial number: 45f3a314
+Valid from: Sun Mar 11 06:35:00 UTC 2007 until: Wed Mar 08 06:35:00 UTC 2017
+Certificate fingerprints:
+Signature algorithm name: SHA1withDSA
+Version: 1
+
+This can be generated using hacked (update the keytool source code so that
+it can be used for version 1 X.509 certificate) keytool command:
+% keytool -genkeypair -alias dummy -keyalg DSA -keysize 1024 \
+  -sigalg SHA1withDSA \
+  -dname "CN=dummy.example.com, OU=Dummy, O=Dummy, L=Cupertino, ST=CA, C=US" \
+  -validity 3652 -keypass passphrase -keystore keystore -storepass passphrase
+
+
+truststore entries
+==================
+This key store contains only trusted certificate entries.  The same
+certificates are used in both keystore and truststore.
+
+
+unknown_keystore
+================
+A keystore you can use when you don't want things to be verified.
+Use this with keystore/truststore, and you'll never get a match.
diff --git a/jdk/test/javax/net/ssl/etc/keystore b/jdk/test/javax/net/ssl/etc/keystore
index 2eb1993f3af..4062e1798c5 100644
Binary files a/jdk/test/javax/net/ssl/etc/keystore and b/jdk/test/javax/net/ssl/etc/keystore differ
diff --git a/jdk/test/javax/net/ssl/etc/truststore b/jdk/test/javax/net/ssl/etc/truststore
index 65a140d7732..12da39e66a5 100644
Binary files a/jdk/test/javax/net/ssl/etc/truststore and b/jdk/test/javax/net/ssl/etc/truststore differ
diff --git a/jdk/test/javax/rmi/TEST.properties b/jdk/test/javax/rmi/TEST.properties
new file mode 100644
index 00000000000..d4bbfc905b9
--- /dev/null
+++ b/jdk/test/javax/rmi/TEST.properties
@@ -0,0 +1 @@
+modules = java.rmi
diff --git a/jdk/test/javax/script/ProviderTest.sh b/jdk/test/javax/script/ProviderTest.sh
index 1db161dfcf6..24b4120912c 100644
--- a/jdk/test/javax/script/ProviderTest.sh
+++ b/jdk/test/javax/script/ProviderTest.sh
@@ -43,8 +43,18 @@ $JAR ${TESTTOOLVMOPTS} -cf ${TESTCLASSES}/dummy.jar \
     -C ${TESTCLASSES} DummyScriptEngineFactory.class \
     -C "${TESTSRC}" META-INF/services/javax.script.ScriptEngineFactory
 
-echo "Running test ..."
+echo "Running test with security manager ..."
+$JAVA ${TESTVMOPTS} -Djava.security.manager -classpath \
+  "${TESTCLASSES}${PS}${TESTCLASSES}/dummy.jar" \
+  ProviderTest
 
+ret=$?
+if [ $ret -ne 0 ]
+then
+  exit $ret
+fi
+
+echo "Running test without security manager ..."
 $JAVA ${TESTVMOPTS} -classpath \
   "${TESTCLASSES}${PS}${TESTCLASSES}/dummy.jar" \
   ProviderTest
diff --git a/jdk/test/javax/script/TEST.properties b/jdk/test/javax/script/TEST.properties
new file mode 100644
index 00000000000..3bb100c3fad
--- /dev/null
+++ b/jdk/test/javax/script/TEST.properties
@@ -0,0 +1 @@
+modules = java.scripting
diff --git a/jdk/test/javax/xml/jaxp/TEST.properties b/jdk/test/javax/xml/jaxp/TEST.properties
new file mode 100644
index 00000000000..fbf9f77ec10
--- /dev/null
+++ b/jdk/test/javax/xml/jaxp/TEST.properties
@@ -0,0 +1 @@
+modules = java.xml
diff --git a/jdk/test/lib/testlibrary/CompilerUtils.java b/jdk/test/lib/testlibrary/CompilerUtils.java
index 91ca9181340..261c2c8f930 100644
--- a/jdk/test/lib/testlibrary/CompilerUtils.java
+++ b/jdk/test/lib/testlibrary/CompilerUtils.java
@@ -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
@@ -50,13 +50,21 @@ public final class CompilerUtils {
      *
      * @return true if the compilation is successful
      *
-     * @throws IOException if there is an I/O error scanning the source tree or
-     *                     creating the destination directory
+     * @throws IOException
+     *         if there is an I/O error scanning the source tree or
+     *         creating the destination directory
+     * @throws UnsupportedOperationException
+     *         if there is no system java compiler
      */
     public static boolean compile(Path source, Path destination, String ... options)
         throws IOException
     {
         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        if (compiler == null) {
+            // no compiler available
+            throw new UnsupportedOperationException("Unable to get system java compiler. " +
+                "Perhaps, jdk.compiler module is not available.");
+        }
         StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null);
 
         List<Path> sources
diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java
index 4e0f0bdac59..d90d9478e2a 100644
--- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java
@@ -235,6 +235,7 @@ public class ImpactOnSNI {
                 hostname);
         // Ignore the test if the hostname does not sound like a domain name.
         if ((hostname == null) || hostname.isEmpty() ||
+                !hostname.contains(".") || hostname.endsWith(".") ||
                 hostname.startsWith("localhost") ||
                 Character.isDigit(hostname.charAt(hostname.length() - 1))) {
 
diff --git a/jdk/test/sun/security/provider/MessageDigest/Offsets.java b/jdk/test/sun/security/provider/MessageDigest/Offsets.java
index eaa98fcbd75..44850c2970d 100644
--- a/jdk/test/sun/security/provider/MessageDigest/Offsets.java
+++ b/jdk/test/sun/security/provider/MessageDigest/Offsets.java
@@ -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
@@ -84,6 +84,10 @@ public class Offsets {
         test("SHA-256", 0, 64, 0, 128);
         test("SHA-384", 0, 128, 0, 256);
         test("SHA-512", 0, 128, 0, 256);
+        test("SHA3-224", 0, 64, 0, 128);
+        test("SHA3-256", 0, 64, 0, 128);
+        test("SHA3-384", 0, 128, 0, 256);
+        test("SHA3-512", 0, 128, 0, 256);
     }
 
 }
diff --git a/jdk/test/sun/security/provider/MessageDigest/TestSHAClone.java b/jdk/test/sun/security/provider/MessageDigest/TestSHAClone.java
index f1d1089f39a..ac809153b39 100644
--- a/jdk/test/sun/security/provider/MessageDigest/TestSHAClone.java
+++ b/jdk/test/sun/security/provider/MessageDigest/TestSHAClone.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,8 +32,13 @@ import java.util.*;
 
 public class TestSHAClone {
 
+    // OracleUcrypto provider gets its digest impl from either
+    // libucrypto (starting S12 with SHA-3 support added) and
+    // libmd (pre-S12, no SHA-3 at all).
+    // The impls from libucrypto does not support clone but ones
+    // from libmd do.
     private static final String[] ALGOS = {
-        "SHA", "SHA-224", "SHA-256", "SHA-512", "SHA-384"
+        "SHA", "SHA-224", "SHA-256", "SHA-384", "SHA-512"
     };
 
     private static byte[] input1 = {
@@ -52,7 +57,13 @@ public class TestSHAClone {
 
     private void run() throws Exception {
         md.update(input1);
-        MessageDigest md2 = (MessageDigest) md.clone();
+        MessageDigest md2;
+        try {
+            md2 = (MessageDigest) md.clone();
+        } catch (CloneNotSupportedException cnse) {
+            System.out.println(md.getAlgorithm() + ": clone unsupported");
+            return;
+        }
         md.update(input2);
         md2.update(input2);
         if (!Arrays.equals(md.digest(), md2.digest())) {
diff --git a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java b/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.java
similarity index 51%
rename from jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java
rename to jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.java
index b96e6ae6239..17a4c5d8d71 100644
--- a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java
+++ b/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.java
@@ -4,9 +4,7 @@
  *
  * 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.
+ * 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
@@ -23,24 +21,31 @@
  * questions.
  */
 
-package jdk.internal.vm.agent.spi;
+/*
+ * @test
+ * @bug 8150468
+ * @summary check that a badly formatted policy file is handled correctly
+ * @run main/othervm BadPolicyFile
+ */
 
-import java.lang.reflect.Layer;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.ServiceLoader;
+import java.io.File;
+import java.net.URI;
+import java.security.AccessControlException;
+import java.security.Policy;
+import java.security.URIParameter;
 
-public final class ToolProviderFinder {
-    private static final Map<String, ToolProvider> providers = init();
+public class BadPolicyFile {
 
-    public static ToolProvider find(String name) {
-        return providers.get(name);
-    }
-
-    private static Map<String, ToolProvider> init() {
-        Map<String, ToolProvider> providers = new HashMap<>();
-        ServiceLoader.load(Layer.boot(), ToolProvider.class)
-                     .forEach(p -> providers.putIfAbsent(p.getName(), p));
-        return providers;
+    public static void main(String[] args) throws Exception {
+        URI uri = new File(System.getProperty("test.src", "."),
+                           "BadPolicyFile.policy").toURI();
+        Policy.setPolicy(Policy.getInstance("JavaPolicy", new URIParameter(uri)));
+        System.setSecurityManager(new SecurityManager());
+        try {
+            String javahome = System.getProperty("java.home");
+            throw new Exception("Expected AccessControlException");
+        } catch (AccessControlException ace) {
+            System.out.println("Test PASSED");
+        }
     }
 }
diff --git a/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.policy b/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.policy
new file mode 100644
index 00000000000..b5abfaf8f42
--- /dev/null
+++ b/jdk/test/sun/security/provider/PolicyFile/BadPolicyFile.policy
@@ -0,0 +1,4 @@
+grant {
+    // permission statement is missing trailing semi-colon
+    permission "java.util.PropertyPermission" "java.home", "read"
+};
diff --git a/jdk/test/sun/security/rsa/SignatureTest.java b/jdk/test/sun/security/rsa/SignatureTest.java
index 0eed4ec1e5f..ef34786977b 100644
--- a/jdk/test/sun/security/rsa/SignatureTest.java
+++ b/jdk/test/sun/security/rsa/SignatureTest.java
@@ -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
@@ -39,9 +39,9 @@ import java.security.spec.RSAPrivateKeySpec;
 import java.security.spec.RSAPublicKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.Arrays;
+import java.util.stream.IntStream;
 import static javax.crypto.Cipher.PRIVATE_KEY;
 import static javax.crypto.Cipher.PUBLIC_KEY;
-import jdk.testlibrary.RandomFactory;
 
 /**
  * @test
@@ -49,36 +49,13 @@ import jdk.testlibrary.RandomFactory;
  * @summary Create a signature for RSA and get its signed data. re-initiate
  *          the signature with the public key. The signature can be verified
  *          by acquired signed data.
- * @key randomness
- * @library ../../../lib/testlibrary
- * @run main SignatureTest MD2withRSA 512
- * @run main SignatureTest MD5withRSA 512
- * @run main SignatureTest SHA1withRSA 512
- * @run main SignatureTest SHA256withRSA 512
- * @run main SignatureTest MD2withRSA 768
- * @run main SignatureTest MD5withRSA 768
- * @run main SignatureTest SHA1withRSA 768
- * @run main SignatureTest SHA256withRSA 768
- * @run main SignatureTest MD2withRSA 1024
- * @run main SignatureTest MD5withRSA 1024
- * @run main SignatureTest SHA1withRSA 1024
- * @run main SignatureTest SHA256withRSA 1024
- * @run main SignatureTest MD2withRSA 2048
- * @run main SignatureTest MD5withRSA 2048
- * @run main SignatureTest SHA1withRSA 2048
- * @run main SignatureTest SHA256withRSA 2048
- * @run main/timeout=240 SignatureTest MD2withRSA 4096
- * @run main/timeout=240 SignatureTest MD5withRSA 4096
- * @run main/timeout=240 SignatureTest SHA1withRSA 4096
- * @run main/timeout=240 SignatureTest SHA256withRSA 4096
- * @run main/timeout=240 SignatureTest MD2withRSA 5120
- * @run main/timeout=240 SignatureTest MD5withRSA 5120
- * @run main/timeout=240 SignatureTest SHA1withRSA 5120
- * @run main/timeout=240 SignatureTest SHA256withRSA 5120
- * @run main/timeout=240 SignatureTest MD2withRSA 6144
- * @run main/timeout=240 SignatureTest MD5withRSA 6144
- * @run main/timeout=240 SignatureTest SHA1withRSA 6144
- * @run main/timeout=240 SignatureTest SHA256withRSA 6144
+ * @run main SignatureTest 512
+ * @run main SignatureTest 768
+ * @run main SignatureTest 1024
+ * @run main SignatureTest 2048
+ * @run main/timeout=240 SignatureTest 4096
+ * @run main/timeout=240 SignatureTest 5120
+ * @run main/timeout=240 SignatureTest 6144
  */
 public class SignatureTest {
     /**
@@ -101,12 +78,19 @@ public class SignatureTest {
      */
     private static final int UPDATE_TIMES_HUNDRED = 100;
 
+    /**
+     * Signature algorithms to test
+     */
+    private static final String[] SIGN_ALG = {"MD2withRSA", "MD5withRSA",
+        "SHA1withRSA", "SHA256withRSA"};
+
     public static void main(String[] args) throws Exception {
-        String testAlg = args[0];
-        int testSize = Integer.parseInt(args[1]);
+        int testSize = Integer.parseInt(args[0]);
 
         byte[] data = new byte[100];
-        RandomFactory.getRandom().nextBytes(data);
+        IntStream.range(0, data.length).forEach(j -> {
+            data[j] = (byte) j;
+        });
 
         // create a key pair
         KeyPair kpair = generateKeys(KEYALG, testSize);
@@ -115,16 +99,17 @@ public class SignatureTest {
         // For signature algorithm, create and verify a signature
 
         Arrays.stream(privs).forEach(priv
-                -> Arrays.stream(pubs).forEach(pub -> {
-                    try {
-                        checkSignature(data, (PublicKey) pub, (PrivateKey) priv,
-                                testAlg);
-                    } catch (NoSuchAlgorithmException | InvalidKeyException
-                            | SignatureException | NoSuchProviderException ex) {
-                        throw new RuntimeException(ex);
-                    }
-                }
-                ));
+                -> Arrays.stream(pubs).forEach(pub
+                -> Arrays.stream(SIGN_ALG).forEach(testAlg -> {
+            try {
+                checkSignature(data, (PublicKey) pub, (PrivateKey) priv,
+                        testAlg);
+            } catch (NoSuchAlgorithmException | InvalidKeyException |
+                    SignatureException | NoSuchProviderException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+        )));
 
     }
 
diff --git a/jdk/test/sun/security/x509/AlgorithmId/OidTableInit.java b/jdk/test/sun/security/x509/AlgorithmId/OidTableInit.java
new file mode 100644
index 00000000000..779ddba6eb3
--- /dev/null
+++ b/jdk/test/sun/security/x509/AlgorithmId/OidTableInit.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Google Inc. 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 8156584
+ * @modules java.base/sun.security.x509
+ * @summary AlgorithmId.get initialization thread safety
+ * @run main/othervm OidTableInit
+ */
+
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import sun.security.x509.AlgorithmId;
+
+public class OidTableInit {
+    public static void main(String[] args) throws Throwable {
+        final String[] algorithmNames = {
+            "PBKDF2WITHHMACSHA1",
+            "PBEWITHMD5ANDDES",
+            "DSA",
+            "SHA384WITHRSA",
+            "RSA",
+            "SHA1WITHDSA",
+            "SHA512WITHRSA",
+            "MD2WITHRSA",
+            "PBEWITHSHA1ANDDESEDE",
+            "SHA1WITHRSA",
+            "DIFFIEHELLMAN",
+            "MD5WITHRSA",
+            "PBEWITHSHA1ANDRC2_40",
+            "SHA256WITHRSA",
+        };
+
+        final int THREADS = 2;
+        final ExecutorService pool = Executors.newFixedThreadPool(THREADS);
+        final CountDownLatch startingGate = new CountDownLatch(THREADS);
+        final Runnable r = new Runnable() { public void run() {
+            startingGate.countDown();
+            do {} while (startingGate.getCount() > 0);
+            try {
+                for (String algorithmName : algorithmNames)
+                    AlgorithmId.get(algorithmName);
+            } catch (Throwable fail) {
+                throw new AssertionError(fail);
+            }
+        }};
+        final ArrayList<Future<?>> futures = new ArrayList<>();
+        for (int i = 0; i < THREADS; i++)
+            futures.add(pool.submit(r));
+        pool.shutdown();
+        for (Future<?> future : futures) future.get();
+    }
+}
diff --git a/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java b/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java
index afba30c6055..b0f3b8d4f73 100644
--- a/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java
+++ b/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java
@@ -31,9 +31,12 @@
  * @run main BasicLauncherTest
  */
 
+import static jdk.testlibrary.Asserts.assertTrue;
+
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Arrays;
@@ -99,7 +102,7 @@ public class BasicLauncherTest {
 
         System.out.println("Starting LingeredApp");
         try {
-            theApp = LingeredApp.startApp();
+            theApp = LingeredApp.startApp(Arrays.asList("-Xmx256m"));
 
             System.out.println("Starting " + toolName + " " + toolArgs.get(0) + " against " + theApp.getPid());
             JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(toolName);
@@ -129,6 +132,21 @@ public class BasicLauncherTest {
         launch(expectedMessage, Arrays.asList(toolArgs));
     }
 
+    public static void testHeapDump() throws IOException {
+        File dump = new File("jhsdb.jmap.dump." +
+                             System.currentTimeMillis() + ".hprof");
+        if (dump.exists()) {
+            dump.delete();
+        }
+        dump.deleteOnExit();
+
+        launch("heap written to", "jmap",
+               "--binaryheap", "--dumpfile=" + dump.getAbsolutePath());
+
+        assertTrue(dump.exists() && dump.isFile(),
+                   "Could not create dump file " + dump.getAbsolutePath());
+    }
+
     public static void main(String[] args)
         throws IOException {
 
@@ -145,6 +163,8 @@ public class BasicLauncherTest {
         launch("Java System Properties", "jinfo");
         launch("java.threads", "jsnap");
 
+        testHeapDump();
+
         // The test throws RuntimeException on error.
         // IOException is thrown if LingeredApp can't start because of some bad
         // environment condition
diff --git a/jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java b/jdk/test/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java
similarity index 98%
rename from jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java
rename to jdk/test/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java
index 5a84b6261d6..c768dd6eb01 100644
--- a/jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java
+++ b/jdk/test/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java
@@ -36,9 +36,9 @@ import jdk.testlibrary.Platform;
  * @test
  * @bug 8042397
  * @summary Unit test for jmap utility test heap configuration reader
+ * @modules jdk.hotspot.agent/sun.jvm.hotspot
  * @library /test/lib/share/classes
  * @library /lib/testlibrary
- * @modules java.management
  * @build jdk.testlibrary.*
  * @build jdk.test.lib.apps.*
  * @build JMapHeapConfigTest TmtoolTestScenario
@@ -149,7 +149,7 @@ public class JMapHeapConfigTest {
         }
         cmd.add("-XX:+PrintFlagsFinal");
 
-        TmtoolTestScenario tmt = TmtoolTestScenario.create("jmap", "-heap");
+        TmtoolTestScenario tmt = TmtoolTestScenario.create("jmap", "--heap");
         int exitcode = tmt.launch(cmd);
         if (exitcode != 0) {
             throw new RuntimeException("Test FAILED jmap exits with non zero exit code " + exitcode);
diff --git a/jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java b/jdk/test/sun/tools/jhsdb/heapconfig/TmtoolTestScenario.java
similarity index 97%
rename from jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java
rename to jdk/test/sun/tools/jhsdb/heapconfig/TmtoolTestScenario.java
index 4558f3e346b..25beea66f72 100644
--- a/jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java
+++ b/jdk/test/sun/tools/jhsdb/heapconfig/TmtoolTestScenario.java
@@ -100,11 +100,13 @@ public class TmtoolTestScenario {
                 theApp = LingeredApp.startApp(vmArgsExtended);
 
                 System.out.println("Starting " + toolName + " against " + theApp.getPid());
-                JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(toolName);
+                JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
+                launcher.addToolArg(toolName);
 
                 for (String cmd : toolArgs) {
                     launcher.addToolArg(cmd);
                 }
+                launcher.addToolArg("--pid");
                 launcher.addToolArg(Long.toString(theApp.getPid()));
 
                 ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
diff --git a/jdk/test/sun/tools/jinfo/JInfoHelper.java b/jdk/test/sun/tools/jinfo/BasicJInfoTest.java
similarity index 51%
rename from jdk/test/sun/tools/jinfo/JInfoHelper.java
rename to jdk/test/sun/tools/jinfo/BasicJInfoTest.java
index 7f945136b4f..c612652f46b 100644
--- a/jdk/test/sun/tools/jinfo/JInfoHelper.java
+++ b/jdk/test/sun/tools/jinfo/BasicJInfoTest.java
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * 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.
+ * 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
@@ -29,41 +27,58 @@ import jdk.testlibrary.JDKToolLauncher;
 import jdk.testlibrary.OutputAnalyzer;
 import jdk.testlibrary.ProcessTools;
 
-/**
- *  The helper class for running jinfo utility.
+/*
+ * @test
+ * @summary Unit test for jinfo utility
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.*
+ * @run main BasicJInfoTest
  */
-public final class JInfoHelper {
+public class BasicJInfoTest {
 
-    /**
-     * Print configuration information for the current process
-     *
-     * @param toolArgs List of jinfo options
-     */
-    public static OutputAnalyzer jinfo(String... toolArgs) throws Exception {
-        return jinfo(true, toolArgs);
+    private static ProcessBuilder processBuilder = new ProcessBuilder();
+
+    public static void main(String[] args) throws Exception {
+        testJinfoNoArgs();
+        testJinfoFlags();
+        testJinfoProps();
+        testJinfoFlagInvalid();
     }
 
-    /**
-     * Print usage information
-     *
-     * @param toolArgs List of jinfo options
-     */
-    public static OutputAnalyzer jinfoNoPid(String... toolArgs) throws Exception {
-        return jinfo(false, toolArgs);
+    private static void testJinfoNoArgs() throws Exception {
+        OutputAnalyzer output = jinfo();
+        output.shouldContain("-XX");
+        output.shouldContain("test.jdk=");
+        output.shouldHaveExitValue(0);
     }
 
-    private static OutputAnalyzer jinfo(boolean toPid, String... toolArgs) throws Exception {
+    private static void testJinfoFlagInvalid() throws Exception {
+        OutputAnalyzer output = jinfo("-flag");
+        output.shouldHaveExitValue(1);
+    }
+
+    private static void testJinfoFlags() throws Exception {
+        OutputAnalyzer output = jinfo("-flags");
+        output.shouldContain("-XX");
+        output.shouldHaveExitValue(0);
+    }
+
+    private static void testJinfoProps() throws Exception {
+        OutputAnalyzer output = jinfo("-props");
+        output.shouldContain("test.jdk=");
+        output.shouldHaveExitValue(0);
+    }
+
+    private static OutputAnalyzer jinfo(String... toolArgs) throws Exception {
         JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jinfo");
         if (toolArgs != null) {
             for (String toolArg : toolArgs) {
                 launcher.addToolArg(toolArg);
             }
         }
-        if (toPid) {
-            launcher.addToolArg(Long.toString(ProcessTools.getProcessId()));
-        }
+        launcher.addToolArg(Long.toString(ProcessTools.getProcessId()));
 
-        ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+        processBuilder.command(launcher.getCommand());
         System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", ""));
         OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
         System.out.println(output.getOutput());
diff --git a/jdk/test/sun/tools/jinfo/JInfoLauncherTest.java b/jdk/test/sun/tools/jinfo/JInfoLauncherTest.java
deleted file mode 100644
index 09b4750d778..00000000000
--- a/jdk/test/sun/tools/jinfo/JInfoLauncherTest.java
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeClass;
-import sun.tools.jinfo.JInfo;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.util.Arrays;
-
-import static org.testng.Assert.*;
-
-/**
- * @test
- * @bug 8039080
- * @modules jdk.jcmd/sun.tools.jinfo
- * @run testng JInfoLauncherTest
- * @summary Test JInfo launcher argument parsing
- */
-@Test
-public class JInfoLauncherTest {
-    public static final String VALIDATION_EXCEPTION_CLSNAME =
-                                IllegalArgumentException.class.getName();
-
-    private Constructor<JInfo> jInfoConstructor;
-    private Field fldUseSA;
-
-    @BeforeClass
-    public void setup() throws Exception {
-        jInfoConstructor = JInfo.class.getDeclaredConstructor(String[].class);
-        jInfoConstructor.setAccessible(true);
-        fldUseSA = JInfo.class.getDeclaredField("useSA");
-        fldUseSA.setAccessible(true);
-    }
-
-    private JInfo newJInfo(String[] args) throws Exception {
-        try {
-            return jInfoConstructor.newInstance((Object) args);
-        } catch (Exception e) {
-            if (isValidationException(e.getCause())) {
-                throw (Exception)e.getCause();
-            }
-            throw e;
-        }
-    }
-
-    private boolean getUseSA(JInfo jinfo) throws Exception {
-        return fldUseSA.getBoolean(jinfo);
-    }
-
-    private void cmdPID(String cmd, String ... params) throws Exception {
-        int offset = (cmd != null ? 1 : 0);
-        String[] args = new String[offset + params.length];
-        args[0] = cmd;
-        System.arraycopy(params, 0, args, offset, params.length);
-        JInfo j = newJInfo(args);
-        assertFalse(getUseSA(j), "Local jinfo must not forward to SA");
-    }
-
-    private void cmdCore(String cmd, String ... params) throws Exception {
-        int offset = (cmd != null ? 1 : 0);
-        String[] args = new String[offset + params.length];
-        args[0] = cmd;
-        System.arraycopy(params, 0, args, offset, params.length);
-        JInfo j = newJInfo(args);
-        assertTrue(getUseSA(j), "Core jinfo must forward to SA");
-    }
-
-    private void cmdRemote(String cmd, String ... params) throws Exception {
-        int offset = (cmd != null ? 1 : 0);
-        String[] args = new String[offset + params.length];
-        args[0] = cmd;
-        System.arraycopy(params, 0, args, offset, params.length);
-        JInfo j = newJInfo(args);
-        assertTrue(getUseSA(j), "Remote jinfo must forward to SA");
-    }
-
-    private void cmdExtraArgs(String cmd, int argsLen) throws Exception {
-        String[] args = new String[argsLen + 1 + (cmd != null ? 1 : 0)];
-        Arrays.fill(args, "a");
-        if (cmd != null) {
-            args[0] = cmd;
-        } else {
-            cmd = "default";
-        }
-        try {
-            JInfo j = newJInfo(args);
-            fail("\"" + cmd + "\" does not support more than " + argsLen +
-                 " arguments");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    private void cmdMissingArgs(String cmd, int reqArgs) throws Exception {
-        String[] args = new String[reqArgs - 1 + (cmd != null ? 1 : 0)];
-        Arrays.fill(args, "a");
-        if (cmd != null) {
-            args[0] = cmd;
-        } else {
-            cmd = "default";
-        }
-        try {
-            JInfo j = newJInfo(args);
-            fail("\"" + cmd + "\" requires at least " + reqArgs + " argument");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    public void testDefaultPID() throws Exception {
-        cmdPID(null, "1234");
-    }
-
-    public void testFlagsPID() throws Exception {
-        cmdPID("-flags", "1234");
-    }
-
-    public void testSyspropsPID() throws Exception {
-        cmdPID("-sysprops", "1234");
-    }
-
-    public void testReadFlagPID() throws Exception {
-        cmdPID("-flag", "SomeManagementFlag", "1234");
-    }
-
-    public void testSetFlag1PID() throws Exception {
-        cmdPID("-flag", "+SomeManagementFlag", "1234");
-    }
-
-    public void testSetFlag2PID() throws Exception {
-        cmdPID("-flag", "-SomeManagementFlag", "1234");
-    }
-
-    public void testSetFlag3PID() throws Exception {
-        cmdPID("-flag", "SomeManagementFlag=314", "1234");
-    }
-
-    public void testDefaultCore() throws Exception {
-        cmdCore(null, "myapp.exe", "my.core");
-    }
-
-    public void testFlagsCore() throws Exception {
-        cmdCore("-flags", "myapp.exe", "my.core");
-    }
-
-    public void testSyspropsCore() throws Exception {
-        cmdCore("-sysprops", "myapp.exe", "my.core");
-    }
-
-    public void testReadFlagCore() throws Exception {
-        try {
-            cmdCore("-flag", "SomeManagementFlag", "myapp.exe", "my.core");
-            fail("Flags can not be read from core files");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    public void testSetFlag1Core() throws Exception {
-        try {
-            cmdCore("-flag", "+SomeManagementFlag", "myapp.exe", "my.core");
-            fail("Flags can not be set in core files");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    public void testSetFlag2Core() throws Exception {
-        try {
-            cmdCore("-flag", "-SomeManagementFlag", "myapp.exe", "my.core");
-            fail("Flags can not be set in core files");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    public void testSetFlag3Core() throws Exception {
-        try {
-            cmdCore("-flag", "SomeManagementFlag=314", "myapp.exe", "my.core");
-            fail("Flags can not be set in core files");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    public void testDefaultRemote() throws Exception {
-        cmdRemote(null, "serverid@host");
-    }
-
-    public void testFlagsRemote() throws Exception {
-        cmdRemote("-flags", "serverid@host");
-    }
-
-    public void testSyspropsRemote() throws Exception {
-        cmdRemote("-sysprops", "serverid@host");
-    }
-
-    public void testReadFlagRemote() throws Exception {
-        try {
-            cmdCore("-flag", "SomeManagementFlag", "serverid@host");
-            fail("Flags can not be read from SA server");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    public void testSetFlag1Remote() throws Exception {
-        try {
-            cmdCore("-flag", "+SomeManagementFlag","serverid@host");
-            fail("Flags can not be set on SA server");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    public void testSetFlag2Remote() throws Exception {
-        try {
-            cmdCore("-flag", "-SomeManagementFlag", "serverid@host");
-            fail("Flags can not be read set on SA server");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    public void testSetFlag3Remote() throws Exception {
-        try {
-            cmdCore("-flag", "SomeManagementFlag=314", "serverid@host");
-            fail("Flags can not be read set on SA server");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    public void testDefaultExtraArgs() throws Exception {
-        cmdExtraArgs(null, 2);
-    }
-
-    public void testFlagsExtraArgs() throws Exception {
-        cmdExtraArgs("-flags", 2);
-    }
-
-    public void testSyspropsExtraArgs() throws Exception {
-        cmdExtraArgs("-sysprops", 2);
-    }
-
-    public void testFlagExtraArgs() throws Exception {
-        cmdExtraArgs("-flag", 2);
-    }
-
-    public void testHelp1ExtraArgs() throws Exception {
-        cmdExtraArgs("-h", 0);
-    }
-
-    public void testHelp2ExtraArgs() throws Exception {
-        cmdExtraArgs("-help", 0);
-    }
-
-    public void testDefaultMissingArgs() throws Exception {
-        cmdMissingArgs(null, 1);
-    }
-
-    public void testFlagsMissingArgs() throws Exception {
-        cmdMissingArgs("-flags", 1);
-    }
-
-    public void testSyspropsMissingArgs() throws Exception {
-        cmdMissingArgs("-sysprops", 1);
-    }
-
-    public void testFlagMissingArgs() throws Exception {
-        cmdMissingArgs("-flag", 2);
-    }
-
-    public void testUnknownCommand() throws Exception {
-        try {
-            JInfo j = newJInfo(new String[]{"-unknown_command"});
-            fail("JInfo accepts unknown commands");
-        } catch (Exception e) {
-            if (!isValidationException(e)) {
-                throw e;
-            }
-            // ignore
-        }
-    }
-
-    private static boolean isValidationException(Throwable e) {
-        return e.getClass().getName().equals(VALIDATION_EXCEPTION_CLSNAME);
-    }
-}
diff --git a/jdk/test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java b/jdk/test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java
deleted file mode 100644
index cb28cc7a49f..00000000000
--- a/jdk/test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.lang.management.ManagementFactory;
-import com.sun.management.HotSpotDiagnosticMXBean;
-import jdk.testlibrary.OutputAnalyzer;
-import static jdk.testlibrary.Platform.isSolaris;
-import static jdk.testlibrary.Asserts.assertEquals;
-import static jdk.testlibrary.Asserts.assertNotEquals;
-import static jdk.testlibrary.Asserts.assertTrue;
-
-/**
- * @test
- * @summary The test sanity checks 'jinfo -flag' option.
- * @library /lib/testlibrary
- * @modules java.management
- * @build jdk.testlibrary.* JInfoHelper
- * @run main/othervm -XX:+HeapDumpOnOutOfMemoryError JInfoRunningProcessFlagTest
- */
-public class JInfoRunningProcessFlagTest {
-
-    public static void main(String[] args) throws Exception {
-        testFlag();
-        testFlagPlus();
-        testFlagMinus();
-        testFlagEqual();
-
-        testInvalidFlag();
-
-        testSolarisSpecificFlag();
-    }
-
-    private static void testFlag() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError");
-        output.shouldHaveExitValue(0);
-        assertTrue(output.getStderr().isEmpty(), "'jinfo -flag HeapDumpOnOutOfMemoryError' stderr should be empty");
-        output.shouldContain("+HeapDumpOnOutOfMemoryError");
-    }
-
-    private static void testFlagPlus() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfo("-flag", "+HeapDumpOnOutOfMemoryError");
-        output.shouldHaveExitValue(0);
-        output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError");
-        output.shouldHaveExitValue(0);
-        output.shouldContain("+HeapDumpOnOutOfMemoryError");
-        verifyIsEnabled("HeapDumpOnOutOfMemoryError");
-    }
-
-    private static void testFlagMinus() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfo("-flag", "-HeapDumpOnOutOfMemoryError");
-        output.shouldHaveExitValue(0);
-        output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError");
-        output.shouldHaveExitValue(0);
-        output.shouldContain("-HeapDumpOnOutOfMemoryError");
-        verifyIsDisabled("HeapDumpOnOutOfMemoryError");
-    }
-
-    private static void testFlagEqual() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError=1");
-        output.shouldHaveExitValue(0);
-        output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError");
-        output.shouldHaveExitValue(0);
-        output.shouldContain("+HeapDumpOnOutOfMemoryError");
-        verifyIsEnabled("HeapDumpOnOutOfMemoryError");
-    }
-
-    private static void testInvalidFlag() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfo("-flag", "monkey");
-        assertNotEquals(output.getExitValue(), 0, "A non-zero exit code should be returned for invalid flag");
-    }
-
-    private static void testSolarisSpecificFlag() throws Exception {
-        if (!isSolaris())
-            return;
-
-        OutputAnalyzer output = JInfoHelper.jinfo("-flag", "+ExtendedDTraceProbes");
-        output.shouldHaveExitValue(0);
-        output = JInfoHelper.jinfo();
-        output.shouldContain("+ExtendedDTraceProbes");
-        verifyIsEnabled("ExtendedDTraceProbes");
-
-        output = JInfoHelper.jinfo("-flag", "-ExtendedDTraceProbes");
-        output.shouldHaveExitValue(0);
-        output = JInfoHelper.jinfo();
-        output.shouldContain("-ExtendedDTraceProbes");
-        verifyIsDisabled("ExtendedDTraceProbes");
-
-        output = JInfoHelper.jinfo("-flag", "ExtendedDTraceProbes");
-        output.shouldContain("-ExtendedDTraceProbes");
-        output.shouldHaveExitValue(0);
-    }
-
-    private static void verifyIsEnabled(String flag) {
-        HotSpotDiagnosticMXBean hotspotDiagnostic =
-                ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
-        String flagValue = hotspotDiagnostic.getVMOption(flag).getValue();
-        assertEquals(flagValue, "true", "Expected '" + flag + "' flag be enabled");
-    }
-
-    private static void verifyIsDisabled(String flag) {
-        HotSpotDiagnosticMXBean hotspotDiagnostic =
-                ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
-        String flagValue = hotspotDiagnostic.getVMOption(flag).getValue();
-        assertEquals(flagValue, "false", "Expected '" + flag + "' flag be disabled");
-    }
-
-}
diff --git a/jdk/test/sun/tools/jinfo/JInfoRunningProcessTest.java b/jdk/test/sun/tools/jinfo/JInfoRunningProcessTest.java
deleted file mode 100644
index 633a2c99b51..00000000000
--- a/jdk/test/sun/tools/jinfo/JInfoRunningProcessTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import jdk.testlibrary.OutputAnalyzer;
-import static jdk.testlibrary.Asserts.assertTrue;
-
-/**
- * @test
- * @summary The test sanity checks functionality of 'jinfo', 'jinfo -sysprops' and 'jinfo -flags'
- * @library /lib/testlibrary
- * @modules java.management
- * @build jdk.testlibrary.* JInfoHelper
- * @run main/othervm -XX:+HeapDumpOnOutOfMemoryError JInfoRunningProcessTest
- */
-public class JInfoRunningProcessTest {
-
-    public static void main(String[] args) throws Exception {
-        testNoOptions();
-        testSysprops();
-        testFlags();
-    }
-
-    private static void testNoOptions() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfo();
-        output.shouldHaveExitValue(0);
-        assertTrue(output.getStderr().isEmpty(), "'jinfo' stderr should be empty");
-        output.shouldContain("+HeapDumpOnOutOfMemoryError");
-    }
-
-    private static void testSysprops() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfo("-sysprops");
-        output.shouldHaveExitValue(0);
-        assertTrue(output.getStderr().isEmpty(), "'jinfo -sysprops' stderr should be empty");
-    }
-
-    private static void testFlags() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfo("-flags");
-        output.shouldHaveExitValue(0);
-        assertTrue(output.getStderr().isEmpty(), "'jinfo -flags' stderr should be empty");
-        output.shouldContain("+HeapDumpOnOutOfMemoryError");
-    }
-
-}
diff --git a/jdk/test/sun/tools/jinfo/JInfoSanityTest.java b/jdk/test/sun/tools/jinfo/JInfoSanityTest.java
deleted file mode 100644
index 9b0bcf1b141..00000000000
--- a/jdk/test/sun/tools/jinfo/JInfoSanityTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import static jdk.testlibrary.Asserts.assertNotEquals;
-import static jdk.testlibrary.Asserts.assertTrue;
-import static jdk.testlibrary.Asserts.assertFalse;
-import jdk.testlibrary.OutputAnalyzer;
-
-/**
- * @test
- * @summary The test sanity checks functionality of 'jinfo -h', 'jinfo -help',
- *          and verifies jinfo exits abnormally if started with invalid options.
- * @library /lib/testlibrary
- * @modules java.management
- * @build jdk.testlibrary.* JInfoHelper
- * @run main JInfoSanityTest
- */
-public class JInfoSanityTest {
-
-    public static void main(String[] args) throws Exception {
-        test_h();
-        test_help();
-        testVersion();
-        testUnknownHost();
-    }
-
-    private static void test_h() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfoNoPid("-h");
-        output.shouldHaveExitValue(0);
-        assertFalse(output.getStderr().isEmpty(), "'jinfo -h' stderr should not be empty");
-        assertTrue(output.getStdout().isEmpty(), "'jinfo -h' stdout should be empty");
-    }
-
-    private static void test_help() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfoNoPid("-help");
-        output.shouldHaveExitValue(0);
-        assertFalse(output.getStderr().isEmpty(), "'jinfo -help' stderr should not be empty");
-        assertTrue(output.getStdout().isEmpty(), "'jinfo -help' stdout should be empty");
-    }
-
-    private static void testVersion() throws Exception {
-        OutputAnalyzer output = JInfoHelper.jinfoNoPid("-version");
-        output.shouldHaveExitValue(1);
-        assertFalse(output.getStderr().isEmpty(), "'jinfo -version' stderr should not be empty");
-        assertTrue(output.getStdout().isEmpty(), "'jinfo -version' stdout should be empty");
-    }
-
-    private static void testUnknownHost() throws Exception {
-        String unknownHost = "Oja781nh2ev7vcvbajdg-Sda1-C";
-        OutputAnalyzer output = JInfoHelper.jinfoNoPid("med@" + unknownHost);
-        assertNotEquals(output.getExitValue(), 0, "A non-zero exit code should be returned for invalid operation");
-        output.shouldMatch(".*(Connection refused to host\\:|UnknownHostException\\:) " + unknownHost + ".*");
-    }
-
-}
diff --git a/jdk/test/sun/tools/jmap/BasicJMapTest.java b/jdk/test/sun/tools/jmap/BasicJMapTest.java
index 75c80a2eec3..fa333cddea7 100644
--- a/jdk/test/sun/tools/jmap/BasicJMapTest.java
+++ b/jdk/test/sun/tools/jmap/BasicJMapTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,12 +34,10 @@ import jdk.testlibrary.ProcessTools;
 
 /*
  * @test
- * @bug 6321286
  * @summary Unit test for jmap utility
  * @key intermittent
  * @library /lib/testlibrary
  * @library /test/lib/share/classes
- * @modules java.management
  * @build jdk.testlibrary.*
  * @build jdk.test.lib.hprof.*
  * @build jdk.test.lib.hprof.model.*
@@ -54,6 +52,8 @@ public class BasicJMapTest {
     public static void main(String[] args) throws Exception {
         testHisto();
         testHistoLive();
+        testFinalizerInfo();
+        testClstats();
         testDump();
         testDumpLive();
     }
@@ -68,6 +68,16 @@ public class BasicJMapTest {
         output.shouldHaveExitValue(0);
     }
 
+    private static void testFinalizerInfo() throws Exception {
+        OutputAnalyzer output = jmap("-finalizerinfo");
+        output.shouldHaveExitValue(0);
+    }
+
+    private static void testClstats() throws Exception {
+        OutputAnalyzer output = jmap("-clstats");
+        output.shouldHaveExitValue(0);
+    }
+
     private static void testDump() throws Exception {
         dump(false);
     }
@@ -105,7 +115,6 @@ public class BasicJMapTest {
 
     private static OutputAnalyzer jmap(String... toolArgs) throws Exception {
         JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jmap");
-        launcher.addVMArg("-XX:+UsePerfData");
         if (toolArgs != null) {
             for (String toolArg : toolArgs) {
                 launcher.addToolArg(toolArg);
diff --git a/jdk/test/sun/tools/jstack/BasicJStackTest.java b/jdk/test/sun/tools/jstack/BasicJStackTest.java
index 9fd0b66b578..997876a54c5 100644
--- a/jdk/test/sun/tools/jstack/BasicJStackTest.java
+++ b/jdk/test/sun/tools/jstack/BasicJStackTest.java
@@ -29,10 +29,8 @@ import jdk.testlibrary.ProcessTools;
 
 /*
  * @test
- * @bug 6260070
  * @summary Unit test for jstack utility
  * @library /lib/testlibrary
- * @modules java.management
  * @build jdk.testlibrary.*
  * @run main BasicJStackTest
  */
diff --git a/jdk/test/sun/tools/jstack/DeadlockDetectionTest.java b/jdk/test/sun/tools/jstack/DeadlockDetectionTest.java
index 4ff2508673b..771fd128ff7 100644
--- a/jdk/test/sun/tools/jstack/DeadlockDetectionTest.java
+++ b/jdk/test/sun/tools/jstack/DeadlockDetectionTest.java
@@ -39,7 +39,6 @@ import jdk.testlibrary.ProcessTools;
  * @summary Test deadlock detection
  * @library /test/lib/share/classes
  * @library /lib/testlibrary
- * @modules java.management
  * @build jdk.testlibrary.*
  * @build jdk.test.lib.apps.*
  * @build DeadlockDetectionTest
diff --git a/jdk/test/sun/util/logging/PlatformLoggerTest.java b/jdk/test/sun/util/logging/PlatformLoggerTest.java
index 530a2acea8a..4fbf0c95c2d 100644
--- a/jdk/test/sun/util/logging/PlatformLoggerTest.java
+++ b/jdk/test/sun/util/logging/PlatformLoggerTest.java
@@ -31,7 +31,6 @@
  *
  * @modules java.base/sun.util.logging
  *          java.logging/sun.util.logging.internal
- * @compile -XDignore.symbol.file PlatformLoggerTest.java
  * @run main/othervm PlatformLoggerTest
  */
 
@@ -42,25 +41,31 @@ import sun.util.logging.PlatformLogger;
 import static sun.util.logging.PlatformLogger.Level.*;
 
 public class PlatformLoggerTest {
+
+    static Logger logger;
+    static PlatformLogger bar;
+    static PlatformLogger goo;
+    static PlatformLogger foo;
+
     public static void main(String[] args) throws Exception {
         final String FOO_PLATFORM_LOGGER = "test.platformlogger.foo";
         final String BAR_PLATFORM_LOGGER = "test.platformlogger.bar";
         final String GOO_PLATFORM_LOGGER = "test.platformlogger.goo";
         final String BAR_LOGGER = "test.logger.bar";
-        PlatformLogger goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER);
+        goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER);
         // test the PlatformLogger methods
         testLogMethods(goo);
 
         // Create a platform logger using the default
-        PlatformLogger foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER);
+        foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER);
         checkPlatformLogger(foo, FOO_PLATFORM_LOGGER);
 
         // create a java.util.logging.Logger
         // now java.util.logging.Logger should be created for each platform logger
-        Logger logger = Logger.getLogger(BAR_LOGGER);
+        logger = Logger.getLogger(BAR_LOGGER);
         logger.setLevel(Level.WARNING);
 
-        PlatformLogger bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER);
+        bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER);
         checkPlatformLogger(bar, BAR_PLATFORM_LOGGER);
 
         // test the PlatformLogger methods
diff --git a/jdk/test/tools/jimage/VerifyJimage.java b/jdk/test/tools/jimage/VerifyJimage.java
index 9c33cc3fa74..5056e6322a5 100644
--- a/jdk/test/tools/jimage/VerifyJimage.java
+++ b/jdk/test/tools/jimage/VerifyJimage.java
@@ -188,7 +188,11 @@ public class VerifyJimage {
                         String cn = removeModule(n).replaceAll("\\.class$", "").replace('/', '.');
                         count.incrementAndGet();
                         try {
+                            System.out.println("Loading " + cn);
                             Class.forName(cn, false, loader);
+                        } catch (VerifyError ve) {
+                            System.err.println("VerifyError for " + cn);
+                            failed.add(reader.imageName() + ": " + cn + " not verified: " + ve.getMessage());
                         } catch (ClassNotFoundException e) {
                             failed.add(reader.imageName() + ": " + cn + " not found");
                         }
diff --git a/jdk/test/tools/jlink/DefaultProviderTest.java b/jdk/test/tools/jlink/DefaultProviderTest.java
index 22c68287d5c..c10e9d37060 100644
--- a/jdk/test/tools/jlink/DefaultProviderTest.java
+++ b/jdk/test/tools/jlink/DefaultProviderTest.java
@@ -33,7 +33,7 @@ import java.util.Set;
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import tests.Helper;
 
@@ -65,26 +65,26 @@ public class DefaultProviderTest {
         private boolean enabled = true;
 
         @Override
-        public Set<PluginType> getType() {
-            Set<PluginType> set = new HashSet<>();
-            set.add(CATEGORY.TRANSFORMER);
+        public Set<Category> getType() {
+            Set<Category> set = new HashSet<>();
+            set.add(Category.TRANSFORMER);
             return Collections.unmodifiableSet(set);
         }
 
         @Override
-        public Set<STATE> getState() {
-             return enabled ? EnumSet.of(STATE.AUTO_ENABLED, STATE.FUNCTIONAL)
-                : EnumSet.of(STATE.DISABLED);
+        public Set<State> getState() {
+             return enabled ? EnumSet.of(State.AUTO_ENABLED, State.FUNCTIONAL)
+                : EnumSet.of(State.DISABLED);
         }
 
         @Override
-        public void visit(Pool in, Pool out) {
+        public void visit(ModulePool in, ModulePool out) {
             if (!enabled) {
                 throw new PluginException(NAME + " was set");
             }
 
             DefaultProviderTest.isNewPluginsCalled = true;
-            in.visit((Pool.ModuleData content) -> {
+            in.transformAndCopy(content -> {
                 return content;
             }, out);
         }
diff --git a/jdk/test/tools/jlink/ImageFileCreatorTest.java b/jdk/test/tools/jlink/ImageFileCreatorTest.java
index 449d950d04d..8e093c69459 100644
--- a/jdk/test/tools/jlink/ImageFileCreatorTest.java
+++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java
@@ -39,7 +39,7 @@ import jdk.tools.jlink.internal.ImageFileCreator;
 import jdk.tools.jlink.internal.ImagePluginStack;
 import jdk.tools.jlink.plugin.ExecutableImage;
 import jdk.tools.jlink.builder.ImageBuilder;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModulePool;
 
 
 /*
@@ -47,6 +47,7 @@ import jdk.tools.jlink.plugin.Pool;
  * @summary ImageFileCreator class test
  * @author Jean-Francois Denise
  * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.builder
  *          java.base/jdk.internal.jimage
  * @run main/othervm -verbose:gc -Xmx1g ImageFileCreatorTest
  */
@@ -214,7 +215,7 @@ public class ImageFileCreatorTest {
             }
 
             @Override
-            public void storeFiles(Pool content) {
+            public void storeFiles(ModulePool content) {
             }
         };
 
diff --git a/jdk/test/tools/jlink/ImageFilePoolTest.java b/jdk/test/tools/jlink/ImageFilePoolTest.java
index 7d35f9da8d6..1ea0fada3d7 100644
--- a/jdk/test/tools/jlink/ImageFilePoolTest.java
+++ b/jdk/test/tools/jlink/ImageFilePoolTest.java
@@ -31,11 +31,12 @@
  */
 
 import java.io.ByteArrayInputStream;
-import jdk.tools.jlink.internal.PoolImpl;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
-import jdk.tools.jlink.plugin.Pool.Visitor;
+import java.util.Optional;
+import java.util.function.Function;
+import jdk.tools.jlink.internal.ModuleEntryImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class ImageFilePoolTest {
     public static void main(String[] args) throws Exception {
@@ -50,45 +51,45 @@ public class ImageFilePoolTest {
     private static final String SUFFIX = "END";
 
     private void checkVisitor() throws Exception {
-        Pool input = new PoolImpl();
+        ModulePool input = new ModulePoolImpl();
         for (int i = 0; i < 1000; ++i) {
             String module = "module" + (i / 100);
             input.add(new InMemoryImageFile(module, "/" + module + "/java/class" + i,
-                    ModuleDataType.CONFIG, "class" + i));
+                    ModuleEntry.Type.CONFIG, "class" + i));
         }
-        if (input.getContent().size() != 1000) {
+        if (input.getEntryCount() != 1000) {
             throw new AssertionError();
         }
-        Pool output = new PoolImpl();
+        ModulePool output = new ModulePoolImpl();
         ResourceVisitor visitor = new ResourceVisitor();
-        input.visit(visitor, output);
+        input.transformAndCopy(visitor, output);
         if (visitor.getAmountBefore() == 0) {
             throw new AssertionError("Resources not found");
         }
-        if (visitor.getAmountBefore() != input.getContent().size()) {
+        if (visitor.getAmountBefore() != input.getEntryCount()) {
             throw new AssertionError("Number of visited resources. Expected: " +
-                    visitor.getAmountBefore() + ", got: " + input.getContent().size());
+                    visitor.getAmountBefore() + ", got: " + input.getEntryCount());
         }
-        if (visitor.getAmountAfter() != output.getContent().size()) {
+        if (visitor.getAmountAfter() != output.getEntryCount()) {
             throw new AssertionError("Number of added resources. Expected: " +
-                    visitor.getAmountAfter() + ", got: " + output.getContent().size());
+                    visitor.getAmountAfter() + ", got: " + output.getEntryCount());
         }
-        for (ModuleData outFile : output.getContent()) {
+        output.entries().forEach(outFile -> {
             String path = outFile.getPath().replaceAll(SUFFIX + "$", "");
-            ModuleData inFile = input.get(path);
-            if (inFile == null) {
+            Optional<ModuleEntry> inFile = input.findEntry(path);
+            if (!inFile.isPresent()) {
                 throw new AssertionError("Unknown resource: " + path);
             }
-        }
+        });
     }
 
-    private static class ResourceVisitor implements Visitor {
+    private static class ResourceVisitor implements Function<ModuleEntry, ModuleEntry> {
 
         private int amountBefore;
         private int amountAfter;
 
         @Override
-        public ModuleData visit(ModuleData file) {
+        public ModuleEntry apply(ModuleEntry file) {
             int index = ++amountBefore % 3;
             switch (index) {
                 case 0:
@@ -113,7 +114,7 @@ public class ImageFilePoolTest {
     }
 
     private void checkNegative() throws Exception {
-        PoolImpl input = new PoolImpl();
+        ModulePoolImpl input = new ModulePoolImpl();
         try {
             input.add(null);
             throw new AssertionError("NullPointerException is not thrown");
@@ -126,30 +127,30 @@ public class ImageFilePoolTest {
         } catch (NullPointerException e) {
             // expected
         }
-        if (input.get("unknown") != null) {
-            throw new AssertionError("ImageFilePool does not return null for unknown file");
+        if (input.findEntry("unknown").isPresent()) {
+            throw new AssertionError("ImageFileModulePool does not return null for unknown file");
         }
-        if (input.contains(new InMemoryImageFile("", "unknown", ModuleDataType.CONFIG, "unknown"))) {
+        if (input.contains(new InMemoryImageFile("", "unknown", ModuleEntry.Type.CONFIG, "unknown"))) {
             throw new AssertionError("'contain' returns true for unknown file");
         }
-        input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleDataType.CONFIG, ""));
+        input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleEntry.Type.CONFIG, ""));
         try {
-            input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleDataType.CONFIG, ""));
+            input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleEntry.Type.CONFIG, ""));
             throw new AssertionError("Exception expected");
         } catch (Exception e) {
             // expected
         }
         input.setReadOnly();
         try {
-            input.add(new InMemoryImageFile("", "/aaa/ccc", ModuleDataType.CONFIG, ""));
+            input.add(new InMemoryImageFile("", "/aaa/ccc", ModuleEntry.Type.CONFIG, ""));
             throw new AssertionError("Exception expected");
         } catch (Exception e) {
             // expected
         }
     }
 
-    private static class InMemoryImageFile extends ModuleData {
-        public InMemoryImageFile(String module, String path, ModuleDataType type, String content) {
+    private static class InMemoryImageFile extends ModuleEntryImpl {
+        public InMemoryImageFile(String module, String path, ModuleEntry.Type type, String content) {
             super(module, path, type, new ByteArrayInputStream(content.getBytes()), content.getBytes().length);
         }
     }
diff --git a/jdk/test/tools/jlink/IntegrationTest.java b/jdk/test/tools/jlink/IntegrationTest.java
index 951c16cff74..e5637b421a8 100644
--- a/jdk/test/tools/jlink/IntegrationTest.java
+++ b/jdk/test/tools/jlink/IntegrationTest.java
@@ -39,7 +39,7 @@ import jdk.tools.jlink.Jlink.JlinkConfiguration;
 import jdk.tools.jlink.Jlink.PluginsConfiguration;
 import jdk.tools.jlink.builder.DefaultImageBuilder;
 import jdk.tools.jlink.plugin.ExecutableImage;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.PostProcessorPlugin;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
@@ -56,6 +56,8 @@ import tests.JImageGenerator;
  * @library ../lib
  * @modules java.base/jdk.internal.jimage
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink
+ *          jdk.jlink/jdk.tools.jlink.builder
  *          jdk.jlink/jdk.tools.jlink.internal
  *          jdk.jlink/jdk.tools.jlink.internal.plugins
  *          jdk.jlink/jdk.tools.jmod
@@ -88,9 +90,9 @@ public class IntegrationTest {
         }
 
         @Override
-        public Set<PluginType> getType() {
-            Set<PluginType> set = new HashSet<>();
-            set.add(CATEGORY.PROCESSOR);
+        public Set<Category> getType() {
+            Set<Category> set = new HashSet<>();
+            set.add(Category.PROCESSOR);
             return Collections.unmodifiableSet(set);
         }
 
@@ -128,18 +130,18 @@ public class IntegrationTest {
         }
 
         @Override
-        public void visit(Pool in, Pool out) {
+        public void visit(ModulePool in, ModulePool out) {
             System.err.println(NAME + index);
             ordered.add(index);
-            in.visit((file) -> {
+            in.transformAndCopy((file) -> {
                 return file;
             }, out);
         }
 
         @Override
-        public Set<PluginType> getType() {
-            Set<PluginType> set = new HashSet<>();
-            set.add(CATEGORY.TRANSFORMER);
+        public Set<Category> getType() {
+            Set<Category> set = new HashSet<>();
+            set.add(Category.TRANSFORMER);
             return Collections.unmodifiableSet(set);
         }
 
diff --git a/jdk/test/tools/jlink/JLinkOptimTest.java b/jdk/test/tools/jlink/JLinkOptimTest.java
index 82c5431f034..acc089c89c0 100644
--- a/jdk/test/tools/jlink/JLinkOptimTest.java
+++ b/jdk/test/tools/jlink/JLinkOptimTest.java
@@ -23,15 +23,15 @@ 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.PluginRepository;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.internal.plugins.OptimizationPlugin;
 import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
 import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
 import jdk.tools.jlink.internal.plugins.asm.AsmPools;
 import jdk.tools.jlink.internal.plugins.optim.ControlFlow;
 import jdk.tools.jlink.internal.plugins.optim.ControlFlow.Block;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 import tests.Helper;
 import tests.JImageGenerator;
@@ -134,9 +134,9 @@ public class JLinkOptimTest {
         }
 
         @Override
-        public Set<PluginType> getType() {
-            Set<PluginType> set = new HashSet<>();
-            set.add(CATEGORY.TRANSFORMER);
+        public Set<Category> getType() {
+            Set<Category> set = new HashSet<>();
+            set.add(Category.TRANSFORMER);
             return Collections.unmodifiableSet(set);
         }
     }
@@ -150,13 +150,13 @@ public class JLinkOptimTest {
         FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
         Path root = fs.getPath("/modules/java.base");
         // Access module-info.class to be reused as fake module-info.class
-        List<ModuleData> javabaseResources = new ArrayList<>();
+        List<ModuleEntry> javabaseResources = new ArrayList<>();
         try (Stream<Path> stream = Files.walk(root)) {
             for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext();) {
                 Path p = iterator.next();
                 if (Files.isRegularFile(p)) {
                     try {
-                        javabaseResources.add(Pool.newResource(p.toString().
+                        javabaseResources.add(ModuleEntry.create(p.toString().
                                 substring("/modules".length()), Files.readAllBytes(p)));
                     } catch (Exception ex) {
                         throw new RuntimeException(ex);
@@ -166,18 +166,18 @@ public class JLinkOptimTest {
         }
 
         //forName folding
-        PoolImpl pool = new PoolImpl();
+        ModulePoolImpl pool = new ModulePoolImpl();
         byte[] content = Files.readAllBytes(classes.
                 resolve("optim").resolve("ForNameTestCase.class"));
         byte[] content2 = Files.readAllBytes(classes.
                 resolve("optim").resolve("AType.class"));
         byte[] mcontent = Files.readAllBytes(classes.resolve("module-info.class"));
 
-        pool.add(Pool.newResource("/optimplugin/optim/ForNameTestCase.class", content));
-        pool.add(Pool.newResource("/optimplugin/optim/AType.class", content2));
-        pool.add(Pool.newResource("/optimplugin/module-info.class", mcontent));
+        pool.add(ModuleEntry.create("/optimplugin/optim/ForNameTestCase.class", content));
+        pool.add(ModuleEntry.create("/optimplugin/optim/AType.class", content2));
+        pool.add(ModuleEntry.create("/optimplugin/module-info.class", mcontent));
 
-        for (ModuleData r : javabaseResources) {
+        for (ModuleEntry r : javabaseResources) {
             pool.add(r);
         }
 
@@ -186,10 +186,10 @@ public class JLinkOptimTest {
         optional.put(OptimizationPlugin.NAME, OptimizationPlugin.FORNAME_REMOVAL);
         optional.put(OptimizationPlugin.LOG, "forName.log");
         plugin.configure(optional);
-        Pool out = new PoolImpl();
+        ModulePool out = new ModulePoolImpl();
         plugin.visit(pool, out);
 
-        ModuleData result = out.getContent().iterator().next();
+        ModuleEntry result = out.entries().iterator().next();
 
         ClassReader optimReader = new ClassReader(result.getBytes());
         ClassNode optimClass = new ClassNode();
diff --git a/jdk/test/tools/jlink/JLinkOptionsTest.java b/jdk/test/tools/jlink/JLinkOptionsTest.java
index 8c8d241f5b7..565c58bffa9 100644
--- a/jdk/test/tools/jlink/JLinkOptionsTest.java
+++ b/jdk/test/tools/jlink/JLinkOptionsTest.java
@@ -24,7 +24,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
@@ -62,7 +62,7 @@ public class JLinkOptionsTest {
         }
 
         @Override
-        public void visit(Pool in, Pool out) {
+        public void visit(ModulePool in, ModulePool out) {
 
         }
 
diff --git a/jdk/test/tools/jlink/JLinkPostProcessingTest.java b/jdk/test/tools/jlink/JLinkPostProcessingTest.java
index b32bf207ff2..abc2b58142e 100644
--- a/jdk/test/tools/jlink/JLinkPostProcessingTest.java
+++ b/jdk/test/tools/jlink/JLinkPostProcessingTest.java
@@ -75,9 +75,9 @@ public class JLinkPostProcessingTest {
         }
 
         @Override
-        public Set<PluginType> getType() {
-            Set<PluginType> set = new HashSet<>();
-            set.add(CATEGORY.PROCESSOR);
+        public Set<Category> getType() {
+            Set<Category> set = new HashSet<>();
+            set.add(Category.PROCESSOR);
             return Collections.unmodifiableSet(set);
         }
 
diff --git a/jdk/test/tools/jlink/ResourcePoolTest.java b/jdk/test/tools/jlink/ResourcePoolTest.java
index 77a82e5c1b2..523503c996a 100644
--- a/jdk/test/tools/jlink/ResourcePoolTest.java
+++ b/jdk/test/tools/jlink/ResourcePoolTest.java
@@ -37,14 +37,14 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
-
-import jdk.tools.jlink.internal.PoolImpl;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.Module;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
-import jdk.tools.jlink.plugin.Pool.Visitor;
+import java.util.function.Function;
+import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.LinkModule;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class ResourcePoolTest {
 
@@ -61,54 +61,53 @@ public class ResourcePoolTest {
     private static final String SUFFIX = "END";
 
     private void checkResourceVisitor() throws Exception {
-        Pool input = new PoolImpl();
+        ModulePool input = new ModulePoolImpl();
         for (int i = 0; i < 1000; ++i) {
             String module = "/module" + (i / 10);
             String resourcePath = module + "/java/package" + i;
             byte[] bytes = resourcePath.getBytes();
-            input.add(new ModuleData(module, resourcePath,
-                    ModuleDataType.CLASS_OR_RESOURCE,
+            input.add(ModuleEntry.create(module, resourcePath,
+                    ModuleEntry.Type.CLASS_OR_RESOURCE,
                     new ByteArrayInputStream(bytes), bytes.length));
         }
-        Pool output = new PoolImpl();
+        ModulePool output = new ModulePoolImpl();
         ResourceVisitor visitor = new ResourceVisitor();
-        input.visit(visitor, output);
+        input.transformAndCopy(visitor, output);
         if (visitor.getAmountBefore() == 0) {
             throw new AssertionError("Resources not found");
         }
-        if (visitor.getAmountBefore() != input.getContent().size()) {
+        if (visitor.getAmountBefore() != input.getEntryCount()) {
             throw new AssertionError("Number of visited resources. Expected: " +
-                    visitor.getAmountBefore() + ", got: " + input.getContent().size());
+                    visitor.getAmountBefore() + ", got: " + input.getEntryCount());
         }
-        if (visitor.getAmountAfter() != output.getContent().size()) {
+        if (visitor.getAmountAfter() != output.getEntryCount()) {
             throw new AssertionError("Number of added resources. Expected: " +
-                    visitor.getAmountAfter() + ", got: " + output.getContent().size());
+                    visitor.getAmountAfter() + ", got: " + output.getEntryCount());
         }
-        for (ModuleData outResource : output.getContent()) {
+        output.entries().forEach(outResource -> {
             String path = outResource.getPath().replaceAll(SUFFIX + "$", "");
-            ModuleData inResource = input.get(path);
-            if (inResource == null) {
+            if (!input.findEntry(path).isPresent()) {
                 throw new AssertionError("Unknown resource: " + path);
             }
-        }
+        });
     }
 
-    private static class ResourceVisitor implements Visitor {
+    private static class ResourceVisitor implements Function<ModuleEntry, ModuleEntry> {
 
         private int amountBefore;
         private int amountAfter;
 
         @Override
-        public ModuleData visit(ModuleData resource) {
+        public ModuleEntry apply(ModuleEntry resource) {
             int index = ++amountBefore % 3;
             switch (index) {
                 case 0:
                     ++amountAfter;
-                    return new ModuleData(resource.getModule(), resource.getPath() + SUFFIX,
+                    return ModuleEntry.create(resource.getModule(), resource.getPath() + SUFFIX,
                             resource.getType(), resource.stream(), resource.getLength());
                 case 1:
                     ++amountAfter;
-                    return new ModuleData(resource.getModule(), resource.getPath(),
+                    return ModuleEntry.create(resource.getModule(), resource.getPath(),
                             resource.getType(), resource.stream(), resource.getLength());
             }
             return null;
@@ -133,8 +132,8 @@ public class ResourcePoolTest {
         samples.add("javax/management/ObjectName");
         test(samples, (resources, module, path) -> {
             try {
-                resources.add(new ModuleData(module, path,
-                        ModuleDataType.CLASS_OR_RESOURCE,
+                resources.add(ModuleEntry.create(module, path,
+                        ModuleEntry.Type.CLASS_OR_RESOURCE,
                         new ByteArrayInputStream(new byte[0]), 0));
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
@@ -142,12 +141,12 @@ public class ResourcePoolTest {
         });
         test(samples, (resources, module, path) -> {
             try {
-                resources.add(PoolImpl.
-                        newCompressedResource(new ModuleData(module, path,
-                                ModuleDataType.CLASS_OR_RESOURCE,
+                resources.add(ModulePoolImpl.
+                        newCompressedResource(ModuleEntry.create(module, path,
+                                ModuleEntry.Type.CLASS_OR_RESOURCE,
                                 new ByteArrayInputStream(new byte[0]), 0),
                                 ByteBuffer.allocate(99), "bitcruncher", null,
-                                ((PoolImpl)resources).getStringTable(), ByteOrder.nativeOrder()));
+                                ((ModulePoolImpl)resources).getStringTable(), ByteOrder.nativeOrder()));
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -158,7 +157,7 @@ public class ResourcePoolTest {
         if (samples.isEmpty()) {
             throw new AssertionError("No sample to test");
         }
-        Pool resources = new PoolImpl();
+        ModulePool resources = new ModulePoolImpl();
         Set<String> modules = new HashSet<>();
         for (int i = 0; i < samples.size(); i++) {
             String module = samples.get(i);
@@ -173,70 +172,69 @@ public class ResourcePoolTest {
             i++;
             String clazz = samples.get(i);
             String path = "/" + module + "/" + clazz + ".class";
-            ModuleData res = resources.get(path);
-            checkModule(resources, res);
-            if (res == null) {
+            Optional<ModuleEntry> res = resources.findEntry(path);
+            if (!res.isPresent()) {
                 throw new AssertionError("Resource not found " + path);
             }
-            ModuleData res2 = resources.get(clazz);
-            if (res2 != null) {
+            checkModule(resources, res.get());
+            if (resources.findEntry(clazz).isPresent()) {
                 throw new AssertionError("Resource found " + clazz);
             }
         }
-        if (resources.getContent().size() != samples.size() / 2) {
+        if (resources.getEntryCount() != samples.size() / 2) {
             throw new AssertionError("Invalid number of resources");
         }
     }
 
-    private void checkModule(Pool resources, ModuleData res) {
-        Module m = resources.getModule(res.getModule());
-        if (m == null) {
+    private void checkModule(ModulePool resources, ModuleEntry res) {
+        Optional<LinkModule> optMod = resources.findModule(res.getModule());
+        if (!optMod.isPresent()) {
             throw new AssertionError("No module " + res.getModule());
         }
+        LinkModule m = optMod.get();
         if (!m.getName().equals(res.getModule())) {
             throw new AssertionError("Not right module name " + res.getModule());
         }
-        if (m.get(res.getPath()) == null) {
+        if (!m.findEntry(res.getPath()).isPresent()) {
             throw new AssertionError("resource " + res.getPath()
                     + " not in module " + m.getName());
         }
     }
 
     private void checkResourcesAfterCompression() throws Exception {
-        PoolImpl resources1 = new PoolImpl();
-        ModuleData res1 = new ModuleData("module1", "/module1/toto1",
-                ModuleDataType.CLASS_OR_RESOURCE,
+        ModulePoolImpl resources1 = new ModulePoolImpl();
+        ModuleEntry res1 = ModuleEntry.create("module1", "/module1/toto1",
+                ModuleEntry.Type.CLASS_OR_RESOURCE,
                 new ByteArrayInputStream(new byte[0]), 0);
-        ModuleData res2 = new ModuleData("module2", "/module2/toto1",
-                ModuleDataType.CLASS_OR_RESOURCE,
+        ModuleEntry res2 = ModuleEntry.create("module2", "/module2/toto1",
+                ModuleEntry.Type.CLASS_OR_RESOURCE,
                 new ByteArrayInputStream(new byte[0]), 0);
         resources1.add(res1);
         resources1.add(res2);
 
         checkResources(resources1, res1, res2);
-        Pool resources2 = new PoolImpl();
-        ModuleData res3 = new ModuleData("module2", "/module2/toto1",
-                ModuleDataType.CLASS_OR_RESOURCE,
+        ModulePool resources2 = new ModulePoolImpl();
+        ModuleEntry res3 = ModuleEntry.create("module2", "/module2/toto1",
+                ModuleEntry.Type.CLASS_OR_RESOURCE,
                 new ByteArrayInputStream(new byte[7]), 7);
         resources2.add(res3);
-        resources2.add(PoolImpl.newCompressedResource(res1,
+        resources2.add(ModulePoolImpl.newCompressedResource(res1,
                 ByteBuffer.allocate(7), "zip", null, resources1.getStringTable(),
                 ByteOrder.nativeOrder()));
         checkResources(resources2, res1, res2);
     }
 
-    private void checkResources(Pool resources, ModuleData... expected) {
-        Collection<Module> ms = resources.getModules();
+    private void checkResources(ModulePool resources, ModuleEntry... expected) {
         List<String> modules = new ArrayList();
-        for(Module m : ms) {
+        resources.modules().forEach(m -> {
             modules.add(m.getName());
-        }
-        for (ModuleData res : expected) {
+        });
+        for (ModuleEntry res : expected) {
             if (!resources.contains(res)) {
                 throw new AssertionError("Resource not found: " + res);
             }
 
-            if (resources.get(res.getPath()) == null) {
+            if (!resources.findEntry(res.getPath()).isPresent()) {
                 throw new AssertionError("Resource not found: " + res);
             }
 
@@ -244,7 +242,7 @@ public class ResourcePoolTest {
                 throw new AssertionError("Module not found: " + res.getModule());
             }
 
-            if (!resources.getContent().contains(res)) {
+            if (!resources.contains(res)) {
                 throw new AssertionError("Resources not found: " + res);
             }
 
@@ -260,17 +258,17 @@ public class ResourcePoolTest {
             throw new AssertionError("ReadOnly resources");
         }
 
-        ((PoolImpl) resources).setReadOnly();
+        ((ModulePoolImpl) resources).setReadOnly();
         try {
-            resources.add(new ModuleData("module2",  "/module2/toto1",
-                    ModuleDataType.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[0]), 0));
-            throw new AssertionError("Pool is read-only, but an exception is not thrown");
+            resources.add(ModuleEntry.create("module2",  "/module2/toto1",
+                    ModuleEntry.Type.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[0]), 0));
+            throw new AssertionError("ModulePool is read-only, but an exception is not thrown");
         } catch (Exception ex) {
             // Expected
         }
     }
 
     interface ResourceAdder {
-        void add(Pool resources, String module, String path);
+        void add(ModulePool resources, String module, String path);
     }
 }
diff --git a/jdk/test/tools/jlink/SecurityTest.java b/jdk/test/tools/jlink/SecurityTest.java
index 9497d6f3f34..dbf593bccc0 100644
--- a/jdk/test/tools/jlink/SecurityTest.java
+++ b/jdk/test/tools/jlink/SecurityTest.java
@@ -25,6 +25,7 @@
  * @test
  * @summary Test JlinkPermission
  * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink
  * @run main/othervm SecurityTest
  */
 
diff --git a/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java b/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java
index 6a414b57d63..4385534e07f 100644
--- a/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java
+++ b/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java
@@ -55,8 +55,8 @@ import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
 import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableClassPool;
 import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableResourcePool;
 import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class AddForgetResourcesTest extends AsmPluginTestBase {
 
@@ -82,7 +82,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
                 new ComboPlugin()
         };
         for (TestPlugin p : plugins) {
-            Pool out = p.visit(getPool());
+            ModulePool out = p.visit(getPool());
             p.test(getPool(), out);
         }
     }
@@ -124,7 +124,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
             AsmGlobalPool globalPool = pools.getGlobalPool();
             WritableClassPool transformedClasses = globalPool.getTransformedClasses();
             expected = globalPool.getClasses().size();
-            for (ModuleData res : globalPool.getClasses()) {
+            for (ModuleEntry res : globalPool.getClasses()) {
                 ClassReader reader = globalPool.getClassReader(res);
                 String className = reader.getClassName();
                 if (!className.endsWith("module-info")) {
@@ -137,14 +137,14 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool inResources, Pool outResources) {
-            Collection<ModuleData> inClasses = extractClasses(inResources);
-            Collection<ModuleData> outClasses = extractClasses(outResources);
+        public void test(ModulePool inResources, ModulePool outResources) {
+            Collection<ModuleEntry> inClasses = extractClasses(inResources);
+            Collection<ModuleEntry> outClasses = extractClasses(outResources);
             if (expected != outClasses.size()) {
                 throw new AssertionError("Classes were not added. Expected: " + expected
                         + ", got: " + outClasses.size());
             }
-            for (ModuleData in : inClasses) {
+            for (ModuleEntry in : inClasses) {
                 String path = in.getPath();
                 if (!outClasses.contains(in)) {
                     throw new AssertionError("Class not found: " + path);
@@ -153,7 +153,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
                     continue;
                 }
                 String modifiedPath = path.replace(".class", SUFFIX + ".class");
-                if (!outClasses.contains(Pool.newResource(modifiedPath, new byte[0]))) {
+                if (!outClasses.contains(ModuleEntry.create(modifiedPath, new byte[0]))) {
                     throw new AssertionError("Class not found: " + modifiedPath);
                 }
             }
@@ -166,7 +166,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         public void visit() {
             AsmPools pools = getPools();
             AsmGlobalPool globalPool = pools.getGlobalPool();
-            for (ModuleData res : globalPool.getResourceFiles()) {
+            for (ModuleEntry res : globalPool.getResourceFiles()) {
                 String path = res.getPath();
                 String moduleName = getModule(path);
                 AsmModulePool modulePool = pools.getModulePool(moduleName);
@@ -177,20 +177,20 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool in, Pool out) throws Exception {
-            Collection<ModuleData> inResources = extractResources(in);
-            Collection<ModuleData> outResources = extractResources(out);
+        public void test(ModulePool in, ModulePool out) throws Exception {
+            Collection<ModuleEntry> inResources = extractResources(in);
+            Collection<ModuleEntry> outResources = extractResources(out);
             if (2 * inResources.size() != outResources.size()) {
                 throw new AssertionError("Classes were not added. Expected: " + (2 * inResources.size())
                         + ", got: " + outResources.size());
             }
-            for (ModuleData r : inResources) {
+            for (ModuleEntry r : inResources) {
                 String path = r.getPath();
                 if (!outResources.contains(r)) {
                     throw new AssertionError("Class not found: " + path);
                 }
                 String modifiedPath = path + SUFFIX;
-                if (!outResources.contains(Pool.newResource(modifiedPath, new byte[0]))) {
+                if (!outResources.contains(ModuleEntry.create(modifiedPath, new byte[0]))) {
                     throw new AssertionError("Class not found: " + modifiedPath);
                 }
             }
@@ -204,7 +204,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
             AsmPools pools = getPools();
             AsmGlobalPool globalPool = pools.getGlobalPool();
             WritableClassPool transformedClasses = globalPool.getTransformedClasses();
-            for (ModuleData res : globalPool.getClasses()) {
+            for (ModuleEntry res : globalPool.getClasses()) {
                 ClassReader reader = globalPool.getClassReader(res);
                 ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
                 reader.accept(new AddMethodClassVisitor(writer), ClassReader.EXPAND_FRAMES);
@@ -213,14 +213,14 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool inResources, Pool outResources) throws Exception {
-            Collection<ModuleData> inClasses = extractClasses(inResources);
-            Collection<ModuleData> outClasses = extractClasses(outResources);
+        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
+            Collection<ModuleEntry> inClasses = extractClasses(inResources);
+            Collection<ModuleEntry> outClasses = extractClasses(outResources);
             if (inClasses.size() != outClasses.size()) {
                 throw new AssertionError("Number of classes. Expected: " + (inClasses.size())
                         + ", got: " + outClasses.size());
             }
-            for (ModuleData out : outClasses) {
+            for (ModuleEntry out : outClasses) {
                 String path = out.getPath();
                 if (!inClasses.contains(out)) {
                     throw new AssertionError("Class not found: " + path);
@@ -248,7 +248,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         public void visit() {
             AsmPools pools = getPools();
             AsmGlobalPool globalPool = pools.getGlobalPool();
-            for (ModuleData res : globalPool.getResourceFiles()) {
+            for (ModuleEntry res : globalPool.getResourceFiles()) {
                 String path = res.getPath();
                 AsmModulePool modulePool = pools.getModulePool(getModule(path));
                 modulePool.getTransformedResourceFiles().addResourceFile(new ResourceFile(removeModule(path),
@@ -257,14 +257,14 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool in, Pool out) throws Exception {
-            Collection<ModuleData> inResources = extractResources(in);
-            Collection<ModuleData> outResources = extractResources(out);
+        public void test(ModulePool in, ModulePool out) throws Exception {
+            Collection<ModuleEntry> inResources = extractResources(in);
+            Collection<ModuleEntry> outResources = extractResources(out);
             if (inResources.size() != outResources.size()) {
                 throw new AssertionError("Number of resources. Expected: " + inResources.size()
                         + ", got: " + outResources.size());
             }
-            for (ModuleData r : outResources) {
+            for (ModuleEntry r : outResources) {
                 String path = r.getPath();
                 if (!inResources.contains(r)) {
                     throw new AssertionError("Resource not found: " + path);
@@ -287,7 +287,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
             AsmGlobalPool globalPool = pools.getGlobalPool();
             WritableClassPool transformedClasses = globalPool.getTransformedClasses();
             int i = 0;
-            for (ModuleData res : globalPool.getClasses()) {
+            for (ModuleEntry res : globalPool.getClasses()) {
                 String path = removeModule(res.getPath());
                 String className = path.replace(".class", "");
                 if ((i & 1) == 0 && !className.endsWith("module-info")) {
@@ -300,8 +300,8 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool inResources, Pool outResources) throws Exception {
-            Collection<ModuleData> outClasses = extractClasses(outResources);
+        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
+            Collection<ModuleEntry> outClasses = extractClasses(outResources);
             if (expected != outClasses.size()) {
                 throw new AssertionError("Number of classes. Expected: " + expected +
                         ", got: " + outClasses.size());
@@ -318,7 +318,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
             AsmPools pools = getPools();
             AsmGlobalPool globalPool = pools.getGlobalPool();
             int i = 0;
-            for (ModuleData res : globalPool.getResourceFiles()) {
+            for (ModuleEntry res : globalPool.getResourceFiles()) {
                 String path = res.getPath();
                 if (!path.contains("META-INF/services")) {
                     if ((i & 1) == 0) {
@@ -335,8 +335,8 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool in, Pool out) throws Exception {
-            Collection<ModuleData> outResources = extractResources(out);
+        public void test(ModulePool in, ModulePool out) throws Exception {
+            Collection<ModuleEntry> outResources = extractResources(out);
             if (expectedAmount != outResources.size()) {
                 throw new AssertionError("Number of classes. Expected: " + expectedAmount
                         + ", got: " + outResources.size());
@@ -354,7 +354,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
             AsmGlobalPool globalPool = pools.getGlobalPool();
             WritableClassPool transformedClasses = globalPool.getTransformedClasses();
             int i = 0;
-            for (ModuleData res : globalPool.getClasses()) {
+            for (ModuleEntry res : globalPool.getClasses()) {
                 ClassReader reader = globalPool.getClassReader(res);
                 String className = reader.getClassName();
                 ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
@@ -374,8 +374,8 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool inResources, Pool outResources) throws Exception {
-            Collection<ModuleData> outClasses = extractClasses(outResources);
+        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
+            Collection<ModuleEntry> outClasses = extractClasses(outResources);
             if (expected != outClasses.size()) {
                 throw new AssertionError("Number of classes. Expected: " + expected
                         + ", got: " + outClasses.size());
@@ -392,7 +392,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
             AsmPools pools = getPools();
             AsmGlobalPool globalPool = pools.getGlobalPool();
             int i = 0;
-            for (ModuleData res : globalPool.getResourceFiles()) {
+            for (ModuleEntry res : globalPool.getResourceFiles()) {
                 String path = res.getPath();
                 String moduleName = getModule(path);
                 if (!path.contains("META-INF")) {
@@ -412,8 +412,8 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool inResources, Pool out) throws Exception {
-            Collection<ModuleData> outResources = extractResources(out);
+        public void test(ModulePool inResources, ModulePool out) throws Exception {
+            Collection<ModuleEntry> outResources = extractResources(out);
             if (expectedAmount != outResources.size()) {
                 throw new AssertionError("Number of classes. Expected: " + expectedAmount
                         + ", got: " + outResources.size());
@@ -446,7 +446,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool inResources, Pool outResources) throws Exception {
+        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
             if (!isVisitCalled()) {
                 throw new AssertionError("Resources not visited");
             }
@@ -455,7 +455,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
                 throw new AssertionError("Number of transformed classes not equal to expected");
             }
             // Check that only renamed classes and resource files are in the result.
-            for (ModuleData r : outResources.getContent()) {
+            outResources.entries().forEach(r -> {
                 String resourceName = r.getPath();
                 if (resourceName.endsWith(".class") && !resourceName.endsWith("module-info.class")) {
                     if (!resourceName.endsWith(SUFFIX + ".class")) {
@@ -467,7 +467,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
                         throw new AssertionError("Resource file not renamed " + resourceName);
                     }
                 }
-            }
+            });
         }
 
         private void renameResources() throws IOException {
@@ -476,7 +476,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
             for (Map.Entry<String, List<String>> mod : MODULES.entrySet()) {
                 String moduleName = mod.getKey();
                 AsmModulePool modulePool = pools.getModulePool(moduleName);
-                for (ModuleData res : modulePool.getResourceFiles()) {
+                for (ModuleEntry res : modulePool.getResourceFiles()) {
                     ResourceFile resFile = modulePool.getResourceFile(res);
                     if (resFile.getPath().startsWith("META-INF/services/")) {
                         String newContent = new String(resFile.getContent()) + SUFFIX;
@@ -492,7 +492,7 @@ public class AddForgetResourcesTest extends AsmPluginTestBase {
             AsmPools pools = getPools();
             AsmGlobalPool globalPool = pools.getGlobalPool();
             WritableClassPool transformedClasses = globalPool.getTransformedClasses();
-            for (ModuleData res : globalPool.getClasses()) {
+            for (ModuleEntry res : globalPool.getClasses()) {
                 if (res.getPath().endsWith("module-info.class")) {
                     continue;
                 }
diff --git a/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java b/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java
index d5c035562fa..c51419e682c 100644
--- a/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java
+++ b/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java
@@ -38,23 +38,23 @@ import java.util.Set;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.internal.StringTable;
 
 import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
 import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public abstract class AsmPluginTestBase {
 
     protected static final String TEST_MODULE = "jlink.test";
     protected static final Map<String, List<String>> MODULES;
 
-    private static final Predicate<ModuleData> isClass = r -> r.getPath().endsWith(".class");
+    private static final Predicate<ModuleEntry> isClass = r -> r.getPath().endsWith(".class");
     private final List<String> classes;
     private final List<String> resources;
-    private final Pool pool;
+    private final ModulePool pool;
 
     static {
         Map<String, List<String>> map = new HashMap<>();
@@ -75,7 +75,7 @@ public abstract class AsmPluginTestBase {
             List<String> classes = new ArrayList<>();
             List<String> resources = new ArrayList<>();
 
-            pool = new PoolImpl();
+            pool = new ModulePoolImpl();
 
             FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
             Path root = fs.getPath("/modules");
@@ -100,7 +100,7 @@ public abstract class AsmPluginTestBase {
                                     MODULES.get(module).add(toResourceFile(p));
                                 }
                                 resources.add(toPath(p.toString()));
-                                ModuleData res = Pool.newResource(toPath(p.toString()), content);
+                                ModuleEntry res = ModuleEntry.create(toPath(p.toString()), content);
                                 pool.add(res);
                             } catch (Exception ex) {
                                 throw new RuntimeException(ex);
@@ -110,17 +110,17 @@ public abstract class AsmPluginTestBase {
                 }
             }
             // There is more than 10 classes in java.base...
-            if (classes.size() < 10 || pool.getContent().size() < 10) {
+            if (classes.size() < 10 || pool.getEntryCount() < 10) {
                 throw new AssertionError("Not expected resource or class number");
             }
 
             //Add a fake resource file
             String content = "java.lang.Object";
             String path = "META-INF/services/com.foo.BarProvider";
-            ModuleData resFile = Pool.newResource("/" + TEST_MODULE + "/" +
+            ModuleEntry resFile = ModuleEntry.create("/" + TEST_MODULE + "/" +
                     path, content.getBytes());
             pool.add(resFile);
-            ModuleData fakeInfoFile = Pool.newResource("/" + TEST_MODULE
+            ModuleEntry fakeInfoFile = ModuleEntry.create("/" + TEST_MODULE
                     + "/module-info.class", moduleInfos.get(0));
             pool.add(fakeInfoFile);
             MODULES.get(TEST_MODULE).add(path);
@@ -144,20 +144,20 @@ public abstract class AsmPluginTestBase {
         return resources;
     }
 
-    public Pool getPool() {
+    public ModulePool getPool() {
         return pool;
     }
 
     public abstract void test() throws Exception;
 
-    public Collection<ModuleData> extractClasses(Pool pool) {
-        return pool.getContent().stream()
+    public Collection<ModuleEntry> extractClasses(ModulePool pool) {
+        return pool.entries()
                 .filter(isClass)
                 .collect(Collectors.toSet());
     }
 
-    public Collection<ModuleData> extractResources(Pool pool) {
-        return pool.getContent().stream()
+    public Collection<ModuleEntry> extractResources(ModulePool pool) {
+        return pool.entries()
                 .filter(isClass.negate())
                 .collect(Collectors.toSet());
     }
@@ -209,9 +209,9 @@ public abstract class AsmPluginTestBase {
             return pools != null;
         }
 
-        public Pool visit(Pool inResources) throws IOException {
+        public ModulePool visit(ModulePool inResources) throws IOException {
             try {
-                Pool outResources = new PoolImpl(inResources.getByteOrder(), new StringTable() {
+                ModulePool outResources = new ModulePoolImpl(inResources.getByteOrder(), new StringTable() {
                     @Override
                     public int addString(String str) {
                         return -1;
@@ -239,7 +239,7 @@ public abstract class AsmPluginTestBase {
         }
 
         public abstract void visit();
-        public abstract void test(Pool inResources, Pool outResources) throws Exception;
+        public abstract void test(ModulePool inResources, ModulePool outResources) throws Exception;
 
         @Override
         public String getName() {
diff --git a/jdk/test/tools/jlink/asmplugin/BasicTest.java b/jdk/test/tools/jlink/asmplugin/BasicTest.java
index 0c42d4cfb99..afc5fd5f634 100644
--- a/jdk/test/tools/jlink/asmplugin/BasicTest.java
+++ b/jdk/test/tools/jlink/asmplugin/BasicTest.java
@@ -45,8 +45,8 @@ import java.util.logging.Logger;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
 import jdk.tools.jlink.internal.plugins.asm.AsmPool;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class BasicTest extends AsmPluginTestBase {
 
@@ -61,7 +61,7 @@ public class BasicTest extends AsmPluginTestBase {
     @Override
     public void test() throws Exception {
         BasicPlugin basicPlugin = new BasicPlugin(getClasses());
-        Pool res = basicPlugin.visit(getPool());
+        ModulePool res = basicPlugin.visit(getPool());
         basicPlugin.test(getPool(), res);
     }
 
@@ -107,13 +107,13 @@ public class BasicTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool inResources, Pool outResources) throws Exception {
+        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
             if (!isVisitCalled()) {
                 throw new AssertionError("Resources not visited");
             }
-            if (inResources.getContent().size() != outResources.getContent().size()) {
-                throw new AssertionError("Input size " + inResources.getContent().size() +
-                        " != to " + outResources.getContent().size());
+            if (inResources.getEntryCount() != outResources.getEntryCount()) {
+                throw new AssertionError("Input size " + inResources.getEntryCount() +
+                        " != to " + outResources.getEntryCount());
             }
         }
 
@@ -142,7 +142,7 @@ public class BasicTest extends AsmPluginTestBase {
 
         private void testPools() throws IOException {
             Set<String> remain = new HashSet<>(classes);
-            for (ModuleData res : getPools().getGlobalPool().getClasses()) {
+            for (ModuleEntry res : getPools().getGlobalPool().getClasses()) {
                 ClassReader reader = getPools().getGlobalPool().getClassReader(res);
                 String className = reader.getClassName();
                 // Wrong naming of module-info.class in ASM
diff --git a/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java b/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java
index ceb2e50f9b9..416d3581552 100644
--- a/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java
+++ b/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java
@@ -35,14 +35,15 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassVisitor;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableClassPool;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class IdentityPluginTest extends AsmPluginTestBase {
 
@@ -56,7 +57,7 @@ public class IdentityPluginTest extends AsmPluginTestBase {
 
     public void test() throws Exception {
         IdentityPlugin asm = new IdentityPlugin();
-        Pool resourcePool = asm.visit(getPool());
+        ModulePool resourcePool = asm.visit(getPool());
         asm.test(getPool(), resourcePool);
     }
 
@@ -64,7 +65,7 @@ public class IdentityPluginTest extends AsmPluginTestBase {
 
         @Override
         public void visit() {
-            for (ModuleData res : getPools().getGlobalPool().getClasses()) {
+            for (ModuleEntry res : getPools().getGlobalPool().getClasses()) {
                 if (res.getPath().endsWith("module-info.class")) {
                     continue;
                 }
@@ -77,7 +78,7 @@ public class IdentityPluginTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool inResources, Pool outResources) throws IOException {
+        public void test(ModulePool inResources, ModulePool outResources) throws IOException {
             if (outResources.isEmpty()) {
                 throw new AssertionError("Empty result");
             }
@@ -93,13 +94,17 @@ public class IdentityPluginTest extends AsmPluginTestBase {
                     throw new AssertionError("Class not transformed " + className);
                 }
             }
-            for (ModuleData r : outResources.getContent()) {
+            outResources.entries().forEach(r -> {
                 if (r.getPath().endsWith(".class") && !r.getPath().endsWith("module-info.class")) {
-                    ClassReader reader = new ClassReader(new ByteArrayInputStream(r.getBytes()));
-                    ClassWriter w = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
-                    reader.accept(w, ClassReader.EXPAND_FRAMES);
+                    try {
+                        ClassReader reader = new ClassReader(new ByteArrayInputStream(r.getBytes()));
+                        ClassWriter w = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
+                        reader.accept(w, ClassReader.EXPAND_FRAMES);
+                    } catch (IOException exp) {
+                        throw new UncheckedIOException(exp);
+                    }
                 }
-            }
+            });
         }
 
         @Override
diff --git a/jdk/test/tools/jlink/asmplugin/NegativeTest.java b/jdk/test/tools/jlink/asmplugin/NegativeTest.java
index f95b7c62399..6263fcaaa4a 100644
--- a/jdk/test/tools/jlink/asmplugin/NegativeTest.java
+++ b/jdk/test/tools/jlink/asmplugin/NegativeTest.java
@@ -43,7 +43,7 @@ import jdk.internal.org.objectweb.asm.ClassVisitor;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.internal.StringTable;
 import jdk.tools.jlink.internal.plugins.asm.AsmGlobalPool;
 import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
@@ -51,7 +51,7 @@ import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
 import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
 import jdk.tools.jlink.internal.plugins.asm.AsmPools;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class NegativeTest extends AsmPluginTestBase {
     public static void main(String[] args) throws Exception {
@@ -102,7 +102,7 @@ public class NegativeTest extends AsmPluginTestBase {
                 }
             }
         };
-        Pool resources = new PoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() {
+        ModulePool resources = new ModulePoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() {
             @Override
             public int addString(String str) {
                 return -1;
@@ -136,7 +136,7 @@ public class NegativeTest extends AsmPluginTestBase {
                 action(() -> pools.fillOutputResources(null), "Output resource is null", NullPointerException.class);
             }
         };
-        Pool resources = new PoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() {
+        ModulePool resources = new ModulePoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() {
             @Override
             public int addString(String str) {
                 return -1;
diff --git a/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java b/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java
index 9453ac5f917..bd0a8fdbf4d 100644
--- a/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java
+++ b/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java
@@ -48,8 +48,8 @@ import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
 import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
 import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableResourcePool;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class PackageMappingTest extends AsmPluginTestBase {
 
@@ -72,7 +72,7 @@ public class PackageMappingTest extends AsmPluginTestBase {
             new PackageMappingPlugin(newFiles, true)
         };
         for (TestPlugin p : plugins) {
-            Pool pool = p.visit(getPool());
+            ModulePool pool = p.visit(getPool());
             p.test(getPool(), pool);
         }
     }
@@ -105,12 +105,12 @@ public class PackageMappingTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool inResources, Pool outResources) {
+        public void test(ModulePool inResources, ModulePool outResources) {
             Set<String> in = getPools().getGlobalPool().getResourceFiles().stream()
-                    .map(ModuleData::getPath)
+                    .map(ModuleEntry::getPath)
                     .collect(Collectors.toSet());
             Set<String> out = extractResources(outResources).stream()
-                    .map(ModuleData::getPath)
+                    .map(ModuleEntry::getPath)
                     .collect(Collectors.toSet());
             in.addAll(PackageMappingTest.this.newFiles);
             if (!Objects.equals(in, out)) {
diff --git a/jdk/test/tools/jlink/asmplugin/SortingTest.java b/jdk/test/tools/jlink/asmplugin/SortingTest.java
index 0fc4c7a6854..26974b3b065 100644
--- a/jdk/test/tools/jlink/asmplugin/SortingTest.java
+++ b/jdk/test/tools/jlink/asmplugin/SortingTest.java
@@ -35,12 +35,13 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class SortingTest extends AsmPluginTestBase {
 
@@ -66,7 +67,7 @@ public class SortingTest extends AsmPluginTestBase {
         List<String> sorted = new ArrayList<>(getResources());
         sorted.sort(null);
         ClassSorterPlugin sorterPlugin = new ClassSorterPlugin(sorted);
-        Pool resourcePool = sorterPlugin.visit(getPool());
+        ModulePool resourcePool = sorterPlugin.visit(getPool());
         sorterPlugin.test(getPool(), resourcePool);
     }
 
@@ -78,7 +79,7 @@ public class SortingTest extends AsmPluginTestBase {
         List<String> sorted = new ArrayList<>(getResources());
         sorted.sort((s1, s2) -> -getModuleName(s1).compareTo(getModuleName(s2)));
         ModuleSorterPlugin sorterPlugin = new ModuleSorterPlugin();
-        Pool resourcePool = sorterPlugin.visit(getPool());
+        ModulePool resourcePool = sorterPlugin.visit(getPool());
         sorterPlugin.test(getPool(), resourcePool);
     }
 
@@ -88,8 +89,8 @@ public class SortingTest extends AsmPluginTestBase {
         public void visit() {
             for (AsmModulePool modulePool : getPools().getModulePools()) {
                 modulePool.setSorter(resources -> {
-                    List<String> sort = resources.getContent().stream()
-                            .map(ModuleData::getPath)
+                    List<String> sort = resources.entries()
+                            .map(ModuleEntry::getPath)
                             .collect(Collectors.toList());
                     sort.sort(null);
                     return sort;
@@ -102,21 +103,21 @@ public class SortingTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool inResources, Pool outResources) throws Exception {
+        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
             if (!isVisitCalled()) {
                 throw new AssertionError("Resources not visited");
             }
-            List<String> sortedResourcePaths = outResources.getContent().stream()
-                    .map(ModuleData::getPath)
+            List<String> sortedResourcePaths = outResources.entries()
+                    .map(ModuleEntry::getPath)
                     .collect(Collectors.toList());
 
             List<String> defaultResourceOrder = new ArrayList<>();
-            for (ModuleData r : inResources.getContent()) {
-                if (!inResources.getContent().contains(r)) {
+            inResources.entries().forEach(r -> {
+                if (!inResources.contains(r)) {
                     throw new AssertionError("Resource " + r.getPath() + " not in result pool");
                 }
                 defaultResourceOrder.add(r.getPath());
-            }
+            });
             // Check that default sorting is not equal to sorted one
             if (defaultResourceOrder.equals(sortedResourcePaths)) {
                 throw new AssertionError("Sorting not applied, default ordering");
@@ -147,27 +148,28 @@ public class SortingTest extends AsmPluginTestBase {
         public void visit() {
             getPools().getGlobalPool().setSorter(
                     (resources) -> expectedClassesOrder.stream()
-                            .map(resources::get)
-                            .map(ModuleData::getPath)
+                            .map(resources::findEntry)
+                            .map(Optional::get)
+                            .map(ModuleEntry::getPath)
                             .collect(Collectors.toList()));
         }
 
         @Override
-        public void test(Pool inResources, Pool outResources) throws Exception {
+        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
             if (!isVisitCalled()) {
                 throw new AssertionError("Resources not visited");
             }
-            List<String> sortedResourcePaths = outResources.getContent().stream()
-                    .map(ModuleData::getPath)
+            List<String> sortedResourcePaths = outResources.entries()
+                    .map(ModuleEntry::getPath)
                     .collect(Collectors.toList());
 
             List<String> defaultResourceOrder = new ArrayList<>();
-            for (ModuleData r : getPool().getContent()) {
-                if (!getPool().getContent().contains(r)) {
+            getPool().entries().forEach(r -> {
+                if (!getPool().contains(r)) {
                     throw new AssertionError("Resource " + r.getPath() + " not in result pool");
                 }
                 defaultResourceOrder.add(r.getPath());
-            }
+            });
             // Check that default sorting is not equal to sorted one
             if (defaultResourceOrder.equals(sortedResourcePaths)) {
                 throw new AssertionError("Sorting not applied, default ordering");
diff --git a/jdk/test/tools/jlink/asmplugin/VisitorTest.java b/jdk/test/tools/jlink/asmplugin/VisitorTest.java
index 1b278a8bd48..500d415bc50 100644
--- a/jdk/test/tools/jlink/asmplugin/VisitorTest.java
+++ b/jdk/test/tools/jlink/asmplugin/VisitorTest.java
@@ -46,8 +46,8 @@ import jdk.tools.jlink.internal.plugins.asm.AsmPool.ClassReaderVisitor;
 import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
 import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFileVisitor;
 import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class VisitorTest extends AsmPluginTestBase {
 
@@ -69,7 +69,7 @@ public class VisitorTest extends AsmPluginTestBase {
         };
         for (TestPlugin p : plugins) {
             System.err.println("Testing: " + p.getName());
-            Pool out = p.visit(getPool());
+            ModulePool out = p.visit(getPool());
             p.test(getPool(), out);
         }
     }
@@ -149,15 +149,15 @@ public class VisitorTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool in, Pool out) throws Exception {
-            Collection<ModuleData> inClasses = getPool.apply(getPools()).getClasses();
+        public void test(ModulePool in, ModulePool out) throws Exception {
+            Collection<ModuleEntry> inClasses = getPool.apply(getPools()).getClasses();
             if (inClasses.size() != classReaderVisitor.getAmount()) {
                 throw new AssertionError("Testing " + name + ". Number of visited classes. Expected: " +
                         inClasses.size() + ", got: " + classReaderVisitor.getAmount());
             }
-            Collection<ModuleData> outClasses = extractClasses(out);
+            Collection<ModuleEntry> outClasses = extractClasses(out);
             int changedClasses = 0;
-            for (ModuleData r : outClasses) {
+            for (ModuleEntry r : outClasses) {
                 if (r.getPath().endsWith("Changed.class")) {
                     ++changedClasses;
                 }
@@ -192,15 +192,15 @@ public class VisitorTest extends AsmPluginTestBase {
         }
 
         @Override
-        public void test(Pool in, Pool out) throws Exception {
-            Collection<ModuleData> inResources = getPool.apply(getPools()).getResourceFiles();
+        public void test(ModulePool in, ModulePool out) throws Exception {
+            Collection<ModuleEntry> inResources = getPool.apply(getPools()).getResourceFiles();
             if (inResources.size() != resourceFileVisitor.getAmount()) {
                 throw new AssertionError("Testing " + name + ". Number of visited resources. Expected: " +
                         inResources.size() + ", got: " + resourceFileVisitor.getAmount());
             }
-            Collection<ModuleData> outResources = extractResources(out);
+            Collection<ModuleEntry> outResources = extractResources(out);
             int changedClasses = 0;
-            for (ModuleData r : outResources) {
+            for (ModuleEntry r : outResources) {
                 if (r.getPath().endsWith("Changed")) {
                     ++changedClasses;
                 }
diff --git a/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java b/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java
index 38054ec2015..781039a517a 100644
--- a/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java
+++ b/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java
@@ -26,7 +26,9 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import jdk.tools.jlink.plugin.Pool;
+import java.util.function.Function;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class CustomPlugin implements TransformerPlugin {
@@ -37,13 +39,8 @@ public class CustomPlugin implements TransformerPlugin {
     }
 
     @Override
-    public void visit(Pool in, Pool out) {
-        in.visit(new Pool.Visitor() {
-            @Override
-            public Pool.ModuleData visit(Pool.ModuleData content) {
-                return content;
-            }
-        }, out);
+    public void visit(ModulePool in, ModulePool out) {
+        in.transformAndCopy(Function.identity(), out);
     }
 
     @Override
@@ -61,9 +58,9 @@ public class CustomPlugin implements TransformerPlugin {
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.PROCESSOR);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.PROCESSOR);
         return Collections.unmodifiableSet(set);
     }
 }
diff --git a/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java b/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java
index d06f99050b1..aa150350d7f 100644
--- a/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java
+++ b/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java
@@ -29,8 +29,8 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 /**
@@ -49,23 +49,23 @@ public final class HelloPlugin implements TransformerPlugin {
     }
 
     @Override
-    public void visit(Pool inResources, Pool outResources) {
+    public void visit(ModulePool inResources, ModulePool outResources) {
         try {
             System.out.println("Hello!!!!!!!!!!");
             File f = new File(OUTPUT_FILE);
             f.createNewFile();
-            for (ModuleData res : inResources.getContent()) {
+            inResources.entries().forEach(res -> {
                 outResources.add(res);
-            }
+            });
         } catch (IOException ex) {
             throw new UncheckedIOException(ex);
         }
     }
 
     @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.TRANSFORMER);
+    public Set<Category> getType() {
+        Set<Category> set = new HashSet<>();
+        set.add(Category.TRANSFORMER);
         return Collections.unmodifiableSet(set);
     }
 
diff --git a/jdk/test/tools/jlink/plugins/CompressorPluginTest.java b/jdk/test/tools/jlink/plugins/CompressorPluginTest.java
index cd01b93836b..d37bf1b73d2 100644
--- a/jdk/test/tools/jlink/plugins/CompressorPluginTest.java
+++ b/jdk/test/tools/jlink/plugins/CompressorPluginTest.java
@@ -53,14 +53,14 @@ import jdk.internal.jimage.decompressor.ResourceDecompressor;
 import jdk.internal.jimage.decompressor.ResourceDecompressorFactory;
 import jdk.internal.jimage.decompressor.StringSharingDecompressorFactory;
 import jdk.internal.jimage.decompressor.ZipDecompressorFactory;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.internal.StringTable;
 import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
 import jdk.tools.jlink.internal.plugins.StringSharingPlugin;
 import jdk.tools.jlink.internal.plugins.ZipPlugin;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class CompressorPluginTest {
@@ -86,7 +86,7 @@ public class CompressorPluginTest {
                     new ZipDecompressorFactory()
                 });
 
-        Pool classes = gatherClasses(javabase);
+        ModulePool classes = gatherClasses(javabase);
         // compress = String sharing
         checkCompress(classes, new StringSharingPlugin(), null,
                 new ResourceDecompressorFactory[]{
@@ -173,8 +173,8 @@ public class CompressorPluginTest {
                 Collections.singletonList(".*IOException.class"));
     }
 
-    private Pool gatherResources(Path module) throws Exception {
-        Pool pool = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+    private ModulePool gatherResources(Path module) throws Exception {
+        ModulePool pool = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() {
 
             @Override
             public int addString(String str) {
@@ -191,15 +191,15 @@ public class CompressorPluginTest {
                 Path p = iterator.next();
                 if (Files.isRegularFile(p)) {
                     byte[] content = Files.readAllBytes(p);
-                    pool.add(Pool.newResource(p.toString(), content));
+                    pool.add(ModuleEntry.create(p.toString(), content));
                 }
             }
         }
         return pool;
     }
 
-    private Pool gatherClasses(Path module) throws Exception {
-        Pool pool = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+    private ModulePool gatherClasses(Path module) throws Exception {
+        ModulePool pool = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() {
 
             @Override
             public int addString(String str) {
@@ -216,27 +216,27 @@ public class CompressorPluginTest {
                 Path p = iterator.next();
                 if (Files.isRegularFile(p) && p.toString().endsWith(".class")) {
                     byte[] content = Files.readAllBytes(p);
-                    pool.add(Pool.newResource(p.toString(), content));
+                    pool.add(ModuleEntry.create(p.toString(), content));
                 }
             }
         }
         return pool;
     }
 
-    private void checkCompress(Pool resources, Plugin prov,
+    private void checkCompress(ModulePool resources, Plugin prov,
             Properties config,
             ResourceDecompressorFactory[] factories) throws Exception {
         checkCompress(resources, prov, config, factories, Collections.emptyList(), Collections.emptyList());
     }
 
-    private void checkCompress(Pool resources, Plugin prov,
+    private void checkCompress(ModulePool resources, Plugin prov,
             Properties config,
             ResourceDecompressorFactory[] factories,
             List<String> includes,
             List<String> excludes) throws Exception {
-        long original = 0;
-        long compressed = 0;
-        for (ModuleData resource : resources.getContent()) {
+        long[] original = new long[1];
+        long[] compressed = new long[1];
+        resources.entries().forEach(resource -> {
             List<Pattern> includesPatterns = includes.stream()
                     .map(Pattern::compile)
                     .collect(Collectors.toList());
@@ -252,7 +252,7 @@ public class CompressorPluginTest {
             }
             prov.configure(props);
             final Map<Integer, String> strings = new HashMap<>();
-            PoolImpl inputResources = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+            ModulePoolImpl inputResources = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() {
                 @Override
                 public int addString(String str) {
                     int id = strID;
@@ -267,32 +267,32 @@ public class CompressorPluginTest {
                 }
             });
             inputResources.add(resource);
-            Pool compressedResources = applyCompressor(prov, inputResources, resource, includesPatterns, excludesPatterns);
-            original += resource.getLength();
-            compressed += compressedResources.get(resource.getPath()).getLength();
+            ModulePool compressedResources = applyCompressor(prov, inputResources, resource, includesPatterns, excludesPatterns);
+            original[0] += resource.getLength();
+            compressed[0] += compressedResources.findEntry(resource.getPath()).get().getLength();
             applyDecompressors(factories, inputResources, compressedResources, strings, includesPatterns, excludesPatterns);
-        }
+        });
         String compressors = Stream.of(factories)
                 .map(Object::getClass)
                 .map(Class::getSimpleName)
                 .collect(Collectors.joining(", "));
-        String size = "Compressed size: " + compressed + ", original size: " + original;
+        String size = "Compressed size: " + compressed[0] + ", original size: " + original[0];
         System.out.println("Used " + compressors + ". " + size);
-        if (original <= compressed) {
+        if (original[0] <= compressed[0]) {
             throw new AssertionError("java.base not compressed.");
         }
     }
 
-    private Pool applyCompressor(Plugin plugin,
-            PoolImpl inputResources,
-            ModuleData res,
+    private ModulePool applyCompressor(Plugin plugin,
+            ModulePoolImpl inputResources,
+            ModuleEntry res,
             List<Pattern> includesPatterns,
-            List<Pattern> excludesPatterns) throws Exception {
+            List<Pattern> excludesPatterns) {
         TransformerPlugin compressor = (TransformerPlugin) plugin;
-        Pool compressedPool = new PoolImpl(ByteOrder.nativeOrder(), inputResources.getStringTable());
-        compressor.visit(inputResources, compressedPool);
+        ModulePool compressedModulePool = new ModulePoolImpl(ByteOrder.nativeOrder(), inputResources.getStringTable());
+        compressor.visit(inputResources, compressedModulePool);
         String path = res.getPath();
-        ModuleData compressed = compressedPool.get(path);
+        ModuleEntry compressed = compressedModulePool.findEntry(path).get();
         CompressedResourceHeader header
                 = CompressedResourceHeader.readFromResource(ByteOrder.nativeOrder(), compressed.getBytes());
         if (isIncluded(includesPatterns, excludesPatterns, path)) {
@@ -310,29 +310,33 @@ public class CompressorPluginTest {
         } else if (header != null) {
             throw new AssertionError("Path should not be compressed: " + path);
         }
-        return compressedPool;
+        return compressedModulePool;
     }
 
     private void applyDecompressors(ResourceDecompressorFactory[] decompressors,
-            Pool inputResources,
-            Pool compressedResources,
+            ModulePool inputResources,
+            ModulePool compressedResources,
             Map<Integer, String> strings,
             List<Pattern> includesPatterns,
-            List<Pattern> excludesPatterns) throws Exception {
-        for (ModuleData compressed : compressedResources.getContent()) {
+            List<Pattern> excludesPatterns) {
+        compressedResources.entries().forEach(compressed -> {
             CompressedResourceHeader header = CompressedResourceHeader.readFromResource(
                     ByteOrder.nativeOrder(), compressed.getBytes());
             String path = compressed.getPath();
-            ModuleData orig = inputResources.get(path);
+            ModuleEntry orig = inputResources.findEntry(path).get();
             if (!isIncluded(includesPatterns, excludesPatterns, path)) {
-                continue;
+                return;
             }
             byte[] decompressed = compressed.getBytes();
             for (ResourceDecompressorFactory factory : decompressors) {
-                ResourceDecompressor decompressor = factory.newDecompressor(new Properties());
-                decompressed = decompressor.decompress(
+                try {
+                    ResourceDecompressor decompressor = factory.newDecompressor(new Properties());
+                    decompressed = decompressor.decompress(
                         strings::get, decompressed,
                         CompressedResourceHeader.getSize(), header.getUncompressedSize());
+                } catch (Exception exp) {
+                    throw new RuntimeException(exp);
+                }
             }
 
             if (decompressed.length != orig.getLength()) {
@@ -345,7 +349,7 @@ public class CompressorPluginTest {
                     throw new AssertionError("Decompressed and original differ at index " + i);
                 }
             }
-        }
+        });
     }
 
     private boolean isIncluded(List<Pattern> includesPatterns, List<Pattern> excludesPatterns, String path) {
diff --git a/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java
index cde83aa2761..744d7a2ba25 100644
--- a/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java
+++ b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java
@@ -35,12 +35,11 @@ import java.io.File;
 import java.nio.file.Files;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 
 import jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class ExcludeFilesPluginTest {
@@ -73,20 +72,20 @@ public class ExcludeFilesPluginTest {
         prop.put(ExcludeFilesPlugin.NAME, s);
         ExcludeFilesPlugin fplug = new ExcludeFilesPlugin();
         fplug.configure(prop);
-        PoolImpl files = new PoolImpl();
-        PoolImpl fresult = new PoolImpl();
-        ModuleData f = Pool.newImageFile(module, "/" + module + "/" + sample,
-                ModuleDataType.CONFIG, new ByteArrayInputStream(new byte[0]), 0);
+        ModulePoolImpl files = new ModulePoolImpl();
+        ModulePoolImpl fresult = new ModulePoolImpl();
+        ModuleEntry f = ModuleEntry.create(module, "/" + module + "/" + sample,
+                ModuleEntry.Type.CONFIG, new ByteArrayInputStream(new byte[0]), 0);
         files.add(f);
 
         fplug.visit(files, fresult);
 
         if (exclude) {
-            if (fresult.getContent().contains(f)) {
+            if (fresult.contains(f)) {
                 throw new Exception(sample + " should be excluded by " + s);
             }
         } else {
-            if (!fresult.getContent().contains(f)) {
+            if (!fresult.contains(f)) {
                 throw new Exception(sample + " shouldn't be excluded by " + s);
             }
         }
diff --git a/jdk/test/tools/jlink/plugins/ExcludePluginTest.java b/jdk/test/tools/jlink/plugins/ExcludePluginTest.java
index 0f508073288..c39e738e079 100644
--- a/jdk/test/tools/jlink/plugins/ExcludePluginTest.java
+++ b/jdk/test/tools/jlink/plugins/ExcludePluginTest.java
@@ -34,11 +34,11 @@ import java.io.File;
 import java.nio.file.Files;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 
 import jdk.tools.jlink.internal.plugins.ExcludePlugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class ExcludePluginTest {
 
@@ -75,17 +75,17 @@ public class ExcludePluginTest {
         prop.put(ExcludePlugin.NAME, s);
         ExcludePlugin excludePlugin = new ExcludePlugin();
         excludePlugin.configure(prop);
-        Pool resources = new PoolImpl();
-        ModuleData resource = Pool.newResource(sample, new byte[0]);
+        ModulePool resources = new ModulePoolImpl();
+        ModuleEntry resource = ModuleEntry.create(sample, new byte[0]);
         resources.add(resource);
-        Pool result = new PoolImpl();
+        ModulePool result = new ModulePoolImpl();
         excludePlugin.visit(resources, result);
         if (exclude) {
-            if (result.getContent().contains(resource)) {
+            if (result.contains(resource)) {
                 throw new AssertionError(sample + " should be excluded by " + s);
             }
         } else {
-            if (!result.getContent().contains(resource)) {
+            if (!result.contains(resource)) {
                 throw new AssertionError(sample + " shouldn't be excluded by " + s);
             }
         }
diff --git a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java
index 701368c3dd0..edc10702eb3 100644
--- a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java
+++ b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java
@@ -32,13 +32,12 @@
 import java.io.ByteArrayInputStream;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 
 import jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class ExcludeVMPluginTest {
@@ -165,14 +164,14 @@ public class ExcludeVMPluginTest {
     private void doCheckVM(String vm, String[] input, String jvmcfg, String[] expectedOutput, String expectdJvmCfg) throws Exception {
         // Create a pool with jvm.cfg and the input paths.
         byte[] jvmcfgContent = jvmcfg.getBytes();
-        Pool pool = new PoolImpl();
-        pool.add(Pool.newImageFile("java.base", "/java.base/native/jvm.cfg",
-                ModuleDataType.NATIVE_LIB, new ByteArrayInputStream(jvmcfgContent), jvmcfgContent.length));
+        ModulePool pool = new ModulePoolImpl();
+        pool.add(ModuleEntry.create("java.base", "/java.base/native/jvm.cfg",
+                ModuleEntry.Type.NATIVE_LIB, new ByteArrayInputStream(jvmcfgContent), jvmcfgContent.length));
         for (String in : input) {
-            pool.add(Pool.newImageFile("java.base", in,
-                    ModuleDataType.NATIVE_LIB, new ByteArrayInputStream(new byte[0]), 0));
+            pool.add(ModuleEntry.create("java.base", in,
+                    ModuleEntry.Type.NATIVE_LIB, new ByteArrayInputStream(new byte[0]), 0));
         }
-        Pool out = new PoolImpl();
+        ModulePool out = new ModulePoolImpl();
 
         TransformerPlugin p = new ExcludeVMPlugin();
         Map<String, String> config = new HashMap<>();
@@ -182,22 +181,22 @@ public class ExcludeVMPluginTest {
         p.configure(config);
         p.visit(pool, out);
 
-        String newContent = new String(out.get("/java.base/native/jvm.cfg").stream().readAllBytes());
+        String newContent = new String(out.findEntry("/java.base/native/jvm.cfg").get().stream().readAllBytes());
 
         if (!expectdJvmCfg.equals(newContent)) {
             throw new Exception("Got content " + newContent + " expected " + expectdJvmCfg);
         }
 
-        if (out.getContent().size() != (expectedOutput.length + 1)) {
-            for (ModuleData m : out.getContent()) {
+        if (out.getEntryCount() != (expectedOutput.length + 1)) {
+            out.entries().forEach(m -> {
                 System.err.println(m.getPath());
-            }
-            throw new Exception("Invalid output size " + out.getContent().size() + " expected " + (expectedOutput.length + 1));
+            });
+            throw new Exception("Invalid output size " + out.getEntryCount() + " expected " + (expectedOutput.length + 1));
         }
 
-        for (ModuleData md : out.getContent()) {
+        out.entries().forEach(md -> {
             if (md.getPath().equals("/java.base/native/jvm.cfg")) {
-                continue;
+                return;
             }
             boolean contained = false;
             for (String o : expectedOutput) {
@@ -207,9 +206,9 @@ public class ExcludeVMPluginTest {
                 }
             }
             if (!contained) {
-                throw new Exception(md.getPath() + " not expected");
+                throw new RuntimeException(md.getPath() + " not expected");
             }
-        }
+        });
 
     }
 
diff --git a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java
index 5fecfec388b..a6fb749ba7f 100644
--- a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java
+++ b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java
@@ -26,6 +26,7 @@
  * @summary Test files copy plugin
  * @author Jean-Francois Denise
  * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.builder
  *          jdk.jlink/jdk.tools.jlink.internal.plugins
  * @run main FileCopierPluginTest
  */
@@ -36,13 +37,12 @@ import java.nio.file.Path;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.builder.DefaultImageBuilder;
 
 import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 
 public class FileCopierPluginTest {
 
@@ -85,21 +85,20 @@ public class FileCopierPluginTest {
         Map<String, String> conf = new HashMap<>();
         conf.put(FileCopierPlugin.NAME, builder.toString());
         plug.configure(conf);
-        Pool pool = new PoolImpl();
-        plug.visit(new PoolImpl(), pool);
-        if (pool.getContent().size() != expected) {
+        ModulePool pool = new ModulePoolImpl();
+        plug.visit(new ModulePoolImpl(), pool);
+        if (pool.getEntryCount() != expected) {
             throw new AssertionError("Wrong number of added files");
         }
-        for (ModuleData f : pool.getContent()) {
-            if (!f.getType().equals(ModuleDataType.OTHER)) {
+        pool.entries().forEach(f -> {
+            if (!f.getType().equals(ModuleEntry.Type.OTHER)) {
                 throw new AssertionError("Invalid type " + f.getType()
                         + " for file " + f.getPath());
             }
             if (f.stream() == null) {
                 throw new AssertionError("Null stream for file " + f.getPath());
             }
-
-        }
+        });
         Path root = new File(".").toPath();
         DefaultImageBuilder imgbuilder = new DefaultImageBuilder(root);
         imgbuilder.storeFiles(pool);
diff --git a/jdk/test/tools/jlink/plugins/LastSorterTest.java b/jdk/test/tools/jlink/plugins/LastSorterTest.java
index 100ca1e4674..0dc27b44ec8 100644
--- a/jdk/test/tools/jlink/plugins/LastSorterTest.java
+++ b/jdk/test/tools/jlink/plugins/LastSorterTest.java
@@ -26,6 +26,7 @@
  * @summary Test last sorter property
  * @author Jean-Francois Denise
  * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink
  * @run main/othervm LastSorterTest
  */
 
@@ -40,12 +41,12 @@ import java.util.Set;
 import jdk.tools.jlink.internal.ImagePluginConfiguration;
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.internal.ImagePluginStack;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.Jlink.PluginsConfiguration;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class LastSorterTest {
@@ -80,7 +81,7 @@ public class LastSorterTest {
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
 
         // check order
-        PoolImpl res = fillOutResourcePool();
+        ModulePoolImpl res = fillOutResourceModulePool();
 
         try {
             stack.visitResources(res);
@@ -91,18 +92,18 @@ public class LastSorterTest {
         }
     }
 
-    private PoolImpl fillOutResourcePool() throws Exception {
-        PoolImpl res = new PoolImpl();
-        res.add(Pool.newResource("/eee/bbb/res1.class", new byte[90]));
-        res.add(Pool.newResource("/aaaa/bbb/res2.class", new byte[90]));
-        res.add(Pool.newResource("/bbb/aa/res1.class", new byte[90]));
-        res.add(Pool.newResource("/aaaa/bbb/res3.class", new byte[90]));
-        res.add(Pool.newResource("/bbb/aa/res2.class", new byte[90]));
-        res.add(Pool.newResource("/fff/bbb/res1.class", new byte[90]));
-        res.add(Pool.newResource("/aaaa/bbb/res1.class", new byte[90]));
-        res.add(Pool.newResource("/bbb/aa/res3.class", new byte[90]));
-        res.add(Pool.newResource("/ccc/bbb/res1.class", new byte[90]));
-        res.add(Pool.newResource("/ddd/bbb/res1.class", new byte[90]));
+    private ModulePoolImpl fillOutResourceModulePool() throws Exception {
+        ModulePoolImpl res = new ModulePoolImpl();
+        res.add(ModuleEntry.create("/eee/bbb/res1.class", new byte[90]));
+        res.add(ModuleEntry.create("/aaaa/bbb/res2.class", new byte[90]));
+        res.add(ModuleEntry.create("/bbb/aa/res1.class", new byte[90]));
+        res.add(ModuleEntry.create("/aaaa/bbb/res3.class", new byte[90]));
+        res.add(ModuleEntry.create("/bbb/aa/res2.class", new byte[90]));
+        res.add(ModuleEntry.create("/fff/bbb/res1.class", new byte[90]));
+        res.add(ModuleEntry.create("/aaaa/bbb/res1.class", new byte[90]));
+        res.add(ModuleEntry.create("/bbb/aa/res3.class", new byte[90]));
+        res.add(ModuleEntry.create("/ccc/bbb/res1.class", new byte[90]));
+        res.add(ModuleEntry.create("/ddd/bbb/res1.class", new byte[90]));
         return res;
     }
 
@@ -124,7 +125,7 @@ public class LastSorterTest {
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
 
         // check order
-        PoolImpl res = fillOutResourcePool();
+        ModulePoolImpl res = fillOutResourceModulePool();
 
         stack.visitResources(res);
     }
@@ -159,7 +160,7 @@ public class LastSorterTest {
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
 
         // check order
-        PoolImpl res = fillOutResourcePool();
+        ModulePoolImpl res = fillOutResourceModulePool();
         try {
             stack.visitResources(res);
             throw new AssertionError("Order was changed after the last sorter, but no exception occurred");
@@ -178,17 +179,17 @@ public class LastSorterTest {
         }
 
         @Override
-        public void visit(Pool resources, Pool output) {
-            List<ModuleData> paths = new ArrayList<>();
-            for (ModuleData res : resources.getContent()) {
+        public void visit(ModulePool resources, ModulePool output) {
+            List<ModuleEntry> paths = new ArrayList<>();
+            resources.entries().forEach(res -> {
                 if (res.getPath().startsWith(starts)) {
                     paths.add(0, res);
                 } else {
                     paths.add(res);
                 }
-            }
+            });
 
-            for (ModuleData r : paths) {
+            for (ModuleEntry r : paths) {
                 output.add(r);
             }
         }
@@ -199,9 +200,9 @@ public class LastSorterTest {
         }
 
         @Override
-        public Set<PluginType> getType() {
-            Set<PluginType> set = new HashSet<>();
-            set.add(CATEGORY.TRANSFORMER);
+        public Set<Category> getType() {
+            Set<Category> set = new HashSet<>();
+            set.add(Category.TRANSFORMER);
             return Collections.unmodifiableSet(set);
         }
 
diff --git a/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java b/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java
index cbf418669c0..701736139c6 100644
--- a/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java
+++ b/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java
@@ -36,11 +36,12 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.PoolImpl;
+import java.util.stream.Collectors;
 
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.internal.plugins.OrderResourcesPlugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class OrderResourcesPluginTest {
@@ -50,52 +51,52 @@ public class OrderResourcesPluginTest {
     }
 
     public void test() throws Exception {
-        ModuleData[] array = {
-                Pool.newResource("/module1/toto1.class", new byte[0]),
-                Pool.newResource("/module2/toto2.class", new byte[0]),
-                Pool.newResource("/module3/toto3.class", new byte[0]),
-                Pool.newResource("/module3/toto3/module-info.class", new byte[0]),
-                Pool.newResource("/zazou/toto.class", new byte[0]),
-                Pool.newResource("/module4/zazou.class", new byte[0]),
-                Pool.newResource("/module5/toto5.class", new byte[0]),
-                Pool.newResource("/module6/toto6/module-info.class", new byte[0])
+        ModuleEntry[] array = {
+                ModuleEntry.create("/module1/toto1.class", new byte[0]),
+                ModuleEntry.create("/module2/toto2.class", new byte[0]),
+                ModuleEntry.create("/module3/toto3.class", new byte[0]),
+                ModuleEntry.create("/module3/toto3/module-info.class", new byte[0]),
+                ModuleEntry.create("/zazou/toto.class", new byte[0]),
+                ModuleEntry.create("/module4/zazou.class", new byte[0]),
+                ModuleEntry.create("/module5/toto5.class", new byte[0]),
+                ModuleEntry.create("/module6/toto6/module-info.class", new byte[0])
         };
 
-        ModuleData[] sorted = {
-                Pool.newResource("/zazou/toto.class", new byte[0]),
-                Pool.newResource("/module3/toto3/module-info.class", new byte[0]),
-                Pool.newResource("/module6/toto6/module-info.class", new byte[0]),
-                Pool.newResource("/module1/toto1.class", new byte[0]),
-                Pool.newResource("/module2/toto2.class", new byte[0]),
-                Pool.newResource("/module3/toto3.class", new byte[0]),
-                Pool.newResource("/module4/zazou.class", new byte[0]),
-                Pool.newResource("/module5/toto5.class", new byte[0])
+        ModuleEntry[] sorted = {
+                ModuleEntry.create("/zazou/toto.class", new byte[0]),
+                ModuleEntry.create("/module3/toto3/module-info.class", new byte[0]),
+                ModuleEntry.create("/module6/toto6/module-info.class", new byte[0]),
+                ModuleEntry.create("/module1/toto1.class", new byte[0]),
+                ModuleEntry.create("/module2/toto2.class", new byte[0]),
+                ModuleEntry.create("/module3/toto3.class", new byte[0]),
+                ModuleEntry.create("/module4/zazou.class", new byte[0]),
+                ModuleEntry.create("/module5/toto5.class", new byte[0])
         };
 
-        ModuleData[] sorted2 = {
-            Pool.newResource("/module5/toto5.class", new byte[0]),
-            Pool.newResource("/module6/toto6/module-info.class", new byte[0]),
-            Pool.newResource("/module4/zazou.class", new byte[0]),
-            Pool.newResource("/module3/toto3.class", new byte[0]),
-            Pool.newResource("/module3/toto3/module-info.class", new byte[0]),
-            Pool.newResource("/module1/toto1.class", new byte[0]),
-            Pool.newResource("/module2/toto2.class", new byte[0]),
-            Pool.newResource("/zazou/toto.class", new byte[0])
+        ModuleEntry[] sorted2 = {
+            ModuleEntry.create("/module5/toto5.class", new byte[0]),
+            ModuleEntry.create("/module6/toto6/module-info.class", new byte[0]),
+            ModuleEntry.create("/module4/zazou.class", new byte[0]),
+            ModuleEntry.create("/module3/toto3.class", new byte[0]),
+            ModuleEntry.create("/module3/toto3/module-info.class", new byte[0]),
+            ModuleEntry.create("/module1/toto1.class", new byte[0]),
+            ModuleEntry.create("/module2/toto2.class", new byte[0]),
+            ModuleEntry.create("/zazou/toto.class", new byte[0])
         };
 
-        Pool resources = new PoolImpl();
-        for (ModuleData r : array) {
+        ModulePool resources = new ModulePoolImpl();
+        for (ModuleEntry r : array) {
             resources.add(r);
         }
 
         {
-            Pool out = new PoolImpl();
+            ModulePool out = new ModulePoolImpl();
             Map<String, String> config = new HashMap<>();
             config.put(OrderResourcesPlugin.NAME, "/zazou/*,*/module-info.class");
             TransformerPlugin p = new OrderResourcesPlugin();
             p.configure(config);
             p.visit(resources, out);
-            check(out.getContent(), sorted);
+            check(out.entries().collect(Collectors.toList()), sorted);
         }
 
         {
@@ -112,26 +113,26 @@ public class OrderResourcesPluginTest {
             }
             Files.write(order.toPath(), builder.toString().getBytes());
 
-            Pool out = new PoolImpl();
+            ModulePool out = new ModulePoolImpl();
             Map<String, String> config = new HashMap<>();
             config.put(OrderResourcesPlugin.NAME, "@" + order.getAbsolutePath());
             TransformerPlugin p = new OrderResourcesPlugin();
             p.configure(config);
             p.visit(resources, out);
-            check(out.getContent(), sorted2);
+            check(out.entries().collect(Collectors.toList()), sorted2);
 
         }
     }
 
-    private void check(Collection<ModuleData> outResources,
-            ModuleData[] sorted) {
+    private void check(Collection<ModuleEntry> outResources,
+            ModuleEntry[] sorted) {
         if (outResources.size() != sorted.length) {
             throw new AssertionError("Wrong number of resources:\n"
                     + "expected: " + Arrays.toString(sorted) + ",\n"
                     + "     got: " + outResources);
         }
         int i = 0;
-        for (ModuleData r : outResources) {
+        for (ModuleEntry r : outResources) {
             System.err.println("Resource: " + r);
             if (!sorted[i].getPath().equals(r.getPath())) {
                 throw new AssertionError("Resource not properly sorted, difference at: " + i + "\n"
diff --git a/jdk/test/tools/jlink/plugins/PluginOrderTest.java b/jdk/test/tools/jlink/plugins/PluginOrderTest.java
index 42655d408fe..4c9f2c2241d 100644
--- a/jdk/test/tools/jlink/plugins/PluginOrderTest.java
+++ b/jdk/test/tools/jlink/plugins/PluginOrderTest.java
@@ -44,8 +44,8 @@ import java.util.Set;
 
 import jdk.tools.jlink.internal.PluginOrderingGraph;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.Plugin.CATEGORY;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Plugin.Category;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class PluginOrderTest {
@@ -96,8 +96,8 @@ public class PluginOrderTest {
         set.add("plug2");
         List<Plugin> plugins = new ArrayList<>();
         plugins.add(new Plug("plug2", Collections.emptySet(), Collections.emptySet(),
-                CATEGORY.TRANSFORMER));
-        plugins.add(new Plug("plug1", set, Collections.emptySet(), CATEGORY.TRANSFORMER));
+                Category.TRANSFORMER));
+        plugins.add(new Plug("plug1", set, Collections.emptySet(), Category.TRANSFORMER));
         List<Plugin> ordered = PluginOrderingGraph.sort(plugins);
         if (ordered.get(0) != plugins.get(1) || ordered.get(1) != plugins.get(0)) {
             throw new Exception("Invalid sorting");
@@ -108,32 +108,32 @@ public class PluginOrderTest {
         Set<String> lst1 = new HashSet<>();
         lst1.add("plug2");
         lst1.add("plug3");
-        Plugin p1 = new Plug("plug1", lst1, Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p1 = new Plug("plug1", lst1, Collections.emptySet(), Category.TRANSFORMER);
 
-        Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER);
 
         Set<String> lst3 = new HashSet<>();
         lst3.add("plug4");
         lst3.add("plug6");
-        Plugin p3 = new Plug("plug3", lst3, Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p3 = new Plug("plug3", lst3, Collections.emptySet(), Category.TRANSFORMER);
 
-        Plugin p4 = new Plug("plug4", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p4 = new Plug("plug4", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER);
 
         Set<String> lst5 = new HashSet<>();
         lst5.add("plug3");
         lst5.add("plug1");
         lst5.add("plug2");
         lst5.add("plug6");
-        Plugin p5 = new Plug("plug5", lst5, Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p5 = new Plug("plug5", lst5, Collections.emptySet(), Category.TRANSFORMER);
 
         Set<String> lst6 = new HashSet<>();
         lst6.add("plug4");
         lst6.add("plug2");
-        Plugin p6 = new Plug("plug6", lst6, Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p6 = new Plug("plug6", lst6, Collections.emptySet(), Category.TRANSFORMER);
 
-        Plugin p7 = new Plug("plug7", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p7 = new Plug("plug7", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER);
 
-        Plugin p8 = new Plug("plug8", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p8 = new Plug("plug8", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER);
 
         List<Plugin> plugins = new ArrayList<>();
         plugins.add(p1);
@@ -153,11 +153,11 @@ public class PluginOrderTest {
         set2.add("plug1");
         List<Plugin> plugins = new ArrayList<>();
         plugins.add(new Plug("plug2", set2, Collections.emptySet(),
-                CATEGORY.TRANSFORMER));
+                Category.TRANSFORMER));
 
         Set<String> set1 = new HashSet<>();
         set1.add("plug2");
-        plugins.add(new Plug("plug1", set1, Collections.emptySet(), CATEGORY.TRANSFORMER));
+        plugins.add(new Plug("plug1", set1, Collections.emptySet(), Category.TRANSFORMER));
         PluginOrderingGraph.sort(plugins);
 
     }
@@ -166,31 +166,31 @@ public class PluginOrderTest {
         Set<String> lst1 = new HashSet<>();
         lst1.add("plug2");
         lst1.add("plug3");
-        Plugin p1 = new Plug("plug1", lst1, Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p1 = new Plug("plug1", lst1, Collections.emptySet(), Category.TRANSFORMER);
 
-        Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER);
 
         Set<String> lst3 = new HashSet<>();
         lst3.add("plug4");
         lst3.add("plug6");
-        Plugin p3 = new Plug("plug3", lst3, Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p3 = new Plug("plug3", lst3, Collections.emptySet(), Category.TRANSFORMER);
 
-        Plugin p4 = new Plug("plug4", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p4 = new Plug("plug4", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER);
 
         Set<String> lst5 = new HashSet<>();
         lst5.add("plug3");
         lst5.add("plug1");
         lst5.add("plug2");
-        Plugin p5 = new Plug("plug5", lst5, Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p5 = new Plug("plug5", lst5, Collections.emptySet(), Category.TRANSFORMER);
 
         Set<String> lst6 = new HashSet<>();
         lst6.add("plug4");
         lst6.add("plug1");
-        Plugin p6 = new Plug("plug6", lst6, Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p6 = new Plug("plug6", lst6, Collections.emptySet(), Category.TRANSFORMER);
 
-        Plugin p7 = new Plug("plug7", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p7 = new Plug("plug7", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER);
 
-        Plugin p8 = new Plug("plug8", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p8 = new Plug("plug8", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER);
 
         List<Plugin> plugins = new ArrayList<>();
         plugins.add(p1);
@@ -208,8 +208,8 @@ public class PluginOrderTest {
         Set<String> lst1 = new HashSet<>();
         lst1.add("plug2");
         lst1.add("plug3");
-        Plugin p = new Plug("plug1", lst1, Collections.emptySet(), CATEGORY.TRANSFORMER);
-        Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p = new Plug("plug1", lst1, Collections.emptySet(), Category.TRANSFORMER);
+        Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), Category.TRANSFORMER);
 
         Set<String> lst3 = new HashSet<>();
         lst3.add("plug2");
@@ -217,7 +217,7 @@ public class PluginOrderTest {
         Set<String> lst4 = new HashSet<>();
         lst4.add("plug1");
 
-        Plugin p3 = new Plug("plug3", lst4, lst3, CATEGORY.TRANSFORMER);
+        Plugin p3 = new Plug("plug3", lst4, lst3, Category.TRANSFORMER);
         List<Plugin> plugins = new ArrayList<>();
         plugins.add(p);
         plugins.add(p2);
@@ -229,10 +229,10 @@ public class PluginOrderTest {
 
         private final Set<String> isBefore;
         private final Set<String> isAfter;
-        private final CATEGORY category;
+        private final Category category;
         private final String name;
 
-        private Plug(String name, Set<String> isBefore, Set<String> isAfter, CATEGORY category) {
+        private Plug(String name, Set<String> isBefore, Set<String> isAfter, Category category) {
             this.name = name;
             this.isBefore = isBefore;
             this.isAfter = isAfter;
@@ -255,12 +255,12 @@ public class PluginOrderTest {
         }
 
         @Override
-        public void visit(Pool in, Pool out) {
+        public void visit(ModulePool in, ModulePool out) {
 
         }
 
         @Override
-        public Set<PluginType> getType() {
+        public Set<Category> getType() {
             return Collections.singleton(category);
         }
 
diff --git a/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java
index 525fb0b5ce2..5b8ed2d6c83 100644
--- a/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java
+++ b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java
@@ -26,6 +26,7 @@
  * @summary Negative test for ImagePluginStack.
  * @author Andrei Eremeev
  * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink
  * @run main/othervm PluginsNegativeTest
  */
 import java.lang.reflect.Layer;
@@ -39,11 +40,12 @@ import java.util.Set;
 import jdk.tools.jlink.internal.ImagePluginConfiguration;
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.internal.ImagePluginStack;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.Jlink.PluginsConfiguration;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class PluginsNegativeTest {
@@ -96,8 +98,8 @@ public class PluginsNegativeTest {
         plugins.add(createPlugin("plugin"));
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new PluginsConfiguration(plugins,
                 null, null));
-        PoolImpl inResources = new PoolImpl();
-        inResources.add(Pool.newResource("/aaa/bbb/A", new byte[10]));
+        ModulePoolImpl inResources = new ModulePoolImpl();
+        inResources.add(ModuleEntry.create("/aaa/bbb/A", new byte[10]));
         try {
             stack.visitResources(inResources);
             throw new AssertionError("Exception expected when output resource is empty");
@@ -110,8 +112,8 @@ public class PluginsNegativeTest {
         plugins.add(createPlugin("plugin"));
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new PluginsConfiguration(plugins,
                 null, null));
-        PoolImpl inResources = new PoolImpl();
-        PoolImpl outResources = (PoolImpl) stack.visitResources(inResources);
+        ModulePoolImpl inResources = new ModulePoolImpl();
+        ModulePoolImpl outResources = (ModulePoolImpl) stack.visitResources(inResources);
         if (!outResources.isEmpty()) {
             throw new AssertionError("Output resource is not empty");
         }
@@ -126,7 +128,7 @@ public class PluginsNegativeTest {
         }
 
         @Override
-        public void visit(Pool inResources, Pool outResources) {
+        public void visit(ModulePool inResources, ModulePool outResources) {
             // do nothing
         }
 
@@ -136,9 +138,9 @@ public class PluginsNegativeTest {
         }
 
         @Override
-        public Set<PluginType> getType() {
-            Set<PluginType> set = new HashSet<>();
-            set.add(CATEGORY.TRANSFORMER);
+        public Set<Category> getType() {
+            Set<Category> set = new HashSet<>();
+            set.add(Category.TRANSFORMER);
             return Collections.unmodifiableSet(set);
         }
 
diff --git a/jdk/test/tools/jlink/plugins/PrevisitorTest.java b/jdk/test/tools/jlink/plugins/PrevisitorTest.java
index 16d79f0c068..1f721d66d5f 100644
--- a/jdk/test/tools/jlink/plugins/PrevisitorTest.java
+++ b/jdk/test/tools/jlink/plugins/PrevisitorTest.java
@@ -26,6 +26,7 @@
  * @summary Test previsitor
  * @author Andrei Eremeev
  * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink
  * @run main/othervm PrevisitorTest
  */
 import java.nio.ByteOrder;
@@ -36,19 +37,20 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
 import jdk.tools.jlink.internal.ImagePluginConfiguration;
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.internal.ImagePluginStack;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.internal.ResourcePrevisitor;
 import jdk.tools.jlink.internal.StringTable;
 import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 
 public class PrevisitorTest {
@@ -68,17 +70,17 @@ public class PrevisitorTest {
         plugins.add(createPlugin(CustomPlugin.NAME));
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new Jlink.PluginsConfiguration(plugins,
                 null, null));
-        PoolImpl inResources = new PoolImpl(ByteOrder.nativeOrder(), new CustomStringTable());
-        inResources.add(Pool.newResource("/aaa/bbb/res1.class", new byte[90]));
-        inResources.add(Pool.newResource("/aaa/bbb/res2.class", new byte[90]));
-        inResources.add(Pool.newResource("/aaa/bbb/res3.class", new byte[90]));
-        inResources.add(Pool.newResource("/aaa/ddd/res1.class", new byte[90]));
-        inResources.add(Pool.newResource("/aaa/res1.class", new byte[90]));
-        Pool outResources = stack.visitResources(inResources);
-        Collection<String> input = inResources.getContent().stream()
+        ModulePoolImpl inResources = new ModulePoolImpl(ByteOrder.nativeOrder(), new CustomStringTable());
+        inResources.add(ModuleEntry.create("/aaa/bbb/res1.class", new byte[90]));
+        inResources.add(ModuleEntry.create("/aaa/bbb/res2.class", new byte[90]));
+        inResources.add(ModuleEntry.create("/aaa/bbb/res3.class", new byte[90]));
+        inResources.add(ModuleEntry.create("/aaa/ddd/res1.class", new byte[90]));
+        inResources.add(ModuleEntry.create("/aaa/res1.class", new byte[90]));
+        ModulePool outResources = stack.visitResources(inResources);
+        Collection<String> input = inResources.entries()
                 .map(Object::toString)
                 .collect(Collectors.toList());
-        Collection<String> output = outResources.getContent().stream()
+        Collection<String> output = outResources.entries()
                 .map(Object::toString)
                 .collect(Collectors.toList());
         if (!input.equals(output)) {
@@ -114,19 +116,20 @@ public class PrevisitorTest {
         private boolean isPrevisitCalled = false;
 
         @Override
-        public void visit(Pool inResources, Pool outResources) {
+        public void visit(ModulePool inResources, ModulePool outResources) {
             if (!isPrevisitCalled) {
                 throw new AssertionError("Previsit was not called");
             }
             CustomStringTable table = (CustomStringTable)
-                    ((PoolImpl) inResources).getStringTable();
+                    ((ModulePoolImpl) inResources).getStringTable();
             if (table.size() == 0) {
                 throw new AssertionError("Table is empty");
             }
             Map<String, Integer> count = new HashMap<>();
             for (int i = 0; i < table.size(); ++i) {
                 String s = table.getString(i);
-                if (inResources.get(s) != null) {
+                Optional<ModuleEntry> e = inResources.findEntry(s);
+                if (e.isPresent()) {
                     throw new AssertionError();
                 }
                 count.compute(s, (k, c) -> 1 + (c == null ? 0 : c));
@@ -136,9 +139,9 @@ public class PrevisitorTest {
                     throw new AssertionError("Expected one entry in the table, got: " + v + " for " + k);
                 }
             });
-            for (ModuleData r : inResources.getContent()) {
+            inResources.entries().forEach(r -> {
                 outResources.add(r);
-            }
+            });
         }
 
         @Override
@@ -147,21 +150,21 @@ public class PrevisitorTest {
         }
 
         @Override
-        public void previsit(Pool resources, StringTable strings) {
+        public void previsit(ModulePool resources, StringTable strings) {
             isPrevisitCalled = true;
-            for (ModuleData r : resources.getContent()) {
+            resources.entries().forEach(r -> {
                 String s = r.getPath();
                 int lastIndexOf = s.lastIndexOf('/');
                 if (lastIndexOf >= 0) {
                     strings.addString(s.substring(0, lastIndexOf));
                 }
-            }
+            });
         }
 
         @Override
-        public Set<PluginType> getType() {
-            Set<PluginType> set = new HashSet<>();
-            set.add(CATEGORY.TRANSFORMER);
+        public Set<Category> getType() {
+            Set<Category> set = new HashSet<>();
+            set.add(Category.TRANSFORMER);
             return Collections.unmodifiableSet(set);
         }
     }
diff --git a/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java
index 786da460990..c02a8e6db0c 100644
--- a/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java
+++ b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java
@@ -38,6 +38,8 @@
  * @run main StringSharingPluginTest
  */
 
+import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.file.Files;
@@ -50,11 +52,11 @@ import java.util.function.Consumer;
 
 import jdk.internal.jimage.decompressor.CompressedResourceHeader;
 import jdk.internal.jimage.decompressor.StringSharingDecompressor;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.internal.StringTable;
 import jdk.tools.jlink.internal.plugins.StringSharingPlugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import tests.Helper;
 import tests.JImageValidator;
@@ -78,7 +80,7 @@ public class StringSharingPluginTest {
         Map<String, Integer> map = new HashMap<>();
         Map<Integer, String> reversedMap = new HashMap<>();
 
-        PoolImpl resources = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+        ModulePoolImpl resources = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() {
             @Override
             public int addString(String str) {
                 Integer id = map.get(str);
@@ -104,7 +106,7 @@ public class StringSharingPluginTest {
                     byte[] content = Files.readAllBytes(p);
                     String path = p.toString().replace('\\', '/');
                     path = path.substring("/modules".length());
-                    ModuleData res = Pool.newResource(path, content);
+                    ModuleEntry res = ModuleEntry.create(path, content);
                     resources.add(res);
                 } catch (Exception ex) {
                     throw new RuntimeException(ex);
@@ -115,19 +117,23 @@ public class StringSharingPluginTest {
             stream.forEach(c);
         }
         TransformerPlugin plugin = new StringSharingPlugin();
-        PoolImpl result = new PoolImpl(resources.getByteOrder(), resources.getStringTable());
+        ModulePoolImpl result = new ModulePoolImpl(resources.getByteOrder(), resources.getStringTable());
         plugin.visit(resources, result);
 
         if (result.isEmpty()) {
             throw new AssertionError("No result");
         }
 
-        for (ModuleData res : result.getContent()) {
+        result.entries().forEach(res -> {
             if (res.getPath().endsWith(".class")) {
-                byte[] uncompacted = StringSharingDecompressor.normalize(reversedMap::get, res.getBytes(),
+                try {
+                    byte[] uncompacted = StringSharingDecompressor.normalize(reversedMap::get, res.getBytes(),
                         CompressedResourceHeader.getSize());
-                JImageValidator.readClass(uncompacted);
+                    JImageValidator.readClass(uncompacted);
+                } catch (IOException exp) {
+                    throw new UncheckedIOException(exp);
+                }
             }
-        }
+        });
     }
 }
diff --git a/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java b/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java
index fd8acae896c..d3617db6f8a 100644
--- a/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java
+++ b/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java
@@ -54,10 +54,10 @@ import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.classfile.Method;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ModulePool;
 import jdk.tools.jlink.plugin.TransformerPlugin;
 import tests.Helper;
 
@@ -106,7 +106,7 @@ public class StripDebugPluginTest {
         path = path.replace('\\', '/');
         StripDebugPlugin debug = new StripDebugPlugin();
         debug.configure(new HashMap<>());
-        ModuleData result1 = stripDebug(debug, Pool.newResource(path,content), path, infoPath, moduleInfo);
+        ModuleEntry result1 = stripDebug(debug, ModuleEntry.create(path,content), path, infoPath, moduleInfo);
 
         if (!path.endsWith("module-info.class")) {
             if (result1.getLength() >= content.length) {
@@ -116,7 +116,7 @@ public class StripDebugPluginTest {
             checkDebugAttributes(result1.getBytes());
         }
 
-        ModuleData result2 = stripDebug(debug, result1, path, infoPath, moduleInfo);
+        ModuleEntry result2 = stripDebug(debug, result1, path, infoPath, moduleInfo);
         if (result1.getLength() != result2.getLength()) {
             throw new AssertionError("removing debug info twice reduces class size of "
                     + path);
@@ -124,18 +124,18 @@ public class StripDebugPluginTest {
         checkDebugAttributes(result1.getBytes());
     }
 
-    private ModuleData stripDebug(TransformerPlugin debug, ModuleData classResource,
+    private ModuleEntry stripDebug(TransformerPlugin debug, ModuleEntry classResource,
             String path, String infoPath, byte[] moduleInfo) throws Exception {
-        Pool resources = new PoolImpl();
+        ModulePool resources = new ModulePoolImpl();
         resources.add(classResource);
         if (!path.endsWith("module-info.class")) {
-            ModuleData res2 = Pool.newResource(infoPath, moduleInfo);
+            ModuleEntry res2 = ModuleEntry.create(infoPath, moduleInfo);
             resources.add(res2);
         }
-        Pool results = new PoolImpl();
+        ModulePool results = new ModulePoolImpl();
         debug.visit(resources, results);
         System.out.println(classResource.getPath());
-        return results.get(classResource.getPath());
+        return results.findEntry(classResource.getPath()).get();
     }
 
     private void checkDebugAttributes(byte[] strippedClassFile) throws IOException, ConstantPoolException {
diff --git a/langtools/.hgtags b/langtools/.hgtags
index ab91141afde..5f7979643e2 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -360,3 +360,4 @@ cba09a2e6ae969b029783eb59bb01017b78f8eef jdk-9+114
 31c8b18fdc5b94a2ddd5ea0694f350a2c907e9f7 jdk-9+115
 3e3553ee39d9e081573bc7c88a252214a3152763 jdk-9+116
 59adcdd0cd3b6724b4fc0083c258bf4682689f2f jdk-9+117
+59a16fa5dedea9ff5bea0a501e4d0d40193426f3 jdk-9+118
diff --git a/langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java b/langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java
index e24d5a2e915..2c33367f7d6 100644
--- a/langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java
+++ b/langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.util.Arrays;
+import java.util.Collection;
 
 import static javax.tools.FileManagerUtils.*;
 
@@ -176,7 +177,8 @@ public interface StandardJavaFileManager extends JavaFileManager {
     /**
      * Returns file objects representing the given paths.
      *
-     * <p>The default implementation converts each path to a file and calls
+     * @implSpec
+     * The default implementation converts each path to a file and calls
      * {@link #getJavaFileObjectsFromFiles getJavaObjectsFromFiles}.
      * IllegalArgumentException will be thrown if any of the paths
      * cannot be converted to a file.
@@ -280,10 +282,21 @@ public interface StandardJavaFileManager extends JavaFileManager {
      * Associates the given search path with the given location.  Any
      * previous value will be discarded.
      *
-     * <p>The default implementation converts each path to a file and calls
+     * @apiNote
+     * The type of the {@code paths} parameter is a {@code Collection}
+     * and not {@code Iterable}. This is to prevent the possibility of
+     * accidentally calling the method with a single {@code Path} as
+     * the second argument, because although {@code Path} implements
+     * {@code Iterable<Path>}, it would almost never be correct to call
+     * this method with a single {@code Path} and have it be treated as
+     * an {@code Iterable} of its components.
+     *
+     *
+     * @implSpec
+     * The default implementation converts each path to a file and calls
      * {@link #getJavaFileObjectsFromFiles getJavaObjectsFromFiles}.
      * IllegalArgumentException will be thrown if any of the paths
-     * cannot be converted to a file.</p>
+     * cannot be converted to a file.
      *
      * @param location a location
      * @param paths a list of paths, if {@code null} use the default
@@ -297,8 +310,8 @@ public interface StandardJavaFileManager extends JavaFileManager {
      *
      * @since 9
      */
-    default void setLocationFromPaths(Location location, Iterable<? extends Path> paths)
-        throws IOException {
+    default void setLocationFromPaths(Location location, Collection<? extends Path> paths)
+            throws IOException {
         setLocation(location, asFiles(paths));
     }
 
@@ -319,6 +332,11 @@ public interface StandardJavaFileManager extends JavaFileManager {
     /**
      * Returns the search path associated with the given location.
      *
+     * @implSpec
+     * The default implementation calls {@link #getLocation getLocation}
+     * and then returns an {@code Iterable} formed by calling {@code toPath()}
+     * on each {@code File} returned from {@code getLocation}.
+     *
      * @param location a location
      * @return a list of paths or {@code null} if this location has no
      * associated search path
@@ -337,8 +355,9 @@ public interface StandardJavaFileManager extends JavaFileManager {
      * {@link java.nio.file.Path Path} object. In such cases, this method may be
      * used to access that object.
      *
-     * <p>The default implementation throws {@link UnsupportedOperationException}
-     * for all files.</p>
+     * @implSpec
+     * The default implementation throws {@link UnsupportedOperationException}
+     * for all files.
      *
      * @param file a file object
      * @return a path representing the same underlying file system artifact
@@ -351,4 +370,36 @@ public interface StandardJavaFileManager extends JavaFileManager {
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * Factory to create {@code Path} objects from strings.
+     *
+     * @since 9
+     */
+    interface PathFactory {
+        /**
+         * Converts a path string, or a sequence of strings that when joined form a path string, to a Path.
+         *
+         * @param first  the path string or initial part of the path string
+         * @param more   additional strings to be joined to form the path string
+         * @return       the resulting {@code Path}
+         */
+        Path getPath(String first, String... more);
+    }
+
+     /**
+      * Specify a factory that can be used to generate a path from a string, or series of strings.
+      *
+      * If this method is not called, a factory whose {@code getPath} method is
+      * equivalent to calling
+      * {@link java.nio.file.Paths#get(String, String...) java.nio.file.Paths.get(first, more)}
+      * will be used.
+      *
+      * @implSpec
+      * The default implementation of this method ignores the factory that is provided.
+      *
+      * @param f  the factory
+      *
+      * @since 9
+      */
+    default void setPathFactory(PathFactory f) { }
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
index 3bdd3169d9e..5895f2e77ec 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
@@ -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
@@ -492,7 +492,7 @@ public class ClientCodeWrapper {
         }
 
         @Override @DefinedBy(Api.COMPILER)
-        public void setLocationFromPaths(Location location, Iterable<? extends Path> paths) throws IOException {
+        public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException {
             try {
                 ((StandardJavaFileManager)clientJavaFileManager).setLocationFromPaths(location, paths);
             } catch (ClientCodeException e) {
@@ -534,6 +534,17 @@ public class ClientCodeWrapper {
                 throw new ClientCodeException(e);
             }
         }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public void setPathFactory(PathFactory f) {
+            try {
+                ((StandardJavaFileManager)clientJavaFileManager).setPathFactory(f);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
     }
 
     protected class WrappedFileObject implements FileObject {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java
index 9867b008487..7fc0ffa47dd 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,7 +98,9 @@ public abstract class Directive implements ModuleElement.Directive {
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
         public java.util.List<? extends ModuleElement> getTargetModules() {
-            return Collections.unmodifiableList(modules);
+            return modules == null
+                    ? null
+                    : Collections.unmodifiableList(modules);
         }
 
         @Override
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
index 8e8665dd1eb..33e82384993 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
@@ -841,6 +841,28 @@ public class TypeEnter implements Completer {
             super(CompletionCause.MEMBERS_PHASE, null);
         }
 
+        private boolean completing;
+        private List<Env<AttrContext>> todo = List.nil();
+
+        @Override
+        protected void doCompleteEnvs(List<Env<AttrContext>> envs) {
+            todo = todo.prependList(envs);
+            if (completing) {
+                return ; //the top-level invocation will handle all envs
+            }
+            boolean prevCompleting = completing;
+            completing = true;
+            try {
+                while (todo.nonEmpty()) {
+                    Env<AttrContext> head = todo.head;
+                    todo = todo.tail;
+                    super.doCompleteEnvs(List.of(head));
+                }
+            } finally {
+                completing = prevCompleting;
+            }
+        }
+
         @Override
         protected void runPhase(Env<AttrContext> env) {
             JCClassDecl tree = env.enclClass;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java
index fea4ef7a60a..9d11bb8683a 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package com.sun.tools.javac.file;
 
 import java.io.IOException;
+import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -108,7 +109,7 @@ public class FSInfo {
             for (StringTokenizer st = new StringTokenizer(path);
                  st.hasMoreTokens(); ) {
                 String elt = st.nextToken();
-                Path f = Paths.get(elt);
+                Path f = FileSystems.getDefault().getPath(elt);
                 if (!f.isAbsolute() && parent != null)
                     f = parent.resolve(f).toAbsolutePath();
                 list.add(f);
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
index fa1a3a5c608..53f515da4eb 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
@@ -109,6 +109,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
 
     protected boolean symbolFileEnabled;
 
+    private PathFactory pathFactory = Paths::get;
+
     protected enum SortFiles implements Comparator<Path> {
         FORWARD {
             @Override
@@ -166,6 +168,16 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
         }
     }
 
+    @Override @DefinedBy(DefinedBy.Api.COMPILER)
+    public void setPathFactory(PathFactory f) {
+        pathFactory = Objects.requireNonNull(f);
+        locations.setPathFactory(f);
+    }
+
+    private Path getPath(String first, String... more) {
+        return pathFactory.getPath(first, more);
+    }
+
     /**
      * Set whether or not to use ct.sym as an alternate to rt.jar.
      */
@@ -199,7 +211,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
     public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
         ListBuffer<Path> paths = new ListBuffer<>();
         for (String name : names)
-            paths.append(Paths.get(nullCheck(name)));
+            paths.append(getPath(nullCheck(name)));
         return getJavaFileObjectsFromPaths(paths.toList());
     }
 
@@ -837,7 +849,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
                 if (sibling != null && sibling instanceof PathFileObject) {
                     return ((PathFileObject) sibling).getSibling(baseName);
                 } else {
-                    Path p = Paths.get(baseName);
+                    Path p = getPath(baseName);
                     Path real = fsInfo.getCanonicalFile(p);
                     return PathFileObject.forSimplePath(this, real, p);
                 }
@@ -855,7 +867,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
 
         try {
             if (dir == null) {
-                dir = Paths.get(System.getProperty("user.dir"));
+                dir = getPath(System.getProperty("user.dir"));
             }
             Path path = fileName.resolveAgainst(fsInfo.getCanonicalFile(dir));
             return PathFileObject.forDirectoryPath(this, path, dir, fileName);
@@ -918,7 +930,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
 
     @Override @DefinedBy(Api.COMPILER)
     public void setLocationFromPaths(Location location,
-                            Iterable<? extends Path> searchpath)
+                            Collection<? extends Path> searchpath)
         throws IOException
     {
         nullCheck(location);
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
index 68f7781b0ef..12106e3ecc1 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
@@ -68,6 +68,7 @@ import javax.lang.model.SourceVersion;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardJavaFileManager.PathFactory;
 import javax.tools.StandardLocation;
 
 import com.sun.tools.javac.code.Lint;
@@ -121,7 +122,9 @@ public class Locations {
 
     private ModuleNameReader moduleNameReader;
 
-    static final Path javaHome = Paths.get(System.getProperty("java.home"));
+    private PathFactory pathFactory = Paths::get;
+
+    static final Path javaHome = FileSystems.getDefault().getPath(System.getProperty("java.home"));
     static final Path thisSystemModules = javaHome.resolve("lib").resolve("modules");
 
     Map<Path, FileSystem> fileSystems = new LinkedHashMap<>();
@@ -131,6 +134,10 @@ public class Locations {
         initHandlers();
     }
 
+    Path getPath(String first, String... more) {
+        return pathFactory.getPath(first, more);
+    }
+
     public void close() throws IOException {
         ListBuffer<IOException> list = new ListBuffer<>();
         closeables.forEach(closeable -> {
@@ -155,6 +162,10 @@ public class Locations {
         this.fsInfo = fsInfo;
     }
 
+    void setPathFactory(PathFactory f) {
+        pathFactory = f;
+    }
+
     boolean isDefaultBootClassPath() {
         BootClassPathLocationHandler h
                 = (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
@@ -167,7 +178,7 @@ public class Locations {
      * @param searchPath The search path to be split
      * @return The elements of the path
      */
-    private static Iterable<Path> getPathEntries(String searchPath) {
+    private Iterable<Path> getPathEntries(String searchPath) {
         return getPathEntries(searchPath, null);
     }
 
@@ -181,7 +192,7 @@ public class Locations {
      * empty path elements
      * @return The elements of the path
      */
-    private static Iterable<Path> getPathEntries(String searchPath, Path emptyPathDefault) {
+    private Iterable<Path> getPathEntries(String searchPath, Path emptyPathDefault) {
         ListBuffer<Path> entries = new ListBuffer<>();
         for (String s: searchPath.split(Pattern.quote(File.pathSeparator), -1)) {
             if (s.isEmpty()) {
@@ -189,7 +200,7 @@ public class Locations {
                     entries.add(emptyPathDefault);
                 }
             } else {
-                entries.add(Paths.get(s));
+                entries.add(getPath(s));
             }
         }
         return entries;
@@ -465,7 +476,7 @@ public class Locations {
             // need to decide how best to report issue for benefit of
             // direct API call on JavaFileManager.handleOption(specifies IAE)
             // vs. command line decoding.
-            outputDir = (value == null) ? null : Paths.get(value);
+            outputDir = (value == null) ? null : getPath(value);
             return true;
         }
 
@@ -606,7 +617,7 @@ public class Locations {
         protected SearchPath createPath() {
             return new SearchPath()
                     .expandJarClassPaths(true) // Only search user jars for Class-Paths
-                    .emptyPathDefault(Paths.get("."));  // Empty path elt ==> current directory
+                    .emptyPathDefault(getPath("."));  // Empty path elt ==> current directory
         }
 
         private void lazy() {
@@ -791,7 +802,7 @@ public class Locations {
             paths.addAll(modules);
 
             for (String s : files.split(Pattern.quote(File.pathSeparator))) {
-                paths.add(Paths.get(s));
+                paths.add(getPath(s));
             }
 
             return paths;
@@ -1170,12 +1181,12 @@ public class Locations {
             for (String seg: segments) {
                 int markStart = seg.indexOf(MARKER);
                 if (markStart == -1) {
-                    add(map, Paths.get(seg), null);
+                    add(map, getPath(seg), null);
                 } else {
                     if (markStart == 0 || !isSeparator(seg.charAt(markStart - 1))) {
                         throw new IllegalArgumentException("illegal use of " + MARKER + " in " + seg);
                     }
-                    Path prefix = Paths.get(seg.substring(0, markStart - 1));
+                    Path prefix = getPath(seg.substring(0, markStart - 1));
                     Path suffix;
                     int markEnd = markStart + MARKER.length();
                     if (markEnd == seg.length()) {
@@ -1184,7 +1195,7 @@ public class Locations {
                             || seg.indexOf(MARKER, markEnd) != -1) {
                         throw new IllegalArgumentException("illegal use of " + MARKER + " in " + seg);
                     } else {
-                        suffix = Paths.get(seg.substring(markEnd + 1));
+                        suffix = getPath(seg.substring(markEnd + 1));
                     }
                     add(map, prefix, suffix);
                 }
@@ -1331,13 +1342,13 @@ public class Locations {
     }
 
     private class SystemModulesLocationHandler extends BasicLocationHandler {
-        private Path javaHome;
+        private Path systemJavaHome;
         private Path modules;
         private Map<String, ModuleLocationHandler> systemModules;
 
         SystemModulesLocationHandler() {
             super(StandardLocation.SYSTEM_MODULES, Option.SYSTEM);
-            javaHome = Paths.get(System.getProperty("java.home"));
+            systemJavaHome = Locations.javaHome;
         }
 
         @Override
@@ -1347,11 +1358,11 @@ public class Locations {
             }
 
             if (value == null) {
-                javaHome = Paths.get(System.getProperty("java.home"));
+                systemJavaHome = Locations.javaHome;
             } else if (value.equals("none")) {
-                javaHome = null;
+                systemJavaHome = null;
             } else {
-                update(Paths.get(value));
+                update(getPath(value));
             }
 
             modules = null;
@@ -1360,13 +1371,13 @@ public class Locations {
 
         @Override
         Collection<Path> getPaths() {
-            return (javaHome == null) ? null : Collections.singleton(javaHome);
+            return (systemJavaHome == null) ? null : Collections.singleton(systemJavaHome);
         }
 
         @Override
         void setPaths(Iterable<? extends Path> files) throws IOException {
             if (files == null) {
-                javaHome = null;
+                systemJavaHome = null;
             } else {
                 Iterator<? extends Path> pathIter = files.iterator();
                 if (!pathIter.hasNext()) {
@@ -1386,16 +1397,15 @@ public class Locations {
         }
 
         private void update(Path p) {
-            if (!isCurrentPlatform(p) && !Files.exists(p.resolve("jrt-fs.jar")) && !Files.exists(javaHome.resolve("modules")))
+            if (!isCurrentPlatform(p) && !Files.exists(p.resolve("jrt-fs.jar")) && !Files.exists(systemJavaHome.resolve("modules")))
                 throw new IllegalArgumentException(p.toString());
-            javaHome = p;
+            systemJavaHome = p;
             modules = null;
         }
 
         private boolean isCurrentPlatform(Path p) {
-            Path jh = Paths.get(System.getProperty("java.home"));
             try {
-                return Files.isSameFile(p, jh);
+                return Files.isSameFile(p, Locations.javaHome);
             } catch (IOException ex) {
                 throw new IllegalArgumentException(p.toString(), ex);
             }
@@ -1421,7 +1431,7 @@ public class Locations {
                 return;
             }
 
-            if (javaHome == null) {
+            if (systemJavaHome == null) {
                 systemModules = Collections.emptyMap();
                 return;
             }
@@ -1431,15 +1441,15 @@ public class Locations {
                     URI jrtURI = URI.create("jrt:/");
                     FileSystem jrtfs;
 
-                    if (isCurrentPlatform(javaHome)) {
+                    if (isCurrentPlatform(systemJavaHome)) {
                         jrtfs = FileSystems.getFileSystem(jrtURI);
                     } else {
                         try {
                             Map<String, String> attrMap =
-                                    Collections.singletonMap("java.home", javaHome.toString());
+                                    Collections.singletonMap("java.home", systemJavaHome.toString());
                             jrtfs = FileSystems.newFileSystem(jrtURI, attrMap);
                         } catch (ProviderNotFoundException ex) {
-                            URL javaHomeURL = javaHome.resolve("jrt-fs.jar").toUri().toURL();
+                            URL javaHomeURL = systemJavaHome.resolve("jrt-fs.jar").toUri().toURL();
                             ClassLoader currentLoader = Locations.class.getClassLoader();
                             URLClassLoader fsLoader =
                                     new URLClassLoader(new URL[] {javaHomeURL}, currentLoader);
@@ -1454,7 +1464,7 @@ public class Locations {
 
                     modules = jrtfs.getPath("/modules");
                 } catch (FileSystemNotFoundException | ProviderNotFoundException e) {
-                    modules = javaHome.resolve("modules");
+                    modules = systemJavaHome.resolve("modules");
                     if (!Files.exists(modules))
                         throw new IOException("can't find system classes", e);
                 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java
index 73be502e052..f30896c2cbc 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java
@@ -109,7 +109,7 @@ public abstract class PathFileObject implements JavaFileObject {
         private DirectoryFileObject(BaseFileManager fileManager, Path path,
                 Path userPackageRootDir, RelativePath relativePath) {
             super(fileManager, path);
-            this.userPackageRootDir = userPackageRootDir;
+            this.userPackageRootDir = Objects.requireNonNull(userPackageRootDir);
             this.relativePath = relativePath;
         }
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java
index 3e541b884f1..75fdcf1b031 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java
@@ -26,10 +26,8 @@
 package com.sun.tools.javac.file;
 
 import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
@@ -58,13 +56,8 @@ public abstract class RelativePath implements Comparable<RelativePath> {
     public abstract String basename();
 
     public Path resolveAgainst(Path directory) throws /*unchecked*/ InvalidPathException {
-        if (directory == null) {
-            String sep = FileSystems.getDefault().getSeparator();
-            return Paths.get(path.replace("/", sep));
-        } else {
-            String sep = directory.getFileSystem().getSeparator();
-            return directory.resolve(path.replace("/", sep));
-        }
+        String sep = directory.getFileSystem().getSeparator();
+        return directory.resolve(path.replace("/", sep));
     }
 
     public Path resolveAgainst(FileSystem fs) throws /*unchecked*/ InvalidPathException {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
index 3ef115ff8dd..62bfd05484c 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -108,7 +108,7 @@ public class ClassFile {
         V50(50, 0),   // JDK 1.6: stackmaps
         V51(51, 0),   // JDK 1.7
         V52(52, 0),   // JDK 1.8: lambda, type annos, param names
-        V53(52, 0);   // JDK 1.9: modules  **** FIXME TO 53 BEFORE RELEASE *****
+        V53(53, 0);   // JDK 1.9: modules, indy string concat
         Version(int major, int minor) {
             this.major = major;
             this.minor = minor;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java
index 75f314b1912..b0737558596 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java
@@ -60,8 +60,8 @@ public enum Target {
     /** JDK 8. */
     JDK1_8("1.8", 52, 0),
 
-    /** JDK 9, initially an alias for 8. */
-    JDK1_9("1.9", 52, 0);
+    /** JDK 9. */
+    JDK1_9("1.9", 53, 0);
 
     private static final Context.Key<Target> targetKey = new Context.Key<>();
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java
index 6eac715fa98..348054f1269 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java
@@ -28,7 +28,7 @@ package com.sun.tools.doclets.formats.html;
 import java.util.*;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javadoc.RootDocImpl;
+import com.sun.tools.javadoc.main.RootDocImpl;
 import com.sun.tools.doclets.formats.html.markup.*;
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.builders.*;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
index 5751a70807b..83fc46a34e0 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
@@ -40,7 +40,7 @@ import com.sun.tools.doclint.DocLint;
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.StringUtils;
-import com.sun.tools.javadoc.RootDocImpl;
+import com.sun.tools.javadoc.main.RootDocImpl;
 
 /**
  * Configure the output based on the command line options.
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java
index 2c8f185d981..216f0f7886a 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java
@@ -149,8 +149,8 @@ public class SourceToHTMLConverter {
                 return;
             Reader r;
             // temp hack until we can update SourcePosition API.
-            if (sp instanceof com.sun.tools.javadoc.SourcePositionImpl) {
-                FileObject fo = ((com.sun.tools.javadoc.SourcePositionImpl) sp).fileObject();
+            if (sp instanceof com.sun.tools.javadoc.main.SourcePositionImpl) {
+                FileObject fo = ((com.sun.tools.javadoc.main.SourcePositionImpl) sp).fileObject();
                 if (fo == null)
                     return;
                 r = fo.openReader(true);
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Main.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Main.java
index dfc21b27702..467fd2d34e0 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Main.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Main.java
@@ -27,6 +27,8 @@ package com.sun.tools.javadoc;
 
 import java.io.PrintWriter;
 
+import com.sun.tools.javadoc.main.Start;
+
 /**
  * Provides external entry points (tool and programmatic)
  * for the javadoc program.
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AbstractTypeImpl.java
similarity index 98%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AbstractTypeImpl.java
index 856cd558ea8..c0570aa7516 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AbstractTypeImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotatedTypeImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotatedTypeImpl.java
index 3ee1c0a99c1..982b8744ed5 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotatedTypeImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 import com.sun.tools.javac.code.Attribute;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationDescImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationDescImpl.java
index 2647d9983be..d348f35ec02 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationDescImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationTypeDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeDocImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationTypeDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeDocImpl.java
index 2ff3ba6d971..d691959f4c3 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationTypeDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationTypeElementDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeElementDocImpl.java
similarity index 98%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationTypeElementDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeElementDocImpl.java
index 230542958f0..bd0f8284c2d 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationTypeElementDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeElementDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationValueImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationValueImpl.java
index b79a19ce8ff..036f2b40a88 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationValueImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ClassDocImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ClassDocImpl.java
index acebdb840f6..c1437e007ed 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ClassDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Comment.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Comment.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Comment.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Comment.java
index e2e29007874..ade553baba9 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Comment.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Comment.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ConstructorDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ConstructorDocImpl.java
similarity index 98%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ConstructorDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ConstructorDocImpl.java
index d0a0853dc3f..ca53d182e6c 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ConstructorDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ConstructorDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocEnv.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocEnv.java
index 2ac36520cd6..d123013013b 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocEnv.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.lang.reflect.Modifier;
 import java.util.*;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocImpl.java
index bf77bd089e0..0f085e7eeef 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.io.DataInputStream;
 import java.io.IOException;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocLocale.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocLocale.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocLocale.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocLocale.java
index 5dcd1b72201..4460d7e311c 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocLocale.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocLocale.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.text.BreakIterator;
 import java.text.Collator;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocletInvoker.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocletInvoker.java
index 91e333e8ccb..402e67ef70b 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocletInvoker.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ExecutableMemberDocImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ExecutableMemberDocImpl.java
index cfbc0cb4001..30075a96d78 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ExecutableMemberDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.lang.reflect.Modifier;
 import java.text.CollationKey;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/FieldDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/FieldDocImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/FieldDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/FieldDocImpl.java
index 8317128c945..c3432633dc8 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/FieldDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/FieldDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.source.util.TreePath;
 import java.lang.reflect.Modifier;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocClassFinder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocClassFinder.java
similarity index 98%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocClassFinder.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocClassFinder.java
index ecb3659f174..997b8d97759 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocClassFinder.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocClassFinder.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.util.EnumSet;
 import javax.tools.JavaFileObject;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocEnter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocEnter.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java
index 3732098289f..a49abaeabb6 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocEnter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import javax.tools.JavaFileObject;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocMemberEnter.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocMemberEnter.java
index 220ffb5504e..452cc614938 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocMemberEnter.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.source.util.TreePath;
 import com.sun.tools.javac.code.Flags;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTodo.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTodo.java
similarity index 98%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTodo.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTodo.java
index cbeaf699376..88ab1ad1dd2 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTodo.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTodo.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.tools.javac.comp.*;
 import com.sun.tools.javac.util.*;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java
index b29c2899222..fa358ddf47d 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/MemberDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MemberDocImpl.java
similarity index 98%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/MemberDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MemberDocImpl.java
index 37c7c66eb46..d87c0ae01f1 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/MemberDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MemberDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Messager.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Messager.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Messager.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Messager.java
index 2a97cd0ff25..d181fb2a82d 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Messager.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Messager.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.io.PrintWriter;
 import java.util.Locale;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/MethodDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MethodDocImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/MethodDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MethodDocImpl.java
index b624694a771..391eab2b8d3 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/MethodDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MethodDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.lang.reflect.Modifier;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ModifierFilter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ModifierFilter.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ModifierFilter.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ModifierFilter.java
index 40a9040971c..76624e64f60 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ModifierFilter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ModifierFilter.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import static com.sun.tools.javac.code.Flags.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PackageDocImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PackageDocImpl.java
index 13753959b3e..a5683240e67 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PackageDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParamTagImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParamTagImpl.java
similarity index 98%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParamTagImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParamTagImpl.java
index e8775393776..56cf966f62f 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParamTagImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParamTagImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.util.regex.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParameterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterImpl.java
similarity index 98%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParameterImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterImpl.java
index 14de4a2f43a..ce047b59c37 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParameterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParameterizedTypeImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterizedTypeImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParameterizedTypeImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterizedTypeImpl.java
index 2fac11119d3..e7c8875f76b 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParameterizedTypeImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterizedTypeImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PrimitiveType.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PrimitiveType.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PrimitiveType.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PrimitiveType.java
index a3a81983734..79d2a3a246f 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PrimitiveType.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PrimitiveType.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ProgramElementDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ProgramElementDocImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ProgramElementDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ProgramElementDocImpl.java
index d647b491639..663263ee166 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ProgramElementDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ProgramElementDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.lang.reflect.Modifier;
 import java.text.CollationKey;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/RootDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/RootDocImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java
index d4b0da6d03d..03157373e7f 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/RootDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.io.IOException;
 import java.util.Collection;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SeeTagImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SeeTagImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SeeTagImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SeeTagImpl.java
index de73bc87b6a..626a54d81b1 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SeeTagImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SeeTagImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.io.File;
 import java.util.Locale;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SerialFieldTagImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerialFieldTagImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SerialFieldTagImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerialFieldTagImpl.java
index e89866d9de9..a7dc95da462 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SerialFieldTagImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerialFieldTagImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SerializedForm.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerializedForm.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SerializedForm.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerializedForm.java
index f6d056a52c7..f06987ce89e 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SerializedForm.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerializedForm.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 import com.sun.tools.javac.code.*;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SourcePositionImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SourcePositionImpl.java
index b508b615ea6..911e57c8f99 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SourcePositionImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.io.File;
 import javax.tools.FileObject;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Start.java
similarity index 98%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Start.java
index c05762504e5..188c6b5fd84 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Start.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -95,7 +95,7 @@ public class Start extends ToolOption.Helper {
 
     private JavaFileManager fileManager;
 
-    Start(String programName,
+    public Start(String programName,
           PrintWriter errWriter,
           PrintWriter warnWriter,
           PrintWriter noticeWriter,
@@ -119,11 +119,11 @@ public class Start extends ToolOption.Helper {
         this.docletParentClassLoader = docletParentClassLoader;
     }
 
-    Start(String programName, String defaultDocletClassName) {
+    public Start(String programName, String defaultDocletClassName) {
         this(programName, defaultDocletClassName, null);
     }
 
-    Start(String programName, String defaultDocletClassName,
+    public Start(String programName, String defaultDocletClassName,
           ClassLoader docletParentClassLoader) {
         context = new Context();
         messager = new Messager(context, programName);
@@ -131,15 +131,15 @@ public class Start extends ToolOption.Helper {
         this.docletParentClassLoader = docletParentClassLoader;
     }
 
-    Start(String programName, ClassLoader docletParentClassLoader) {
+    public Start(String programName, ClassLoader docletParentClassLoader) {
         this(programName, standardDocletClassName, docletParentClassLoader);
     }
 
-    Start(String programName) {
+    public Start(String programName) {
         this(programName, standardDocletClassName);
     }
 
-    Start(ClassLoader docletParentClassLoader) {
+    public Start(ClassLoader docletParentClassLoader) {
         this(javadocName, docletParentClassLoader);
     }
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TagImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TagImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TagImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TagImpl.java
index a106bb68f40..352c9fc7152 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TagImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TagImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ThrowsTagImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ThrowsTagImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ThrowsTagImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ThrowsTagImpl.java
index 6da454fdbb8..e92d871263b 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ThrowsTagImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ThrowsTagImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ToolOption.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ToolOption.java
index 18ab44f3c06..180f99b5162 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ToolOption.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import java.util.LinkedHashMap;
 import java.util.Map;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TypeMaker.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeMaker.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TypeMaker.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeMaker.java
index aae1917d573..7c18ce120b2 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TypeMaker.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeMaker.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 import com.sun.tools.javac.code.Symbol;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeVariableImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeVariableImpl.java
index 93d4e31dd20..8207695e285 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeVariableImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/WildcardTypeImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/WildcardTypeImpl.java
similarity index 99%
rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/WildcardTypeImpl.java
rename to langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/WildcardTypeImpl.java
index cf458d2335c..f3b4138e9d7 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/WildcardTypeImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/WildcardTypeImpl.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package com.sun.tools.javadoc;
+package com.sun.tools.javadoc.main;
 
 import com.sun.javadoc.*;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java
index 3d6a248da57..61b101ce5e6 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java
@@ -90,6 +90,19 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter
         this.next = nextType;
     }
 
+    /**
+     * Get the module link.
+     *
+     * @return a content tree for the module link
+     */
+    @Override
+    protected Content getNavLinkModule() {
+        Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(annotationType),
+                moduleLabel);
+        Content li = HtmlTree.LI(linkContent);
+        return li;
+    }
+
     /**
      * Get this package link.
      *
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
index 9e3834dffba..61993e1490b 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
@@ -504,6 +504,19 @@ public class ClassUseWriter extends SubWriterHolderWriter {
         return bodyTree;
     }
 
+    /**
+     * Get the module link.
+     *
+     * @return a content tree for the module link
+     */
+    @Override
+    protected Content getNavLinkModule() {
+        Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(typeElement),
+                moduleLabel);
+        Content li = HtmlTree.LI(linkContent);
+        return li;
+    }
+
     /**
      * Get this package link.
      *
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
index 4137cefb6f7..3758a0bd665 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
@@ -104,6 +104,19 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite
         this.next = nextClass;
     }
 
+    /**
+     * Get the module link.
+     *
+     * @return a content tree for the module link
+     */
+    @Override
+    protected Content getNavLinkModule() {
+        Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(typeElement),
+                moduleLabel);
+        Content li = HtmlTree.LI(linkContent);
+        return li;
+    }
+
     /**
      * Get this package link.
      *
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
index 71eedc88e42..c5af88209b9 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
@@ -570,6 +570,11 @@ public class HtmlDocletWriter extends HtmlDocWriter {
             if (configuration.createoverview) {
                 navList.addContent(getNavLinkContents());
             }
+            if (configuration.modules.size() == 1) {
+                navList.addContent(getNavLinkModule(configuration.modules.first()));
+            } else if (!configuration.modules.isEmpty()) {
+                navList.addContent(getNavLinkModule());
+            }
             if (configuration.packages.size() == 1) {
                 navList.addContent(getNavLinkPackage(configuration.packages.first()));
             } else if (!configuration.packages.isEmpty()) {
@@ -678,6 +683,28 @@ public class HtmlDocletWriter extends HtmlDocWriter {
         return li;
     }
 
+    /**
+     * Get link to the module summary page for the module passed.
+     *
+     * @param mdle Module to which link will be generated
+     * @return a content tree for the link
+     */
+    protected Content getNavLinkModule(ModuleElement mdle) {
+        Content linkContent = getModuleLink(mdle, moduleLabel);
+        Content li = HtmlTree.LI(linkContent);
+        return li;
+    }
+
+    /**
+     * Get the word "Module", to indicate that link is not available here.
+     *
+     * @return a content tree for the link
+     */
+    protected Content getNavLinkModule() {
+        Content li = HtmlTree.LI(moduleLabel);
+        return li;
+    }
+
     /**
      * Get link to the "package-summary.html" page for the package passed.
      *
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
index 555f0dcb03d..0a61c05fb76 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
@@ -267,6 +267,17 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
         }
     }
 
+    /**
+     * Get this module link.
+     *
+     * @return a content tree for the module link
+     */
+    @Override
+    protected Content getNavLinkModule() {
+        Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, moduleLabel);
+        return li;
+    }
+
     /**
      * Get "PREV MODULE" link in the navigation bar.
      *
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java
index 9dac9a3bf18..4db9a00c804 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java
@@ -223,6 +223,19 @@ public class PackageTreeWriter extends AbstractTreeWriter {
         }
     }
 
+    /**
+     * Get the module link.
+     *
+     * @return a content tree for the module link
+     */
+    @Override
+    protected Content getNavLinkModule() {
+        Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement),
+                moduleLabel);
+        Content li = HtmlTree.LI(linkContent);
+        return li;
+    }
+
     /**
      * Get link to the package summary page for the package of this tree.
      *
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java
index 3763e725892..d73fab18f8d 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java
@@ -303,6 +303,19 @@ public class PackageUseWriter extends SubWriterHolderWriter {
         return bodyTree;
     }
 
+    /**
+     * Get the module link.
+     *
+     * @return a content tree for the module link
+     */
+    @Override
+    protected Content getNavLinkModule() {
+        Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement),
+                moduleLabel);
+        Content li = HtmlTree.LI(linkContent);
+        return li;
+    }
+
     /**
      * Get this package link.
      *
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
index 64d76a0743c..438687b0d6c 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
@@ -375,6 +375,19 @@ public class PackageWriterImpl extends HtmlDocletWriter
         return li;
     }
 
+    /**
+     * Get the module link.
+     *
+     * @return a content tree for the module link
+     */
+    @Override
+    protected Content getNavLinkModule() {
+        Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement),
+                moduleLabel);
+        Content li = HtmlTree.LI(linkContent);
+        return li;
+    }
+
     /**
      * Highlight "Package" in the navigation bar, as this is the package page.
      *
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java
index 917063e98ae..34eced11854 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java
@@ -329,6 +329,7 @@ public abstract class Configuration {
     public abstract MessageRetriever getDocletSpecificMsg();
 
     public CommentUtils cmtUtils;
+    public SortedSet<ModuleElement> modules;
 
     /**
      * A sorted set of packages specified on the command-line merged with a
@@ -395,6 +396,8 @@ public abstract class Configuration {
                 s.add(p);
             }
         }
+        modules = new TreeSet<>(utils.makeModuleComparator());
+        modules.addAll(modulePackages.keySet());
         showModules = (modulePackages.size() > 1);
     }
 
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
index 2cca6849e26..a0058e15b0d 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
@@ -283,8 +283,8 @@ public class Start extends ToolOption.Helper {
             }
         } else {
             if (this.apiMode) {
-                com.sun.tools.javadoc.Start ostart
-                        = new com.sun.tools.javadoc.Start(context);
+                com.sun.tools.javadoc.main.Start ostart
+                        = new com.sun.tools.javadoc.main.Start(context);
                 return ostart.begin(docletClass, options, fileObjects);
             }
             warn("main.legacy_api");
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
index ca6b08612b9..50959ba539a 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,10 +40,13 @@ import com.sun.source.tree.Scope;
 import com.sun.source.tree.Tree;
 import com.sun.source.tree.Tree.Kind;
 import com.sun.source.tree.VariableTree;
+import com.sun.source.util.JavacTask;
 import com.sun.source.util.SourcePositions;
 import com.sun.source.util.TreePath;
 import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
 import com.sun.tools.javac.api.JavacScope;
+import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
@@ -119,8 +122,12 @@ import javax.lang.model.type.ExecutableType;
 import javax.lang.model.type.TypeKind;
 import javax.lang.model.util.ElementFilter;
 import javax.lang.model.util.Types;
+import javax.tools.JavaCompiler;
 import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
 import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
 
 import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME;
 
@@ -932,6 +939,12 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis {
         }
     }
 
+    //tweaked by tests to disable reading parameter names from classfiles so that tests using
+    //JDK's classes are stable for both release and fastdebug builds:
+    private final String[] keepParameterNames = new String[] {
+        "-XDsave-parameter-names=true"
+    };
+
     private String documentationImpl(String code, int cursor) {
         code = code.substring(0, cursor);
         if (code.trim().isEmpty()) { //TODO: comment handling
@@ -942,7 +955,7 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis {
             return null;
 
         OuterWrap codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code));
-        AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap);
+        AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap, keepParameterNames);
         SourcePositions sp = at.trees().getSourcePositions();
         CompilationUnitTree topLevel = at.firstCuTree();
         TreePath tp = pathFor(topLevel, sp, codeWrap.snippetIndexToWrapIndex(cursor));
@@ -983,9 +996,11 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis {
                         .collect(Collectors.toList());
         }
 
-        return Util.stream(candidates)
-                .map(method -> Util.expunge(element2String(method.fst)))
-                .collect(joining("\n"));
+        try (SourceCache sourceCache = new SourceCache(at)) {
+            return Util.stream(candidates)
+                    .map(method -> Util.expunge(element2String(sourceCache, method.fst)))
+                    .collect(joining("\n"));
+        }
     }
 
     private boolean isEmptyArgumentsContext(List<? extends ExpressionTree> arguments) {
@@ -996,19 +1011,173 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis {
         return false;
     }
 
-    private String element2String(Element el) {
+    private String element2String(SourceCache sourceCache, Element el) {
+        try {
+            if (hasSyntheticParameterNames(el)) {
+                el = sourceCache.getSourceMethod(el);
+            }
+        } catch (IOException ex) {
+            proc.debug(ex, "SourceCodeAnalysisImpl.element2String(..., " + el + ")");
+        }
+
+        return Util.expunge(elementHeader(el));
+    }
+
+    private boolean hasSyntheticParameterNames(Element el) {
+        if (el.getKind() != ElementKind.CONSTRUCTOR && el.getKind() != ElementKind.METHOD)
+            return false;
+
+        ExecutableElement ee = (ExecutableElement) el;
+
+        if (ee.getParameters().isEmpty())
+            return false;
+
+        return ee.getParameters()
+                 .stream()
+                 .allMatch(param -> param.getSimpleName().toString().startsWith("arg"));
+    }
+
+    private final class SourceCache implements AutoCloseable {
+        private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        private final Map<String, Map<String, Element>> topLevelName2Signature2Method = new HashMap<>();
+        private final AnalyzeTask originalTask;
+        private final StandardJavaFileManager fm;
+
+        public SourceCache(AnalyzeTask originalTask) {
+            this.originalTask = originalTask;
+            List<Path> sources = findSources();
+            if (sources.iterator().hasNext()) {
+                StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null);
+                try {
+                    fm.setLocationFromPaths(StandardLocation.SOURCE_PATH, sources);
+                } catch (IOException ex) {
+                    proc.debug(ex, "SourceCodeAnalysisImpl.SourceCache.<init>(...)");
+                    fm = null;
+                }
+                this.fm = fm;
+            } else {
+                //don't waste time if there are no sources
+                this.fm = null;
+            }
+        }
+
+        public Element getSourceMethod(Element method) throws IOException {
+            if (fm == null)
+                return method;
+
+            TypeElement type = topLevelType(method);
+
+            if (type == null)
+                return method;
+
+            String binaryName = originalTask.task.getElements().getBinaryName(type).toString();
+
+            Map<String, Element> cache = topLevelName2Signature2Method.get(binaryName);
+
+            if (cache == null) {
+                topLevelName2Signature2Method.put(binaryName, cache = createMethodCache(binaryName));
+            }
+
+            String handle = elementHeader(method, false);
+
+            return cache.getOrDefault(handle, method);
+        }
+
+        private TypeElement topLevelType(Element el) {
+            while (el != null && el.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
+                el = el.getEnclosingElement();
+            }
+
+            return el != null && (el.getKind().isClass() || el.getKind().isInterface()) ? (TypeElement) el : null;
+        }
+
+        private Map<String, Element> createMethodCache(String binaryName) throws IOException {
+            Pair<JavacTask, CompilationUnitTree> source = findSource(binaryName);
+
+            if (source == null)
+                return Collections.emptyMap();
+
+            Map<String, Element> signature2Method = new HashMap<>();
+            Trees trees = Trees.instance(source.fst);
+
+            new TreePathScanner<Void, Void>() {
+                @Override @DefinedBy(Api.COMPILER_TREE)
+                public Void visitMethod(MethodTree node, Void p) {
+                    Element currentMethod = trees.getElement(getCurrentPath());
+
+                    if (currentMethod != null) {
+                        signature2Method.put(elementHeader(currentMethod, false), currentMethod);
+                    }
+
+                    return null;
+                }
+            }.scan(source.snd, null);
+
+            return signature2Method;
+        }
+
+        private Pair<JavacTask, CompilationUnitTree> findSource(String binaryName) throws IOException {
+            JavaFileObject jfo = fm.getJavaFileForInput(StandardLocation.SOURCE_PATH,
+                                                        binaryName,
+                                                        JavaFileObject.Kind.SOURCE);
+
+            if (jfo == null)
+                return null;
+
+            List<JavaFileObject> jfos = Arrays.asList(jfo);
+            JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, fm, d -> {}, null, null, jfos);
+            Iterable<? extends CompilationUnitTree> cuts = task.parse();
+
+            task.enter();
+
+            return Pair.of(task, cuts.iterator().next());
+        }
+
+        @Override
+        public void close() {
+            try {
+                if (fm != null) {
+                    fm.close();
+                }
+            } catch (IOException ex) {
+                proc.debug(ex, "SourceCodeAnalysisImpl.SourceCache.close()");
+            }
+        }
+    }
+
+    private List<Path> availableSources;
+
+    private List<Path> findSources() {
+        if (availableSources != null) {
+            return availableSources;
+        }
+        List<Path> result = new ArrayList<>();
+        Path home = Paths.get(System.getProperty("java.home"));
+        Path srcZip = home.resolve("src.zip");
+        if (!Files.isReadable(srcZip))
+            srcZip = home.getParent().resolve("src.zip");
+        if (Files.isReadable(srcZip))
+            result.add(srcZip);
+        return availableSources = result;
+    }
+
+    private String elementHeader(Element el) {
+        return elementHeader(el, true);
+    }
+
+    private String elementHeader(Element el, boolean includeParameterNames) {
         switch (el.getKind()) {
             case ANNOTATION_TYPE: case CLASS: case ENUM: case INTERFACE:
                 return ((TypeElement) el).getQualifiedName().toString();
             case FIELD:
-                return element2String(el.getEnclosingElement()) + "." + el.getSimpleName() + ":" + el.asType();
+                return elementHeader(el.getEnclosingElement()) + "." + el.getSimpleName() + ":" + el.asType();
             case ENUM_CONSTANT:
-                return element2String(el.getEnclosingElement()) + "." + el.getSimpleName();
+                return elementHeader(el.getEnclosingElement()) + "." + el.getSimpleName();
             case EXCEPTION_PARAMETER: case LOCAL_VARIABLE: case PARAMETER: case RESOURCE_VARIABLE:
                 return el.getSimpleName() + ":" + el.asType();
             case CONSTRUCTOR: case METHOD:
                 StringBuilder header = new StringBuilder();
-                header.append(element2String(el.getEnclosingElement()));
+                header.append(elementHeader(el.getEnclosingElement()));
                 if (el.getKind() == ElementKind.METHOD) {
                     header.append(".");
                     header.append(el.getSimpleName());
@@ -1026,8 +1195,10 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis {
                     } else {
                         header.append(p.asType());
                     }
-                    header.append(" ");
-                    header.append(p.getSimpleName());
+                    if (includeParameterNames) {
+                        header.append(" ");
+                        header.append(p.getSimpleName());
+                    }
                     sep = ", ";
                 }
                 header.append(")");
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
index ce34f5f16a6..fe0a3b73f74 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
@@ -215,17 +215,21 @@ class TaskFactory {
 
         private final Iterable<? extends CompilationUnitTree> cuts;
 
-        AnalyzeTask(final OuterWrap wrap) {
-            this(Collections.singletonList(wrap));
+        AnalyzeTask(final OuterWrap wrap, String... extraArgs) {
+            this(Collections.singletonList(wrap), extraArgs);
         }
 
-        AnalyzeTask(final Collection<OuterWrap> wraps) {
+        AnalyzeTask(final Collection<OuterWrap> wraps, String... extraArgs) {
             this(wraps.stream(),
                     new WrapSourceHandler(),
-                    "-XDshouldStopPolicy=FLOW", "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none");
+                    Util.join(new String[] {
+                        "-XDshouldStopPolicy=FLOW", "-Xlint:unchecked",
+                        "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED",
+                        "-proc:none"
+                    }, extraArgs));
         }
 
-        <T>AnalyzeTask(final Stream<T> stream, SourceHandler<T> sourceHandler,
+        private <T>AnalyzeTask(final Stream<T> stream, SourceHandler<T> sourceHandler,
                 String... extraOptions) {
             super(stream, sourceHandler, extraOptions);
             cuts = analyze();
@@ -264,7 +268,7 @@ class TaskFactory {
 
         CompileTask(final Collection<OuterWrap> wraps) {
             super(wraps.stream(), new WrapSourceHandler(),
-                    "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none");
+                    "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none", "-parameters");
         }
 
         boolean compile() {
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java
index 553e6c97fb3..413c30baa13 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java
@@ -25,6 +25,9 @@
 
 package jdk.jshell;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Locale;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
@@ -95,6 +98,15 @@ class Util {
         return StreamSupport.stream(iterable.spliterator(), false);
     }
 
+    static String[] join(String[] a1, String[] a2) {
+        List<String> result = new ArrayList<>();
+
+        result.addAll(Arrays.asList(a1));
+        result.addAll(Arrays.asList(a2));
+
+        return result.toArray(new String[0]);
+    }
+
     static class Pair<T, U> {
         final T first;
         final U second;
diff --git a/langtools/test/Makefile b/langtools/test/Makefile
index 0940c512fdc..f5b43ab0b0b 100644
--- a/langtools/test/Makefile
+++ b/langtools/test/Makefile
@@ -86,6 +86,8 @@ endif
 # Default JTREG to run
 ifdef JPRT_JTREG_HOME
   JTREG_HOME = $(JPRT_JTREG_HOME)
+else ifdef JT_HOME
+  JTREG_HOME = $(JT_HOME)
 else
   JTREG_HOME = $(SLASH_JAVA)/re/jtreg/4.1-jigsaw/nightly/binaries/jtreg/
 endif
@@ -113,10 +115,12 @@ endif
 #
 # JT_JAVA is the version of java used to run jtreg/JCK. 
 #
-ifdef JPRT_JAVA_HOME
-  JT_JAVA = $(JPRT_JAVA_HOME)
-else
-  JT_JAVA = $(SLASH_JAVA)/re/jdk/1.9.0/archive/fcs/binaries/$(PLATFORM)-$(ARCH)
+ifndef JT_JAVA
+  ifdef JPRT_JAVA_HOME
+    JT_JAVA = $(JPRT_JAVA_HOME)
+  else
+    JT_JAVA = $(SLASH_JAVA)/re/jdk/1.9.0/archive/fcs/binaries/$(PLATFORM)-$(ARCH)
+  endif
 endif
 
 # Default JDK to test
@@ -149,6 +153,10 @@ ifdef TESTBOOTCLASSPATH
 	-refvmoptions:-Xbootclasspath/p:$(TESTBOOTCLASSPATH)
 endif
 
+ifdef EXTRA_JTREG_OPTIONS
+  JTREG_OPTIONS += $(EXTRA_JTREG_OPTIONS)
+endif
+
 # Concurrency is the number of tests that can execute at once.
 # On an otherwise empty machine, suggest setting to (#cpus + 2)
 # If unset, the default is (#cpus)
@@ -262,6 +270,12 @@ javah:		JTREG_TESTDIRS = tools/javah
 javap:		JTREG_TESTDIRS = tools/javap
 jdeps:		JTREG_TESTDIRS = tools/jdeps
 
+# a way to select jtreg tests from outside
+ifdef TEST_SELECTION
+  JTREG_TESTDIRS = $(TEST_SELECTION)
+endif
+
+
 # Run jtreg tests
 #
 # JTREG_HOME
@@ -290,13 +304,13 @@ jtreg-tests: check-jtreg FRC
 	  -J-Xmx512m \
 	  -vmoption:-Xmx768m \
 	  -a -ignore:quiet $(if $(JTREG_VERBOSE),-v:$(JTREG_VERBOSE)) \
-          -r:$(JTREG_OUTPUT_DIR)/JTreport \
-          -w:$(JTREG_OUTPUT_DIR)/JTwork \
-          -jdk:$(TESTJAVA) \
-          $(JAVA_ARGS:%=-vmoption:%) \
-          $(JTREG_EXCLUSIONS) \
+	  -r:$(JTREG_OUTPUT_DIR)/JTreport \
+	  -w:$(JTREG_OUTPUT_DIR)/JTwork \
+	  -jdk:$(TESTJAVA) \
+	  $(JAVA_ARGS:%=-vmoption:%) \
+	  $(JTREG_EXCLUSIONS) \
 	  $(JTREG_OPTIONS) \
-          $(JTREG_TESTDIRS) \
+	  $(JTREG_TESTDIRS) \
 	|| ( $(call EXIT_IF_FATAL,$(FATAL_JTREG_EXIT)) ; \
 	    echo $$status > $(JTREG_OUTPUT_DIR)/status.txt \
 	)
diff --git a/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java
index d887c0933a7..1848e172ab7 100644
--- a/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java
+++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8154119
+ * @bug 8154119 8154262
  * @summary Test modules support in javadoc.
  * @author bpatel
  * @library ../lib
@@ -41,46 +41,58 @@ public class TestModules extends JavadocTester {
 
     @Test
     void test1() {
-        javadoc("-d", "out",
+        javadoc("-d", "out", "-use",
                 "-modulesourcepath", testSrc,
                 "-addmods", "module1,module2",
                 "testpkgmdl1", "testpkgmdl2");
         checkExit(Exit.OK);
         testDescription(true);
         testNoDescription(false);
+        testModuleLink();
     }
 
     @Test
     void test2() {
-        javadoc("-d", "out-html5", "-html5",
+        javadoc("-d", "out-html5", "-html5", "-use",
                 "-modulesourcepath", testSrc,
                 "-addmods", "module1,module2",
                 "testpkgmdl1", "testpkgmdl2");
         checkExit(Exit.OK);
         testHtml5Description(true);
         testHtml5NoDescription(false);
+        testModuleLink();
     }
 
     @Test
     void test3() {
-        javadoc("-d", "out-nocomment", "-nocomment",
+        javadoc("-d", "out-nocomment", "-nocomment", "-use",
                 "-modulesourcepath", testSrc,
                 "-addmods", "module1,module2",
                 "testpkgmdl1", "testpkgmdl2");
         checkExit(Exit.OK);
         testDescription(false);
         testNoDescription(true);
+        testModuleLink();
     }
 
     @Test
     void test4() {
-        javadoc("-d", "out-html5-nocomment", "-nocomment", "-html5",
+        javadoc("-d", "out-html5-nocomment", "-nocomment", "-html5", "-use",
                 "-modulesourcepath", testSrc,
                 "-addmods", "module1,module2",
                 "testpkgmdl1", "testpkgmdl2");
         checkExit(Exit.OK);
         testHtml5Description(false);
         testHtml5NoDescription(true);
+        testModuleLink();
+    }
+
+    @Test
+    void test5() {
+        javadoc("-d", "out-nomodule", "-use",
+                "-sourcepath", testSrc,
+                "testpkgnomodule");
+        checkExit(Exit.OK);
     }
 
     void testDescription(boolean found) {
@@ -142,4 +154,37 @@ public class TestModules extends JavadocTester {
                 + "<li class=\"blockList\">\n"
                 + "<table class=\"overviewSummary\">");
     }
+
+    void testModuleLink() {
+        checkOutput("overview-summary.html", true,
+                "<li>Module</li>");
+        checkOutput("module1-summary.html", true,
+                "<li class=\"navBarCell1Rev\">Module</li>");
+        checkOutput("module2-summary.html", true,
+                "<li class=\"navBarCell1Rev\">Module</li>");
+        checkOutput("testpkgmdl1/package-summary.html", true,
+                "<li><a href=\"../module1-summary.html\">Module</a></li>");
+        checkOutput("testpkgmdl1/TestClassInModule1.html", true,
+                "<li><a href=\"../module1-summary.html\">Module</a></li>");
+        checkOutput("testpkgmdl1/class-use/TestClassInModule1.html", true,
+                "<li><a href=\"../../module1-summary.html\">Module</a></li>");
+        checkOutput("testpkgmdl2/package-summary.html", true,
+                "<li><a href=\"../module2-summary.html\">Module</a></li>");
+        checkOutput("testpkgmdl2/TestClassInModule2.html", true,
+                "<li><a href=\"../module2-summary.html\">Module</a></li>");
+        checkOutput("testpkgmdl2/class-use/TestClassInModule2.html", true,
+                "<li><a href=\"../../module2-summary.html\">Module</a></li>");
+    }
+
+    void testNoModuleLink() {
+        checkOutput("testpkgnomodule/package-summary.html", true,
+                "<ul class=\"navList\" title=\"Navigation\">\n"
+                + "<li><a href=\"../testpkgnomodule/package-summary.html\">Package</a></li>");
+        checkOutput("testpkgnomodule/TestClassNoModule.html", true,
+                "<ul class=\"navList\" title=\"Navigation\">\n"
+                + "<li><a href=\"../testpkgnomodule/package-summary.html\">Package</a></li>");
+        checkOutput("testpkgnomodule/class-use/TestClassNoModule.html", true,
+                "<ul class=\"navList\" title=\"Navigation\">\n"
+                + "<li><a href=\"../../testpkgnomodule/package-summary.html\">Package</a></li>");
+    }
 }
diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java b/langtools/test/jdk/javadoc/doclet/testModules/testpkgnomodule/TestClassNoModule.java
similarity index 85%
rename from jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java
rename to langtools/test/jdk/javadoc/doclet/testModules/testpkgnomodule/TestClassNoModule.java
index c9ff689a931..018413ec8a0 100644
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java
+++ b/langtools/test/jdk/javadoc/doclet/testModules/testpkgnomodule/TestClassNoModule.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,10 +20,9 @@
  *
  * 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 testpkgnomodule;
 
-package java.net.http;
-
-public interface HttpHeaders1 extends HttpHeaders {
-    public void makeUnmodifiable();
+public class TestClassNoModule {
 }
diff --git a/langtools/test/jdk/jshell/CompletionSuggestionTest.java b/langtools/test/jdk/jshell/CompletionSuggestionTest.java
index 10b7b94a2aa..beb5a783a00 100644
--- a/langtools/test/jdk/jshell/CompletionSuggestionTest.java
+++ b/langtools/test/jdk/jshell/CompletionSuggestionTest.java
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8141092
+ * @bug 8141092 8153761
  * @summary Test Completion
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -34,14 +34,20 @@
  * @run testng CompletionSuggestionTest
  */
 
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Set;
 import java.util.HashSet;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
 
 import jdk.jshell.Snippet;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import static jdk.jshell.Snippet.Status.VALID;
@@ -295,10 +301,11 @@ public class CompletionSuggestionTest extends KullaTesting {
         assertCompletion("import inner.|");
     }
 
-    public void testDocumentation() {
+    public void testDocumentation() throws Exception {
+        dontReadParameterNamesFromClassFile();
         assertDocumentation("System.getProperty(|",
-                "java.lang.System.getProperty(java.lang.String arg0)",
-                "java.lang.System.getProperty(java.lang.String arg0, java.lang.String arg1)");
+                "java.lang.System.getProperty(java.lang.String key)",
+                "java.lang.System.getProperty(java.lang.String key, java.lang.String def)");
         assertEval("char[] chars = null;");
         assertDocumentation("new String(chars, |",
                 "java.lang.String(char[] arg0, int arg1, int arg2)");
@@ -313,7 +320,8 @@ public class CompletionSuggestionTest extends KullaTesting {
                                                      "java.lang.String.getBytes(java.nio.charset.Charset arg0)");
     }
 
-    public void testMethodsWithNoArguments() {
+    public void testMethodsWithNoArguments() throws Exception {
+        dontReadParameterNamesFromClassFile();
         assertDocumentation("System.out.println(|",
                 "java.io.PrintStream.println()",
                 "java.io.PrintStream.println(boolean arg0)",
@@ -442,29 +450,30 @@ public class CompletionSuggestionTest extends KullaTesting {
     public void testDocumentationOfUserDefinedMethods() {
         assertEval("void f() {}");
         assertDocumentation("f(|", "f()");
-        assertEval("void f(int a) {}");
-        assertDocumentation("f(|", "f()", "f(int arg0)");
-        assertEval("<T> void f(T... a) {}", DiagCheck.DIAG_WARNING, DiagCheck.DIAG_OK);
-        assertDocumentation("f(|", "f()", "f(int arg0)", "f(T... arg0)");
+        assertEval("void f(int i) {}");
+        assertDocumentation("f(|", "f()", "f(int i)");
+        assertEval("<T> void f(T... ts) {}", DiagCheck.DIAG_WARNING, DiagCheck.DIAG_OK);
+        assertDocumentation("f(|", "f()", "f(int i)", "f(T... ts)");
         assertEval("class A {}");
         assertEval("void f(A a) {}");
-        assertDocumentation("f(|", "f()", "f(int arg0)", "f(T... arg0)", "f(A arg0)");
+        assertDocumentation("f(|", "f()", "f(int i)", "f(T... ts)", "f(A a)");
     }
 
     public void testDocumentationOfUserDefinedConstructors() {
         Snippet a = classKey(assertEval("class A {}"));
         assertDocumentation("new A(|", "A()");
-        Snippet a2 = classKey(assertEval("class A { A() {} A(int a) {}}",
+        Snippet a2 = classKey(assertEval("class A { A() {} A(int i) {}}",
                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
                 ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
-        assertDocumentation("new A(|", "A()", "A(int arg0)");
-        assertEval("class A<T> { A(T a) {} A(int a) {}}",
+        assertDocumentation("new A(|", "A()", "A(int i)");
+        assertEval("class A<T> { A(T t) {} A(int i) {}}",
                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
                 ste(a2, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
-        assertDocumentation("new A(|", "A(T arg0)", "A(int arg0)");
+        assertDocumentation("new A(|", "A(T t)", "A(int i)");
     }
 
-    public void testDocumentationOfOverriddenMethods() {
+    public void testDocumentationOfOverriddenMethods() throws Exception {
+        dontReadParameterNamesFromClassFile();
         assertDocumentation("\"\".wait(|",
             "java.lang.Object.wait(long arg0)",
             "java.lang.Object.wait(long arg0, int arg1)",
@@ -502,13 +511,13 @@ public class CompletionSuggestionTest extends KullaTesting {
         assertEval("void method(int n, Object o) { }");
         assertEval("void method(Object n, int o) { }");
         assertDocumentation("method(primitive,|",
-                "method(int arg0, java.lang.Object arg1)",
-                "method(java.lang.Object arg0, int arg1)");
+                "method(int n, java.lang.Object o)",
+                "method(java.lang.Object n, int o)");
         assertDocumentation("method(boxed,|",
-                "method(int arg0, java.lang.Object arg1)",
-                "method(java.lang.Object arg0, int arg1)");
+                "method(int n, java.lang.Object o)",
+                "method(java.lang.Object n, int o)");
         assertDocumentation("method(object,|",
-                "method(java.lang.Object arg0, int arg1)");
+                "method(java.lang.Object n, int o)");
     }
 
     public void testVarArgs() {
@@ -546,4 +555,36 @@ public class CompletionSuggestionTest extends KullaTesting {
         assertEval("class Foo { static void m(String str) {} static void m(Baz<String> baz) {} }");
         assertCompletion("Foo.m(new Baz<>(|", true, "str");
     }
+
+    @BeforeMethod
+    public void setUp() {
+        super.setUp();
+
+        Path srcZip = Paths.get("src.zip");
+
+        try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(srcZip))) {
+            out.putNextEntry(new JarEntry("java/lang/System.java"));
+            out.write(("package java.lang;\n" +
+                       "public class System {\n" +
+                       "    public String getProperty(String key) { return null; }\n" +
+                       "    public String getProperty(String key, String def) { return def; }\n" +
+                       "}\n").getBytes());
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        }
+
+        try {
+            Field availableSources = getAnalysis().getClass().getDeclaredField("availableSources");
+            availableSources.setAccessible(true);
+            availableSources.set(getAnalysis(), Arrays.asList(srcZip));
+        } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    private void dontReadParameterNamesFromClassFile() throws Exception {
+        Field keepParameterNames = getAnalysis().getClass().getDeclaredField("keepParameterNames");
+        keepParameterNames.setAccessible(true);
+        keepParameterNames.set(getAnalysis(), new String[0]);
+    }
 }
diff --git a/langtools/test/tools/javac/6330997/T6330997.java b/langtools/test/tools/javac/6330997/T6330997.java
index c5de10eefba..8fa38415296 100644
--- a/langtools/test/tools/javac/6330997/T6330997.java
+++ b/langtools/test/tools/javac/6330997/T6330997.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,8 +32,8 @@
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  * @clean T1 T2
- * @compile -source 8 -target 8 T1.java
- * @compile -source 8 -target 8 T2.java
+ * @compile -source 9 -target 9 T1.java
+ * @compile -source 9 -target 9 T2.java
  * @run main/othervm T6330997
  */
 
diff --git a/langtools/test/tools/javac/classfiles/ClassVersionChecker.java b/langtools/test/tools/javac/classfiles/ClassVersionChecker.java
index 0ab5aee4a0a..419ec1313da 100644
--- a/langtools/test/tools/javac/classfiles/ClassVersionChecker.java
+++ b/langtools/test/tools/javac/classfiles/ClassVersionChecker.java
@@ -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
@@ -38,7 +38,7 @@ import java.util.regex.*;
 public class ClassVersionChecker {
 
     int errors;
-    String[] jdk = {"","1.6","1.7","1.8"};
+    String[] jdk = {"", "1.6", "1.7", "1.8", "1.9"};
     File javaFile = null;
 
     public static void main(String[] args) throws Throwable {
@@ -58,10 +58,10 @@ public class ClassVersionChecker {
          * -1 => invalid combinations
          */
         int[][] ver =
-                {{52, -1, -1, -1},
-                 {52, 50, 51, 52},
-                 {52, -1, 51, 52},
-                 {52, -1, -1, 52}};
+                {{53, -1, -1, -1, -1},
+                 {53, 50, 51, 52, 53},
+                 {53, -1, 51, 52, 53},
+                 {53, -1, -1, 52, 53}};
 
         // Loop to run all possible combinations of source/target values
         for (int i = 0; i< ver.length; i++) {
diff --git a/langtools/test/tools/javac/importscope/TestDeepFinishClassStack.java b/langtools/test/tools/javac/importscope/TestDeepFinishClassStack.java
new file mode 100644
index 00000000000..0b7bc3e18b3
--- /dev/null
+++ b/langtools/test/tools/javac/importscope/TestDeepFinishClassStack.java
@@ -0,0 +1,67 @@
+/*
+ * 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 8156097
+ * @summary Check that nested TypeEnter.MembersPhase invocations don't cause StackOverflowError
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ */
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import toolbox.JavacTask;
+import toolbox.ToolBox;
+
+public class TestDeepFinishClassStack {
+    public static void main(String... args) throws IOException {
+        new TestDeepFinishClassStack().run();
+    }
+
+    int depth = 1000;
+
+    void run() throws IOException {
+        Path src = Paths.get("src");
+
+        Files.createDirectories(src);
+
+        ToolBox tb = new ToolBox();
+
+        for (int i = 0; i < depth; i++) {
+            tb.writeJavaFiles(src, "public class C" + i + " { public void test(C" + (i + 1) + " c) { } }");
+        }
+
+        tb.writeJavaFiles(src, "public class C" + depth + " { }");
+
+        new JavacTask(tb).files(src.resolve("C0.java"))
+                         .sourcepath(src)
+                         .outdir(".")
+                         .run()
+                         .writeAll();
+    }
+
+}
diff --git a/langtools/test/tools/javac/versions/Versions.java b/langtools/test/tools/javac/versions/Versions.java
index f4a6eaeb26f..f90f44935c9 100644
--- a/langtools/test/tools/javac/versions/Versions.java
+++ b/langtools/test/tools/javac/versions/Versions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,16 +61,14 @@ public class Versions {
 
     void run() {
 
-        String jdk9cv = "52.0";  // class version.change when ./dev pushed to 53
-
         String TC = "";
         System.out.println("Version.java: Starting");
 
-        check("52.0");
-        check("52.0", "-source 1.6");
-        check("52.0", "-source 1.7");
-        check("52.0", "-source 1.8");
-        check(jdk9cv, "-source 1.9");
+        check("53.0");
+        check("53.0", "-source 1.6");
+        check("53.0", "-source 1.7");
+        check("53.0", "-source 1.8");
+        check("53.0", "-source 1.9");
 
         check_source_target("50.0", "6", "6");
         check_source_target("51.0", "6", "7");
@@ -78,10 +76,10 @@ public class Versions {
         check_source_target("52.0", "6", "8");
         check_source_target("52.0", "7", "8");
         check_source_target("52.0", "8", "8");
-        check_source_target(jdk9cv, "6", "9");
-        check_source_target(jdk9cv, "7", "9");
-        check_source_target(jdk9cv, "8", "9");
-        check_source_target(jdk9cv, "9", "9");
+        check_source_target("53.0", "6", "9");
+        check_source_target("53.0", "7", "9");
+        check_source_target("53.0", "8", "9");
+        check_source_target("53.0", "9", "9");
 
         checksrc16("-source 1.6");
         checksrc16("-source 6");
diff --git a/make/Images.gmk b/make/Images.gmk
index 302bc2b3e42..564f2b27ddb 100644
--- a/make/Images.gmk
+++ b/make/Images.gmk
@@ -114,8 +114,18 @@ JMODS := $(wildcard $(IMAGES_OUTPUTDIR)/jmods/*.jmod)
 # Use this file inside the image as target for make rule
 JIMAGE_TARGET_FILE := bin/java$(EXE_SUFFIX)
 
+JLINK_ORDER_RESOURCES := \
+    *module-info.class* \
+    @$(SUPPORT_OUTPUTDIR)/classlist/classlist,/java.base/java/* \
+    /java.base/jdk/* \
+    /java.base/sun/* \
+    /java.base/com/* \
+    /jdk.localedata/* \
+    #
+
 JLINK_TOOL := $(JLINK) --modulepath $(IMAGES_OUTPUTDIR)/jmods \
               --endian $(OPENJDK_BUILD_CPU_ENDIAN) \
+              --order-resources=$(call CommaList, $(JLINK_ORDER_RESOURCES)) \
               --release-info $(BASE_RELEASE_FILE)
 
 ifeq ($(JLINK_KEEP_PACKAGED_MODULES), true)
diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk
index d595e044013..db09eb5bbf3 100644
--- a/make/common/NativeCompilation.gmk
+++ b/make/common/NativeCompilation.gmk
@@ -770,13 +770,20 @@ define SetupNativeCompilationBody
 		$$(call ExecuteWithLog, $$@, \
 		    $$($1_RC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \
 		    $$($1_VERSIONINFO_RESOURCE))
-                # Windows RC compiler does not support -showIncludes, so we mis-use CL for this.
+                # Windows RC compiler does not support -showIncludes, so we mis-use CL
+                # for this. Filter out RC specific arguments that are unknown to CL.
+                # For some unknown reason, in this case CL actually outputs the show
+                # includes to stderr so need to redirect it to hide the output from the
+                # main log.
 		$$(call ExecuteWithLog, $$($1_RES_DEP).obj, \
-		    $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
-		    $(CC_OUT_OPTION)$$($1_RES_DEP).obj -P -Fi$$($1_RES_DEP).pp \
-		    $$($1_VERSIONINFO_RESOURCE)) > $$($1_RES_DEP).raw 2>&1 || true ; \
+		    $$($1_CC) $$(filter-out -l%, $$($1_RC_FLAGS)) \
+		        $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
+		        $(CC_OUT_OPTION)$$($1_RES_DEP).obj -P -Fi$$($1_RES_DEP).pp \
+		        $$($1_VERSIONINFO_RESOURCE)) 2>&1 \
+		    | $(GREP) -v -e "^Note: including file:" \
+		        -e "^$$(notdir $$($1_VERSIONINFO_RESOURCE))$$$$" || test "$$$$?" = "1" ; \
 		$(ECHO) $$($1_RES): \\ > $$($1_RES_DEP) ; \
-		$(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEP).raw >> $$($1_RES_DEP) ; \
+		$(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEP).obj.log >> $$($1_RES_DEP) ; \
 		$(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEP) > $$($1_RES_DEP_TARGETS)
     endif
   endif
diff --git a/make/idea/idea.gmk b/make/idea/idea.gmk
new file mode 100644
index 00000000000..329c01cd5ea
--- /dev/null
+++ b/make/idea/idea.gmk
@@ -0,0 +1,39 @@
+include Makefile
+include make/MainSupport.gmk
+
+.PHONY: idea
+
+ifeq ($(SPEC),)
+  ifneq ($(words $(SPECS)),1)
+	@echo "Error: Multiple build specification files found. Please select one explicitly."
+	@exit 2
+  endif
+  idea:
+	@cd $(topdir)
+	@$(MAKE) $(MFLAGS) $(MAKE_LOG_FLAGS) -r -R -j 1 -f $(topdir)/make/idea/idea.gmk SPEC=$(SPECS) HAS_SPEC=true ACTUAL_TOPDIR=$(topdir) MODULES="$(MODULES)" idea
+else #with SPEC
+  include make/common/Modules.gmk
+
+  ifeq ($(MODULES),)
+    SEL_MODULES := $(call FindAllModules)
+  else
+    SEL_MODULES := $(MODULES)
+  endif
+
+  # Find all source dirs for a particular module
+  # $1 - Module to find source dirs for
+  FindIdeaModuleSrcDirs = \
+    $(strip $(addsuffix /$(strip $1), $(GENERATED_SRC_DIRS) $(IMPORT_MODULES_SRC)) \
+        $(wildcard $(foreach sub, $(SRC_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS)))))
+
+
+  idea:
+	$(ECHO) "SUPPORT=$(SUPPORT_OUTPUTDIR)" >> $(OUT)
+	$(ECHO) "MODULE_ROOTS=\"$(foreach mod, $(SEL_MODULES), $(call FindIdeaModuleSrcDirs,$(mod)))\"" >> $(OUT)
+	$(ECHO) "MODULE_NAMES=\"$(strip $(foreach mod, $(SEL_MODULES), $(mod)))\"" >> $(OUT)
+	$(ECHO) "SEL_MODULES=\"$(SEL_MODULES)\"" >> $(OUT)
+	$(ECHO) "BOOT_JDK=\"$(BOOT_JDK)\"" >> $(OUT)
+	$(ECHO) "CYGPATH=\"$(CYGPATH)\"" >> $(OUT)
+	$(ECHO) "SPEC=\"$(SPEC)\"" >> $(OUT)
+
+endif
diff --git a/make/idea/template/.name b/make/idea/template/.name
new file mode 100644
index 00000000000..b4835685793
--- /dev/null
+++ b/make/idea/template/.name
@@ -0,0 +1 @@
+jdk
diff --git a/make/idea/template/ant.xml b/make/idea/template/ant.xml
new file mode 100644
index 00000000000..6e72e478cbc
--- /dev/null
+++ b/make/idea/template/ant.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AntConfiguration">
+    <buildFile url="file://$PROJECT_DIR$/.idea/build.xml">
+      <properties>
+        <property name="boot.java.home" value="$JDKPath$" />
+        <property name="jtreg.tests" value="$FilePath$" />
+        <property name="jtreg.home" value="###" />
+        <property name="build.target.dir" value="specDir" /> <!-- this will be replaced --> 
+        <property name="jtreg.jpda.jvmargs" value="-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5900,suspend=y" />
+        <property name="module.name" value="java.base" /> <!-- this will be replaced -->
+      </properties>
+      <executeOn event="afterCompilation" target="post-make" />
+    </buildFile>
+  </component>
+</project>
diff --git a/make/idea/template/build.xml b/make/idea/template/build.xml
new file mode 100644
index 00000000000..ed62f296726
--- /dev/null
+++ b/make/idea/template/build.xml
@@ -0,0 +1,126 @@
+<!-- importing.xml -->
+<project name="jdk" basedir="..">
+
+    <script language="javascript" classpath=".idea/classes">
+        var JdkLogger = Java.type("idea.JdkIdeaAntLogger");
+        new JdkLogger(project)
+    </script>
+
+     <!-- java.marker is set to a marker file to check for within a Java install dir.
+         The best file to check for across Solaris/Linux/Windows/MacOS is one of the
+         executables; regrettably, that is OS-specific. -->
+    <condition property="java.marker" value="bin/java">
+        <os family="unix"/>
+    </condition>
+    <condition property="java.marker" value="bin/java.exe">
+        <os family="windows"/>
+    </condition>
+
+    <property name="test.dir" value="${basedir}/jdk/test"/>
+
+    <macrodef name="call-make">
+            <attribute name="dir"/>
+            <attribute name="args"/>
+            <sequential>
+                <exec executable="make" dir="@{dir}" failonerror="true">
+                    <arg line="@{args}"/>
+                    <env key="CLASSPATH" value = ""/>
+                </exec>
+            </sequential>
+        </macrodef>
+
+    <macrodef name="exec-target">
+        <attribute name="antfile" default="${ant.file}" />
+        <attribute name="target" />
+        <sequential>
+            <java classname="org.apache.tools.ant.Main" fork="true" spawn="true">
+                <arg value="-f"/>
+                <arg value="@{antfile}"/>  
+                <arg value="-Dboot.java.home=${boot.java.home}"/>
+                <arg value="-Dbuild.target.dir=${build.target.dir}"/>
+                <arg value="-Djtreg.home=${jtreg.home}"/>
+                <arg value="-Djtreg.tests=${jtreg.tests}"/>
+                <arg value="-Djtreg.jpda.jvmargs=${jtreg.jpda.jvmargs}"/>
+                <arg value="@{target}"/>
+                <classpath>           
+                    <pathelement path="${java.class.path}"/>
+                </classpath>
+            </java>
+        </sequential>
+    </macrodef>
+
+    <target name="post-make" depends="build-module"/>
+
+    <!--
+        **** Global JDK Build Targets
+    -->
+
+    <target name="clean" depends="-do-configure">
+        <echo message="base = ${basedir}"/>
+        <call-make dir = "${build.target.dir}" args = "clean"/>
+    </target>
+    
+    <target name="-do-configure">
+        <echo message="base = ${basedir}"/>
+        <fail message="Not part of a full JDK forest">
+            <condition>
+                <not>
+                    <available file="${basedir}/configure" />
+                </not>
+            </condition>
+        </fail>
+        <exec executable="sh" dir="${basedir}" failonerror="true">
+            <arg line="configure --with-boot-jdk=${boot.java.home}"/>
+        </exec>
+    </target>
+
+    <target name="images">
+        <call-make dir = "${build.target.dir}" args = "images"/>
+    </target>
+
+    <target name="jimages">
+        <call-make dir = "${build.target.dir}" args = "jimages"/>
+    </target>
+
+    <target name="check-env">
+        <exec executable="env" dir="${basedir}"/>
+    </target>
+
+    <target name="build-module">
+        <call-make dir = "${build.target.dir}" args = "${module.name}"/>
+    </target>
+
+    <target name="-check-boot.java.home" depends="-def-check">
+        <check name="bootstrap java" property="boot.java.home" marker="${java.marker}"/>
+    </target>
+
+    <target name="-def-check">
+        <macrodef name="check">
+            <attribute name="name"/>
+            <attribute name="property"/>
+            <attribute name="marker" default=""/>
+            <sequential>
+                <fail message="Cannot locate @{name}: please set @{property} to its location">
+                    <condition>
+                        <not>
+                            <isset property="@{property}"/>
+                        </not>
+                    </condition>
+                </fail>
+                <fail message="@{name} is not installed in ${@{property}}">
+                    <condition>
+                        <and>
+                            <not>
+                                <equals arg1="@{marker}" arg2=""/>
+                            </not>
+                            <not>
+                                <available file="${@{property}}/@{marker}"/>
+                            </not>
+                        </and>
+                    </condition>
+                </fail>
+            </sequential>
+        </macrodef>
+    </target>
+</project>
+
diff --git a/make/idea/template/compiler.xml b/make/idea/template/compiler.xml
new file mode 100644
index 00000000000..f801895e7f7
--- /dev/null
+++ b/make/idea/template/compiler.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <option name="DEFAULT_COMPILER" value="Javac" />
+    <excludeFromCompile>
+      <directory url="file://$PROJECT_DIR$/jdk/src" includeSubdirectories="true" />
+      <directory url="file://$PROJECT_DIR$/langtools/src" includeSubdirectories="true" />
+      <directory url="file://$PROJECT_DIR$/jaxp/src" includeSubdirectories="true" />
+      <directory url="file://$PROJECT_DIR$/jaxws/src" includeSubdirectories="true" />
+      <directory url="file://$PROJECT_DIR$/corba/src" includeSubdirectories="true" />
+      <directory url="file://$PROJECT_DIR$/nashorn/src" includeSubdirectories="true" />
+      <directory url="file://$PROJECT_DIR$/build" includeSubdirectories="true" />
+      <directory url="file://$PROJECT_DIR$/jdk/test" includeSubdirectories="true" />
+      <directory url="file://$PROJECT_DIR$/jaxp/test" includeSubdirectories="true" />
+      <directory url="file://$PROJECT_DIR$/langtools/test" includeSubdirectories="true" />
+      <directory url="file://$PROJECT_DIR$/langtools" includeSubdirectories="true" />
+    </excludeFromCompile>
+    <resourceExtensions />
+    <wildcardResourcePatterns>
+      <entry name="!?*.java" />
+      <entry name="!?*.form" />
+      <entry name="!?*.class" />
+      <entry name="!?*.groovy" />
+      <entry name="!?*.scala" />
+      <entry name="!?*.flex" />
+      <entry name="!?*.kt" />
+      <entry name="!?*.clj" />
+    </wildcardResourcePatterns>
+    <annotationProcessing>
+      <profile default="true" name="Default" enabled="false">
+        <processorPath useClasspath="true" />
+      </profile>
+    </annotationProcessing>
+  </component>
+</project>
\ No newline at end of file
diff --git a/make/idea/template/copyright/profiles_settings.xml b/make/idea/template/copyright/profiles_settings.xml
new file mode 100644
index 00000000000..7d61b5cdf1f
--- /dev/null
+++ b/make/idea/template/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+<component name="CopyrightManager">
+  <settings default="" />
+</component>
diff --git a/make/idea/template/jdk.iml b/make/idea/template/jdk.iml
new file mode 100644
index 00000000000..5e1436c949a
--- /dev/null
+++ b/make/idea/template/jdk.iml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/####" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/jdk/test" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/langtools/test" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/jaxp/test" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/####/buildtools" />
+      <excludeFolder url="file://$MODULE_DIR$/####/configure-support" />
+      <excludeFolder url="file://$MODULE_DIR$/####/hotspot" />
+      <excludeFolder url="file://$MODULE_DIR$/####/images" />
+      <excludeFolder url="file://$MODULE_DIR$/####/ide" />
+      <excludeFolder url="file://$MODULE_DIR$/####/jdk" />
+      <excludeFolder url="file://$MODULE_DIR$/####/make-support" />
+      <excludeFolder url="file://$MODULE_DIR$/####/testoutput" />
+    </content>    
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="inheritedJdk" />
+  </component>
+</module>
diff --git a/make/idea/template/misc.xml b/make/idea/template/misc.xml
new file mode 100644
index 00000000000..e5caa22e0d6
--- /dev/null
+++ b/make/idea/template/misc.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="EntryPointsManager">
+    <entry_points version="2.0" />
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_9" assert-keyword="true" jdk-15="true">
+    <output url="file://$PROJECT_DIR$/build/idea/out" />
+  </component>
+</project>
diff --git a/make/idea/template/modules.xml b/make/idea/template/modules.xml
new file mode 100644
index 00000000000..2d8401d0398
--- /dev/null
+++ b/make/idea/template/modules.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/jdk.iml" filepath="$PROJECT_DIR$/.idea/jdk.iml" />
+    </modules>
+  </component>
+</project>
+
diff --git a/make/idea/template/scopes/scope_settings.xml b/make/idea/template/scopes/scope_settings.xml
new file mode 100644
index 00000000000..db1b8ba4462
--- /dev/null
+++ b/make/idea/template/scopes/scope_settings.xml
@@ -0,0 +1,5 @@
+<component name="DependencyValidationManager">
+  <state>
+    <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+  </state>
+</component>
diff --git a/make/idea/template/src/idea/JdkIdeaAntLogger.java b/make/idea/template/src/idea/JdkIdeaAntLogger.java
new file mode 100644
index 00000000000..9913499e7a0
--- /dev/null
+++ b/make/idea/template/src/idea/JdkIdeaAntLogger.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package idea;
+
+import org.apache.tools.ant.BuildEvent;
+import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.DefaultLogger;
+import org.apache.tools.ant.Project;
+
+import java.util.EnumSet;
+import java.util.Stack;
+
+import static org.apache.tools.ant.Project.*;
+
+/**
+ * This class is used to wrap the IntelliJ ant logger in order to provide more meaningful
+ * output when building langtools. The basic ant output in IntelliJ can be quite cumbersome to
+ * work with, as it provides two separate views: (i) a tree view, which is good to display build task
+ * in a hierarchical fashion as they are processed; and a (ii) plain text view, which gives you
+ * the full ant output. The main problem is that javac-related messages are buried into the
+ * ant output (which is made very verbose by IntelliJ in order to support the tree view). It is
+ * not easy to figure out which node to expand in order to see the error message; switching
+ * to plain text doesn't help either, as now the output is totally flat.
+ *
+ * This logger class removes a lot of verbosity from the IntelliJ ant logger by not propagating
+ * all the events to the IntelliJ's logger. In addition, certain events are handled in a custom
+ * fashion, to generate better output during the build.
+ */
+public final class JdkIdeaAntLogger extends DefaultLogger {
+
+    /**
+     * This is just a way to pass in customized binary string predicates;
+     *
+     * TODO: replace with @code{BiPredicate<String, String>} and method reference when moving to 8
+     */
+    enum StringBinaryPredicate {
+        CONTAINS() {
+            @Override
+            boolean apply(String s1, String s2) {
+                return s1.contains(s2);
+            }
+        },
+        STARTS_WITH {
+            @Override
+            boolean apply(String s1, String s2) {
+                return s1.startsWith(s2);
+            }
+        },
+        MATCHES {
+            @Override
+            boolean apply(String s1, String s2) {
+                return s1.matches(s2);
+            }
+        };
+
+        abstract boolean apply(String s1, String s2);
+    }
+
+    /**
+     * Various kinds of ant messages that we shall intercept
+     */
+    enum MessageKind {
+
+        /** a make error */
+        MAKE_ERROR(StringBinaryPredicate.CONTAINS, MSG_ERR, "error:", "compiler.err"),
+        /** a make warning */
+        MAKE_WARNING(StringBinaryPredicate.CONTAINS, MSG_WARN, "warning:", "compiler.warn"),
+        /** a make note */
+        MAKE_NOTE(StringBinaryPredicate.CONTAINS, MSG_INFO, "note:", "compiler.note"),
+        /** std make output */
+        MAKE_OTHER(StringBinaryPredicate.MATCHES, MSG_INFO, ".*"),
+        /** a javac crash */
+        JAVAC_CRASH(StringBinaryPredicate.STARTS_WITH, MSG_ERR, "An exception has occurred in the compiler"),
+        /** jtreg test success */
+        JTREG_TEST_PASSED(StringBinaryPredicate.STARTS_WITH, MSG_INFO, "Passed: "),
+        /** jtreg test failure */
+        JTREG_TEST_FAILED(StringBinaryPredicate.STARTS_WITH, MSG_ERR, "FAILED: "),
+        /** jtreg test error */
+        JTREG_TEST_ERROR(StringBinaryPredicate.STARTS_WITH, MSG_ERR, "Error: ");
+
+        StringBinaryPredicate sbp;
+        int priority;
+        String[] keys;
+
+        MessageKind(StringBinaryPredicate sbp, int priority, String... keys) {
+            this.sbp = sbp;
+            this.priority = priority;
+            this.keys = keys;
+        }
+
+        /**
+         * Does a given message string matches this kind?
+         */
+        boolean matches(String s) {
+            for (String key : keys) {
+                if (sbp.apply(s, key)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * This enum is used to represent the list of tasks we need to keep track of during logging.
+     */
+    enum Task {
+        /** javac task - invoked during compilation */
+        MAKE("exec", MessageKind.MAKE_ERROR, MessageKind.MAKE_WARNING, MessageKind.MAKE_NOTE,
+                       MessageKind.MAKE_OTHER, MessageKind.JAVAC_CRASH),
+        /** jtreg task - invoked during test execution */
+        JTREG("jtreg", MessageKind.JTREG_TEST_PASSED, MessageKind.JTREG_TEST_FAILED, MessageKind.JTREG_TEST_ERROR),
+        /** initial synthetic task when the logger is created */
+        ROOT("") {
+            @Override
+            boolean matches(String s) {
+                return false;
+            }
+        },
+        /** synthetic task catching any other tasks not in this list */
+        ANY("") {
+            @Override
+            boolean matches(String s) {
+                return true;
+            }
+        };
+
+        String taskName;
+        MessageKind[] msgs;
+
+        Task(String taskName, MessageKind... msgs) {
+            this.taskName = taskName;
+            this.msgs = msgs;
+        }
+
+        boolean matches(String s) {
+            return s.equals(taskName);
+        }
+    }
+
+    /**
+     * This enum is used to represent the list of targets we need to keep track of during logging.
+     * A regular expression is used to match a given target name.
+     */
+    enum Target {
+        /** jtreg target - executed when launching tests */
+        JTREG("jtreg") {
+            @Override
+            String getDisplayMessage(BuildEvent e) {
+                return "Running jtreg tests: " + e.getProject().getProperty("jtreg.tests");
+            }
+        },
+        /** build selected modules */
+        BUILD_MODULE("build-module") {
+            @Override
+            String getDisplayMessage(BuildEvent e) {
+                return "Building modules: " + e.getProject().getProperty("module.name") + "...";
+            }
+        },
+        /** build images */
+        BUILD_IMAGES("images") {
+            @Override
+            String getDisplayMessage(BuildEvent e) {
+                return "Building images...";
+            }
+        },
+        /** build images */
+        CONFIGURE("-do-configure") {
+            @Override
+            String getDisplayMessage(BuildEvent e) {
+                return "Configuring build...";
+            }
+        },
+        /** synthetic target catching any other target not in this list */
+        ANY("") {
+            @Override
+            String getDisplayMessage(BuildEvent e) {
+                return "Executing Ant target(s): " + e.getProject().getProperty("ant.project.invoked-targets");
+            }
+            @Override
+            boolean matches(String msg) {
+                return true;
+            }
+        };
+
+        String targetRegex;
+
+        Target(String targetRegex) {
+            this.targetRegex = targetRegex;
+        }
+
+        boolean matches(String msg) {
+            return msg.matches(targetRegex);
+        }
+
+        abstract String getDisplayMessage(BuildEvent e);
+    }
+
+    /**
+     * A custom build event used to represent status changes which should be notified inside
+     * Intellij
+     */
+    static class StatusEvent extends BuildEvent {
+
+        /** the target to which the status update refers */
+        Target target;
+
+        StatusEvent(BuildEvent e, Target target) {
+            super(new StatusTask(e, target.getDisplayMessage(e)));
+            this.target = target;
+            setMessage(getTask().getTaskName(), 2);
+        }
+
+        /**
+         * A custom task used to channel info regarding a status change
+         */
+        static class StatusTask extends org.apache.tools.ant.Task {
+            StatusTask(BuildEvent event, String msg) {
+                setProject(event.getProject());
+                setOwningTarget(event.getTarget());
+                setTaskName(msg);
+            }
+        }
+    }
+
+    /** wrapped ant logger (IntelliJ's own logger) */
+    DefaultLogger logger;
+
+    /** flag - is this the first target we encounter? */
+    boolean firstTarget = true;
+
+    /** flag - should subsequenet failures be suppressed ? */
+    boolean suppressTaskFailures = false;
+
+    /** flag - have we ran into a javac crash ? */
+    boolean crashFound = false;
+
+    /** stack of status changes associated with pending targets */
+    Stack<StatusEvent> statusEvents = new Stack<>();
+
+    /** stack of pending tasks */
+    Stack<Task> tasks = new Stack<>();
+
+    public JdkIdeaAntLogger(Project project) {
+        for (Object o : project.getBuildListeners()) {
+            if (o instanceof DefaultLogger) {
+                this.logger = (DefaultLogger)o;
+                project.removeBuildListener((BuildListener)o);
+                project.addBuildListener(this);
+            }
+        }
+        tasks.push(Task.ROOT);
+    }
+
+    @Override
+    public void buildStarted(BuildEvent event) {
+        //do nothing
+    }
+
+    @Override
+    public void buildFinished(BuildEvent event) {
+        //do nothing
+    }
+
+    @Override
+    public void targetStarted(BuildEvent event) {
+        EnumSet<Target> statusKinds = firstTarget ?
+                EnumSet.allOf(Target.class) :
+                EnumSet.complementOf(EnumSet.of(Target.ANY));
+
+        String targetName = event.getTarget().getName();
+
+        for (Target statusKind : statusKinds) {
+            if (statusKind.matches(targetName)) {
+                StatusEvent statusEvent = new StatusEvent(event, statusKind);
+                statusEvents.push(statusEvent);
+                logger.taskStarted(statusEvent);
+                firstTarget = false;
+                return;
+            }
+        }
+    }
+
+    @Override
+    public void targetFinished(BuildEvent event) {
+        if (!statusEvents.isEmpty()) {
+            StatusEvent lastEvent = statusEvents.pop();
+            if (lastEvent.target.matches(event.getTarget().getName())) {
+                logger.taskFinished(lastEvent);
+            }
+        }
+    }
+
+    @Override
+    public void taskStarted(BuildEvent event) {
+        String taskName = event.getTask().getTaskName();
+        System.err.println("task started " + taskName);
+        for (Task task : Task.values()) {
+            if (task.matches(taskName)) {
+                tasks.push(task);
+                return;
+            }
+        }
+    }
+
+    @Override
+    public void taskFinished(BuildEvent event) {
+        if (tasks.peek() == Task.ROOT) {
+            //we need to 'close' the root task to get nicer output
+            logger.taskFinished(event);
+        } else if (!suppressTaskFailures && event.getException() != null) {
+            //the first (innermost) task failure should always be logged
+            event.setMessage(event.getException().toString(), 0);
+            event.setException(null);
+            //note: we turn this into a plain message to avoid stack trace being logged by Idea
+            logger.messageLogged(event);
+            suppressTaskFailures = true;
+        }
+        tasks.pop();
+    }
+
+    @Override
+    public void messageLogged(BuildEvent event) {
+        String msg = event.getMessage();
+
+        boolean processed = false;
+
+        if (!tasks.isEmpty()) {
+            Task task = tasks.peek();
+            for (MessageKind messageKind : task.msgs) {
+                if (messageKind.matches(msg)) {
+                    event.setMessage(msg, messageKind.priority);
+                    processed = true;
+                    if (messageKind == MessageKind.JAVAC_CRASH) {
+                        crashFound = true;
+                    }
+                    break;
+                }
+            }
+        }
+
+        if (event.getPriority() == MSG_ERR || crashFound) {
+            //we log errors regardless of owning task
+            logger.messageLogged(event);
+            suppressTaskFailures = true;
+        } else if (processed) {
+            logger.messageLogged(event);
+        }
+    }
+}
diff --git a/make/idea/template/vcs.xml b/make/idea/template/vcs.xml
new file mode 100644
index 00000000000..876d3cd2ef8
--- /dev/null
+++ b/make/idea/template/vcs.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="hg4idea" />
+    <mapping directory="$PROJECT_DIR$/jdk" vcs="hg4idea" />
+    <mapping directory="$PROJECT_DIR$/langtools" vcs="hg4idea" />
+    <mapping directory="$PROJECT_DIR$/hotspot" vcs="hg4idea" />
+    <mapping directory="$PROJECT_DIR$/nashorn" vcs="hg4idea" />
+    <mapping directory="$PROJECT_DIR$/jaxp" vcs="hg4idea" />
+    <mapping directory="$PROJECT_DIR$/jaxws" vcs="hg4idea" />
+    <mapping directory="$PROJECT_DIR$/corba" vcs="hg4idea" />
+  </component>
+</project>
+
diff --git a/make/idea/template/workspace.xml b/make/idea/template/workspace.xml
new file mode 100644
index 00000000000..2423c3d41fb
--- /dev/null
+++ b/make/idea/template/workspace.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ChangeListManager">
+    <ignored path="jdk.iws" />
+    <ignored path="$PROJECT_DIR$/build/idea/out/" />
+    <ignored path=".idea/" />
+  </component>
+  <component name="StructureViewFactory">
+    <option name="ACTIVE_ACTIONS" value=",ALPHA_COMPARATOR" />
+  </component>
+  <component name="antWorkspaceConfiguration">
+    <option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
+    <option name="FILTER_TARGETS" value="false" />
+    <buildFile url="file://$PROJECT_DIR$/.idea/build.xml">
+      <runInBackground value="false" />
+      <targetFilters>
+        <filter targetName="post-make" isVisible="false" />
+        <filter targetName="clean" isVisible="true" />
+        <filter targetName="-do-configure" isVisible="false" />
+        <filter targetName="images" isVisible="true" />
+        <filter targetName="build-module" isVisible="true" />
+        <filter targetName="jtreg-debug" isVisible="false" />
+        <filter targetName="jtreg-debug-internal" isVisible="false" />
+        <filter targetName="jtreg" isVisible="false" />
+        <filter targetName="-check-jtreg.home" isVisible="false" />
+        <filter targetName="-def-check" isVisible="false" />
+        <filter targetName="-def-jtreg" isVisible="false" />
+        <filter targetName="-check-boot.java.home" isVisible="false" />
+        <filter targetName="-check-target.java.home" isVisible="false" />
+        <filter targetName="find-jdk-build-dir" isVisible="false" />
+        <filter targetName="check-env" isVisible="false" />
+      </targetFilters>
+      <treeView value="false" />
+      <expanded value="true" />
+    </buildFile>
+  </component>
+  <component name="ProjectView">
+    <navigator currentView="PackagesPane" proportions="" version="1">
+      <flattenPackages />
+      <showMembers />
+      <showModules />
+      <showLibraryContents />
+      <hideEmptyPackages />
+      <abbreviatePackageNames />
+      <autoscrollToSource />
+      <autoscrollFromSource />
+      <sortByType />
+    </navigator>
+    <panes>
+      <pane id="ProjectPane">
+        <subPane>
+          <PATH>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="jdk" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+            </PATH_ELEMENT>
+          </PATH>
+        </subPane>
+      </pane>
+      <pane id="PackagesPane">
+        <subPane>
+          <PATH>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="jdk" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
+            </PATH_ELEMENT>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="jdk" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
+            </PATH_ELEMENT>
+          </PATH>
+        </subPane>
+      </pane>
+      <pane id="Scope" />
+    </panes>
+  </component>
+</project>
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index 3a4c6daf2fb..2140054b988 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -351,3 +351,4 @@ ba21793a0e4816283cc0ecdab5142a4959363529 jdk-9+114
 295ac208a4443d433214d0c1f32d2ea45a3a32d2 jdk-9+115
 208388a5622dcca8227d6ad6c268f2c88087d283 jdk-9+116
 5267e91811614bac129817e566f730e9d63cf22a jdk-9+117
+05679aac2f7ec3d8dd2a96d7e7899906224bf5cf jdk-9+118
diff --git a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java
index be981997107..703fd6ced2c 100644
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -83,6 +83,7 @@
 
 package jdk.dynalink;
 
+import java.lang.StackWalker.StackFrame;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
@@ -172,6 +173,8 @@ public final class DynamicLinker {
     private static final String INITIAL_LINK_METHOD_NAME = "linkCallSite";
     private static final String INVOKE_PACKAGE_PREFIX = "java.lang.invoke.";
 
+    private static final StackWalker stackWalker = StackWalker.getInstance(StackWalker.Option.SHOW_HIDDEN_FRAMES);
+
     private final LinkerServices linkerServices;
     private final GuardedInvocationTransformer prelinkTransformer;
     private final boolean syncOnRelink;
@@ -300,21 +303,16 @@ public final class DynamicLinker {
      *         site is being linked.
      */
     public static StackTraceElement getLinkedCallSiteLocation() {
-        final StackTraceElement[] trace = new Throwable().getStackTrace();
-        for(int i = 0; i < trace.length - 1; ++i) {
-            final StackTraceElement frame = trace[i];
-            // If we found any of our linking entry points on the stack...
-            if(isRelinkFrame(frame) || isInitialLinkFrame(frame)) {
+        return stackWalker.walk(s -> s
+                // Find one of our linking entry points on the stack...
+                .dropWhile(f -> !(isRelinkFrame(f) || isInitialLinkFrame(f)))
+                .skip(1)
                 // ... then look for the first thing calling it that isn't j.l.invoke
-                for (int j = i + 1; j < trace.length; ++j) {
-                    final StackTraceElement frame2 = trace[j];
-                    if (!frame2.getClassName().startsWith(INVOKE_PACKAGE_PREFIX)) {
-                        return frame2;
-                    }
-                }
-            }
-        }
-        return null;
+                .dropWhile(f -> f.getClassName().startsWith(INVOKE_PACKAGE_PREFIX))
+                .findFirst()
+                .map(StackFrame::toStackTraceElement)
+                .orElse(null)
+        );
     }
 
     /**
@@ -326,7 +324,7 @@ public final class DynamicLinker {
      *
      * @return {@code true} if this frame represents {@code MethodHandleNatives.linkCallSite()}.
      */
-    private static boolean isInitialLinkFrame(final StackTraceElement frame) {
+    private static boolean isInitialLinkFrame(final StackFrame frame) {
         return testFrame(frame, INITIAL_LINK_METHOD_NAME, INITIAL_LINK_CLASS_NAME);
     }
 
@@ -339,11 +337,11 @@ public final class DynamicLinker {
      *
      * @return {@code true} if this frame represents {@code DynamicLinker.relink()}.
      */
-    private static boolean isRelinkFrame(final StackTraceElement frame) {
+    private static boolean isRelinkFrame(final StackFrame frame) {
         return testFrame(frame, RELINK_METHOD_NAME, CLASS_NAME);
     }
 
-    private static boolean testFrame(final StackTraceElement frame, final String methodName, final String className) {
+    private static boolean testFrame(final StackFrame frame, final String methodName, final String className) {
         return methodName.equals(frame.getMethodName()) && className.equals(frame.getClassName());
     }
 }
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java
index fc1a7464df0..b082076e593 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java
@@ -174,10 +174,8 @@ public abstract class NashornException extends RuntimeException {
                 String methodName = st.getMethodName();
                 if (methodName.equals(CompilerConstants.PROGRAM.symbolName())) {
                     methodName = "<program>";
-                }
-
-                if (methodName.contains(CompilerConstants.ANON_FUNCTION_PREFIX.symbolName())) {
-                    methodName = "<anonymous>";
+                } else {
+                    methodName = stripMethodName(methodName);
                 }
 
                 filtered.add(new StackTraceElement(className, methodName,
@@ -187,6 +185,22 @@ public abstract class NashornException extends RuntimeException {
         return filtered.toArray(new StackTraceElement[0]);
     }
 
+    private static String stripMethodName(final String methodName) {
+        String name = methodName;
+
+        final int nestedSeparator = name.lastIndexOf(CompilerConstants.NESTED_FUNCTION_SEPARATOR.symbolName());
+        if (nestedSeparator >= 0) {
+            name = name.substring(nestedSeparator + 1);
+        }
+
+        final int idSeparator = name.indexOf(CompilerConstants.ID_FUNCTION_SEPARATOR.symbolName());
+        if (idSeparator >= 0) {
+            name = name.substring(0, idSeparator);
+        }
+
+        return name.contains(CompilerConstants.ANON_FUNCTION_PREFIX.symbolName()) ? "<anonymous>" : name;
+    }
+
     /**
      * Return a formatted script stack trace string with frames information separated by '\n'
      *
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilerConstants.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilerConstants.java
index 0d64ac2ef64..28bd19f8709 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilerConstants.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilerConstants.java
@@ -78,6 +78,12 @@ public enum CompilerConstants {
     /** function prefix for anonymous functions */
     ANON_FUNCTION_PREFIX("L:"),
 
+    /** separator for method names of nested functions */
+    NESTED_FUNCTION_SEPARATOR("#"),
+
+    /** separator for making method names unique by appending numeric ids */
+    ID_FUNCTION_SEPARATOR("-"),
+
     /** method name for Java method that is the program entry point */
     PROGRAM(":program"),
 
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Namespace.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Namespace.java
index 17304a905ab..08ae356ed64 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Namespace.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Namespace.java
@@ -68,7 +68,7 @@ public class Namespace {
     }
 
     /**
-     * Create a uniqueName name in the namespace in the form base$n where n varies.
+     * Create a uniqueName name in the namespace in the form base-n where n varies.
      * Also truncates very long names that would otherwise break ASM.
      *
      * @param base Base of name.  Base will be returned if uniqueName.
@@ -83,7 +83,7 @@ public class Namespace {
             if (counter != null) {
                 final int count = counter + 1;
                 namespaceDirectory.put(truncatedBase, count);
-                return truncatedBase + '-' + count;
+                return truncatedBase + CompilerConstants.ID_FUNCTION_SEPARATOR.symbolName() + count;
             }
         }
 
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java
index da61ff7ff5a..1b239da48aa 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java
@@ -203,8 +203,10 @@ public abstract class AbstractParser {
      * @return tokenType of next token.
      */
     private TokenType nextToken() {
-        // Capture last token tokenType.
-        last = type;
+        // Capture last token type, but ignore comments (which are irrelevant for the purpose of newline detection).
+        if (type != COMMENT) {
+            last = type;
+        }
         if (type != EOF) {
 
             // Set up next token.
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
index dde20817853..6527f6be8d0 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
@@ -534,7 +534,7 @@ public class Parser extends AbstractParser implements Loggable {
 
         final ParserContextFunctionNode parentFunction = lc.getCurrentFunction();
         if (parentFunction != null && !parentFunction.isProgram()) {
-            sb.append(parentFunction.getName()).append('$');
+            sb.append(parentFunction.getName()).append(CompilerConstants.NESTED_FUNCTION_SEPARATOR.symbolName());
         }
 
         assert ident.getName() != null;
@@ -1827,7 +1827,7 @@ public class Parser extends AbstractParser implements Loggable {
 
     /**
      * ExpressionStatement :
-     *      Expression ; // [lookahead ~( or  function )]
+     *      Expression ; // [lookahead ~({ or  function )]
      *
      * See 12.4
      *
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java
index 767989531e1..9ac75ecd217 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java
@@ -313,18 +313,8 @@ public final class ScriptRuntime {
         }
     }
 
-    /**
-     * Returns an iterator over property values used in the {@code for each...in} statement. Aside from built-in JS
-     * objects, it also operates on Java arrays, any {@link Iterable}, as well as on {@link Map} objects, iterating over
-     * map values.
-     * @param obj object to iterate on.
-     * @return iterator over the object's property values.
-     */
-    public static Iterator<?> toValueIterator(final Object obj) {
-        if (obj instanceof ScriptObject) {
-            return ((ScriptObject)obj).valueIterator();
-        }
-
+    // value Iterator for important Java objects - arrays, maps, iterables.
+    private static Iterator<?> iteratorForJavaArrayOrList(final Object obj) {
         if (obj != null && obj.getClass().isArray()) {
             final Object array  = obj;
             final int    length = Array.getLength(obj);
@@ -352,16 +342,36 @@ public final class ScriptRuntime {
             };
         }
 
+        if (obj instanceof Iterable) {
+            return ((Iterable<?>)obj).iterator();
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns an iterator over property values used in the {@code for each...in} statement. Aside from built-in JS
+     * objects, it also operates on Java arrays, any {@link Iterable}, as well as on {@link Map} objects, iterating over
+     * map values.
+     * @param obj object to iterate on.
+     * @return iterator over the object's property values.
+     */
+    public static Iterator<?> toValueIterator(final Object obj) {
+        if (obj instanceof ScriptObject) {
+            return ((ScriptObject)obj).valueIterator();
+        }
+
         if (obj instanceof JSObject) {
             return ((JSObject)obj).values().iterator();
         }
 
-        if (obj instanceof Map) {
-            return ((Map<?,?>)obj).values().iterator();
+        final Iterator<?> itr = iteratorForJavaArrayOrList(obj);
+        if (itr != null) {
+            return itr;
         }
 
-        if (obj instanceof Iterable) {
-            return ((Iterable<?>)obj).iterator();
+        if (obj instanceof Map) {
+            return ((Map<?,?>)obj).values().iterator();
         }
 
         final Object wrapped = Global.instance().wrapAsObject(obj);
@@ -380,6 +390,14 @@ public final class ScriptRuntime {
      * @return iterator based on the ECMA 6 Iterator interface.
      */
     public static Iterator<?> toES6Iterator(final Object obj) {
+        // if not a ScriptObject, try convenience iterator for Java objects!
+        if (!(obj instanceof ScriptObject)) {
+            final Iterator<?> itr = iteratorForJavaArrayOrList(obj);
+            if (itr != null) {
+                return itr;
+            }
+        }
+
         final Global global = Global.instance();
         final Object iterator = AbstractIterator.getIterator(Global.toObject(obj), global);
 
diff --git a/nashorn/test/Makefile b/nashorn/test/Makefile
new file mode 100644
index 00000000000..d4f5afe6da1
--- /dev/null
+++ b/nashorn/test/Makefile
@@ -0,0 +1,371 @@
+#
+# Copyright (c) 1995, 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.
+#
+
+#
+# Makefile to run various nashorn tests
+#
+
+.DEFAULT : all
+
+# Empty these to get rid of some default rules
+.SUFFIXES:
+.SUFFIXES: .java
+CO=
+GET=
+
+# Utilities used
+AWK       = awk
+CAT       = cat
+CD        = cd
+CHMOD     = chmod
+CP        = cp
+CUT       = cut
+DIRNAME   = dirname
+ECHO      = echo
+EGREP     = egrep
+EXPAND    = expand
+FIND      = find
+MKDIR     = mkdir
+PWD       = pwd
+SED       = sed
+SORT      = sort
+TEE       = tee
+UNAME     = uname
+UNIQ      = uniq
+WC        = wc
+ZIP       = zip
+
+# Get OS name from uname (Cygwin inexplicably adds _NT-5.1)
+UNAME_S := $(shell $(UNAME) -s | $(CUT) -f1 -d_)
+
+# Commands to run on paths to make mixed paths for java on windows
+ifeq ($(UNAME_S), CYGWIN)
+  # Location of developer shared files
+  SLASH_JAVA = J:
+  GETMIXEDPATH = cygpath -m
+else
+  # Location of developer shared files
+  SLASH_JAVA = /java
+
+  GETMIXEDPATH=$(ECHO)
+endif
+
+# Root of this test area (important to use full paths in some places)
+TEST_ROOT := $(shell $(PWD))
+
+# Root of all test results
+ifdef TEST_OUTPUT_DIR
+  $(shell $(MKDIR) -p $(TEST_OUTPUT_DIR)/jtreg)
+  ABS_TEST_OUTPUT_DIR := \
+    $(shell $(CD) $(TEST_OUTPUT_DIR)/jtreg && $(PWD))
+else
+  ifdef ALT_OUTPUTDIR
+    ABS_OUTPUTDIR = $(shell $(CD) $(ALT_OUTPUTDIR) && $(PWD))
+  else
+    ABS_OUTPUTDIR = $(shell $(CD) $(TEST_ROOT)/.. && $(PWD))
+  endif
+
+  ABS_PLATFORM_BUILD_ROOT = $(ABS_OUTPUTDIR)
+  ABS_TEST_OUTPUT_DIR := $(ABS_PLATFORM_BUILD_ROOT)/testoutput/$(UNIQUE_DIR)
+endif
+
+# Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
+ifndef PRODUCT_HOME
+  # Try to use images/jdk if it exists
+  ABS_JDK_IMAGE = $(ABS_PLATFORM_BUILD_ROOT)/images/jdk
+  PRODUCT_HOME :=                       		\
+    $(shell                             		\
+      if [ -d $(ABS_JDK_IMAGE) ] ; then 		\
+         $(ECHO) "$(ABS_JDK_IMAGE)";    		\
+       else                             		\
+         $(ECHO) "$(ABS_PLATFORM_BUILD_ROOT)";		\
+       fi)
+  PRODUCT_HOME := $(PRODUCT_HOME)
+endif
+
+# Expect JPRT to set JPRT_PRODUCT_ARGS (e.g. -server etc.)
+#   Should be passed into 'java' only.
+#   Could include: -d64 -server -client OR any java option
+ifdef JPRT_PRODUCT_ARGS
+  JAVA_ARGS = $(JPRT_PRODUCT_ARGS)
+endif
+
+# Expect JPRT to set JPRT_PRODUCT_VM_ARGS (e.g. -Xcomp etc.)
+#   Should be passed into anything running the vm (java, javac, javadoc, ...).
+ifdef JPRT_PRODUCT_VM_ARGS
+  JAVA_VM_ARGS = $(JPRT_PRODUCT_VM_ARGS)
+endif
+
+# jtreg -nativepath <dir>
+#
+# Local make tests will be TEST_IMAGE_DIR and JPRT with jprt.use.reg.test.bundle=true
+# should be JPRT_TESTNATIVE_PATH
+ifdef TEST_IMAGE_DIR
+  TESTNATIVE_DIR = $(TEST_IMAGE_DIR)
+else ifdef JPRT_TESTNATIVE_PATH
+  TESTNATIVE_DIR = $(JPRT_TESTNATIVE_PATH)
+endif
+ifdef TESTNATIVE_DIR
+  JTREG_NATIVE_PATH = -nativepath:$(shell $(GETMIXEDPATH) "$(TESTNATIVE_DIR)/nashorn/jtreg/native")
+endif
+
+# jtreg failure handler config
+ifeq ($(FAILURE_HANDLER_DIR), )
+  ifneq ($(TESTNATIVE_DIR), )
+    FAILURE_HANDLER_DIR := $(TESTNATIVE_DIR)/failure_handler
+  endif
+endif
+ifneq ($(FAILURE_HANDLER_DIR), )
+  FAILURE_HANDLER_DIR_MIXED := $(shell $(GETMIXEDPATH) "$(FAILURE_HANDLER_DIR)")
+  JTREG_FAILURE_HANDLER_OPTIONS := \
+      -timeoutHandlerDir:$(FAILURE_HANDLER_DIR_MIXED)/jtregFailureHandler.jar \
+      -observerDir:$(FAILURE_HANDLER_DIR_MIXED)/jtregFailureHandler.jar \
+      -timeoutHandler:jdk.test.failurehandler.jtreg.GatherProcessInfoTimeoutHandler \
+      -observer:jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver
+  ifeq ($(UNAME_S), CYGWIN)
+    JTREG_FAILURE_HANDLER_OPTIONS += -J-Djava.library.path="$(FAILURE_HANDLER_DIR_MIXED)"
+  endif
+endif
+
+# Expect JPRT to set JPRT_ARCHIVE_BUNDLE (path to zip bundle for results)
+ifdef JPRT_ARCHIVE_BUNDLE
+  ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE)
+else
+  ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip
+endif
+
+# How to create the test bundle (pass or fail, we want to create this)
+#   Follow command with ";$(BUNDLE_UP_AND_EXIT)", so it always gets executed.
+ZIP_UP_RESULTS = ( $(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)`     \
+	           && $(CD) $(ABS_TEST_OUTPUT_DIR)             \
+	           && $(CHMOD) -R a+r . \
+	           && $(ZIP) -q -r $(ARCHIVE_BUNDLE) . )
+
+# important results files
+SUMMARY_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport/text/summary.txt")
+STATS_TXT_NAME = Stats.txt
+STATS_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/$(STATS_TXT_NAME)")
+RUNLIST   = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/runlist.txt")
+PASSLIST  = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/passlist.txt")
+FAILLIST  = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/faillist.txt")
+EXITCODE  = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/exitcode.txt")
+
+TESTEXIT = \
+  if [ ! -s $(EXITCODE) ] ; then \
+    $(ECHO) "ERROR: EXITCODE file not filled in."; \
+    $(ECHO) "1" > $(EXITCODE); \
+  fi ; \
+  testExitCode=`$(CAT) $(EXITCODE)`; \
+  $(ECHO) "EXIT CODE: $${testExitCode}"; \
+  exit $${testExitCode}
+
+BUNDLE_UP_AND_EXIT = \
+( \
+  jtregExitCode=$$? && \
+  _summary="$(SUMMARY_TXT)"; \
+  $(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST) $(EXITCODE); \
+  $(ECHO) "$${jtregExitCode}" > $(EXITCODE); \
+  if [ -r "$${_summary}" ] ; then \
+    $(ECHO) "Summary: $(UNIQUE_DIR)" > $(STATS_TXT); \
+    $(EXPAND) $${_summary} | $(EGREP) -v ' Not run\.' > $(RUNLIST); \
+    $(EGREP) ' Passed\.' $(RUNLIST) \
+      | $(EGREP) -v ' Error\.' \
+      | $(EGREP) -v ' Failed\.' > $(PASSLIST); \
+    ( $(EGREP) ' Failed\.' $(RUNLIST); \
+      $(EGREP) ' Error\.' $(RUNLIST); \
+      $(EGREP) -v ' Passed\.' $(RUNLIST) ) \
+      | $(SORT) | $(UNIQ) > $(FAILLIST); \
+    if [ $${jtregExitCode} != 0 -o -s $(FAILLIST) ] ; then \
+      $(EXPAND) $(FAILLIST) \
+        | $(CUT) -d' ' -f1 \
+        | $(SED) -e 's@^@FAILED: @' >> $(STATS_TXT); \
+      if [ $${jtregExitCode} = 0 ] ; then \
+        jtregExitCode=1; \
+      fi; \
+    fi; \
+    runc="`$(CAT) $(RUNLIST)      | $(WC) -l | $(AWK) '{print $$1;}'`"; \
+    passc="`$(CAT) $(PASSLIST)    | $(WC) -l | $(AWK) '{print $$1;}'`"; \
+    failc="`$(CAT) $(FAILLIST)    | $(WC) -l | $(AWK) '{print $$1;}'`"; \
+    exclc="FIXME CODETOOLS-7900176"; \
+    $(ECHO) "TEST STATS: name=$(UNIQUE_DIR)  run=$${runc}  pass=$${passc}  fail=$${failc}" \
+      >> $(STATS_TXT); \
+  else \
+    $(ECHO) "Missing file: $${_summary}" >> $(STATS_TXT); \
+  fi; \
+  if [ -f $(STATS_TXT) ] ; then \
+    $(CAT) $(STATS_TXT); \
+  fi; \
+  $(ZIP_UP_RESULTS) ; \
+  $(TESTEXIT) \
+)
+
+################################################################
+
+# Default make rule (runs default nashorn tests)
+all: nashorn_default
+	@$(ECHO) "Testing completed successfully"
+
+# Prep for output
+# Change execute permissions on shared library files.
+# Files in repositories should never have execute permissions, but
+# there are some tests that have pre-built shared libraries, and these
+# windows dll files must have execute permission. Adding execute
+# permission may happen automatically on windows when using certain
+# versions of mercurial but it cannot be guaranteed. And blindly
+# adding execute permission might be seen as a mercurial 'change', so
+# we avoid adding execute permission to repository files. But testing
+# from a plain source tree needs the chmod a+rx. Applying the chmod to
+# all shared libraries not just dll files. And with CYGWIN and sshd
+# service, you may need CYGWIN=ntsec for this to work.
+prep:
+	@$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR)
+	@$(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)`
+	@if [ ! -d $(TEST_ROOT)/../.hg ] ; then                          \
+	  $(FIND) $(TEST_ROOT) \( -name \*.dll -o -name \*.DLL -o -name \*.so \)  \
+	        -exec $(CHMOD) a+rx {} \; ;                             \
+        fi
+
+# Cleanup
+clean:
+	@$(RM) -r $(ABS_TEST_OUTPUT_DIR)
+	@$(RM) $(ARCHIVE_BUNDLE)
+
+################################################################
+
+# jtreg tests
+
+# Expect JT_HOME to be set for jtreg tests. (home for jtreg)
+ifndef JT_HOME
+  JT_HOME = $(SLASH_JAVA)/re/jtreg/4.2/promoted/latest/binaries/jtreg
+  ifdef JPRT_JTREG_HOME
+    JT_HOME = $(JPRT_JTREG_HOME)
+  endif
+endif
+
+# Problematic tests to be excluded
+PROBLEM_LISTS=$(call MixedDirs,$(wildcard ProblemList.txt closed/ProblemList.txt))
+
+# Create exclude list for this platform and arch
+ifdef NO_EXCLUDES
+  JTREG_EXCLUSIONS =
+else
+  JTREG_EXCLUSIONS = $(PROBLEM_LISTS:%=-exclude:%)
+endif
+
+# convert list of directories to dos paths
+define MixedDirs
+$(foreach i,$1,$(shell $(GETMIXEDPATH) "${i}"))
+endef
+
+define SummaryInfo
+$(ECHO) "########################################################"
+$(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME))
+$(ECHO) "########################################################"
+endef
+
+# ------------------------------------------------------------------
+
+nashorn_%:
+	$(ECHO) "Running tests: $@"
+	for each in $@; do \
+	        $(MAKE) -j 1 TEST_SELECTION=":$$each" UNIQUE_DIR=$$each jtreg_tests; \
+	done
+
+# ------------------------------------------------------------------
+
+# When called from JPRT the TESTDIRS variable is set to the jtreg tests to run
+ifdef TESTDIRS
+  TEST_SELECTION = $(TESTDIRS)
+endif
+
+ifdef CONCURRENCY
+  EXTRA_JTREG_OPTIONS += -concurrency:$(CONCURRENCY)
+endif
+
+# Default JTREG to run
+JTREG = $(JT_HOME)/bin/jtreg
+# run in agentvm mode
+JTREG_BASIC_OPTIONS += -agentvm
+# Only run automatic tests
+JTREG_BASIC_OPTIONS += -a
+# Always turn on assertions
+JTREG_ASSERT_OPTION = -ea -esa
+JTREG_BASIC_OPTIONS += $(JTREG_ASSERT_OPTION)
+# Report details on all failed or error tests, times too
+JTREG_BASIC_OPTIONS += -v:fail,error,time
+# Retain all files for failing tests
+JTREG_BASIC_OPTIONS += -retain:fail,error
+# Ignore tests are not run and completely silent about it
+JTREG_IGNORE_OPTION = -ignore:quiet
+JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION)
+# Multiple by 4 the timeout numbers
+JTREG_TIMEOUT_OPTION =  -timeoutFactor:4
+JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
+# Set the max memory for jtreg control vm
+JTREG_MEMORY_OPTION = -J-Xmx512m
+JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION)
+# Give tests access to JT_JAVA, see JDK-8141609
+JTREG_BASIC_OPTIONS += -e:JDK8_HOME=${JT_JAVA}
+# Add any extra options
+JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS)
+# Set other vm and test options
+JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%)
+# Set the GC options for test vms
+#JTREG_GC_OPTION = -vmoption:-XX:+UseSerialGC
+#JTREG_TEST_OPTIONS += $(JTREG_GC_OPTION)
+# Set the max memory for jtreg target test vms
+JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx512m
+JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
+
+# Make sure jtreg exists
+$(JTREG): $(JT_HOME)
+
+# Run jtreg
+jtreg_tests: prep $(PRODUCT_HOME) $(JTREG)
+	(                                                                    \
+	  ( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)");                   \
+            export JT_HOME;                                                  \
+            $(shell $(GETMIXEDPATH) "$(JTREG)")                              \
+              $(JTREG_BASIC_OPTIONS)                                         \
+              -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport")  \
+              -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTwork")    \
+              -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)")                \
+              $(JTREG_NATIVE_PATH)                                           \
+              $(JTREG_FAILURE_HANDLER_OPTIONS)                               \
+              $(JTREG_EXCLUSIONS)                                            \
+              $(JTREG_TEST_OPTIONS)                                          \
+              $(TEST_SELECTION)                                                    \
+	  ) ;                                                                \
+	  $(BUNDLE_UP_AND_EXIT)                                              \
+	) 2>&1 | $(TEE) $(ABS_TEST_OUTPUT_DIR)/output.txt ; $(TESTEXIT)
+
+PHONY_LIST += jtreg_tests
+
+################################################################
+
+# Phony targets (e.g. these are not filenames)
+.PHONY: all clean prep $(PHONY_LIST)
+
+################################################################
diff --git a/nashorn/test/script/basic/JDK-8025515.js b/nashorn/test/script/basic/JDK-8025515.js
index b88897b654b..6538f54f247 100644
--- a/nashorn/test/script/basic/JDK-8025515.js
+++ b/nashorn/test/script/basic/JDK-8025515.js
@@ -61,8 +61,8 @@ testMethodName(function() { throw new Error() }, "L:59");
 var f = (function() {
     return function() { a.b.c; };
 })();
-testMethodName(f, "f$L:62");
+testMethodName(f, "f#L:62");
 
 testMethodName((function() {
     return function() { return a.b.c; };
-})(), "L:66$L:67");
+})(), "L:66#L:67");
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java b/nashorn/test/script/basic/JDK-8156714.js
similarity index 69%
rename from jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java
rename to nashorn/test/script/basic/JDK-8156714.js
index 9e5a4a7df61..93a4e906f5f 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java
+++ b/nashorn/test/script/basic/JDK-8156714.js
@@ -1,37 +1,50 @@
 /*
  * 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package jdk.tools.jlink.plugin;
-
-import java.util.Properties;
 
 /**
- * Interface to plugin (container) context.
+ * JDK-8156714: Parsing issue with automatic semicolon insertion
+ *
+ * @test
+ * @run
  */
-public interface PluginContext {
-    /**
-     * Returns 'release' properties
-     */
-    public Properties getReleaseProperties();
+
+a = function() {
+}
+
+/* */ function b() {
+}
+
+c = function() {
+} /*
+
+*/ function d() {
+}
+
+try {
+    eval("x = function() {} /* */ function y() {}");
+    throw new Error("Error expected");
+} catch (e) {
+    if (!(e instanceof SyntaxError)) {
+        throw new Error("Unexpected error: " + e);
+    }
 }
diff --git a/nashorn/test/script/basic/JDK-8156896.js b/nashorn/test/script/basic/JDK-8156896.js
new file mode 100644
index 00000000000..fc71f07c941
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8156896.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8156896: Script stack trace should display function names
+ *
+ * @test
+ * @run
+ */
+
+function checkNamedFunction(stack) {
+    Assert.assertTrue(stack.indexOf("Error\n\tat bar (") === 0);
+}
+
+function checkAnonymousFunction(stack) {
+    Assert.assertTrue(stack.indexOf("Error\n\tat <anonymous> (") === 0);
+}
+
+// Named functions
+function bar() { try { throw new Error(); } catch(e) { return e.stack; } }
+checkNamedFunction(bar());
+
+bar = function() { try { throw new Error(); } catch(e) { return e.stack; } };
+checkNamedFunction(bar());
+
+f = (function() {return function bar() { try { throw new Error(); } catch(e) { return e.stack; } } })();
+checkNamedFunction(f());
+
+f = new Function("return function bar() { try { throw new Error(); } catch(e) { return e.stack; } }")();
+checkNamedFunction(f());
+
+// Anonymous functions
+checkAnonymousFunction((function() { try { throw new Error(); } catch(e) { return e.stack; } })());
+
+f = (function() {return function() { try { throw new Error(); } catch(e) { return e.stack; } } })();
+checkAnonymousFunction(f());
+
+f = new Function("return function() { try { throw new Error(); } catch(e) { return e.stack; } }")();
+checkAnonymousFunction(f());
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginContextImpl.java b/nashorn/test/script/basic/es6/JDK-8156665.js
similarity index 65%
rename from jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginContextImpl.java
rename to nashorn/test/script/basic/es6/JDK-8156665.js
index 7fe7dcea36e..d405b188be5 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginContextImpl.java
+++ b/nashorn/test/script/basic/es6/JDK-8156665.js
@@ -1,37 +1,40 @@
 /*
  * 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package jdk.tools.jlink.internal;
 
-import java.util.Properties;
+/**
+ * JDK-8156665: ES6 for..of should work on Java Iterables and Java arrays
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
 
-import jdk.tools.jlink.plugin.PluginContext;
+var ca = new (Java.type("char[]"))(3);
+ca[0] = 'a', ca[1] = 'b', ca[2] = 'c';
+for (i of ca) print(i);
 
-public final class PluginContextImpl implements PluginContext {
-    private final Properties releaseProps = new Properties();
+var al = new java.util.ArrayList();
+al.add("hello");
+al.add("world");
 
-    public Properties getReleaseProperties() {
-        return releaseProps;
-    }
-}
+for (i of al) print(i);
diff --git a/nashorn/test/script/basic/es6/JDK-8156665.js.EXPECTED b/nashorn/test/script/basic/es6/JDK-8156665.js.EXPECTED
new file mode 100644
index 00000000000..ddf6f6d20ba
--- /dev/null
+++ b/nashorn/test/script/basic/es6/JDK-8156665.js.EXPECTED
@@ -0,0 +1,5 @@
+a
+b
+c
+hello
+world
diff --git a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED
index 8fbd95117da..82f4506ed69 100644
--- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED
+++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED
@@ -4864,7 +4864,7 @@
   "kind": "COMPILATION_UNIT",
   "sourceElements": [
     {
-      "endPosition": "1242",
+      "endPosition": "1222",
       "kind": "FUNCTION",
       "name": "Parser",
       "body": {
@@ -5419,7 +5419,7 @@
         },
         "startPosition": "1809"
       },
-      "endPosition": "1973",
+      "endPosition": "1901",
       "kind": "EXPRESSION_STATEMENT",
       "startPosition": "1809"
     },
@@ -6310,7 +6310,7 @@
       "startPosition": "1974"
     },
     {
-      "endPosition": "3767",
+      "endPosition": "3726",
       "kind": "FUNCTION",
       "name": "processFiles",
       "body": {
diff --git a/nashorn/test/src/jdk/dynalink/test/LinkedCallSiteLocationTest.java b/nashorn/test/src/jdk/dynalink/test/LinkedCallSiteLocationTest.java
new file mode 100644
index 00000000000..8e2b03b6a67
--- /dev/null
+++ b/nashorn/test/src/jdk/dynalink/test/LinkedCallSiteLocationTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.dynalink.test;
+
+import static jdk.dynalink.StandardOperation.CALL_METHOD;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.DynamicLinker;
+import jdk.dynalink.DynamicLinkerFactory;
+import jdk.dynalink.NamedOperation;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.support.SimpleRelinkableCallSite;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class LinkedCallSiteLocationTest {
+    @Test
+    public void testLinkedCallSiteLocation() throws Throwable {
+        final StackTraceElement[] lastLinked = new StackTraceElement[1];
+
+        final GuardingDynamicLinker testLinker =
+                (r, s) -> { lastLinked[0] = DynamicLinker.getLinkedCallSiteLocation(); return null; };
+
+        final DynamicLinkerFactory factory = new DynamicLinkerFactory();
+        factory.setPrioritizedLinker(testLinker);
+        final DynamicLinker linker = factory.createLinker();
+        final SimpleRelinkableCallSite callSite = new SimpleRelinkableCallSite(
+                new CallSiteDescriptor(
+                        MethodHandles.lookup(),
+                        new NamedOperation(CALL_METHOD, "foo"),
+                        MethodType.methodType(void.class, Object.class)));
+        linker.link(callSite);
+
+        // Test initial linking
+        callSite.dynamicInvoker().invoke(new TestClass1()); final int l1 = getLineNumber();
+        assertLocation(lastLinked[0], l1);
+
+        // Test relinking
+        callSite.dynamicInvoker().invoke(new TestClass2()); final int l2 = getLineNumber();
+        assertLocation(lastLinked[0], l2);
+    }
+
+    private void assertLocation(final StackTraceElement frame, final int lineNumber) {
+        Assert.assertNotNull(frame);
+        Assert.assertEquals(frame.getLineNumber(), lineNumber);
+        Assert.assertEquals(frame.getClassName(), this.getClass().getName());
+    }
+
+    private static int getLineNumber() {
+        return StackWalker.getInstance().walk(s -> s.skip(1).findFirst().get().getLineNumber());
+    }
+
+    public static class TestClass1 {
+        public void foo() {
+        }
+    }
+
+    public static class TestClass2 {
+        public void foo() {
+        }
+    }
+}
diff --git a/test/Makefile b/test/Makefile
index e31dbedea87..41a20170e0e 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -87,7 +87,7 @@ hotspot_%:
 #
 # Invocation:
 #
-# make jtreg_tests TESTDIRS=<test-dirs>
+# make jtreg_tests TESTDIRS=<test-dirs> TEST_SELECTION=<path to test or jtreg group> TEST_OUTPUT_DIR=<path>
 #
 # where <test-dirs> is something like '../<component>/test/runtime',
 # <component> in turn being one of the top level directories (for
diff --git a/test/make/TestIdea.gmk b/test/make/TestIdea.gmk
new file mode 100644
index 00000000000..39d93c5cdaf
--- /dev/null
+++ b/test/make/TestIdea.gmk
@@ -0,0 +1,46 @@
+
+# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include $(SPEC)
+include MakeBase.gmk
+
+default: all
+
+IDEA_OUTPUT_DIR := $(TESTMAKE_OUTPUTDIR)/verify-idea
+
+clean-idea:
+	$(RM) -r $(IDEA_OUTPUT_DIR)
+
+verify-idea:
+	$(MKDIR) -p $(IDEA_OUTPUT_DIR)
+	$(BASH) $(TOPDIR)/common/bin/idea.sh -o $(IDEA_OUTPUT_DIR)/idea1
+	$(BASH) $(TOPDIR)/common/bin/idea.sh -o $(IDEA_OUTPUT_DIR)/idea2 java.base
+	$(BASH) $(TOPDIR)/common/bin/idea.sh -o $(IDEA_OUTPUT_DIR)/idea3 java.base jdk.compiler
+
+TEST_TARGETS += verify-idea 
+
+all: $(TEST_TARGETS)
+
+.PHONY: default all verify-idea
diff --git a/test/make/TestMake.gmk b/test/make/TestMake.gmk
index 1f33e1786a7..f3676a00153 100644
--- a/test/make/TestMake.gmk
+++ b/test/make/TestMake.gmk
@@ -33,7 +33,10 @@ make-base:
 java-compilation:
 	+$(MAKE) -f TestJavaCompilation.gmk $(TEST_SUBTARGET)
 
+test-idea:
+	+$(MAKE) -f TestIdea.gmk $(TEST_SUBTARGET)
 
-all: make-base java-compilation
 
-.PHONY: default all make-base java-compilation
+all: make-base java-compilation test-idea
+
+.PHONY: default all make-base java-compilation test-idea