Merge jdk-9+119
authorduke
Wed, 05 Jul 2017 21:42:16 +0200
changeset 37948 caf97b37ebec
parent 37947 f69560487686 (diff)
parent 37859 fceb44d97ec0 (current diff)
child 37949 27ea61260ecc
child 37950 426bfd72832d
child 37951 ce2744a0f1a7
child 37969 2203863bfe3e
child 37983 f02dd4db99ca
child 38303 1d0016127806
child 38319 739e70ea7187
child 38320 e24c7029e8ba
child 38480 de65331b1a57
child 38482 0cc343dc14db
child 38483 84396baa1cb3
child 38496 388f1b371c16
child 38497 06b1977d0f4f
child 38504 4f596861374b
child 38506 005e8449db11
child 38507 d48ba9db4b7d
Merge
--- a/.hgignore	Wed Jul 05 21:41:02 2017 +0200
+++ b/.hgignore	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,6 @@
 ^build/
 ^dist/
+^.idea/
 nbproject/private/
 ^webrev
 ^.hgtip
--- a/.hgtags-top-repo	Wed Jul 05 21:41:02 2017 +0200
+++ b/.hgtags-top-repo	Wed Jul 05 21:42:16 2017 +0200
@@ -360,3 +360,4 @@
 09617ce980b99d49abfd54dacfed353c47e2a115 jdk-9+115
 6743a8e0cab7b5f6f4a0575f6664892f0ab740af jdk-9+116
 e882bcdbdac436523f3d5681611d3118a3804ea7 jdk-9+117
+047f95de8f918d8ff5e8cd2636a2abb5c3c8adb8 jdk-9+118
--- a/common/autoconf/flags.m4	Wed Jul 05 21:41:02 2017 +0200
+++ b/common/autoconf/flags.m4	Wed Jul 05 21:42:16 2017 +0200
@@ -768,7 +768,7 @@
         $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 @@
         -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 @@
         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 @@
         BUILD_CC_DISABLE_WARNING_PREFIX=
       fi
       CC="$CC_OLD"
+      CXX="$CXX_OLD"
+      CFLAGS="$CFLAGS_OLD"
       ;;
     clang)
       DISABLE_WARNING_PREFIX="-Wno-"
--- a/common/autoconf/generated-configure.sh	Wed Jul 05 21:41:02 2017 +0200
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 21:42:16 2017 +0200
@@ -4900,6 +4900,8 @@
 
 # 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 @@
 #   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 @@
 #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 @@
 
 
   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
@@ -34858,6 +34861,13 @@
 
 
 
+
+
+
+
+
+
+
     # Execute function body
 
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
@@ -34897,6 +34907,8 @@
 
 
 
+
+
   fi
 
   #
@@ -46475,6 +46487,268 @@
     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.
@@ -49135,6 +49409,18 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
     # Execute function body
 
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
@@ -49711,6 +49997,8 @@
 
 
 
+
+
   elif test "x$TOOLCHAIN_TYPE" = xclang; then
     JVM_CFLAGS="$JVM_CFLAGS -D_GNU_SOURCE"
 
@@ -49948,6 +50236,18 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
     # Execute function body
 
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
@@ -49987,6 +50287,8 @@
 
 
 
+
+
     fi
     if !   [[ " $JVM_VARIANTS " =~ " zero " ]]   && !   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
       # Non-zero builds have stricter warnings
@@ -50453,6 +50755,18 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
     # Execute function body
 
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
@@ -50469,7 +50783,7 @@
   # 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 @@
 
 
 
+
+
   elif test "x$TOOLCHAIN_TYPE" = xclang; then
     OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_GNU_SOURCE"
 
@@ -50725,6 +51041,18 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
     # Execute function body
 
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
@@ -50741,7 +51069,7 @@
   # 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 @@
 
 
 
+
+
     fi
     if !   [[ " $JVM_VARIANTS " =~ " zero " ]]   && !   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
       # Non-zero builds have stricter warnings
@@ -51918,9 +52248,15 @@
         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 @@
         BUILD_CC_DISABLE_WARNING_PREFIX=
       fi
       CC="$CC_OLD"
+      CXX="$CXX_OLD"
+      CFLAGS="$CFLAGS_OLD"
       ;;
     clang)
       DISABLE_WARNING_PREFIX="-Wno-"
--- a/common/autoconf/toolchain.m4	Wed Jul 05 21:41:02 2017 +0200
+++ b/common/autoconf/toolchain.m4	Wed Jul 05 21:42:16 2017 +0200
@@ -59,23 +59,25 @@
 
 # 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 @@
 #   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 @@
   # 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 @@
     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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/bin/idea.sh	Wed Jul 05 21:42:16 2017 +0200
@@ -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
--- a/common/bin/jib.sh	Wed Jul 05 21:41:02 2017 +0200
+++ b/common/bin/jib.sh	Wed Jul 05 21:42:16 2017 +0200
@@ -89,7 +89,7 @@
     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
--- a/corba/.hgtags	Wed Jul 05 21:41:02 2017 +0200
+++ b/corba/.hgtags	Wed Jul 05 21:42:16 2017 +0200
@@ -360,3 +360,4 @@
 7bab1b1b36824924b1c657a8419369ba93d198d3 jdk-9+115
 7dfa7377a5e601b8f740741a9a80e04c72dd04d6 jdk-9+116
 7a1b36bf2fe55a9a7732489ccdd326c910329a7e jdk-9+117
+8c2c2d17f7ce92a31c9ccb44a122ec62f5a85ace jdk-9+118
--- a/hotspot/.hgtags	Wed Jul 05 21:41:02 2017 +0200
+++ b/hotspot/.hgtags	Wed Jul 05 21:42:16 2017 +0200
@@ -520,3 +520,4 @@
 88dd08d7be0fe7fb9f1914b1628f0aae9bf56e25 jdk-9+115
 61a214186dae6811dd989e9165e42f7dbf02acde jdk-9+116
 88170d3642905b9e6cac03e8efcc976885a7e6da jdk-9+117
+9b1075cac08dc836ec32e7b368415cbe3aceaf8c jdk-9+118
--- a/hotspot/src/share/vm/prims/jvm.cpp	Wed Jul 05 21:41:02 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Jul 05 21:42:16 2017 +0200
@@ -3387,14 +3387,14 @@
   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);
     }
   }
--- a/hotspot/test/Makefile	Wed Jul 05 21:41:02 2017 +0200
+++ b/hotspot/test/Makefile	Wed Jul 05 21:42:16 2017 +0200
@@ -120,24 +120,33 @@
 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.)
--- a/jaxp/.hgtags	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/.hgtags	Wed Jul 05 21:42:16 2017 +0200
@@ -360,3 +360,4 @@
 1902a5bda18e794b31fc5f520f5e7d827714b50d jdk-9+115
 9d71d20e614777cd23c1a43b38b5c08a9094d27a jdk-9+116
 46b57560cd06ebcdd21489250628ff5f9d9d8916 jdk-9+117
+a8aa25fc6c5fda0ed7a93b8ffee62da326a752fc jdk-9+118
--- a/jaxp/THIRD_PARTY_README	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/THIRD_PARTY_README	Wed Jul 05 21:42:16 2017 +0200
@@ -3387,7 +3387,6 @@
   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 
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java	Wed Jul 05 21:42:16 2017 +0200
@@ -4,64 +4,29 @@
  */
 package com.sun.org.apache.bcel.internal.util;
 
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 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.
+/*
+ * 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
  *
- * 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.
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * 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.
- * ====================================================================
+ *  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.
  *
- * 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 @@
     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);
 
-        InstructionHandle[] match = getMatch(startExpr, lenExpr);
+    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);
 
-        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();
   }
 
   /**
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/CharacterArrayCharacterIterator.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/CharacterIterator.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RE.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RECompiler.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-        }
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REDebugCompiler.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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("");
-        }
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REProgram.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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;
-                }
-            }
-        }
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RESyntaxException.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/RETest.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-        }
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/REUtil.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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);
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/ReaderCharacterIterator.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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());
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/StreamCharacterIterator.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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());
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/StringCharacterIterator.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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());
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/regexp/internal/recompile.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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());
-            }
-        }
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -1346,6 +1346,15 @@
     }
 
     /**
+     * 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 @@
             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 @@
             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;
             }
--- a/jaxp/src/java.xml/share/classes/module-info.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/module-info.java	Wed Jul 05 21:42:16 2017 +0200
@@ -86,5 +86,6 @@
     uses javax.xml.transform.TransformerFactory;
     uses javax.xml.validation.SchemaFactory;
     uses javax.xml.xpath.XPathFactory;
+    uses org.xml.sax.XMLReader;
 }
 
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/AttributeList.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/AttributeList.java	Wed Jul 05 21:42:16 2017 +0200
@@ -93,6 +93,7 @@
  * @see org.xml.sax.DocumentHandler#startElement startElement
  * @see org.xml.sax.helpers.AttributeListImpl AttributeListImpl
  */
+@Deprecated(since="5")
 public interface AttributeList {
 
 
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/DocumentHandler.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/DocumentHandler.java	Wed Jul 05 21:42:16 2017 +0200
@@ -68,6 +68,7 @@
  * @see org.xml.sax.Locator
  * @see org.xml.sax.HandlerBase
  */
+@Deprecated(since="5")
 public interface DocumentHandler {
 
 
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/Parser.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/Parser.java	Wed Jul 05 21:42:16 2017 +0200
@@ -73,6 +73,7 @@
  * @see org.xml.sax.HandlerBase
  * @see org.xml.sax.InputSource
  */
+@Deprecated(since="5")
 public interface Parser
 {
 
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/NewInstance.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/NewInstance.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
  * @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());
     }
 
 }
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/ParserFactory.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/ParserFactory.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
  * @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 @@
      * @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 @@
      * @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);
     }
 
 }
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/SecuritySupport.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/SecuritySupport.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
  */
 class SecuritySupport  {
 
+    /**
+     * 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();
+            }
 
-    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;
-            }
+            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())));
     }
 
 }
--- a/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/XMLReaderFactory.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/org/xml/sax/helpers/XMLReaderFactory.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 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;
-import org.xml.sax.SAXException;
 
 
 /**
@@ -70,7 +77,11 @@
  * @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 @@
     }
 
     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>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>
-     *
-     * <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>
+     * 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>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>
+     * @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.
      *
-     * <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 @@
         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 @@
         }
         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. Distro-specific fallback
+        if (className == null) {
+            return new com.sun.org.apache.xerces.internal.parsers.SAXParser();
+        }
 
-        // 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?");
-        }
+        return loadClass (cl, className);
     }
 
 
@@ -217,14 +188,14 @@
     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 @@
                                    " 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);
+
+          }
+      }
+
 }
--- a/jaxp/test/Makefile	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/test/Makefile	Wed Jul 05 21:42:16 2017 +0200
@@ -76,14 +76,20 @@
 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
--- a/jaxp/test/ProblemList.txt	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/test/ProblemList.txt	Wed Jul 05 21:42:16 2017 +0200
@@ -29,3 +29,5 @@
 # 8150145
 javax/xml/jaxp/unittest/common/TransformationWarningsTest.java	generic-all
 
+# 8156508
+javax/xml/jaxp/unittest/stream/FactoryFindTest.java             generic-all
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -38,7 +38,7 @@
  * @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 @@
  *          javax.xml.transform.TransformerFactory
  *          javax.xml.validation.SchemaFactory
  *          javax.xml.xpath.XPathFactory
+ *          org.xml.sax.XMLReader
  */
 
 @Test
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -50,7 +50,7 @@
  * @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 @@
      * 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/XMLReaderFactoryTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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);
+        }
+    }
+}
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java	Wed Jul 05 21:42:16 2017 +0200
@@ -31,6 +31,8 @@
 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 @@
         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
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java	Wed Jul 05 21:42:16 2017 +0200
@@ -30,6 +30,8 @@
 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 @@
      */
     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 @@
             "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"};
 
 }
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java	Wed Jul 05 21:42:16 2017 +0200
@@ -26,4 +26,5 @@
 
     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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLReaderImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/legacy/META-INF/services/org.xml.sax.driver	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,1 @@
+xp3.XMLReaderImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/service/META-INF/services/org.xml.sax.XMLReader	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,1 @@
+xp3.XMLReaderImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider3/xp3/XMLReaderImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/SurrogatesTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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"},
+        };
+    }
+}
--- a/jaxws/.hgtags	Wed Jul 05 21:41:02 2017 +0200
+++ b/jaxws/.hgtags	Wed Jul 05 21:42:16 2017 +0200
@@ -363,3 +363,4 @@
 4ff86e5489e4c0513dadfa69def8601c110ca5cd jdk-9+115
 529f0bf896e58525614d863e283ad155531941cb jdk-9+116
 58265b39fc74b932bda4d4f4649c530a89f55c4e jdk-9+117
+6ba73d04589ccc0705a5d8ae5111b63632b6ad20 jdk-9+118
--- a/jdk/.hgtags	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/.hgtags	Wed Jul 05 21:42:16 2017 +0200
@@ -360,3 +360,4 @@
 35225b837d66582037eeadeb471c13235dfd793d jdk-9+115
 baeb5edb38939cdb78ae0ac6f4fd368465cbf188 jdk-9+116
 4da0f73ce03aaf245b92cc040cc0ab0e3fa54dc2 jdk-9+117
+e1eba5cfa5cc8c66d524396a05323dc93568730a jdk-9+118
--- a/jdk/make/Tools.gmk	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/make/Tools.gmk	Wed Jul 05 21:42:16 2017 +0200
@@ -37,10 +37,6 @@
 
 ################################################################################
 
-# Add a checksum ("jsum") to the end of a text file. Prevents trivial tampering with class lists.
-TOOL_ADDJSUM = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
-    build.tools.addjsum.AddJsum
-
 ifeq ($(BOOT_JDK_MODULAR), true)
   COMPILEFONTCONFIG_ADD_EXPORTS := -XaddExports:java.desktop/sun.awt=ALL-UNNAMED
 endif
--- a/jdk/make/launcher/Launcher-java.base.gmk	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/make/launcher/Launcher-java.base.gmk	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,11 @@
 
 include LauncherCommon.gmk
 
-JAVA_RC_FLAGS += -i $(JDK_TOPDIR)/src/java.base/windows/native/common
+JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/java.base/windows/native/common
 ifdef OPENJDK
-  JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons"
+  JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons
 else
-  JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons"
+  JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons
 endif
 
 ################################################################################
--- a/jdk/make/lib/Awt2dLibraries.gmk	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/make/lib/Awt2dLibraries.gmk	Wed Jul 05 21:42:16 2017 +0200
@@ -224,9 +224,9 @@
   endif
 
   ifdef OPENJDK
-    LIBAWT_RC_FLAGS := -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons"
+    LIBAWT_RC_FLAGS := -I $(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons
   else
-    LIBAWT_RC_FLAGS := -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons"
+    LIBAWT_RC_FLAGS := -I $(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons
   endif
   LIBAWT_VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/java.desktop/windows/native/libawt/windows/awt.rc
 endif
--- a/jdk/make/mapfiles/libj2ucrypto/mapfile-vers	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/make/mapfiles/libj2ucrypto/mapfile-vers	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -30,28 +30,35 @@
                 JNI_OnLoad;
                 Java_com_oracle_security_ucrypto_UcryptoProvider_loadLibraries;
                 Java_com_oracle_security_ucrypto_UcryptoProvider_getMechList;
-		Java_com_oracle_security_ucrypto_NativeDigest_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone;
+                Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree;
+                Java_com_oracle_security_ucrypto_NativeDigest_nativeInit;
                 Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate;
                 Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest;
-                Java_com_oracle_security_ucrypto_NativeDigest_nativeClone;
                 Java_com_oracle_security_ucrypto_NativeDigest_nativeFree;
-		Java_com_oracle_security_ucrypto_NativeCipher_nativeInit;
-		Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
-		Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
+                Java_com_oracle_security_ucrypto_NativeCipher_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
+                Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
                 Java_com_oracle_security_ucrypto_NativeKey_nativeFree;
                 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit;
                 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
                 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
-		Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
-		Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
-
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
+                Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
+                Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone;
+                JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest;
-                JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone;
                 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree;
                 JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
@@ -60,10 +67,10 @@
                 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
                 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
-		JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
+                JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
                 JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
 
 	local:
--- a/jdk/make/mapfiles/libjava/mapfile-vers	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Wed Jul 05 21:42:16 2017 +0200
@@ -262,7 +262,7 @@
 		Java_jdk_internal_reflect_Reflection_getCallerClass__;
 		Java_jdk_internal_reflect_Reflection_getCallerClass__I;
 		Java_jdk_internal_reflect_Reflection_getClassAccessFlags;
-		Java_jdk_internal_misc_VM_latestUserDefinedLoader;
+		Java_jdk_internal_misc_VM_latestUserDefinedLoader0;
                 Java_jdk_internal_misc_VM_getuid;
                 Java_jdk_internal_misc_VM_geteuid;
                 Java_jdk_internal_misc_VM_getgid;
--- a/jdk/make/non-build-utils/src/build/tools/makeclasslist/makeClasslist.js	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +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.
- */
-
-/**
- * This tool is used to help create the class list for class data sharing.
- *
- * The classlist is produced internally by first running a select number of
- * startup benchmarks with the -XX:DumpLoadedClassList=<file> option, then
- * running this tool in the following fashion to produce a complete classlist:
- *
- * jjs -scripting makeClasslist.js -- list1 list2 list3 > classlist.platform
- *
- * The lists should be listed in roughly smallest to largest order based on
- * application size.
- *
- * After generating the classlist it's necessary to add a checksum (using
- * AddJsum.java) before checking it into the workspace as the corresponding
- * platform-specific classlist, such as make/data/classlist/classlist.linux 
- */
-"use strict";
-var classlist = [];
-var seenClasses = {};
-
-for (var a in $ARG) {
-  var arg = $ARG[a];
-
-  var classes = readFully(arg).replace(/[\r\n]+/g, "\n").split("\n");
-
-  for (var c in classes) {
-    var clazz = classes[c];
-    if (clazz !== "" && seenClasses[clazz] === undefined) {
-      seenClasses[clazz] = clazz;
-      classlist.push(clazz);
-    }
-  }
-}
-
-for (c in classlist) {
-  print(classlist[c]);
-}
--- a/jdk/make/src/classes/build/tools/addjsum/AddJsum.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package build.tools.addjsum;
-
-import java.io.*;
-import java.util.regex.*;
-
-/** Adds a checksum ("jsum") to the end of a text file. The algorithm
-    used is known to the JVM and prevents trivial tampering with the
-    class list used for class data sharing.
-*/
-
-public class AddJsum {
-  private static final long JSUM_SEED = 0xCAFEBABEBABECAFEL;
-
-  public static void main(String[] args) throws Exception {
-    if (args.length != 2) {
-      System.err.println("Usage: java AddJsum [input file name] [output file name]");
-      System.exit(1);
-    }
-
-    try {
-      File inFile  = new File(args[0]);
-      File outFile = new File(args[1]);
-      BufferedReader reader = new BufferedReader(new FileReader(inFile));
-      BufferedWriter writer = new BufferedWriter(new FileWriter(outFile));
-      Pattern p = Pattern.compile("# [0-9A-Fa-f]*");
-      long computedJsum = JSUM_SEED;
-
-      String line = null;
-      while ((line = reader.readLine()) != null) {
-        if (line.length() > 0 && line.charAt(0) == '#') {
-          Matcher m = p.matcher(line);
-          if (!m.matches()) {
-            writer.write(line);
-            writer.newLine();
-          }
-        } else {
-          computedJsum = jsum(computedJsum, line);
-          writer.write(line);
-          writer.newLine();
-        }
-      }
-      String hex = Long.toHexString(computedJsum);
-      int diff = 16 - hex.length();
-      for (int i = 0; i < diff; i++) {
-        hex = "0" + hex;
-      }
-      writer.write("# " + hex);
-      writer.newLine();
-      reader.close();
-      writer.close();
-    } catch (IOException e) {
-      System.err.println("Error reading or writing file");
-      throw(e);
-    }
-  }
-
-  private static long jsum(long start, String str) {
-    long h = start;
-    int len = str.length();
-    for (int i = 0; i < len; i++) {
-      char c = str.charAt(i);
-      if (c <= ' ') {
-        /* Skip spaces and control characters */
-        continue;
-      }
-      h = 31 * h + c;
-    }
-    return h;
-  }
-}
--- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java	Wed Jul 05 21:42:16 2017 +0200
@@ -603,12 +603,12 @@
      *     Class.forName(desc.getName(), false, loader)
      * </pre>
      * where <code>loader</code> is determined as follows: if there is a
-     * method on the current thread's stack whose declaring class was
-     * defined by a user-defined class loader (and was not a generated to
-     * implement reflective invocations), then <code>loader</code> is class
-     * loader corresponding to the closest such method to the currently
-     * executing frame; otherwise, <code>loader</code> is
-     * <code>null</code>. If this call results in a
+     * method on the current thread's stack whose declaring class is not a
+     * <a href="../lang/ClassLoader.html#builtinLoaders">
+     * <em>platform class</em></a>, then <code>loader</code> is
+     * the class loader of such class; otherwise, <code>loader</code>
+     * is the {@linkplain ClassLoader#getPlatformClassLoader()
+     * platform class loader}.  If this call results in a
      * <code>ClassNotFoundException</code> and the name of the passed
      * <code>ObjectStreamClass</code> instance is the Java language keyword
      * for a primitive type or void, then the <code>Class</code> object
@@ -666,12 +666,15 @@
      * <pre>
      *     Class.forName(i, false, loader)
      * </pre>
-     * where <code>loader</code> is that of the first non-<code>null</code>
-     * class loader up the execution stack, or <code>null</code> if no
-     * non-<code>null</code> class loaders are on the stack (the same class
-     * loader choice used by the <code>resolveClass</code> method).  Unless any
-     * of the resolved interfaces are non-public, this same value of
-     * <code>loader</code> is also the class loader passed to
+     * where <code>loader</code> is determined as follows: if there is a
+     * method on the current thread's stack whose declaring class is not a
+     * <a href="../lang/ClassLoader.html#builtinLoaders">
+     * <em>platform class</em></a>, then <code>loader</code> is
+     * the class loader of such class; otherwise, <code>loader</code>
+     * is the {@linkplain ClassLoader#getPlatformClassLoader()
+     * platform class loader}.
+     * Unless any of the resolved interfaces are non-public, this same value
+     * of <code>loader</code> is also the class loader passed to
      * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
      * their class loader is passed instead (if more than one non-public
      * interface class loader is encountered, an
@@ -2154,10 +2157,11 @@
                                               int ndoubles);
 
     /**
-     * Returns the first non-null class loader (not counting class loaders of
-     * generated reflection implementation classes) up the execution stack, or
-     * null if only code from the null class loader is on the stack.  This
-     * method is also called via reflection by the following RMI-IIOP class:
+     * Returns the first non-null and non-platform class loader
+     * (not counting class loaders of generated reflection implementation classes)
+     * up the execution stack, or null if only code from the bootstrap and
+     * platform class loader is on the stack.
+     * This method is also called via reflection by the following RMI-IIOP class:
      *
      *     com.sun.corba.se.internal.util.JDKClassLoader
      *
--- a/jdk/src/java.base/share/classes/java/lang/Integer.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/Integer.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1221,13 +1221,13 @@
     }
 
     /**
-     * Returns a hash code for a {@code int} value; compatible with
+     * Returns a hash code for an {@code int} value; compatible with
      * {@code Integer.hashCode()}.
      *
      * @param value the value to hash
      * @since 1.8
      *
-     * @return a hash code value for a {@code int} value.
+     * @return a hash code value for an {@code int} value.
      */
     public static int hashCode(int value) {
         return value;
@@ -1596,7 +1596,7 @@
     @Native public static final int SIZE = 32;
 
     /**
-     * The number of bytes used to represent a {@code int} value in two's
+     * The number of bytes used to represent an {@code int} value in two's
      * complement binary form.
      *
      * @since 1.8
@@ -1790,9 +1790,8 @@
         i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
         i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
         i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
-        i = (i << 24) | ((i & 0xff00) << 8) |
-            ((i >>> 8) & 0xff00) | (i >>> 24);
-        return i;
+
+        return reverseBytes(i);
     }
 
     /**
@@ -1820,10 +1819,10 @@
      */
     @HotSpotIntrinsicCandidate
     public static int reverseBytes(int i) {
-        return ((i >>> 24)           ) |
-               ((i >>   8) &   0xFF00) |
-               ((i <<   8) & 0xFF0000) |
-               ((i << 24));
+        return (i << 24)            |
+               ((i & 0xff00) << 8)  |
+               ((i >>> 8) & 0xff00) |
+               (i >>> 24);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/lang/Long.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/Long.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1952,10 +1952,8 @@
         i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L;
         i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L;
         i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL;
-        i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL;
-        i = (i << 48) | ((i & 0xffff0000L) << 16) |
-            ((i >>> 16) & 0xffff0000L) | (i >>> 48);
-        return i;
+
+        return reverseBytes(i);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1627,8 +1627,7 @@
      * @deprecated This method relies on the caller being at a stack depth
      *             of 4 which is error-prone and cannot be enforced by the runtime.
      *             Users of this method should instead invoke {@link #checkPermission}
-     *             directly.  This method will be changed in a future release
-     *             to check the permission {@code java.security.AllPermission}.
+     *             directly.
      *             This method is subject to removal in a future version of Java SE.
      *
      * @see java.lang.reflect.Member
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	Wed Jul 05 21:42:16 2017 +0200
@@ -318,7 +318,7 @@
         /**
          * Tests this module export for equality with the given object.
          *
-         * <p> If the given object is not a {@code Exports} then this method
+         * <p> If the given object is not an {@code Exports} then this method
          * returns {@code false}. Two module exports objects are equal if the
          * package names are equal and the set of target module names is equal.
          * </p>
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Field.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Field.java	Wed Jul 05 21:42:16 2017 +0200
@@ -903,7 +903,7 @@
      * Sets the value of a field as an {@code int} on the specified object.
      * This method is equivalent to
      * {@code set(obj, iObj)},
-     * where {@code iObj} is a {@code Integer} object and
+     * where {@code iObj} is an {@code Integer} object and
      * {@code iObj.intValue() == i}.
      *
      * @param obj the object whose field should be modified
--- a/jdk/src/java.base/share/classes/java/lang/reflect/InaccessibleObjectException.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/InaccessibleObjectException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -36,13 +36,13 @@
     private static final long serialVersionUID = 4158786093378140901L;
 
     /**
-     * Constructs a {@code InaccessibleObjectException} with no detail message.
+     * Constructs an {@code InaccessibleObjectException} with no detail message.
      */
     public InaccessibleObjectException() {
     }
 
     /**
-     * Constructs a {@code InaccessibleObjectException} with the given detail
+     * Constructs an {@code InaccessibleObjectException} with the given detail
      * message.
      *
      * @param msg
--- a/jdk/src/java.base/share/classes/java/math/BigInteger.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java	Wed Jul 05 21:42:16 2017 +0200
@@ -4676,7 +4676,7 @@
      *
      * @return this {@code BigInteger} converted to an {@code int}.
      * @throws ArithmeticException if the value of {@code this} will
-     * not exactly fit in a {@code int}.
+     * not exactly fit in an {@code int}.
      * @see BigInteger#intValue
      * @since  1.8
      */
--- a/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java	Wed Jul 05 21:42:16 2017 +0200
@@ -246,7 +246,7 @@
      *                  the range of valid port values, or if the hostname
      *                  parameter is {@code null}.
      * @see     #isUnresolved()
-     * @return  a {@code InetSocketAddress} representing the unresolved
+     * @return  an {@code InetSocketAddress} representing the unresolved
      *          socket address
      * @since 1.5
      */
--- a/jdk/src/java.base/share/classes/java/net/URLDecoder.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/net/URLDecoder.java	Wed Jul 05 21:42:16 2017 +0200
@@ -106,8 +106,8 @@
     }
 
     /**
-     * Decodes a {@code application/x-www-form-urlencoded} string using a specific
-     * encoding scheme.
+     * Decodes an {@code application/x-www-form-urlencoded} string using
+     * a specific encoding scheme.
      * The supplied encoding is used to determine
      * what characters are represented by any consecutive sequences of the
      * form "<i>{@code %xy}</i>".
--- a/jdk/src/java.base/share/classes/java/net/URLEncoder.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/net/URLEncoder.java	Wed Jul 05 21:42:16 2017 +0200
@@ -225,7 +225,7 @@
                     /*
                      * If this character represents the start of a Unicode
                      * surrogate pair, then pass in two characters. It's not
-                     * clear what should be done if a bytes reserved in the
+                     * clear what should be done if a byte reserved in the
                      * surrogate pairs range occurs outside of a legal
                      * surrogate pair. For now, just treat it as if it were
                      * any other character.
--- a/jdk/src/java.base/share/classes/java/security/DrbgParameters.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/DrbgParameters.java	Wed Jul 05 21:42:16 2017 +0200
@@ -196,10 +196,9 @@
  * of the JDK reference implementation.
  * <p>
  * This implementation supports the Hash_DRBG and HMAC_DRBG mechanisms with
- * DRBG algorithm SHA-1, SHA-224, SHA-512/224, SHA-256, SHA-512/256,
- * SHA-384 and SHA-512, and CTR_DRBG (both using derivation function and
- * not using derivation function) with DRBG algorithm 3KeyTDEA
- * (also known as DESede in JCE), AES-128, AES-192 and AES-256.
+ * DRBG algorithm SHA-224, SHA-512/224, SHA-256, SHA-512/256, SHA-384 and
+ * SHA-512, and CTR_DRBG (both using derivation function and not using
+ * derivation function) with DRBG algorithm AES-128, AES-192 and AES-256.
  * <p>
  * The mechanism name and DRBG algorithm name are determined by the
  * {@linkplain Security#getProperty(String) security property}
--- a/jdk/src/java.base/share/classes/java/security/InvalidAlgorithmParameterException.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/InvalidAlgorithmParameterException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -65,7 +65,7 @@
     }
 
     /**
-     * Creates a {@code InvalidAlgorithmParameterException} with the
+     * Creates an {@code InvalidAlgorithmParameterException} with the
      * specified detail message and cause.
      *
      * @param message the detail message (which is saved for later retrieval
@@ -80,7 +80,7 @@
     }
 
     /**
-     * Creates a {@code InvalidAlgorithmParameterException} with the
+     * Creates an {@code InvalidAlgorithmParameterException} with the
      * specified cause and a detail message of
      * {@code (cause==null ? null : cause.toString())}
      * (which typically contains the class and detail message of
--- a/jdk/src/java.base/share/classes/java/security/InvalidKeyException.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/InvalidKeyException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -58,7 +58,7 @@
     }
 
     /**
-     * Creates a {@code InvalidKeyException} with the specified
+     * Creates an {@code InvalidKeyException} with the specified
      * detail message and cause.
      *
      * @param message the detail message (which is saved for later retrieval
@@ -73,7 +73,7 @@
     }
 
     /**
-     * Creates a {@code InvalidKeyException} with the specified cause
+     * Creates an {@code InvalidKeyException} with the specified cause
      * and a detail message of {@code (cause==null ? null : cause.toString())}
      * (which typically contains the class and detail message of
      * {@code cause}).
--- a/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java	Wed Jul 05 21:42:16 2017 +0200
@@ -139,12 +139,10 @@
      */
     final Key key = new Key();
 
-    private static final Debug debug = Debug.getInstance("domain");
-
     /**
      * Creates a new ProtectionDomain with the given CodeSource and
      * Permissions. If the permissions object is not null, then
-     *  {@code setReadOnly())} will be called on the passed in
+     *  {@code setReadOnly()} will be called on the passed in
      * Permissions object. The only permissions granted to this domain
      * are the ones specified; the current Policy will not be consulted.
      *
@@ -338,6 +336,13 @@
             " "+pc+"\n";
     }
 
+    /*
+     * holder class for the static field "debug" to delay its initialization
+     */
+    private static class DebugHolder {
+        private static final Debug debug = Debug.getInstance("domain");
+    }
+
     /**
      * Return true (merge policy permissions) in the following cases:
      *
@@ -359,7 +364,7 @@
         if (sm == null) {
             return true;
         } else {
-            if (debug != null) {
+            if (DebugHolder.debug != null) {
                 if (sm.getClass().getClassLoader() == null &&
                     Policy.getPolicyNoCheck().getClass().getClassLoader()
                                                                 == null) {
--- a/jdk/src/java.base/share/classes/java/security/Provider.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/Provider.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1809,7 +1809,7 @@
         }
 
         /**
-         * Return whether this service has its Supported* properties for
+         * Return whether this service has its supported properties for
          * keys defined. Parses the attributes if not yet initialized.
          */
         private boolean hasKeyAttributes() {
--- a/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java	Wed Jul 05 21:42:16 2017 +0200
@@ -62,8 +62,6 @@
     private final Map<CodeSourceKey, ProtectionDomain> pdcache
             = new ConcurrentHashMap<>(11);
 
-    private static final Debug debug = Debug.getInstance("scl");
-
     static {
         ClassLoader.registerAsParallelCapable();
     }
@@ -203,6 +201,13 @@
     }
 
     /*
+     * holder class for the static field "debug" to delay its initialization
+     */
+    private static class DebugHolder {
+        private static final Debug debug = Debug.getInstance("scl");
+    }
+
+    /*
      * Returned cached ProtectionDomain for the specified CodeSource.
      */
     private ProtectionDomain getProtectionDomain(CodeSource cs) {
@@ -222,9 +227,9 @@
                         = SecureClassLoader.this.getPermissions(cs);
                 ProtectionDomain pd = new ProtectionDomain(
                         cs, perms, SecureClassLoader.this, null);
-                if (debug != null) {
-                    debug.println(" getPermissions " + pd);
-                    debug.println("");
+                if (DebugHolder.debug != null) {
+                    DebugHolder.debug.println(" getPermissions " + pd);
+                    DebugHolder.debug.println("");
                 }
                 return pd;
             }
--- a/jdk/src/java.base/share/classes/java/security/Security.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/Security.java	Wed Jul 05 21:42:16 2017 +0200
@@ -549,7 +549,7 @@
 
     /**
      * Returns an array containing all installed providers that satisfy the
-     * specified* selection criteria, or null if no such providers have been
+     * specified selection criteria, or null if no such providers have been
      * installed. The returned providers are ordered
      * according to their
      * {@linkplain #insertProviderAt(java.security.Provider, int)
--- a/jdk/src/java.base/share/classes/java/security/spec/InvalidKeySpecException.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/spec/InvalidKeySpecException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -63,7 +63,7 @@
     }
 
     /**
-     * Creates a {@code InvalidKeySpecException} with the specified
+     * Creates an {@code InvalidKeySpecException} with the specified
      * detail message and cause.
      *
      * @param message the detail message (which is saved for later retrieval
@@ -78,7 +78,7 @@
     }
 
     /**
-     * Creates a {@code InvalidKeySpecException} with the specified cause
+     * Creates an {@code InvalidKeySpecException} with the specified cause
      * and a detail message of {@code (cause==null ? null : cause.toString())}
      * (which typically contains the class and detail message of
      * {@code cause}).
--- a/jdk/src/java.base/share/classes/java/text/MessageFormat.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/text/MessageFormat.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1068,7 +1068,7 @@
      *            index information as described above.
      * @return An <code>Object</code> array parsed from the string. In case of
      *         error, returns null.
-     * @throws NullPointerException if {@code source} or {@code pos} is null.
+     * @throws NullPointerException if {@code pos} is null.
      */
     public Object parseObject(String source, ParsePosition pos) {
         return parse(source, pos);
--- a/jdk/src/java.base/share/classes/java/time/Instant.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/Instant.java	Wed Jul 05 21:42:16 2017 +0200
@@ -799,33 +799,33 @@
      * The supported fields behave as follows:
      * <ul>
      * <li>{@code NANOS} -
-     *  Returns a {@code Instant} with the specified number of nanoseconds added.
+     *  Returns an {@code Instant} with the specified number of nanoseconds added.
      *  This is equivalent to {@link #plusNanos(long)}.
      * <li>{@code MICROS} -
-     *  Returns a {@code Instant} with the specified number of microseconds added.
+     *  Returns an {@code Instant} with the specified number of microseconds added.
      *  This is equivalent to {@link #plusNanos(long)} with the amount
      *  multiplied by 1,000.
      * <li>{@code MILLIS} -
-     *  Returns a {@code Instant} with the specified number of milliseconds added.
+     *  Returns an {@code Instant} with the specified number of milliseconds added.
      *  This is equivalent to {@link #plusNanos(long)} with the amount
      *  multiplied by 1,000,000.
      * <li>{@code SECONDS} -
-     *  Returns a {@code Instant} with the specified number of seconds added.
+     *  Returns an {@code Instant} with the specified number of seconds added.
      *  This is equivalent to {@link #plusSeconds(long)}.
      * <li>{@code MINUTES} -
-     *  Returns a {@code Instant} with the specified number of minutes added.
+     *  Returns an {@code Instant} with the specified number of minutes added.
      *  This is equivalent to {@link #plusSeconds(long)} with the amount
      *  multiplied by 60.
      * <li>{@code HOURS} -
-     *  Returns a {@code Instant} with the specified number of hours added.
+     *  Returns an {@code Instant} with the specified number of hours added.
      *  This is equivalent to {@link #plusSeconds(long)} with the amount
      *  multiplied by 3,600.
      * <li>{@code HALF_DAYS} -
-     *  Returns a {@code Instant} with the specified number of half-days added.
+     *  Returns an {@code Instant} with the specified number of half-days added.
      *  This is equivalent to {@link #plusSeconds(long)} with the amount
      *  multiplied by 43,200 (12 hours).
      * <li>{@code DAYS} -
-     *  Returns a {@code Instant} with the specified number of days added.
+     *  Returns an {@code Instant} with the specified number of days added.
      *  This is equivalent to {@link #plusSeconds(long)} with the amount
      *  multiplied by 86,400 (24 hours).
      * </ul>
@@ -958,7 +958,7 @@
     /**
      * Returns a copy of this instant with the specified amount subtracted.
      * <p>
-     * This returns a {@code Instant}, based on this one, with the amount
+     * This returns an {@code Instant}, based on this one, with the amount
      * in terms of the unit subtracted. If it is not possible to subtract the amount,
      * because the unit is not supported or for some other reason, an exception is thrown.
      * <p>
--- a/jdk/src/java.base/share/classes/java/time/LocalDateTime.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/LocalDateTime.java	Wed Jul 05 21:42:16 2017 +0200
@@ -665,7 +665,7 @@
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY},
      * {@code EPOCH_DAY} and {@code PROLEPTIC_MONTH} which are too large to fit in
-     * an {@code int} and throw a {@code UnsupportedTemporalTypeException}.
+     * an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
--- a/jdk/src/java.base/share/classes/java/time/LocalTime.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/LocalTime.java	Wed Jul 05 21:42:16 2017 +0200
@@ -619,7 +619,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this time, except {@code NANO_OF_DAY} and {@code MICRO_OF_DAY}
-     * which are too large to fit in an {@code int} and throw a {@code UnsupportedTemporalTypeException}.
+     * which are too large to fit in an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
--- a/jdk/src/java.base/share/classes/java/time/OffsetDateTime.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/OffsetDateTime.java	Wed Jul 05 21:42:16 2017 +0200
@@ -576,7 +576,7 @@
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY},
      * {@code EPOCH_DAY}, {@code PROLEPTIC_MONTH} and {@code INSTANT_SECONDS} which are too
-     * large to fit in an {@code int} and throw a {@code UnsupportedTemporalTypeException}.
+     * large to fit in an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
--- a/jdk/src/java.base/share/classes/java/time/OffsetTime.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/OffsetTime.java	Wed Jul 05 21:42:16 2017 +0200
@@ -481,7 +481,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this time, except {@code NANO_OF_DAY} and {@code MICRO_OF_DAY}
-     * which are too large to fit in an {@code int} and throw a {@code UnsupportedTemporalTypeException}.
+     * which are too large to fit in an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
--- a/jdk/src/java.base/share/classes/java/time/ZonedDateTime.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/ZonedDateTime.java	Wed Jul 05 21:42:16 2017 +0200
@@ -793,7 +793,7 @@
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY},
      * {@code EPOCH_DAY}, {@code PROLEPTIC_MONTH} and {@code INSTANT_SECONDS} which are too
-     * large to fit in an {@code int} and throw a {@code UnsupportedTemporalTypeException}.
+     * large to fit in an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -308,6 +308,7 @@
  *   N       nano-of-day                 number            1234000000
  *
  *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
+ *   v       generic time-zone name      zone-name         Pacific Time; PT
  *   z       time-zone name              zone-name         Pacific Standard Time; PST
  *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00
  *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
@@ -365,9 +366,17 @@
  * letters throws {@code IllegalArgumentException}.
  * <p>
  * <b>Zone names</b>: This outputs the display name of the time-zone ID. If the
- * count of letters is one, two or three, then the short name is output. If the
- * count of letters is four, then the full name is output. Five or more letters
- * throws {@code IllegalArgumentException}.
+ * pattern letter is 'z' the output is the daylight savings aware zone name.
+ * If there is insufficient information to determine whether DST applies,
+ * the name ignoring daylight savings time will be used.
+ * If the count of letters is one, two or three, then the short name is output.
+ * If the count of letters is four, then the full name is output.
+ * Five or more letters throws {@code IllegalArgumentException}.
+ * <p>
+ * If the pattern letter is 'v' the output provides the zone name ignoring
+ * daylight savings time. If the count of letters is one, then the short name is output.
+ * If the count of letters is four, then the full name is output.
+ * Two, three and five or more letters throw {@code IllegalArgumentException}.
  * <p>
  * <b>Offset X and x</b>: This formats the offset based on the number of pattern
  * letters. One letter outputs just the hour, such as '+01', unless the minute
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Wed Jul 05 21:42:16 2017 +0200
@@ -81,9 +81,11 @@
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.ChronoLocalDateTime;
 import java.time.chrono.Chronology;
 import java.time.chrono.Era;
 import java.time.chrono.IsoChronology;
@@ -1157,10 +1159,11 @@
      * result of {@link ZoneOffset#getId()}.
      * If the zone is not an offset, the textual name will be looked up
      * for the locale set in the {@link DateTimeFormatter}.
-     * If the temporal object being printed represents an instant, then the text
-     * will be the summer or winter time text as appropriate.
+     * If the temporal object being printed represents an instant, or if it is a
+     * local date-time that is not in a daylight saving gap or overlap then
+     * the text will be the summer or winter time text as appropriate.
      * If the lookup for text does not find any suitable result, then the
-     * {@link ZoneId#getId() ID} will be printed instead.
+     * {@link ZoneId#getId() ID} will be printed.
      * If the zone cannot be obtained then an exception is thrown unless the
      * section of the formatter is optional.
      * <p>
@@ -1177,7 +1180,7 @@
      * @return this, for chaining, not null
      */
     public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle) {
-        appendInternal(new ZoneTextPrinterParser(textStyle, null));
+        appendInternal(new ZoneTextPrinterParser(textStyle, null, false));
         return this;
     }
 
@@ -1193,10 +1196,11 @@
      * result of {@link ZoneOffset#getId()}.
      * If the zone is not an offset, the textual name will be looked up
      * for the locale set in the {@link DateTimeFormatter}.
-     * If the temporal object being printed represents an instant, then the text
+     * If the temporal object being printed represents an instant, or if it is a
+     * local date-time that is not in a daylight saving gap or overlap, then the text
      * will be the summer or winter time text as appropriate.
      * If the lookup for text does not find any suitable result, then the
-     * {@link ZoneId#getId() ID} will be printed instead.
+     * {@link ZoneId#getId() ID} will be printed.
      * If the zone cannot be obtained then an exception is thrown unless the
      * section of the formatter is optional.
      * <p>
@@ -1220,7 +1224,70 @@
     public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle,
                                                    Set<ZoneId> preferredZones) {
         Objects.requireNonNull(preferredZones, "preferredZones");
-        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones));
+        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones, false));
+        return this;
+    }
+    //----------------------------------------------------------------------
+    /**
+     * Appends the generic time-zone name, such as 'Pacific Time', to the formatter.
+     * <p>
+     * This appends an instruction to format/parse the generic textual
+     * name of the zone to the builder. The generic name is the same throughout the whole
+     * year, ignoring any daylight saving changes. For example, 'Pacific Time' is the
+     * generic name, whereas 'Pacific Standard Time' and 'Pacific Daylight Time' are the
+     * specific names, see {@link #appendZoneText(TextStyle)}.
+     * <p>
+     * During formatting, the zone is obtained using a mechanism equivalent
+     * to querying the temporal with {@link TemporalQueries#zoneId()}.
+     * If the zone is a {@code ZoneOffset} it will be printed using the
+     * result of {@link ZoneOffset#getId()}.
+     * If the zone is not an offset, the textual name will be looked up
+     * for the locale set in the {@link DateTimeFormatter}.
+     * If the lookup for text does not find any suitable result, then the
+     * {@link ZoneId#getId() ID} will be printed.
+     * If the zone cannot be obtained then an exception is thrown unless the
+     * section of the formatter is optional.
+     * <p>
+     * During parsing, either the textual zone name, the zone ID or the offset
+     * is accepted. Many textual zone names are not unique, such as CST can be
+     * for both "Central Standard Time" and "China Standard Time". In this
+     * situation, the zone id will be determined by the region information from
+     * formatter's  {@link DateTimeFormatter#getLocale() locale} and the standard
+     * zone id for that area, for example, America/New_York for the America Eastern zone.
+     * The {@link #appendGenericZoneText(TextStyle, Set)} may be used
+     * to specify a set of preferred {@link ZoneId} in this situation.
+     *
+     * @param textStyle  the text style to use, not null
+     * @return this, for chaining, not null
+     */
+    public DateTimeFormatterBuilder appendGenericZoneText(TextStyle textStyle) {
+        appendInternal(new ZoneTextPrinterParser(textStyle, null, true));
+        return this;
+    }
+
+    /**
+     * Appends the generic time-zone name, such as 'Pacific Time', to the formatter.
+     * <p>
+     * This appends an instruction to format/parse the generic textual
+     * name of the zone to the builder. The generic name is the same throughout the whole
+     * year, ignoring any daylight saving changes. For example, 'Pacific Time' is the
+     * generic name, whereas 'Pacific Standard Time' and 'Pacific Daylight Time' are the
+     * specific names, see {@link #appendZoneText(TextStyle)}.
+     * <p>
+     * This method also allows a set of preferred {@link ZoneId} to be
+     * specified for parsing. The matched preferred zone id will be used if the
+     * textural zone name being parsed is not unique.
+     * <p>
+     * See {@link #appendGenericZoneText(TextStyle)} for details about
+     * formatting and parsing.
+     *
+     * @param textStyle  the text style to use, not null
+     * @param preferredZones  the set of preferred zone ids, not null
+     * @return this, for chaining, not null
+     */
+    public DateTimeFormatterBuilder appendGenericZoneText(TextStyle textStyle,
+                                                          Set<ZoneId> preferredZones) {
+        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones, true));
         return this;
     }
 
@@ -1416,6 +1483,7 @@
      *   N       nano-of-day                 number            1234000000
      *
      *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
+     *   v       generic time-zone name      zone-name         PT, Pacific Time
      *   z       time-zone name              zone-name         Pacific Standard Time; PST
      *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
      *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
@@ -1537,6 +1605,8 @@
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
      *    VV      2      appendZoneId()
+     *    v       1      appendGenericZoneText(TextStyle.SHORT)
+     *    vvvv    4      appendGenericZoneText(TextStyle.FULL)
      *    z       1      appendZoneText(TextStyle.SHORT)
      *    zz      2      appendZoneText(TextStyle.SHORT)
      *    zzz     3      appendZoneText(TextStyle.SHORT)
@@ -1643,6 +1713,14 @@
                         throw new IllegalArgumentException("Pattern letter count must be 2: " + cur);
                     }
                     appendZoneId();
+                } else if (cur == 'v') {
+                    if (count == 1) {
+                        appendGenericZoneText(TextStyle.SHORT);
+                    } else if (count == 4) {
+                        appendGenericZoneText(TextStyle.FULL);
+                    } else {
+                        throw new IllegalArgumentException("Wrong number of  pattern letters: " + cur);
+                    }
                 } else if (cur == 'Z') {
                     if (count < 4) {
                         appendOffset("+HHMM", "+0000");
@@ -1894,6 +1972,8 @@
         // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4
         // 310 - Z - matches SimpleDateFormat and LDML
         // 310 - V - time-zone id, matches LDML
+        // 310 - v - general timezone names, not matching exactly with LDML because LDML specify to fall back
+        //           to 'VVVV' if general-nonlocation unavailable but here it's not falling back because of lack of data
         // 310 - p - prefix for padding
         // 310 - X - matches LDML, almost matches SDF for 1, exact match 2&3, extended 4&5
         // 310 - x - matches LDML
@@ -1901,7 +1981,6 @@
         // LDML - U - cycle year name, not supported by 310 yet
         // LDML - l - deprecated
         // LDML - j - not relevant
-        // LDML - v,V - extended time-zone names
     }
 
     //-----------------------------------------------------------------------
@@ -3723,9 +3802,12 @@
         /** The preferred zoneid map */
         private Set<String> preferredZones;
 
-        ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones) {
+        /**  Display in generic time-zone format. True in case of pattern letter 'v' */
+        private final boolean isGeneric;
+        ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones, boolean isGeneric) {
             super(TemporalQueries.zone(), "ZoneText(" + textStyle + ")");
             this.textStyle = Objects.requireNonNull(textStyle, "textStyle");
+            this.isGeneric = isGeneric;
             if (preferredZones != null && preferredZones.size() != 0) {
                 this.preferredZones = new HashSet<>();
                 for (ZoneId id : preferredZones) {
@@ -3788,11 +3870,21 @@
             String zname = zone.getId();
             if (!(zone instanceof ZoneOffset)) {
                 TemporalAccessor dt = context.getTemporal();
-                String name = getDisplayName(zname,
-                                             dt.isSupported(ChronoField.INSTANT_SECONDS)
-                                             ? (zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD)
-                                             : GENERIC,
-                                             context.getLocale());
+                int type = GENERIC;
+                if (!isGeneric) {
+                    if (dt.isSupported(ChronoField.INSTANT_SECONDS)) {
+                        type = zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD;
+                    } else if (dt.isSupported(ChronoField.EPOCH_DAY) &&
+                               dt.isSupported(ChronoField.NANO_OF_DAY)) {
+                        LocalDate date = LocalDate.ofEpochDay(dt.getLong(ChronoField.EPOCH_DAY));
+                        LocalTime time = LocalTime.ofNanoOfDay(dt.getLong(ChronoField.NANO_OF_DAY));
+                        LocalDateTime ldt = date.atTime(time);
+                        if (zone.getRules().getTransition(ldt) == null) {
+                            type = zone.getRules().isDaylightSavings(ldt.atZone(zone).toInstant()) ? DST : STD;
+                        }
+                    }
+                }
+                String name = getDisplayName(zname, type, context.getLocale());
                 if (name != null) {
                     zname = name;
                 }
--- a/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -402,6 +402,12 @@
                 long moy = temporal.getLong(MONTH_OF_YEAR);
                 return ((moy + 2) / 3);
             }
+            public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
+                if (isSupportedBy(temporal) == false) {
+                    throw new UnsupportedTemporalTypeException("Unsupported field: QuarterOfYear");
+                }
+                return super.rangeRefinedBy(temporal);
+            }
             @SuppressWarnings("unchecked")
             @Override
             public <R extends Temporal> R adjustInto(R temporal, long newValue) {
@@ -529,6 +535,12 @@
                 }
                 return getWeekBasedYear(LocalDate.from(temporal));
             }
+            public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
+                if (isSupportedBy(temporal) == false) {
+                    throw new UnsupportedTemporalTypeException("Unsupported field: WeekBasedYear");
+                }
+                return super.rangeRefinedBy(temporal);
+            }
             @SuppressWarnings("unchecked")
             @Override
             public <R extends Temporal> R adjustInto(R temporal, long newValue) {
--- a/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java	Wed Jul 05 21:42:16 2017 +0200
@@ -614,7 +614,7 @@
      * One technique, using this method, would be:
      * <pre>
      *  ZoneOffsetTransition trans = rules.getTransition(localDT);
-     *  if (trans == null) {
+     *  if (trans != null) {
      *    // Gap or Overlap: determine what to do from transition
      *  } else {
      *    // Normal case: only one valid offset
--- a/jdk/src/java.base/share/classes/java/util/Comparator.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/Comparator.java	Wed Jul 05 21:42:16 2017 +0200
@@ -267,7 +267,7 @@
 
     /**
      * Returns a lexicographic-order comparator with a function that
-     * extracts a {@code int} sort key.
+     * extracts an {@code int} sort key.
      *
      * @implSpec This default implementation behaves as if {@code
      *           thenComparing(comparingInt(keyExtractor))}.
--- a/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -146,12 +146,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
@@ -598,12 +612,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
@@ -1086,12 +1114,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
@@ -1574,12 +1616,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
@@ -2158,12 +2214,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
@@ -2701,12 +2771,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
+            return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
             run[++count] = right;
-        } else if (count <= 1) { // The array is already sorted
-            return;
         }
 
         // Determine alternation base for merge
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/regex/CharPredicates.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,375 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.regex;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.regex.Pattern.CharPredicate;
+import java.util.regex.Pattern.BmpCharPredicate;
+
+class CharPredicates {
+
+    static final CharPredicate ALPHABETIC  = Character::isAlphabetic;
+
+    // \p{gc=Decimal_Number}
+    static final CharPredicate DIGIT       = Character::isDigit;
+
+    static final CharPredicate LETTER      = Character::isLetter;
+
+    static final CharPredicate IDEOGRAPHIC = Character::isIdeographic;
+
+    static final CharPredicate LOWERCASE   = Character::isLowerCase;
+
+    static final CharPredicate UPPERCASE   = Character::isUpperCase;
+
+    static final CharPredicate TITLECASE   = Character::isTitleCase;
+
+    // \p{Whitespace}
+    static final CharPredicate WHITE_SPACE = ch ->
+        ((((1 << Character.SPACE_SEPARATOR) |
+           (1 << Character.LINE_SEPARATOR) |
+           (1 << Character.PARAGRAPH_SEPARATOR)) >> Character.getType(ch)) & 1)
+        != 0 || (ch >= 0x9 && ch <= 0xd) || (ch == 0x85);
+
+    // \p{gc=Control}
+    static final CharPredicate CONTROL     = ch ->
+        Character.getType(ch) == Character.CONTROL;
+
+    // \p{gc=Punctuation}
+    static final CharPredicate PUNCTUATION = ch ->
+        ((((1 << Character.CONNECTOR_PUNCTUATION) |
+           (1 << Character.DASH_PUNCTUATION) |
+           (1 << Character.START_PUNCTUATION) |
+           (1 << Character.END_PUNCTUATION) |
+           (1 << Character.OTHER_PUNCTUATION) |
+           (1 << Character.INITIAL_QUOTE_PUNCTUATION) |
+           (1 << Character.FINAL_QUOTE_PUNCTUATION)) >> Character.getType(ch)) & 1)
+        != 0;
+
+    // \p{gc=Decimal_Number}
+    // \p{Hex_Digit}    -> PropList.txt: Hex_Digit
+    static final CharPredicate HEX_DIGIT = DIGIT.union(
+        ch -> (ch >= 0x0030 && ch <= 0x0039) ||
+              (ch >= 0x0041 && ch <= 0x0046) ||
+              (ch >= 0x0061 && ch <= 0x0066) ||
+              (ch >= 0xFF10 && ch <= 0xFF19) ||
+              (ch >= 0xFF21 && ch <= 0xFF26) ||
+              (ch >= 0xFF41 && ch <= 0xFF46));
+
+    static final CharPredicate ASSIGNED = ch ->
+        Character.getType(ch) != Character.UNASSIGNED;
+
+    // PropList.txt:Noncharacter_Code_Point
+    static final CharPredicate NONCHARACTER_CODE_POINT = ch ->
+        (ch & 0xfffe) == 0xfffe || (ch >= 0xfdd0 && ch <= 0xfdef);
+
+    // \p{alpha}
+    // \p{digit}
+    static final CharPredicate ALNUM = ALPHABETIC.union(DIGIT);
+
+    // \p{Whitespace} --
+    // [\N{LF} \N{VT} \N{FF} \N{CR} \N{NEL}  -> 0xa, 0xb, 0xc, 0xd, 0x85
+    //  \p{gc=Line_Separator}
+    //  \p{gc=Paragraph_Separator}]
+    static final CharPredicate BLANK = ch ->
+        Character.getType(ch) == Character.SPACE_SEPARATOR ||
+        ch == 0x9; // \N{HT}
+
+    // [^
+    //  \p{space}
+    //  \p{gc=Control}
+    //  \p{gc=Surrogate}
+    //  \p{gc=Unassigned}]
+    static final CharPredicate GRAPH = ch ->
+        ((((1 << Character.SPACE_SEPARATOR) |
+           (1 << Character.LINE_SEPARATOR) |
+           (1 << Character.PARAGRAPH_SEPARATOR) |
+           (1 << Character.CONTROL) |
+           (1 << Character.SURROGATE) |
+           (1 << Character.UNASSIGNED)) >> Character.getType(ch)) & 1)
+        == 0;
+
+    // \p{graph}
+    // \p{blank}
+    // -- \p{cntrl}
+    static final CharPredicate PRINT = GRAPH.union(BLANK).and(CONTROL.negate());
+
+    //  200C..200D    PropList.txt:Join_Control
+    static final CharPredicate JOIN_CONTROL = ch -> ch == 0x200C || ch == 0x200D;
+
+    //  \p{alpha}
+    //  \p{gc=Mark}
+    //  \p{digit}
+    //  \p{gc=Connector_Punctuation}
+    //  \p{Join_Control}    200C..200D
+    static final CharPredicate WORD =
+        ALPHABETIC.union(ch -> ((((1 << Character.NON_SPACING_MARK) |
+                                  (1 << Character.ENCLOSING_MARK) |
+                                  (1 << Character.COMBINING_SPACING_MARK) |
+                                  (1 << Character.DECIMAL_DIGIT_NUMBER) |
+                                  (1 << Character.CONNECTOR_PUNCTUATION))
+                                 >> Character.getType(ch)) & 1) != 0,
+                         JOIN_CONTROL);
+
+    /////////////////////////////////////////////////////////////////////////////
+
+    private static final HashMap<String, CharPredicate> posix = new HashMap<>(12);
+    private static final HashMap<String, CharPredicate> uprops = new HashMap<>(18);
+
+    private static void defPosix(String name, CharPredicate p) {
+        posix.put(name, p);
+    }
+    private static void defUProp(String name, CharPredicate p) {
+        uprops.put(name, p);
+    }
+
+    static {
+        defPosix("ALPHA", ALPHABETIC);
+        defPosix("LOWER", LOWERCASE);
+        defPosix("UPPER", UPPERCASE);
+        defPosix("SPACE", WHITE_SPACE);
+        defPosix("PUNCT", PUNCTUATION);
+        defPosix("XDIGIT",HEX_DIGIT);
+        defPosix("ALNUM", ALNUM);
+        defPosix("CNTRL", CONTROL);
+        defPosix("DIGIT", DIGIT);
+        defPosix("BLANK", BLANK);
+        defPosix("GRAPH", GRAPH);
+        defPosix("PRINT", PRINT);
+
+        defUProp("ALPHABETIC", ALPHABETIC);
+        defUProp("ASSIGNED", ASSIGNED);
+        defUProp("CONTROL", CONTROL);
+        defUProp("HEXDIGIT", HEX_DIGIT);
+        defUProp("IDEOGRAPHIC", IDEOGRAPHIC);
+        defUProp("JOINCONTROL", JOIN_CONTROL);
+        defUProp("LETTER", LETTER);
+        defUProp("LOWERCASE", LOWERCASE);
+        defUProp("NONCHARACTERCODEPOINT", NONCHARACTER_CODE_POINT);
+        defUProp("TITLECASE", TITLECASE);
+        defUProp("PUNCTUATION", PUNCTUATION);
+        defUProp("UPPERCASE", UPPERCASE);
+        defUProp("WHITESPACE", WHITE_SPACE);
+        defUProp("WORD", WORD);
+        defUProp("WHITE_SPACE", WHITE_SPACE);
+        defUProp("HEX_DIGIT", HEX_DIGIT);
+        defUProp("NONCHARACTER_CODE_POINT", NONCHARACTER_CODE_POINT);
+        defUProp("JOIN_CONTROL", JOIN_CONTROL);
+    }
+
+    public static CharPredicate forUnicodeProperty(String propName) {
+        propName = propName.toUpperCase(Locale.ROOT);
+        CharPredicate p = uprops.get(propName);
+        if (p != null)
+            return p;
+        return posix.get(propName);
+    }
+
+    public static CharPredicate forPOSIXName(String propName) {
+        return posix.get(propName.toUpperCase(Locale.ENGLISH));
+    }
+
+    /////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Returns a predicate matching all characters belong to a named
+     * UnicodeScript.
+     */
+    static CharPredicate forUnicodeScript(String name) {
+        final Character.UnicodeScript script;
+        try {
+            script = Character.UnicodeScript.forName(name);
+            return ch -> script == Character.UnicodeScript.of(ch);
+        } catch (IllegalArgumentException iae) {}
+        return null;
+    }
+
+    /**
+     * Returns a predicate matching all characters in a UnicodeBlock.
+     */
+    static CharPredicate forUnicodeBlock(String name) {
+        final Character.UnicodeBlock block;
+        try {
+            block = Character.UnicodeBlock.forName(name);
+            return ch -> block == Character.UnicodeBlock.of(ch);
+        } catch (IllegalArgumentException iae) {}
+         return null;
+    }
+
+    /////////////////////////////////////////////////////////////////////////////
+
+    // unicode categories, aliases, properties, java methods ...
+
+    private static final HashMap<String, CharPredicate> props = new HashMap<>(128);
+
+    /**
+     * Returns a predicate matching all characters in a named property.
+     */
+    static CharPredicate forProperty(String name) {
+        return props.get(name);
+    }
+
+    private static void defProp(String name, CharPredicate p) {
+        props.put(name, p);
+    }
+
+    private static void defCategory(String name, final int typeMask) {
+        CharPredicate p = ch -> (typeMask & (1 << Character.getType(ch))) != 0;
+        props.put(name, p);
+    }
+
+    private static void defRange(String name, final int lower, final int upper) {
+        BmpCharPredicate p = ch -> lower <= ch && ch <= upper;
+        props.put(name, p);
+    }
+
+    private static void defCtype(String name, final int ctype) {
+        BmpCharPredicate p = ch -> ch < 128 && ASCII.isType(ch, ctype);
+        // PrintPattern.pmap.put(p, name);
+        props.put(name, p);
+    }
+
+    static {
+        // Unicode character property aliases, defined in
+        // http://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt
+        defCategory("Cn", 1<<Character.UNASSIGNED);
+        defCategory("Lu", 1<<Character.UPPERCASE_LETTER);
+        defCategory("Ll", 1<<Character.LOWERCASE_LETTER);
+        defCategory("Lt", 1<<Character.TITLECASE_LETTER);
+        defCategory("Lm", 1<<Character.MODIFIER_LETTER);
+        defCategory("Lo", 1<<Character.OTHER_LETTER);
+        defCategory("Mn", 1<<Character.NON_SPACING_MARK);
+        defCategory("Me", 1<<Character.ENCLOSING_MARK);
+        defCategory("Mc", 1<<Character.COMBINING_SPACING_MARK);
+        defCategory("Nd", 1<<Character.DECIMAL_DIGIT_NUMBER);
+        defCategory("Nl", 1<<Character.LETTER_NUMBER);
+        defCategory("No", 1<<Character.OTHER_NUMBER);
+        defCategory("Zs", 1<<Character.SPACE_SEPARATOR);
+        defCategory("Zl", 1<<Character.LINE_SEPARATOR);
+        defCategory("Zp", 1<<Character.PARAGRAPH_SEPARATOR);
+        defCategory("Cc", 1<<Character.CONTROL);
+        defCategory("Cf", 1<<Character.FORMAT);
+        defCategory("Co", 1<<Character.PRIVATE_USE);
+        defCategory("Cs", 1<<Character.SURROGATE);
+        defCategory("Pd", 1<<Character.DASH_PUNCTUATION);
+        defCategory("Ps", 1<<Character.START_PUNCTUATION);
+        defCategory("Pe", 1<<Character.END_PUNCTUATION);
+        defCategory("Pc", 1<<Character.CONNECTOR_PUNCTUATION);
+        defCategory("Po", 1<<Character.OTHER_PUNCTUATION);
+        defCategory("Sm", 1<<Character.MATH_SYMBOL);
+        defCategory("Sc", 1<<Character.CURRENCY_SYMBOL);
+        defCategory("Sk", 1<<Character.MODIFIER_SYMBOL);
+        defCategory("So", 1<<Character.OTHER_SYMBOL);
+        defCategory("Pi", 1<<Character.INITIAL_QUOTE_PUNCTUATION);
+        defCategory("Pf", 1<<Character.FINAL_QUOTE_PUNCTUATION);
+        defCategory("L", ((1<<Character.UPPERCASE_LETTER) |
+                          (1<<Character.LOWERCASE_LETTER) |
+                          (1<<Character.TITLECASE_LETTER) |
+                          (1<<Character.MODIFIER_LETTER)  |
+                          (1<<Character.OTHER_LETTER)));
+        defCategory("M", ((1<<Character.NON_SPACING_MARK) |
+                          (1<<Character.ENCLOSING_MARK)   |
+                          (1<<Character.COMBINING_SPACING_MARK)));
+        defCategory("N", ((1<<Character.DECIMAL_DIGIT_NUMBER) |
+                          (1<<Character.LETTER_NUMBER)        |
+                          (1<<Character.OTHER_NUMBER)));
+        defCategory("Z", ((1<<Character.SPACE_SEPARATOR) |
+                          (1<<Character.LINE_SEPARATOR)  |
+                          (1<<Character.PARAGRAPH_SEPARATOR)));
+        defCategory("C", ((1<<Character.CONTROL)     |
+                          (1<<Character.FORMAT)      |
+                          (1<<Character.PRIVATE_USE) |
+                          (1<<Character.SURROGATE))); // Other
+        defCategory("P", ((1<<Character.DASH_PUNCTUATION)      |
+                          (1<<Character.START_PUNCTUATION)     |
+                          (1<<Character.END_PUNCTUATION)       |
+                          (1<<Character.CONNECTOR_PUNCTUATION) |
+                          (1<<Character.OTHER_PUNCTUATION)     |
+                          (1<<Character.INITIAL_QUOTE_PUNCTUATION) |
+                          (1<<Character.FINAL_QUOTE_PUNCTUATION)));
+        defCategory("S", ((1<<Character.MATH_SYMBOL)     |
+                          (1<<Character.CURRENCY_SYMBOL) |
+                          (1<<Character.MODIFIER_SYMBOL) |
+                          (1<<Character.OTHER_SYMBOL)));
+        defCategory("LC", ((1<<Character.UPPERCASE_LETTER) |
+                           (1<<Character.LOWERCASE_LETTER) |
+                           (1<<Character.TITLECASE_LETTER)));
+        defCategory("LD", ((1<<Character.UPPERCASE_LETTER) |
+                           (1<<Character.LOWERCASE_LETTER) |
+                           (1<<Character.TITLECASE_LETTER) |
+                           (1<<Character.MODIFIER_LETTER)  |
+                           (1<<Character.OTHER_LETTER)     |
+                           (1<<Character.DECIMAL_DIGIT_NUMBER)));
+        defRange("L1", 0x00, 0xFF); // Latin-1
+        props.put("all", ch -> true);
+
+        // Posix regular expression character classes, defined in
+        // http://www.unix.org/onlinepubs/009695399/basedefs/xbd_chap09.html
+        defRange("ASCII", 0x00, 0x7F);   // ASCII
+        defCtype("Alnum", ASCII.ALNUM);  // Alphanumeric characters
+        defCtype("Alpha", ASCII.ALPHA);  // Alphabetic characters
+        defCtype("Blank", ASCII.BLANK);  // Space and tab characters
+        defCtype("Cntrl", ASCII.CNTRL);  // Control characters
+        defRange("Digit", '0', '9');     // Numeric characters
+        defCtype("Graph", ASCII.GRAPH);  // printable and visible
+        defRange("Lower", 'a', 'z');     // Lower-case alphabetic
+        defRange("Print", 0x20, 0x7E);   // Printable characters
+        defCtype("Punct", ASCII.PUNCT);  // Punctuation characters
+        defCtype("Space", ASCII.SPACE);  // Space characters
+        defRange("Upper", 'A', 'Z');     // Upper-case alphabetic
+        defCtype("XDigit",ASCII.XDIGIT); // hexadecimal digits
+
+        // Java character properties, defined by methods in Character.java
+        defProp("javaLowerCase", java.lang.Character::isLowerCase);
+        defProp("javaUpperCase",  Character::isUpperCase);
+        defProp("javaAlphabetic", java.lang.Character::isAlphabetic);
+        defProp("javaIdeographic", java.lang.Character::isIdeographic);
+        defProp("javaTitleCase", java.lang.Character::isTitleCase);
+        defProp("javaDigit", java.lang.Character::isDigit);
+        defProp("javaDefined", java.lang.Character::isDefined);
+        defProp("javaLetter", java.lang.Character::isLetter);
+        defProp("javaLetterOrDigit", java.lang.Character::isLetterOrDigit);
+        defProp("javaJavaIdentifierStart", java.lang.Character::isJavaIdentifierStart);
+        defProp("javaJavaIdentifierPart", java.lang.Character::isJavaIdentifierPart);
+        defProp("javaUnicodeIdentifierStart", java.lang.Character::isUnicodeIdentifierStart);
+        defProp("javaUnicodeIdentifierPart", java.lang.Character::isUnicodeIdentifierPart);
+        defProp("javaIdentifierIgnorable", java.lang.Character::isIdentifierIgnorable);
+        defProp("javaSpaceChar", java.lang.Character::isSpaceChar);
+        defProp("javaWhitespace", java.lang.Character::isWhitespace);
+        defProp("javaISOControl", java.lang.Character::isISOControl);
+        defProp("javaMirrored", java.lang.Character::isMirrored);
+    }
+
+    /////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Posix ASCII variants, not in the lookup map
+     */
+    static final BmpCharPredicate ASCII_DIGIT = ch -> ch < 128 && ASCII.isDigit(ch);
+    static final BmpCharPredicate ASCII_WORD  = ch -> ch < 128 && ASCII.isWord(ch);
+    static final BmpCharPredicate ASCII_SPACE = ch -> ch < 128 && ASCII.isSpace(ch);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/regex/IntHashSet.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,98 @@
+/*
+ * 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 java.util.regex;
+
+import java.util.Arrays;
+
+/**
+ * A lightweight hashset implementation for positive 'int'. Not safe for
+ * concurrent access.
+ */
+class IntHashSet {
+    private int[] entries;
+    private int[] hashes;
+    private int pos = 0;
+
+    public IntHashSet() {
+        this.entries = new int[16 << 1];      // initCapacity = 16;
+        this.hashes = new int[(16 / 2) | 1];  // odd -> fewer collisions
+        Arrays.fill(this.entries, -1);
+        Arrays.fill(this.hashes, -1);
+    }
+
+    public boolean contains(int i) {
+        int h = hashes[i % hashes.length];
+        while (h != -1) {
+            if (entries[h] == i)
+                return true;
+            h = entries[h + 1];
+        }
+        return false;
+    }
+
+    public void add(int i) {
+        int h0 = i % hashes.length;
+        int next = hashes[h0];
+        //  if invoker guarantees contains(i) checked before add(i)
+        //  the following check is not needed.
+        int next0 = next;
+        while (next0 != -1) {
+            if (entries[next0 ] == i)
+                return;
+            next0 = entries[next0 + 1];
+        }
+        hashes[h0] = pos;
+        entries[pos++] = i;
+        entries[pos++] = next;
+        if (pos == entries.length)
+            expand();
+    }
+
+    public void clear() {
+        Arrays.fill(this.entries, -1);
+        Arrays.fill(this.hashes, -1);
+        pos = 0;
+    }
+
+    private void expand() {
+        int[] old = entries;
+        int[] es = new int[old.length << 1];
+        int hlen = (old.length / 2) | 1;
+        int[] hs = new int[hlen];
+        Arrays.fill(es, -1);
+        Arrays.fill(hs, -1);
+        for (int n = 0; n < pos;) {  // re-hashing
+            int i = old[n];
+            int hsh = i % hlen;
+            int next = hs[hsh];
+            hs[hsh] = n;
+            es[n++] = i;
+            es[n++] = next;
+        }
+        this.entries = es;
+        this.hashes = hs;
+    }
+}
--- a/jdk/src/java.base/share/classes/java/util/regex/Matcher.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/regex/Matcher.java	Wed Jul 05 21:42:16 2017 +0200
@@ -178,6 +178,14 @@
     int[] locals;
 
     /**
+     * Storage used by top greedy Loop node to store a specific hash set to
+     * keep the beginning index of the failed repetition match. The nodes
+     * themselves are stateless, so they rely on this field to hold state
+     * during a match.
+     */
+    IntHashSet[] localsPos;
+
+    /**
      * Boolean indicating whether or not more input could change
      * the results of the last match.
      *
@@ -239,6 +247,7 @@
         int parentGroupCount = Math.max(parent.capturingGroupCount, 10);
         groups = new int[parentGroupCount * 2];
         locals = new int[parent.localCount];
+        localsPos = new IntHashSet[parent.localTCNCount];
 
         // Put fields into initial states
         reset();
@@ -375,6 +384,7 @@
             groups[i] = -1;
         for (int i = 0; i < locals.length; i++)
             locals[i] = -1;
+        localsPos = new IntHashSet[parentPattern.localTCNCount];
         modCount++;
         return this;
     }
@@ -397,6 +407,10 @@
             groups[i] = -1;
         for(int i=0; i<locals.length; i++)
             locals[i] = -1;
+        for (int i = 0; i < localsPos.length; i++) {
+            if (localsPos[i] != null)
+                localsPos[i].clear();
+        }
         lastAppendPosition = 0;
         from = 0;
         to = getTextLength();
@@ -1706,6 +1720,10 @@
         this.oldLast = oldLast < 0 ? from : oldLast;
         for (int i = 0; i < groups.length; i++)
             groups[i] = -1;
+        for (int i = 0; i < localsPos.length; i++) {
+            if (localsPos[i] != null)
+                localsPos[i].clear();
+        }
         acceptMode = NOANCHOR;
         boolean result = parentPattern.root.match(this, from, text);
         if (!result)
@@ -1729,6 +1747,10 @@
         this.oldLast = oldLast < 0 ? from : oldLast;
         for (int i = 0; i < groups.length; i++)
             groups[i] = -1;
+        for (int i = 0; i < localsPos.length; i++) {
+            if (localsPos[i] != null)
+                localsPos[i].clear();
+        }
         acceptMode = anchor;
         boolean result = parentPattern.matchRoot.match(this, from, text);
         if (!result)
--- a/jdk/src/java.base/share/classes/java/util/regex/Pattern.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/regex/Pattern.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, 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
@@ -26,11 +26,15 @@
 package java.util.regex;
 
 import java.text.Normalizer;
+import java.text.Normalizer.Form;
 import java.util.Locale;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
 import java.util.Arrays;
 import java.util.NoSuchElementException;
 import java.util.Spliterator;
@@ -469,7 +473,7 @@
  *
  *   <li> A line-separator character&nbsp;(<code>'&#92;u2028'</code>), or
  *
- *   <li> A paragraph-separator character&nbsp;(<code>'&#92;u2029</code>).
+ *   <li> A paragraph-separator character&nbsp;(<code>'&#92;u2029'</code>).
  *
  * </ul>
  * <p>If {@link #UNIX_LINES} mode is activated, then the only line terminators
@@ -984,6 +988,11 @@
     transient int[] buffer;
 
     /**
+     * A temporary storage used for predicate for double return.
+     */
+    transient CharPredicate predicate;
+
+    /**
      * Map the "name" of the "named capturing group" to its group id
      * node.
      */
@@ -995,6 +1004,24 @@
     transient GroupHead[] groupNodes;
 
     /**
+     * Temporary storage used to store the top level closure nodes.
+     */
+    transient List<Node> topClosureNodes;
+
+    /**
+     * The number of top greedy closure nodes in this Pattern. Used by
+     * matchers to allocate storage needed for a IntHashSet to keep the
+     * beginning pos {@code i} of all failed match.
+     */
+    transient int localTCNCount;
+
+    /*
+     * Turn off the stop-exponential-backtracking optimization if there
+     * is a group ref in the pattern.
+     */
+    transient boolean hasGroupRef;
+
+    /**
      * Temporary null terminated code point array used by pattern compiling.
      */
     private transient int[] temp;
@@ -1026,7 +1053,7 @@
      * If the Start node might possibly match supplementary characters.
      * It is set to true during compiling if
      * (1) There is supplementary char in pattern, or
-     * (2) There is complement node of Category or Block
+     * (2) There is complement node of a "family" CharProperty
      */
     private transient boolean hasSupplementary;
 
@@ -1338,6 +1365,7 @@
         // Initialize counts
         capturingGroupCount = 1;
         localCount = 0;
+        localTCNCount = 0;
 
         // if length > 0, the Pattern is lazily compiled
         if (pattern.length() == 0) {
@@ -1368,6 +1396,7 @@
         // Reset group index count
         capturingGroupCount = 1;
         localCount = 0;
+        localTCNCount = 0;
 
         if (pattern.length() > 0) {
             compile();
@@ -1378,105 +1407,114 @@
     }
 
     /**
-     * The pattern is converted to normalized form ({@linkplain
-     * java.text.Normalizer.Form.NFD NFD}, canonical decomposition)
-     * and then a pure group is constructed to match canonical
-     * equivalences of the characters.
-     */
-    private void normalize() {
-        int lastCodePoint = -1;
-
-        // Convert pattern into normalized form
-        normalizedPattern = Normalizer.normalize(pattern, Normalizer.Form.NFD);
-        patternLength = normalizedPattern.length();
-
-        // Modify pattern to match canonical equivalences
-        StringBuilder newPattern = new StringBuilder(patternLength);
-        for(int i=0; i<patternLength; ) {
-            int c = normalizedPattern.codePointAt(i);
-            StringBuilder sequenceBuffer;
-            if ((Character.getType(c) == Character.NON_SPACING_MARK)
-                && (lastCodePoint != -1)) {
-                sequenceBuffer = new StringBuilder();
-                sequenceBuffer.appendCodePoint(lastCodePoint);
-                sequenceBuffer.appendCodePoint(c);
-                while(Character.getType(c) == Character.NON_SPACING_MARK) {
-                    i += Character.charCount(c);
-                    if (i >= patternLength)
-                        break;
-                    c = normalizedPattern.codePointAt(i);
-                    sequenceBuffer.appendCodePoint(c);
-                }
-                String ea = produceEquivalentAlternation(
-                                               sequenceBuffer.toString());
-                newPattern.setLength(newPattern.length()-Character.charCount(lastCodePoint));
-                newPattern.append("(?:").append(ea).append(")");
-            } else if (c == '[' && lastCodePoint != '\\') {
-                i = normalizeCharClass(newPattern, i);
-            } else {
-                newPattern.appendCodePoint(c);
-            }
-            lastCodePoint = c;
-            i += Character.charCount(c);
-        }
-        normalizedPattern = newPattern.toString();
-    }
-
-    /**
-     * Complete the character class being parsed and add a set
-     * of alternations to it that will match the canonical equivalences
-     * of the characters within the class.
+     * The pattern is converted to normalized form ({@link
+     * java.text.Normalizer.Form.NFC NFC}, canonical decomposition,
+     * followed by canonical composition for the character class
+     * part, and {@link java.text.Normalizer.Form.NFD NFD},
+     * canonical decomposition) for the rest), and then a pure
+     * group is constructed to match canonical equivalences of the
+     * characters.
      */
-    private int normalizeCharClass(StringBuilder newPattern, int i) {
-        StringBuilder charClass = new StringBuilder();
-        StringBuilder eq = null;
-        int lastCodePoint = -1;
-        String result;
-
-        i++;
-        charClass.append("[");
-        while(true) {
-            int c = normalizedPattern.codePointAt(i);
-            StringBuilder sequenceBuffer;
-
-            if (c == ']' && lastCodePoint != '\\') {
-                charClass.append((char)c);
-                break;
-            } else if (Character.getType(c) == Character.NON_SPACING_MARK) {
-                sequenceBuffer = new StringBuilder();
-                sequenceBuffer.appendCodePoint(lastCodePoint);
-                while(Character.getType(c) == Character.NON_SPACING_MARK) {
-                    sequenceBuffer.appendCodePoint(c);
-                    i += Character.charCount(c);
-                    if (i >= normalizedPattern.length())
-                        break;
-                    c = normalizedPattern.codePointAt(i);
+    private static String normalize(String pattern) {
+        int plen = pattern.length();
+        StringBuilder pbuf = new StringBuilder(plen);
+        char last = 0;
+        int lastStart = 0;
+        char cc = 0;
+        for (int i = 0; i < plen;) {
+            char c = pattern.charAt(i);
+            if (cc == 0 &&    // top level
+                c == '\\' && i + 1 < plen && pattern.charAt(i + 1) == '\\') {
+                i += 2; last = 0;
+                continue;
+            }
+            if (c == '[' && last != '\\') {
+                if (cc == 0) {
+                    if (lastStart < i)
+                        normalizeSlice(pattern, lastStart, i, pbuf);
+                    lastStart = i;
+                }
+                cc++;
+            } else if (c == ']' && last != '\\') {
+                cc--;
+                if (cc == 0) {
+                    normalizeClazz(pattern, lastStart, i + 1, pbuf);
+                    lastStart = i + 1;
                 }
-                String ea = produceEquivalentAlternation(
-                                                  sequenceBuffer.toString());
-
-                charClass.setLength(charClass.length()-Character.charCount(lastCodePoint));
-                if (eq == null)
-                    eq = new StringBuilder();
-                eq.append('|');
-                eq.append(ea);
-            } else {
-                charClass.appendCodePoint(c);
-                i++;
+            }
+            last = c;
+            i++;
+        }
+        assert (cc == 0);
+        if (lastStart < plen)
+            normalizeSlice(pattern, lastStart, plen, pbuf);
+        return pbuf.toString();
+    }
+
+    private static void normalizeSlice(String src, int off, int limit,
+                                       StringBuilder dst)
+    {
+        int len = src.length();
+        int off0 = off;
+        while (off < limit && ASCII.isAscii(src.charAt(off))) {
+            off++;
+        }
+        if (off == limit) {
+            dst.append(src, off0, limit);
+            return;
+        }
+        off--;
+        if (off < off0)
+            off = off0;
+        else
+            dst.append(src, off0, off);
+        while (off < limit) {
+            int ch0 = src.codePointAt(off);
+            if (".$|()[]{}^?*+\\".indexOf(ch0) != -1) {
+                dst.append((char)ch0);
+                off++;
+                continue;
             }
-            if (i == normalizedPattern.length())
-                throw error("Unclosed character class");
-            lastCodePoint = c;
-        }
-
-        if (eq != null) {
-            result = "(?:"+charClass.toString()+eq.toString()+")";
-        } else {
-            result = charClass.toString();
-        }
-
-        newPattern.append(result);
-        return i;
+            int j = off + Character.charCount(ch0);
+            int ch1;
+            while (j < limit) {
+                ch1 = src.codePointAt(j);
+                if (Grapheme.isBoundary(ch0, ch1))
+                    break;
+                ch0 = ch1;
+                j += Character.charCount(ch1);
+            }
+            String seq = src.substring(off, j);
+            String nfd = Normalizer.normalize(seq, Normalizer.Form.NFD);
+            off = j;
+            if (nfd.length() > 1) {
+                ch0 = nfd.codePointAt(0);
+                ch1 = nfd.codePointAt(Character.charCount(ch0));
+                if (Character.getType(ch1) == Character.NON_SPACING_MARK) {
+                    Set<String> altns = new LinkedHashSet<>();
+                    altns.add(seq);
+                    produceEquivalentAlternation(nfd, altns);
+                    dst.append("(?:");
+                    altns.forEach( s -> dst.append(s + "|"));
+                    dst.delete(dst.length() - 1, dst.length());
+                    dst.append(")");
+                    continue;
+                }
+            }
+            String nfc = Normalizer.normalize(seq, Normalizer.Form.NFC);
+            if (!seq.equals(nfc) && !nfd.equals(nfc))
+                dst.append("(?:" + seq + "|" + nfd  + "|" + nfc + ")");
+            else if (!seq.equals(nfd))
+                dst.append("(?:" + seq + "|" + nfd + ")");
+            else
+                dst.append(seq);
+        }
+    }
+
+    private static void normalizeClazz(String src, int off, int limit,
+                                       StringBuilder dst)
+    {
+        dst.append(Normalizer.normalize(src.substring(off, limit), Form.NFC));
     }
 
     /**
@@ -1484,28 +1522,26 @@
      * combining marks that follow it, produce the alternation that will
      * match all canonical equivalences of that sequence.
      */
-    private String produceEquivalentAlternation(String source) {
-        int len = countChars(source, 0, 1);
-        if (source.length() == len)
-            // source has one character.
-            return source;
-
-        String base = source.substring(0,len);
-        String combiningMarks = source.substring(len);
-
+    private static void produceEquivalentAlternation(String src,
+                                                     Set<String> dst)
+    {
+        int len = countChars(src, 0, 1);
+        if (src.length() == len) {
+            dst.add(src);  // source has one character.
+            return;
+        }
+        String base = src.substring(0,len);
+        String combiningMarks = src.substring(len);
         String[] perms = producePermutations(combiningMarks);
-        StringBuilder result = new StringBuilder(source);
-
         // Add combined permutations
-        for(int x=0; x<perms.length; x++) {
+        for(int x = 0; x < perms.length; x++) {
             String next = base + perms[x];
-            if (x>0)
-                result.append("|"+next);
+            dst.add(next);
             next = composeOneStep(next);
-            if (next != null)
-                result.append("|"+produceEquivalentAlternation(next));
-        }
-        return result.toString();
+            if (next != null) {
+                produceEquivalentAlternation(next, dst);
+            }
+        }
     }
 
     /**
@@ -1517,7 +1553,7 @@
      * possibilities must be removed because they are not canonically
      * equivalent.
      */
-    private String[] producePermutations(String input) {
+    private static String[] producePermutations(String input) {
         if (input.length() == countChars(input, 0, 1))
             return new String[] {input};
 
@@ -1575,7 +1611,7 @@
         return result;
     }
 
-    private int getClass(int c) {
+    private static int getClass(int c) {
         return sun.text.Normalizer.getCombiningClass(c);
     }
 
@@ -1586,11 +1622,10 @@
      * combining mark followed by the remaining combining marks. Returns
      * null if the first two characters cannot be further composed.
      */
-    private String composeOneStep(String input) {
+    private static String composeOneStep(String input) {
         int len = countChars(input, 0, 2);
         String firstTwoCharacters = input.substring(0, len);
         String result = Normalizer.normalize(firstTwoCharacters, Normalizer.Form.NFC);
-
         if (result.equals(firstTwoCharacters))
             return null;
         else {
@@ -1677,7 +1712,7 @@
     private void compile() {
         // Handle canonical equivalences
         if (has(CANON_EQ) && !has(LITERAL)) {
-            normalize();
+            normalizedPattern = normalize(pattern);
         } else {
             normalizedPattern = pattern;
         }
@@ -1707,6 +1742,7 @@
         buffer = new int[32];
         groupNodes = new GroupHead[10];
         namedGroups = null;
+        topClosureNodes = new ArrayList<>(10);
 
         if (has(LITERAL)) {
             // Literal pattern handling
@@ -1737,12 +1773,26 @@
             root = hasSupplementary ? new StartS(matchRoot) : new Start(matchRoot);
         }
 
+        // Optimize the greedy Loop to prevent exponential backtracking, IF there
+        // is no group ref in this pattern. With a non-negative localTCNCount value,
+        // the greedy type Loop, Curly will skip the backtracking for any starting
+        // position "i" that failed in the past.
+        if (!hasGroupRef) {
+            for (Node node : topClosureNodes) {
+                if (node instanceof Loop) {
+                    // non-deterministic-greedy-group
+                    ((Loop)node).posIndex = localTCNCount++;
+                }
+            }
+        }
+
         // Release temporary storage
         temp = null;
         buffer = null;
         groupNodes = null;
         patternLength = 0;
         compiled = true;
+        topClosureNodes = null;
     }
 
     Map<String, Integer> namedGroups() {
@@ -1754,44 +1804,6 @@
     }
 
     /**
-     * Used to print out a subtree of the Pattern to help with debugging.
-     */
-    private static void printObjectTree(Node node) {
-        while(node != null) {
-            if (node instanceof Prolog) {
-                System.out.println(node);
-                printObjectTree(((Prolog)node).loop);
-                System.out.println("**** end contents prolog loop");
-            } else if (node instanceof Loop) {
-                System.out.println(node);
-                printObjectTree(((Loop)node).body);
-                System.out.println("**** end contents Loop body");
-            } else if (node instanceof Curly) {
-                System.out.println(node);
-                printObjectTree(((Curly)node).atom);
-                System.out.println("**** end contents Curly body");
-            } else if (node instanceof GroupCurly) {
-                System.out.println(node);
-                printObjectTree(((GroupCurly)node).atom);
-                System.out.println("**** end contents GroupCurly body");
-            } else if (node instanceof GroupTail) {
-                System.out.println(node);
-                System.out.println("Tail next is "+node.next);
-                return;
-            } else {
-                System.out.println(node);
-            }
-            node = node.next;
-            if (node != null)
-                System.out.println("->next:");
-            if (node == Pattern.accept) {
-                System.out.println("Accept Node");
-                node = null;
-            }
-       }
-    }
-
-    /**
      * Used to accumulate information about a subtree of the object graph
      * so that optimizations can be applied to the subtree.
      */
@@ -2083,7 +2095,10 @@
                 tail = root;
                 continue;
             case '[':
-                node = clazz(true);
+                if (has(CANON_EQ) && !has(LITERAL))
+                    node = new NFCCharProperty(clazz(true));
+                else
+                    node = newCharProperty(clazz(true));
                 break;
             case '\\':
                 ch = nextEscaped();
@@ -2096,7 +2111,11 @@
                     } else {
                         oneLetter = false;
                     }
-                    node = family(oneLetter, comp);
+                    // node = newCharProperty(family(oneLetter, comp));
+                    if (has(CANON_EQ) && !has(LITERAL))
+                        node = new NFCCharProperty(family(oneLetter, comp));
+                    else
+                        node = newCharProperty(family(oneLetter, comp));
                 } else {
                     unread();
                     node = atom();
@@ -2123,12 +2142,12 @@
             case '.':
                 next();
                 if (has(DOTALL)) {
-                    node = new All();
+                    node = new CharProperty(ALL);
                 } else {
-                    if (has(UNIX_LINES))
-                        node = new UnixDot();
-                    else {
-                        node = new Dot();
+                    if (has(UNIX_LINES)) {
+                        node = new CharProperty(UNIXDOT);
+                    } else {
+                        node = new CharProperty(DOT);
                     }
                 }
                 break;
@@ -2155,7 +2174,12 @@
             }
 
             node = closure(node);
-
+            /* save the top dot-greedy nodes (.*, .+) as well
+            if (node instanceof GreedyCharProperty &&
+                ((GreedyCharProperty)node).cp instanceof Dot) {
+                topClosureNodes.add(node);
+            }
+            */
             if (head == null) {
                 head = tail = node;
             } else {
@@ -2213,7 +2237,10 @@
                             unread();
                         else
                             oneLetter = false;
-                        return family(oneLetter, comp);
+                        if (has(CANON_EQ) && !has(LITERAL))
+                            return new NFCCharProperty(family(oneLetter, comp));
+                        else
+                            return newCharProperty(family(oneLetter, comp));
                     }
                 }
                 unread();
@@ -2251,7 +2278,7 @@
             break;
         }
         if (first == 1) {
-            return newSingle(buffer[0]);
+            return newCharProperty(single(buffer[0]));
         } else {
             return newSlice(buffer, first, hasSupplementary);
         }
@@ -2302,6 +2329,7 @@
                 break;
             }
         }
+        hasGroupRef = true;
         if (has(CASE_INSENSITIVE))
             return new CIBackRef(refNum, has(UNICODE_CASE));
         else
@@ -2346,9 +2374,13 @@
         case 'C':
             break;
         case 'D':
-            if (create) root = has(UNICODE_CHARACTER_CLASS)
-                               ? new Utype(UnicodeProp.DIGIT).complement()
-                               : new Ctype(ASCII.DIGIT).complement();
+            if (create) {
+                predicate = has(UNICODE_CHARACTER_CLASS) ?
+                            CharPredicates.DIGIT : CharPredicates.ASCII_DIGIT;
+                predicate = predicate.negate();
+                if (!inclass)
+                    root = newCharProperty(predicate);
+            }
             return -1;
         case 'E':
         case 'F':
@@ -2358,7 +2390,11 @@
             if (create) root = new LastMatch();
             return -1;
         case 'H':
-            if (create) root = new HorizWS().complement();
+            if (create) {
+                predicate = HorizWS.negate();
+                if (!inclass)
+                    root = newCharProperty(predicate);
+            }
             return -1;
         case 'I':
         case 'J':
@@ -2377,20 +2413,32 @@
             if (create) root = new LineEnding();
             return -1;
         case 'S':
-            if (create) root = has(UNICODE_CHARACTER_CLASS)
-                               ? new Utype(UnicodeProp.WHITE_SPACE).complement()
-                               : new Ctype(ASCII.SPACE).complement();
+            if (create) {
+                predicate = has(UNICODE_CHARACTER_CLASS) ?
+                            CharPredicates.WHITE_SPACE : CharPredicates.ASCII_SPACE;
+                predicate = predicate.negate();
+                if (!inclass)
+                    root = newCharProperty(predicate);
+            }
             return -1;
         case 'T':
         case 'U':
             break;
         case 'V':
-            if (create) root = new VertWS().complement();
+            if (create) {
+                predicate = VertWS.negate();
+                if (!inclass)
+                    root = newCharProperty(predicate);
+            }
             return -1;
         case 'W':
-            if (create) root = has(UNICODE_CHARACTER_CLASS)
-                               ? new Utype(UnicodeProp.WORD).complement()
-                               : new Ctype(ASCII.WORD).complement();
+            if (create) {
+                predicate = has(UNICODE_CHARACTER_CLASS) ?
+                            CharPredicates.WORD : CharPredicates.ASCII_WORD;
+                predicate = predicate.negate();
+                if (!inclass)
+                    root = newCharProperty(predicate);
+            }
             return -1;
         case 'X':
             if (inclass) break;
@@ -2430,9 +2478,12 @@
         case 'c':
             return c();
         case 'd':
-            if (create) root = has(UNICODE_CHARACTER_CLASS)
-                               ? new Utype(UnicodeProp.DIGIT)
-                               : new Ctype(ASCII.DIGIT);
+            if (create) {
+                predicate = has(UNICODE_CHARACTER_CLASS) ?
+                            CharPredicates.DIGIT : CharPredicates.ASCII_DIGIT;
+                if (!inclass)
+                    root = newCharProperty(predicate);
+            }
             return -1;
         case 'e':
             return '\033';
@@ -2441,7 +2492,11 @@
         case 'g':
             break;
         case 'h':
-            if (create) root = new HorizWS();
+            if (create) {
+                predicate = HorizWS;
+                if (!inclass)
+                    root = newCharProperty(predicate);
+            }
             return -1;
         case 'i':
         case 'j':
@@ -2455,6 +2510,7 @@
             if (!namedGroups().containsKey(name))
                 throw error("(named capturing group <"+ name+"> does not exit");
             if (create) {
+                hasGroupRef = true;
                 if (has(CASE_INSENSITIVE))
                     root = new CIBackRef(namedGroups().get(name), has(UNICODE_CASE));
                 else
@@ -2473,9 +2529,12 @@
         case 'r':
             return '\r';
         case 's':
-            if (create) root = has(UNICODE_CHARACTER_CLASS)
-                               ? new Utype(UnicodeProp.WHITE_SPACE)
-                               : new Ctype(ASCII.SPACE);
+            if (create) {
+                predicate = has(UNICODE_CHARACTER_CLASS) ?
+                            CharPredicates.WHITE_SPACE : CharPredicates.ASCII_SPACE;
+                if (!inclass)
+                    root = newCharProperty(predicate);
+            }
             return -1;
         case 't':
             return '\t';
@@ -2492,12 +2551,19 @@
             // compatibility concern '\013'/0x0B is returned if isrange.
             if (isrange)
                 return '\013';
-            if (create) root = new VertWS();
+            if (create) {
+                predicate = VertWS;
+                if (!inclass)
+                    root = newCharProperty(predicate);
+            }
             return -1;
         case 'w':
-            if (create) root = has(UNICODE_CHARACTER_CLASS)
-                               ? new Utype(UnicodeProp.WORD)
-                               : new Ctype(ASCII.WORD);
+            if (create) {
+                predicate = has(UNICODE_CHARACTER_CLASS) ?
+                            CharPredicates.WORD : CharPredicates.ASCII_WORD;
+                if (!inclass)
+                    root = newCharProperty(predicate);
+            }
             return -1;
         case 'x':
             return x();
@@ -2520,63 +2586,66 @@
      * is true except for the case of [abc&&def] where def is a separate
      * right hand node with "understood" brackets.
      */
-    private CharProperty clazz(boolean consume) {
-        CharProperty prev = null;
-        CharProperty node = null;
+    private CharPredicate clazz(boolean consume) {
+        CharPredicate prev = null;
+        CharPredicate curr = null;
         BitClass bits = new BitClass();
-        boolean include = true;
-        boolean firstInClass = true;
+        BmpCharPredicate bitsP = ch -> ch < 256 && bits.bits[ch];
+
+        boolean isNeg = false;
+        boolean hasBits = false;
         int ch = next();
+
+        // Negates if first char in a class, otherwise literal
+        if (ch == '^' && temp[cursor-1] == '[') {
+            ch = next();
+            isNeg = true;
+        }
         for (;;) {
             switch (ch) {
-                case '^':
-                    // Negates if first char in a class, otherwise literal
-                    if (firstInClass) {
-                        if (temp[cursor-1] != '[')
-                            break;
-                        ch = next();
-                        include = !include;
-                        continue;
-                    } else {
-                        // ^ not first in class, treat as literal
-                        break;
-                    }
                 case '[':
-                    firstInClass = false;
-                    node = clazz(true);
+                    curr = clazz(true);
                     if (prev == null)
-                        prev = node;
+                        prev = curr;
                     else
-                        prev = union(prev, node);
+                        prev = prev.union(curr);
                     ch = peek();
                     continue;
                 case '&':
-                    firstInClass = false;
                     ch = next();
                     if (ch == '&') {
                         ch = next();
-                        CharProperty rightNode = null;
+                        CharPredicate right = null;
                         while (ch != ']' && ch != '&') {
                             if (ch == '[') {
-                                if (rightNode == null)
-                                    rightNode = clazz(true);
+                                if (right == null)
+                                    right = clazz(true);
                                 else
-                                    rightNode = union(rightNode, clazz(true));
+                                    right = right.union(clazz(true));
                             } else { // abc&&def
                                 unread();
-                                rightNode = clazz(false);
+                                right = clazz(false);
                             }
                             ch = peek();
                         }
-                        if (rightNode != null)
-                            node = rightNode;
+                        if (hasBits) {
+                            // bits used, union has high precedence
+                            if (prev == null) {
+                                prev = curr = bitsP;
+                            } else {
+                                prev = prev.union(bitsP);
+                            }
+                            hasBits = false;
+                        }
+                        if (right != null)
+                            curr = right;
                         if (prev == null) {
-                            if (rightNode == null)
+                            if (right == null)
                                 throw error("Bad class syntax");
                             else
-                                prev = rightNode;
+                                prev = right;
                         } else {
-                            prev = intersection(prev, node);
+                            prev = prev.and(curr);
                         }
                     } else {
                         // treat as a literal &
@@ -2585,43 +2654,39 @@
                     }
                     continue;
                 case 0:
-                    firstInClass = false;
                     if (cursor >= patternLength)
                         throw error("Unclosed character class");
                     break;
                 case ']':
-                    firstInClass = false;
-                    if (prev != null) {
+                    if (prev != null || hasBits) {
                         if (consume)
                             next();
+                        if (prev == null)
+                            prev = bitsP;
+                        else if (hasBits)
+                            prev = prev.union(bitsP);
+                        if (isNeg)
+                            return prev.negate();
                         return prev;
                     }
                     break;
                 default:
-                    firstInClass = false;
                     break;
             }
-            node = range(bits);
-            if (include) {
-                if (prev == null) {
-                    prev = node;
-                } else {
-                    if (prev != node)
-                        prev = union(prev, node);
-                }
+            curr = range(bits);
+            if (curr == null) {    // the bits used
+                hasBits = true;
             } else {
-                if (prev == null) {
-                    prev = node.complement();
-                } else {
-                    if (prev != node)
-                        prev = setDifference(prev, node);
-                }
+                if (prev == null)
+                    prev = curr;
+                else if (prev != curr)
+                    prev = prev.union(curr);
             }
             ch = peek();
         }
     }
 
-    private CharProperty bitsOrSingle(BitClass bits, int ch) {
+    private CharPredicate bitsOrSingle(BitClass bits, int ch) {
         /* Bits can only handle codepoints in [u+0000-u+00ff] range.
            Use "single" node instead of bits when dealing with unicode
            case folding for codepoints listed below.
@@ -2643,19 +2708,46 @@
         if (ch < 256 &&
             !(has(CASE_INSENSITIVE) && has(UNICODE_CASE) &&
               (ch == 0xff || ch == 0xb5 ||
-               ch == 0x49 || ch == 0x69 ||  //I and i
-               ch == 0x53 || ch == 0x73 ||  //S and s
-               ch == 0x4b || ch == 0x6b ||  //K and k
-               ch == 0xc5 || ch == 0xe5)))  //A+ring
-            return bits.add(ch, flags());
-        return newSingle(ch);
+               ch == 0x49 || ch == 0x69 ||    //I and i
+               ch == 0x53 || ch == 0x73 ||    //S and s
+               ch == 0x4b || ch == 0x6b ||    //K and k
+               ch == 0xc5 || ch == 0xe5))) {  //A+ring
+            bits.add(ch, flags());
+            return null;
+        }
+        return single(ch);
+    }
+
+    /**
+     *  Returns a suitably optimized, single character predicate
+     */
+    private CharPredicate single(final int ch) {
+        if (has(CASE_INSENSITIVE)) {
+            int lower, upper;
+            if (has(UNICODE_CASE)) {
+                upper = Character.toUpperCase(ch);
+                lower = Character.toLowerCase(upper);
+                // Unicode case insensitive matches
+                if (upper != lower)
+                    return SingleU(lower);
+            } else if (ASCII.isAscii(ch)) {
+                lower = ASCII.toLower(ch);
+                upper = ASCII.toUpper(ch);
+                // Case insensitive matches a given BMP character
+                if (lower != upper)
+                    return SingleI(lower, upper);
+            }
+        }
+        if (isSupplementary(ch))
+            return SingleS(ch);
+        return Single(ch);  // Match a given BMP character
     }
 
     /**
      * Parse a single character or a character range in a character class
      * and return its representative node.
      */
-    private CharProperty range(BitClass bits) {
+    private CharPredicate range(BitClass bits) {
         int ch = peek();
         if (ch == '\\') {
             ch = nextEscaped();
@@ -2674,7 +2766,7 @@
                 unread();
                 ch = escape(true, true, isrange);
                 if (ch == -1)
-                    return (CharProperty) root;
+                    return predicate;
             }
         } else {
             next();
@@ -2696,10 +2788,13 @@
                     if (m < ch) {
                         throw error("Illegal character range");
                     }
-                    if (has(CASE_INSENSITIVE))
-                        return caseInsensitiveRangeFor(ch, m);
-                    else
-                        return rangeFor(ch, m);
+                    if (has(CASE_INSENSITIVE)) {
+                        if (has(UNICODE_CASE))
+                            return CIRangeU(ch, m);
+                        return CIRange(ch, m);
+                    } else {
+                        return Range(ch, m);
+                    }
                 }
             }
             return bitsOrSingle(bits, ch);
@@ -2710,12 +2805,10 @@
     /**
      * Parses a Unicode character family and returns its representative node.
      */
-    private CharProperty family(boolean singleLetter,
-                                boolean maybeComplement)
-    {
+    private CharPredicate family(boolean singleLetter, boolean isComplement) {
         next();
         String name;
-        CharProperty node = null;
+        CharPredicate p = null;
 
         if (singleLetter) {
             int c = temp[cursor];
@@ -2747,88 +2840,62 @@
             switch (name) {
                 case "sc":
                 case "script":
-                    node = unicodeScriptPropertyFor(value);
+                    p = CharPredicates.forUnicodeScript(value);
                     break;
                 case "blk":
                 case "block":
-                    node = unicodeBlockPropertyFor(value);
+                    p = CharPredicates.forUnicodeBlock(value);
                     break;
                 case "gc":
                 case "general_category":
-                    node = charPropertyNodeFor(value);
+                    p = CharPredicates.forProperty(value);
                     break;
                 default:
-                    throw error("Unknown Unicode property {name=<" + name + ">, "
-                                + "value=<" + value + ">}");
+                    break;
             }
+            if (p == null)
+                throw error("Unknown Unicode property {name=<" + name + ">, "
+                             + "value=<" + value + ">}");
+
         } else {
             if (name.startsWith("In")) {
-                // \p{inBlockName}
-                node = unicodeBlockPropertyFor(name.substring(2));
+                // \p{InBlockName}
+                p = CharPredicates.forUnicodeBlock(name.substring(2));
             } else if (name.startsWith("Is")) {
-                // \p{isGeneralCategory} and \p{isScriptName}
+                // \p{IsGeneralCategory} and \p{IsScriptName}
                 name = name.substring(2);
-                UnicodeProp uprop = UnicodeProp.forName(name);
-                if (uprop != null)
-                    node = new Utype(uprop);
-                if (node == null)
-                    node = CharPropertyNames.charPropertyFor(name);
-                if (node == null)
-                    node = unicodeScriptPropertyFor(name);
+                p = CharPredicates.forUnicodeProperty(name);
+                if (p == null)
+                    p = CharPredicates.forProperty(name);
+                if (p == null)
+                    p = CharPredicates.forUnicodeScript(name);
             } else {
                 if (has(UNICODE_CHARACTER_CLASS)) {
-                    UnicodeProp uprop = UnicodeProp.forPOSIXName(name);
-                    if (uprop != null)
-                        node = new Utype(uprop);
+                    p = CharPredicates.forPOSIXName(name);
                 }
-                if (node == null)
-                    node = charPropertyNodeFor(name);
+                if (p == null)
+                    p = CharPredicates.forProperty(name);
             }
-        }
-        if (maybeComplement) {
-            if (node instanceof Category || node instanceof Block)
-                hasSupplementary = true;
-            node = node.complement();
-        }
-        return node;
+            if (p == null)
+                throw error("Unknown character property name {In/Is" + name + "}");
+        }
+        if (isComplement) {
+            // it might be too expensive to detect if a complement of
+            // CharProperty can match "certain" supplementary. So just
+            // go with StartS.
+            hasSupplementary = true;
+            p = p.negate();
+        }
+        return p;
     }
 
-
-    /**
-     * Returns a CharProperty matching all characters belong to
-     * a UnicodeScript.
-     */
-    private CharProperty unicodeScriptPropertyFor(String name) {
-        final Character.UnicodeScript script;
-        try {
-            script = Character.UnicodeScript.forName(name);
-        } catch (IllegalArgumentException iae) {
-            throw error("Unknown character script name {" + name + "}");
-        }
-        return new Script(script);
-    }
-
-    /**
-     * Returns a CharProperty matching all characters in a UnicodeBlock.
-     */
-    private CharProperty unicodeBlockPropertyFor(String name) {
-        final Character.UnicodeBlock block;
-        try {
-            block = Character.UnicodeBlock.forName(name);
-        } catch (IllegalArgumentException iae) {
-            throw error("Unknown character block name {" + name + "}");
-        }
-        return new Block(block);
-    }
-
-    /**
-     * Returns a CharProperty matching all characters in a named property.
-     */
-    private CharProperty charPropertyNodeFor(String name) {
-        CharProperty p = CharPropertyNames.charPropertyFor(name);
+    private CharProperty newCharProperty(CharPredicate p) {
         if (p == null)
-            throw error("Unknown character property name {" + name + "}");
-        return p;
+            return null;
+        if (p instanceof BmpCharPredicate)
+            return new BmpCharProperty((BmpCharPredicate)p);
+        else
+            return new CharProperty(p);
     }
 
     /**
@@ -2859,6 +2926,7 @@
         Node head = null;
         Node tail = null;
         int save = flags;
+        int saveTCNCount = topClosureNodes.size();
         root = null;
         int ch = next();
         if (ch == '?') {
@@ -2884,7 +2952,7 @@
                 head = createGroup(true);
                 tail = root;
                 head.next = expr(tail);
-                head = tail = new Ques(head, INDEPENDENT);
+                head = tail = new Ques(head, Qtype.INDEPENDENT);
                 break;
             case '<':   // (?<xxx)  look behind
                 ch = read();
@@ -2928,6 +2996,9 @@
                 } else {
                     throw error("Unknown look-behind group");
                 }
+                // clear all top-closure-nodes inside lookbehind
+                if (saveTCNCount < topClosureNodes.size())
+                    topClosureNodes.subList(saveTCNCount, topClosureNodes.size()).clear();
                 break;
             case '$':
             case '@':
@@ -2968,15 +3039,20 @@
             return node;    // Dual return
         }
 
+        // have group closure, clear all inner closure nodes from the
+        // top list (no backtracking stopper optimization for inner
+        if (saveTCNCount < topClosureNodes.size())
+            topClosureNodes.subList(saveTCNCount, topClosureNodes.size()).clear();
+
         if (node instanceof Ques) {
             Ques ques = (Ques) node;
-            if (ques.type == POSSESSIVE) {
+            if (ques.type == Qtype.POSSESSIVE) {
                 root = node;
                 return node;
             }
             tail.next = new BranchConn();
             tail = tail.next;
-            if (ques.type == GREEDY) {
+            if (ques.type == Qtype.GREEDY) {
                 head = new Branch(head, null, tail);
             } else { // Reluctant quantifier
                 head = new Branch(null, head, tail);
@@ -2985,7 +3061,7 @@
             return head;
         } else if (node instanceof Curly) {
             Curly curly = (Curly) node;
-            if (curly.type == POSSESSIVE) {
+            if (curly.type == Qtype.POSSESSIVE) {
                 root = node;
                 return node;
             }
@@ -3002,10 +3078,14 @@
             } else { // Non-deterministic
                 int temp = ((GroupHead) head).localIndex;
                 Loop loop;
-                if (curly.type == GREEDY)
+                if (curly.type == Qtype.GREEDY) {
                     loop = new Loop(this.localCount, temp);
-                else  // Reluctant Curly
+                    // add the max_reps greedy to the top-closure-node list
+                    if (curly.cmax == MAX_REPS)
+                        topClosureNodes.add(loop);
+                } else {  // Reluctant Curly
                     loop = new LazyLoop(this.localCount, temp);
+                }
                 Prolog prolog = new Prolog(loop);
                 this.localCount += 1;
                 loop.cmin = curly.cmin;
@@ -3031,6 +3111,10 @@
             groupIndex = capturingGroupCount++;
         GroupHead head = new GroupHead(localIndex);
         root = new GroupTail(localIndex, groupIndex);
+
+        // for debug/print only, head.match does NOT need the "tail" info
+        head.tail = (GroupTail)root;
+
         if (!anonymous && groupIndex < 10)
             groupNodes[groupIndex] = head;
         return head;
@@ -3119,13 +3203,26 @@
 
     static final int MAX_REPS   = 0x7FFFFFFF;
 
-    static final int GREEDY     = 0;
-
-    static final int LAZY       = 1;
-
-    static final int POSSESSIVE = 2;
-
-    static final int INDEPENDENT = 3;
+    static enum Qtype {
+        GREEDY, LAZY, POSSESSIVE, INDEPENDENT
+    }
+
+    private Node curly(Node prev, int cmin) {
+        int ch = next();
+        if (ch == '?') {
+            next();
+            return new Curly(prev, cmin, MAX_REPS, Qtype.LAZY);
+        } else if (ch == '+') {
+            next();
+            return new Curly(prev, cmin, MAX_REPS, Qtype.POSSESSIVE);
+        }
+        if (prev instanceof BmpCharProperty) {
+            return new BmpCharPropertyGreedy((BmpCharProperty)prev, cmin);
+        } else if (prev instanceof CharProperty) {
+            return new CharPropertyGreedy((CharProperty)prev, cmin);
+        }
+        return new Curly(prev, cmin, MAX_REPS, Qtype.GREEDY);
+    }
 
     /**
      * Processes repetition. If the next character peeked is a quantifier
@@ -3140,32 +3237,16 @@
             ch = next();
             if (ch == '?') {
                 next();
-                return new Ques(prev, LAZY);
-            } else if (ch == '+') {
-                next();
-                return new Ques(prev, POSSESSIVE);
-            }
-            return new Ques(prev, GREEDY);
-        case '*':
-            ch = next();
-            if (ch == '?') {
-                next();
-                return new Curly(prev, 0, MAX_REPS, LAZY);
+                return new Ques(prev, Qtype.LAZY);
             } else if (ch == '+') {
                 next();
-                return new Curly(prev, 0, MAX_REPS, POSSESSIVE);
+                return new Ques(prev, Qtype.POSSESSIVE);
             }
-            return new Curly(prev, 0, MAX_REPS, GREEDY);
+            return new Ques(prev, Qtype.GREEDY);
+        case '*':
+            return curly(prev, 0);
         case '+':
-            ch = next();
-            if (ch == '?') {
-                next();
-                return new Curly(prev, 1, MAX_REPS, LAZY);
-            } else if (ch == '+') {
-                next();
-                return new Curly(prev, 1, MAX_REPS, POSSESSIVE);
-            }
-            return new Curly(prev, 1, MAX_REPS, GREEDY);
+            return curly(prev, 1);
         case '{':
             ch = temp[cursor+1];
             if (ASCII.isDigit(ch)) {
@@ -3194,12 +3275,12 @@
                 ch = peek();
                 if (ch == '?') {
                     next();
-                    curly = new Curly(prev, cmin, cmax, LAZY);
+                    curly = new Curly(prev, cmin, cmax, Qtype.LAZY);
                 } else if (ch == '+') {
                     next();
-                    curly = new Curly(prev, cmin, cmax, POSSESSIVE);
+                    curly = new Curly(prev, cmin, cmax, Qtype.POSSESSIVE);
                 } else {
-                    curly = new Curly(prev, cmin, cmax, GREEDY);
+                    curly = new Curly(prev, cmin, cmax, Qtype.GREEDY);
                 }
                 return curly;
             } else {
@@ -3376,10 +3457,15 @@
      *  never matches values above Latin-1, and a complemented BitClass always
      *  matches values above Latin-1.
      */
-    private static final class BitClass extends BmpCharProperty {
+    static final class BitClass extends BmpCharProperty {
         final boolean[] bits;
-        BitClass() { bits = new boolean[256]; }
-        private BitClass(boolean[] bits) { this.bits = bits; }
+        BitClass() {
+            this(new boolean[256]);
+        }
+        private BitClass(boolean[] bits) {
+            super( ch -> ch < 256 && bits[ch]);
+            this.bits = bits;
+        }
         BitClass add(int c, int flags) {
             assert c >= 0 && c <= 255;
             if ((flags & CASE_INSENSITIVE) != 0) {
@@ -3394,32 +3480,6 @@
             bits[c] = true;
             return this;
         }
-        boolean isSatisfiedBy(int ch) {
-            return ch < 256 && bits[ch];
-        }
-    }
-
-    /**
-     *  Returns a suitably optimized, single character matcher.
-     */
-    private CharProperty newSingle(final int ch) {
-        if (has(CASE_INSENSITIVE)) {
-            int lower, upper;
-            if (has(UNICODE_CASE)) {
-                upper = Character.toUpperCase(ch);
-                lower = Character.toLowerCase(upper);
-                if (upper != lower)
-                    return new SingleU(lower);
-            } else if (ASCII.isAscii(ch)) {
-                lower = ASCII.toLower(ch);
-                upper = ASCII.toUpper(ch);
-                if (lower != upper)
-                    return new SingleI(lower, upper);
-            }
-        }
-        if (isSupplementary(ch))
-            return new SingleS(ch);    // Match a given Unicode character
-        return new Single(ch);         // Match a given BMP character
     }
 
     /**
@@ -3827,18 +3887,17 @@
      * Abstract node class to match one character satisfying some
      * boolean property.
      */
-    private abstract static class CharProperty extends Node {
-        abstract boolean isSatisfiedBy(int ch);
-        CharProperty complement() {
-            return new CharProperty() {
-                    boolean isSatisfiedBy(int ch) {
-                        return ! CharProperty.this.isSatisfiedBy(ch);}};
+    static class CharProperty extends Node {
+        CharPredicate predicate;
+
+        CharProperty (CharPredicate predicate) {
+            this.predicate = predicate;
         }
         boolean match(Matcher matcher, int i, CharSequence seq) {
             if (i < matcher.to) {
                 int ch = Character.codePointAt(seq, i);
-                return isSatisfiedBy(ch)
-                    && next.match(matcher, i+Character.charCount(ch), seq);
+                return predicate.is(ch) &&
+                       next.match(matcher, i + Character.charCount(ch), seq);
             } else {
                 matcher.hitEnd = true;
                 return false;
@@ -3855,11 +3914,14 @@
      * Optimized version of CharProperty that works only for
      * properties never satisfied by Supplementary characters.
      */
-    private abstract static class BmpCharProperty extends CharProperty {
+    private static class BmpCharProperty extends CharProperty {
+        BmpCharProperty (BmpCharPredicate predicate) {
+            super(predicate);
+        }
         boolean match(Matcher matcher, int i, CharSequence seq) {
             if (i < matcher.to) {
-                return isSatisfiedBy(seq.charAt(i))
-                    && next.match(matcher, i+1, seq);
+                return predicate.is(seq.charAt(i)) &&
+                       next.match(matcher, i + 1, seq);
             } else {
                 matcher.hitEnd = true;
                 return false;
@@ -3867,135 +3929,53 @@
         }
     }
 
-    /**
-     * Node class that matches a Supplementary Unicode character
-     */
-    static final class SingleS extends CharProperty {
-        final int c;
-        SingleS(int c) { this.c = c; }
-        boolean isSatisfiedBy(int ch) {
-            return ch == c;
-        }
-    }
-
-    /**
-     * Optimization -- matches a given BMP character
-     */
-    static final class Single extends BmpCharProperty {
-        final int c;
-        Single(int c) { this.c = c; }
-        boolean isSatisfiedBy(int ch) {
-            return ch == c;
-        }
-    }
-
-    /**
-     * Case insensitive matches a given BMP character
-     */
-    static final class SingleI extends BmpCharProperty {
-        final int lower;
-        final int upper;
-        SingleI(int lower, int upper) {
-            this.lower = lower;
-            this.upper = upper;
-        }
-        boolean isSatisfiedBy(int ch) {
-            return ch == lower || ch == upper;
-        }
-    }
-
-    /**
-     * Unicode case insensitive matches a given Unicode character
-     */
-    static final class SingleU extends CharProperty {
-        final int lower;
-        SingleU(int lower) {
-            this.lower = lower;
-        }
-        boolean isSatisfiedBy(int ch) {
-            return lower == ch ||
-                lower == Character.toLowerCase(Character.toUpperCase(ch));
-        }
-    }
-
-    /**
-     * Node class that matches a Unicode block.
-     */
-    static final class Block extends CharProperty {
-        final Character.UnicodeBlock block;
-        Block(Character.UnicodeBlock block) {
-            this.block = block;
-        }
-        boolean isSatisfiedBy(int ch) {
-            return block == Character.UnicodeBlock.of(ch);
-        }
-    }
-
-    /**
-     * Node class that matches a Unicode script
-     */
-    static final class Script extends CharProperty {
-        final Character.UnicodeScript script;
-        Script(Character.UnicodeScript script) {
-            this.script = script;
-        }
-        boolean isSatisfiedBy(int ch) {
-            return script == Character.UnicodeScript.of(ch);
-        }
-    }
-
-    /**
-     * Node class that matches a Unicode category.
-     */
-    static final class Category extends CharProperty {
-        final int typeMask;
-        Category(int typeMask) { this.typeMask = typeMask; }
-        boolean isSatisfiedBy(int ch) {
-            return (typeMask & (1 << Character.getType(ch))) != 0;
-        }
-    }
-
-    /**
-     * Node class that matches a Unicode "type"
-     */
-    static final class Utype extends CharProperty {
-        final UnicodeProp uprop;
-        Utype(UnicodeProp uprop) { this.uprop = uprop; }
-        boolean isSatisfiedBy(int ch) {
-            return uprop.is(ch);
-        }
-    }
-
-    /**
-     * Node class that matches a POSIX type.
-     */
-    static final class Ctype extends BmpCharProperty {
-        final int ctype;
-        Ctype(int ctype) { this.ctype = ctype; }
-        boolean isSatisfiedBy(int ch) {
-            return ch < 128 && ASCII.isType(ch, ctype);
-        }
-    }
-
-    /**
-     * Node class that matches a Perl vertical whitespace
-     */
-    static final class VertWS extends BmpCharProperty {
-        boolean isSatisfiedBy(int cp) {
-            return (cp >= 0x0A && cp <= 0x0D) ||
-                   cp == 0x85 || cp == 0x2028 || cp == 0x2029;
-        }
-    }
-
-    /**
-     * Node class that matches a Perl horizontal whitespace
-     */
-    static final class HorizWS extends BmpCharProperty {
-        boolean isSatisfiedBy(int cp) {
-            return cp == 0x09 || cp == 0x20 || cp == 0xa0 ||
-                   cp == 0x1680 || cp == 0x180e ||
-                   cp >= 0x2000 && cp <= 0x200a ||
-                   cp == 0x202f || cp == 0x205f || cp == 0x3000;
+    private static class NFCCharProperty extends Node {
+        CharPredicate predicate;
+        NFCCharProperty (CharPredicate predicate) {
+            this.predicate = predicate;
+        }
+
+        boolean match(Matcher matcher, int i, CharSequence seq) {
+            if (i < matcher.to) {
+                int ch0 = Character.codePointAt(seq, i);
+                int n = Character.charCount(ch0);
+                int j = i + n;
+                while (j < matcher.to) {
+                    int ch1 = Character.codePointAt(seq, j);
+                    if (Grapheme.isBoundary(ch0, ch1))
+                        break;
+                    ch0 = ch1;
+                    j += Character.charCount(ch1);
+                }
+                if (i + n == j) {    // single, assume nfc cp
+                    if (predicate.is(ch0))
+                        return next.match(matcher, j, seq);
+                } else {
+                    while (i + n < j) {
+                        String nfc = Normalizer.normalize(
+                            seq.toString().substring(i, j), Normalizer.Form.NFC);
+                        if (nfc.codePointCount(0, nfc.length()) == 1) {
+                            if (predicate.is(nfc.codePointAt(0)) &&
+                                next.match(matcher, j, seq)) {
+                                return true;
+                            }
+                        }
+
+                        ch0 = Character.codePointBefore(seq, j);
+                        j -= Character.charCount(ch0);
+                    }
+                }
+                if (j < matcher.to)
+                    return false;
+            }
+            matcher.hitEnd = true;
+            return false;
+        }
+
+        boolean study(TreeInfo info) {
+            info.minLength++;
+            info.deterministic = false;
+            return next.study(info);
         }
     }
 
@@ -4217,81 +4197,13 @@
         }
     }
 
-    private static boolean inRange(int lower, int ch, int upper) {
-        return lower <= ch && ch <= upper;
-    }
-
-    /**
-     * Returns node for matching characters within an explicit value range.
-     */
-    private static CharProperty rangeFor(final int lower,
-                                         final int upper) {
-        return new CharProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return inRange(lower, ch, upper);}};
-    }
-
-    /**
-     * Returns node for matching characters within an explicit value
-     * range in a case insensitive manner.
-     */
-    private CharProperty caseInsensitiveRangeFor(final int lower,
-                                                 final int upper) {
-        if (has(UNICODE_CASE))
-            return new CharProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    if (inRange(lower, ch, upper))
-                        return true;
-                    int up = Character.toUpperCase(ch);
-                    return inRange(lower, up, upper) ||
-                           inRange(lower, Character.toLowerCase(up), upper);}};
-        return new CharProperty() {
-            boolean isSatisfiedBy(int ch) {
-                return inRange(lower, ch, upper) ||
-                    ASCII.isAscii(ch) &&
-                        (inRange(lower, ASCII.toUpper(ch), upper) ||
-                         inRange(lower, ASCII.toLower(ch), upper));
-            }};
-    }
-
-    /**
-     * Implements the Unicode category ALL and the dot metacharacter when
-     * in dotall mode.
-     */
-    static final class All extends CharProperty {
-        boolean isSatisfiedBy(int ch) {
-            return true;
-        }
-    }
-
-    /**
-     * Node class for the dot metacharacter when dotall is not enabled.
-     */
-    static final class Dot extends CharProperty {
-        boolean isSatisfiedBy(int ch) {
-            return (ch != '\n' && ch != '\r'
-                    && (ch|1) != '\u2029'
-                    && ch != '\u0085');
-        }
-    }
-
-    /**
-     * Node class for the dot metacharacter when dotall is not enabled
-     * but UNIX_LINES is enabled.
-     */
-    static final class UnixDot extends CharProperty {
-        boolean isSatisfiedBy(int ch) {
-            return ch != '\n';
-        }
-    }
-
     /**
      * The 0 or 1 quantifier. This one class implements all three types.
      */
     static final class Ques extends Node {
         Node atom;
-        int type;
-        Ques(Node node, int type) {
+        Qtype type;
+        Ques(Node node, Qtype type) {
             this.atom = node;
             this.type = type;
         }
@@ -4311,7 +4223,7 @@
             }
         }
         boolean study(TreeInfo info) {
-            if (type != INDEPENDENT) {
+            if (type != Qtype.INDEPENDENT) {
                 int minL = info.minLength;
                 atom.study(info);
                 info.minLength = minL;
@@ -4325,17 +4237,90 @@
     }
 
     /**
+     * Handles the greedy style repetition with the minimum either be
+     * 0 or 1 and the maximum be MAX_REPS, for * and + quantifier.
+     */
+    static class CharPropertyGreedy extends Node {
+        final CharPredicate predicate;
+        final int cmin;
+
+        CharPropertyGreedy(CharProperty cp, int cmin) {
+            this.predicate = cp.predicate;
+            this.cmin = cmin;
+        }
+        boolean match(Matcher matcher, int i,  CharSequence seq) {
+            int n = 0;
+            int to = matcher.to;
+            // greedy, all the way down
+            while (i < to) {
+                int ch = Character.codePointAt(seq, i);
+                if (!predicate.is(ch))
+                   break;
+                i += Character.charCount(ch);
+                n++;
+            }
+            if (i >= to) {
+                matcher.hitEnd = true;
+            }
+            while (n >= cmin) {
+                if (next.match(matcher, i, seq))
+                    return true;
+                if (n == cmin)
+                    return false;
+                 // backing off if match fails
+                int ch = Character.codePointBefore(seq, i);
+                i -= Character.charCount(ch);
+                n--;
+            }
+            return false;
+        }
+
+        boolean study(TreeInfo info) {
+            info.minLength += cmin;
+            if (info.maxValid) {
+                info.maxLength += MAX_REPS;
+            }
+            info.deterministic = false;
+            return next.study(info);
+        }
+    }
+
+    static final class BmpCharPropertyGreedy extends CharPropertyGreedy {
+
+        BmpCharPropertyGreedy(BmpCharProperty bcp, int cmin) {
+            super(bcp, cmin);
+        }
+
+        boolean match(Matcher matcher, int i,  CharSequence seq) {
+            int n = 0;
+            int to = matcher.to;
+            while (i < to && predicate.is(seq.charAt(i))) {
+                i++; n++;
+            }
+            if (i >= to) {
+                matcher.hitEnd = true;
+            }
+            while (n >= cmin) {
+                if (next.match(matcher, i, seq))
+                    return true;
+                i--; n--;  // backing off if match fails
+            }
+            return false;
+        }
+    }
+
+    /**
      * Handles the curly-brace style repetition with a specified minimum and
      * maximum occurrences. The * quantifier is handled as a special case.
      * This class handles the three types.
      */
     static final class Curly extends Node {
         Node atom;
-        int type;
+        Qtype type;
         int cmin;
         int cmax;
 
-        Curly(Node node, int cmin, int cmax, int type) {
+        Curly(Node node, int cmin, int cmax, Qtype type) {
             this.atom = node;
             this.type = type;
             this.cmin = cmin;
@@ -4350,9 +4335,9 @@
                 }
                 return false;
             }
-            if (type == GREEDY)
+            if (type == Qtype.GREEDY)
                 return match0(matcher, i, j, seq);
-            else if (type == LAZY)
+            else if (type == Qtype.LAZY)
                 return match1(matcher, i, j, seq);
             else
                 return match2(matcher, i, j, seq);
@@ -4474,14 +4459,14 @@
      */
     static final class GroupCurly extends Node {
         Node atom;
-        int type;
+        Qtype type;
         int cmin;
         int cmax;
         int localIndex;
         int groupIndex;
         boolean capture;
 
-        GroupCurly(Node node, int cmin, int cmax, int type, int local,
+        GroupCurly(Node node, int cmin, int cmax, Qtype type, int local,
                    int group, boolean capture) {
             this.atom = node;
             this.type = type;
@@ -4521,9 +4506,9 @@
                 }
             }
             if (ret) {
-                if (type == GREEDY) {
+                if (type == Qtype.GREEDY) {
                     ret = match0(matcher, i, cmin, seq);
-                } else if (type == LAZY) {
+                } else if (type == Qtype.LAZY) {
                     ret = match1(matcher, i, cmin, seq);
                 } else {
                     ret = match2(matcher, i, cmin, seq);
@@ -4769,6 +4754,7 @@
      */
     static final class GroupHead extends Node {
         int localIndex;
+        GroupTail tail;    // for debug/print only, match does not need to know
         GroupHead(int localCount) {
             localIndex = localCount;
         }
@@ -4876,9 +4862,11 @@
         int countIndex; // local count index in matcher locals
         int beginIndex; // group beginning index
         int cmin, cmax;
+        int posIndex;
         Loop(int countIndex, int beginIndex) {
             this.countIndex = countIndex;
             this.beginIndex = beginIndex;
+            this.posIndex = -1;
         }
         boolean match(Matcher matcher, int i, CharSequence seq) {
             // Avoid infinite loop in zero-length case.
@@ -4901,14 +4889,25 @@
                 // This block is for after we have the minimum
                 // iterations required for the loop to match
                 if (count < cmax) {
+                    // Let's check if we have already tried and failed
+                    // at this starting position "i" in the past.
+                    // If yes, then just return false wihtout trying
+                    // again, to stop the exponential backtracking.
+                    if (posIndex != -1 &&
+                        matcher.localsPos[posIndex].contains(i)) {
+                        return next.match(matcher, i, seq);
+                    }
                     matcher.locals[countIndex] = count + 1;
                     boolean b = body.match(matcher, i, seq);
                     // If match failed we must backtrack, so
                     // the loop count should NOT be incremented
-                    if (!b)
-                        matcher.locals[countIndex] = count;
-                    else
+                    if (b)
                         return true;
+                    matcher.locals[countIndex] = count;
+                    // save the failed position
+                    if (posIndex != -1) {
+                        matcher.localsPos[posIndex].add(i);
+                    }
                 }
             }
             return next.match(matcher, i, seq);
@@ -4916,6 +4915,9 @@
         boolean matchInit(Matcher matcher, int i, CharSequence seq) {
             int save = matcher.locals[countIndex];
             boolean ret = false;
+            if (posIndex != -1 && matcher.localsPos[posIndex] == null) {
+                matcher.localsPos[posIndex] = new IntHashSet();
+            }
             if (0 < cmin) {
                 matcher.locals[countIndex] = 1;
                 ret = body.match(matcher, i, seq);
@@ -5362,36 +5364,6 @@
     }
 
     /**
-     * Returns the set union of two CharProperty nodes.
-     */
-    private static CharProperty union(final CharProperty lhs,
-                                      final CharProperty rhs) {
-        return new CharProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return lhs.isSatisfiedBy(ch) || rhs.isSatisfiedBy(ch);}};
-    }
-
-    /**
-     * Returns the set intersection of two CharProperty nodes.
-     */
-    private static CharProperty intersection(final CharProperty lhs,
-                                             final CharProperty rhs) {
-        return new CharProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return lhs.isSatisfiedBy(ch) && rhs.isSatisfiedBy(ch);}};
-    }
-
-    /**
-     * Returns the set difference of two CharProperty nodes.
-     */
-    private static CharProperty setDifference(final CharProperty lhs,
-                                              final CharProperty rhs) {
-        return new CharProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return ! rhs.isSatisfiedBy(ch) && lhs.isSatisfiedBy(ch);}};
-    }
-
-    /**
      * Handles word boundaries. Includes a field to allow this one class to
      * deal with the different types of word boundaries we can match. The word
      * characters include underscores, letters, and digits. Non spacing marks
@@ -5411,7 +5383,7 @@
         }
 
         boolean isWord(int ch) {
-            return useUWORD ? UnicodeProp.WORD.is(ch)
+            return useUWORD ? CharPredicates.WORD.is(ch)
                             : (ch == '_' || Character.isLetterOrDigit(ch));
         }
 
@@ -5657,214 +5629,154 @@
         }
     }
 
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
+    @FunctionalInterface
+    static interface CharPredicate {
+        boolean is(int ch);
+
+        default CharPredicate and(CharPredicate p) {
+            return ch -> is(ch) && p.is(ch);
+        }
+        default CharPredicate union(CharPredicate p) {
+            return ch -> is(ch) || p.is(ch);
+        }
+        default CharPredicate union(CharPredicate p1,
+                                    CharPredicate p2 ) {
+            return ch -> is(ch) || p1.is(ch) || p2.is(ch);
+        }
+        default CharPredicate negate() {
+            return ch -> !is(ch);
+        }
+    }
+
+    static interface BmpCharPredicate extends CharPredicate {
+
+        default CharPredicate and(CharPredicate p) {
+            if(p instanceof BmpCharPredicate)
+                return (BmpCharPredicate)(ch -> is(ch) && p.is(ch));
+            return ch -> is(ch) && p.is(ch);
+        }
+        default CharPredicate union(CharPredicate p) {
+            if (p instanceof BmpCharPredicate)
+                return (BmpCharPredicate)(ch -> is(ch) || p.is(ch));
+            return ch -> is(ch) || p.is(ch);
+        }
+        static CharPredicate union(CharPredicate... predicates) {
+            CharPredicate cp = ch -> {
+                for (CharPredicate p : predicates) {
+                    if (!p.is(ch))
+                        return false;
+                }
+                return true;
+            };
+            for (CharPredicate p : predicates) {
+                if (! (p instanceof BmpCharPredicate))
+                    return cp;
+            }
+            return (BmpCharPredicate)cp;
+        }
+    }
+
+    /**
+     * matches a Perl vertical whitespace
+     */
+    static BmpCharPredicate VertWS = cp ->
+        (cp >= 0x0A && cp <= 0x0D) || cp == 0x85 || cp == 0x2028 || cp == 0x2029;
+
+    /**
+     * matches a Perl horizontal whitespace
+     */
+    static BmpCharPredicate HorizWS = cp ->
+        cp == 0x09 || cp == 0x20 || cp == 0xa0 || cp == 0x1680 ||
+        cp == 0x180e || cp >= 0x2000 && cp <= 0x200a ||  cp == 0x202f ||
+        cp == 0x205f || cp == 0x3000;
+
+    /**
+     *  for the Unicode category ALL and the dot metacharacter when
+     *  in dotall mode.
+     */
+    static CharPredicate ALL = ch -> true;
+
+    /**
+     * for the dot metacharacter when dotall is not enabled.
+     */
+    static CharPredicate DOT = ch -> (ch != '\n' && ch != '\r'
+                                          && (ch|1) != '\u2029'
+                                          && ch != '\u0085');
+    /**
+     *  the dot metacharacter when dotall is not enabled but UNIX_LINES is enabled.
+     */
+    static CharPredicate UNIXDOT = ch ->  ch != '\n';
+
+    /**
+     * Indicate that matches a Supplementary Unicode character
+     */
+    static CharPredicate SingleS(int c) {
+        return ch -> ch == c;
+    }
+
+    /**
+     * A bmp/optimized predicate of single
+     */
+    static BmpCharPredicate Single(int c) {
+        return ch -> ch == c;
+    }
+
+    /**
+     * Case insensitive matches a given BMP character
+     */
+    static BmpCharPredicate SingleI(int lower, int upper) {
+        return ch -> ch == lower || ch == upper;
+    }
+
+    /**
+     * Unicode case insensitive matches a given Unicode character
+     */
+    static CharPredicate SingleU(int lower) {
+        return ch -> lower == ch ||
+                     lower == Character.toLowerCase(Character.toUpperCase(ch));
+    }
+
+    private static boolean inRange(int lower, int ch, int upper) {
+        return lower <= ch && ch <= upper;
+    }
+
+    /**
+     * Charactrs within a explicit value range
+     */
+    static CharPredicate Range(int lower, int upper) {
+        if (upper < Character.MIN_HIGH_SURROGATE ||
+            lower > Character.MAX_HIGH_SURROGATE &&
+            upper < Character.MIN_SUPPLEMENTARY_CODE_POINT)
+            return (BmpCharPredicate)(ch -> inRange(lower, ch, upper));
+        return ch -> inRange(lower, ch, upper);
+    }
+
+   /**
+    * Charactrs within a explicit value range in a case insensitive manner.
+    */
+    static CharPredicate CIRange(int lower, int upper) {
+        return ch -> inRange(lower, ch, upper) ||
+                     ASCII.isAscii(ch) &&
+                     (inRange(lower, ASCII.toUpper(ch), upper) ||
+                      inRange(lower, ASCII.toLower(ch), upper));
+    }
+
+    static CharPredicate CIRangeU(int lower, int upper) {
+        return ch -> {
+            if (inRange(lower, ch, upper))
+                return true;
+            int up = Character.toUpperCase(ch);
+            return inRange(lower, up, upper) ||
+                   inRange(lower, Character.toLowerCase(up), upper);
+        };
+    }
 
     /**
      *  This must be the very first initializer.
      */
-    static Node accept = new Node();
-
-    static Node lastAccept = new LastNode();
-
-    private static class CharPropertyNames {
-
-        static CharProperty charPropertyFor(String name) {
-            CharPropertyFactory m = map.get(name);
-            return m == null ? null : m.make();
-        }
-
-        private abstract static class CharPropertyFactory {
-            abstract CharProperty make();
-        }
-
-        private static void defCategory(String name,
-                                        final int typeMask) {
-            map.put(name, new CharPropertyFactory() {
-                    CharProperty make() { return new Category(typeMask);}});
-        }
-
-        private static void defRange(String name,
-                                     final int lower, final int upper) {
-            map.put(name, new CharPropertyFactory() {
-                    CharProperty make() { return rangeFor(lower, upper);}});
-        }
-
-        private static void defCtype(String name,
-                                     final int ctype) {
-            map.put(name, new CharPropertyFactory() {
-                    CharProperty make() { return new Ctype(ctype);}});
-        }
-
-        private abstract static class CloneableProperty
-            extends CharProperty implements Cloneable
-        {
-            public CloneableProperty clone() {
-                try {
-                    return (CloneableProperty) super.clone();
-                } catch (CloneNotSupportedException e) {
-                    throw new AssertionError(e);
-                }
-            }
-        }
-
-        private static void defClone(String name,
-                                     final CloneableProperty p) {
-            map.put(name, new CharPropertyFactory() {
-                    CharProperty make() { return p.clone();}});
-        }
-
-        private static final HashMap<String, CharPropertyFactory> map
-            = new HashMap<>();
-
-        static {
-            // Unicode character property aliases, defined in
-            // http://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt
-            defCategory("Cn", 1<<Character.UNASSIGNED);
-            defCategory("Lu", 1<<Character.UPPERCASE_LETTER);
-            defCategory("Ll", 1<<Character.LOWERCASE_LETTER);
-            defCategory("Lt", 1<<Character.TITLECASE_LETTER);
-            defCategory("Lm", 1<<Character.MODIFIER_LETTER);
-            defCategory("Lo", 1<<Character.OTHER_LETTER);
-            defCategory("Mn", 1<<Character.NON_SPACING_MARK);
-            defCategory("Me", 1<<Character.ENCLOSING_MARK);
-            defCategory("Mc", 1<<Character.COMBINING_SPACING_MARK);
-            defCategory("Nd", 1<<Character.DECIMAL_DIGIT_NUMBER);
-            defCategory("Nl", 1<<Character.LETTER_NUMBER);
-            defCategory("No", 1<<Character.OTHER_NUMBER);
-            defCategory("Zs", 1<<Character.SPACE_SEPARATOR);
-            defCategory("Zl", 1<<Character.LINE_SEPARATOR);
-            defCategory("Zp", 1<<Character.PARAGRAPH_SEPARATOR);
-            defCategory("Cc", 1<<Character.CONTROL);
-            defCategory("Cf", 1<<Character.FORMAT);
-            defCategory("Co", 1<<Character.PRIVATE_USE);
-            defCategory("Cs", 1<<Character.SURROGATE);
-            defCategory("Pd", 1<<Character.DASH_PUNCTUATION);
-            defCategory("Ps", 1<<Character.START_PUNCTUATION);
-            defCategory("Pe", 1<<Character.END_PUNCTUATION);
-            defCategory("Pc", 1<<Character.CONNECTOR_PUNCTUATION);
-            defCategory("Po", 1<<Character.OTHER_PUNCTUATION);
-            defCategory("Sm", 1<<Character.MATH_SYMBOL);
-            defCategory("Sc", 1<<Character.CURRENCY_SYMBOL);
-            defCategory("Sk", 1<<Character.MODIFIER_SYMBOL);
-            defCategory("So", 1<<Character.OTHER_SYMBOL);
-            defCategory("Pi", 1<<Character.INITIAL_QUOTE_PUNCTUATION);
-            defCategory("Pf", 1<<Character.FINAL_QUOTE_PUNCTUATION);
-            defCategory("L", ((1<<Character.UPPERCASE_LETTER) |
-                              (1<<Character.LOWERCASE_LETTER) |
-                              (1<<Character.TITLECASE_LETTER) |
-                              (1<<Character.MODIFIER_LETTER)  |
-                              (1<<Character.OTHER_LETTER)));
-            defCategory("M", ((1<<Character.NON_SPACING_MARK) |
-                              (1<<Character.ENCLOSING_MARK)   |
-                              (1<<Character.COMBINING_SPACING_MARK)));
-            defCategory("N", ((1<<Character.DECIMAL_DIGIT_NUMBER) |
-                              (1<<Character.LETTER_NUMBER)        |
-                              (1<<Character.OTHER_NUMBER)));
-            defCategory("Z", ((1<<Character.SPACE_SEPARATOR) |
-                              (1<<Character.LINE_SEPARATOR)  |
-                              (1<<Character.PARAGRAPH_SEPARATOR)));
-            defCategory("C", ((1<<Character.CONTROL)     |
-                              (1<<Character.FORMAT)      |
-                              (1<<Character.PRIVATE_USE) |
-                              (1<<Character.SURROGATE))); // Other
-            defCategory("P", ((1<<Character.DASH_PUNCTUATION)      |
-                              (1<<Character.START_PUNCTUATION)     |
-                              (1<<Character.END_PUNCTUATION)       |
-                              (1<<Character.CONNECTOR_PUNCTUATION) |
-                              (1<<Character.OTHER_PUNCTUATION)     |
-                              (1<<Character.INITIAL_QUOTE_PUNCTUATION) |
-                              (1<<Character.FINAL_QUOTE_PUNCTUATION)));
-            defCategory("S", ((1<<Character.MATH_SYMBOL)     |
-                              (1<<Character.CURRENCY_SYMBOL) |
-                              (1<<Character.MODIFIER_SYMBOL) |
-                              (1<<Character.OTHER_SYMBOL)));
-            defCategory("LC", ((1<<Character.UPPERCASE_LETTER) |
-                               (1<<Character.LOWERCASE_LETTER) |
-                               (1<<Character.TITLECASE_LETTER)));
-            defCategory("LD", ((1<<Character.UPPERCASE_LETTER) |
-                               (1<<Character.LOWERCASE_LETTER) |
-                               (1<<Character.TITLECASE_LETTER) |
-                               (1<<Character.MODIFIER_LETTER)  |
-                               (1<<Character.OTHER_LETTER)     |
-                               (1<<Character.DECIMAL_DIGIT_NUMBER)));
-            defRange("L1", 0x00, 0xFF); // Latin-1
-            map.put("all", new CharPropertyFactory() {
-                    CharProperty make() { return new All(); }});
-
-            // Posix regular expression character classes, defined in
-            // http://www.unix.org/onlinepubs/009695399/basedefs/xbd_chap09.html
-            defRange("ASCII", 0x00, 0x7F);   // ASCII
-            defCtype("Alnum", ASCII.ALNUM);  // Alphanumeric characters
-            defCtype("Alpha", ASCII.ALPHA);  // Alphabetic characters
-            defCtype("Blank", ASCII.BLANK);  // Space and tab characters
-            defCtype("Cntrl", ASCII.CNTRL);  // Control characters
-            defRange("Digit", '0', '9');     // Numeric characters
-            defCtype("Graph", ASCII.GRAPH);  // printable and visible
-            defRange("Lower", 'a', 'z');     // Lower-case alphabetic
-            defRange("Print", 0x20, 0x7E);   // Printable characters
-            defCtype("Punct", ASCII.PUNCT);  // Punctuation characters
-            defCtype("Space", ASCII.SPACE);  // Space characters
-            defRange("Upper", 'A', 'Z');     // Upper-case alphabetic
-            defCtype("XDigit",ASCII.XDIGIT); // hexadecimal digits
-
-            // Java character properties, defined by methods in Character.java
-            defClone("javaLowerCase", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isLowerCase(ch);}});
-            defClone("javaUpperCase", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isUpperCase(ch);}});
-            defClone("javaAlphabetic", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isAlphabetic(ch);}});
-            defClone("javaIdeographic", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isIdeographic(ch);}});
-            defClone("javaTitleCase", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isTitleCase(ch);}});
-            defClone("javaDigit", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isDigit(ch);}});
-            defClone("javaDefined", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isDefined(ch);}});
-            defClone("javaLetter", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isLetter(ch);}});
-            defClone("javaLetterOrDigit", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isLetterOrDigit(ch);}});
-            defClone("javaJavaIdentifierStart", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isJavaIdentifierStart(ch);}});
-            defClone("javaJavaIdentifierPart", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isJavaIdentifierPart(ch);}});
-            defClone("javaUnicodeIdentifierStart", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isUnicodeIdentifierStart(ch);}});
-            defClone("javaUnicodeIdentifierPart", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isUnicodeIdentifierPart(ch);}});
-            defClone("javaIdentifierIgnorable", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isIdentifierIgnorable(ch);}});
-            defClone("javaSpaceChar", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isSpaceChar(ch);}});
-            defClone("javaWhitespace", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isWhitespace(ch);}});
-            defClone("javaISOControl", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isISOControl(ch);}});
-            defClone("javaMirrored", new CloneableProperty() {
-                boolean isSatisfiedBy(int ch) {
-                    return Character.isMirrored(ch);}});
-        }
-    }
+    static final Node accept = new Node();
+
+    static final Node lastAccept = new LastNode();
 
     /**
      * Creates a predicate which can be used to match a string.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/regex/PrintPattern.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,220 @@
+/*
+ * 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 java.util.regex;
+
+import java.util.HashMap;
+import java.util.regex.Pattern.CharPredicate;
+import java.util.regex.CharPredicates;
+import static java.util.regex.ASCII.*;
+
+/**
+ * A utility class to print out the pattern node tree.
+ */
+
+class PrintPattern {
+
+    private static HashMap<Pattern.Node, Integer> ids = new HashMap<>();
+
+    private static void print(Pattern.Node node, String text, int depth) {
+        if (!ids.containsKey(node))
+            ids.put(node, ids.size());
+        print("%6d:%" + (depth==0? "": depth<<1) + "s<%s>", ids.get(node), "", text);
+        if (ids.containsKey(node.next))
+            print(" (=>%d)", ids.get(node.next));
+        print("%n");
+    }
+
+    private static void print(String s, int depth) {
+        print("       %" + (depth==0?"":depth<<1) + "s<%s>%n", "", s);
+    }
+
+    private static void print(String fmt, Object ... args) {
+        System.err.printf(fmt, args);
+    }
+
+    private static String toStringCPS(int[] cps) {
+        StringBuilder sb = new StringBuilder(cps.length);
+        for (int cp : cps)
+            sb.append(toStringCP(cp));
+        return sb.toString();
+    }
+
+    private static String toStringCP(int cp) {
+        return (isPrint(cp) ? "" + (char)cp
+                            : "\\u" + Integer.toString(cp, 16));
+    }
+
+    private static String toStringRange(int min, int max) {
+       if (max == Pattern.MAX_REPS) {
+           if (min == 0)
+               return " * ";
+           else if (min == 1)
+               return " + ";
+           return "{" + min + ", max}";
+       }
+       return "{" + min + ", " +  max + "}";
+    }
+
+    private static String toStringCtype(int type) {
+        switch(type) {
+        case UPPER:  return "ASCII.UPPER";
+        case LOWER:  return "ASCII.LOWER";
+        case DIGIT:  return "ASCII.DIGIT";
+        case SPACE:  return "ASCII.SPACE";
+        case PUNCT:  return "ASCII.PUNCT";
+        case CNTRL:  return "ASCII.CNTRL";
+        case BLANK:  return "ASCII.BLANK";
+        case UNDER:  return "ASCII.UNDER";
+        case ASCII:  return "ASCII.ASCII";
+        case ALPHA:  return "ASCII.ALPHA";
+        case ALNUM:  return "ASCII.ALNUM";
+        case GRAPH:  return "ASCII.GRAPH";
+        case WORD:   return "ASCII.WORD";
+        case XDIGIT: return "ASCII.XDIGIT";
+        default: return "ASCII ?";
+        }
+    }
+
+    private static String toString(Pattern.Node node) {
+        String name = node.getClass().getName();
+        return name.substring(name.lastIndexOf('$') + 1);
+    }
+
+    static HashMap<CharPredicate, String> pmap;
+    static {
+        pmap = new HashMap<>();
+        pmap.put(Pattern.ALL, "All");
+        pmap.put(Pattern.DOT, "Dot");
+        pmap.put(Pattern.UNIXDOT, "UnixDot");
+        pmap.put(Pattern.VertWS, "VertWS");
+        pmap.put(Pattern.HorizWS, "HorizWS");
+
+        pmap.put(CharPredicates.ASCII_DIGIT, "ASCII.DIGIT");
+        pmap.put(CharPredicates.ASCII_WORD,  "ASCII.WORD");
+        pmap.put(CharPredicates.ASCII_SPACE, "ASCII.SPACE");
+    }
+
+    static void walk(Pattern.Node node, int depth) {
+        depth++;
+        while(node != null) {
+            String name = toString(node);
+            String str;
+            if (node instanceof Pattern.Prolog) {
+                print(node, name, depth);
+                // print the loop here
+                Pattern.Loop loop = ((Pattern.Prolog)node).loop;
+                name = toString(loop);
+                str = name + " " + toStringRange(loop.cmin, loop.cmax);
+                print(loop, str, depth);
+                walk(loop.body, depth);
+                print("/" + name, depth);
+                node = loop;
+            } else if (node instanceof Pattern.Loop) {
+                return;  // stop here, body.next -> loop
+            } else if (node instanceof Pattern.Curly) {
+                Pattern.Curly c = (Pattern.Curly)node;
+                str = "Curly " + c.type + " " + toStringRange(c.cmin, c.cmax);
+                print(node, str, depth);
+                walk(c.atom, depth);
+                print("/Curly", depth);
+            } else if (node instanceof Pattern.GroupCurly) {
+                Pattern.GroupCurly gc = (Pattern.GroupCurly)node;
+                str = "GroupCurly " + gc.groupIndex / 2 +
+                      ", " + gc.type + " " + toStringRange(gc.cmin, gc.cmax);
+                print(node, str, depth);
+                walk(gc.atom, depth);
+                print("/GroupCurly", depth);
+            } else if (node instanceof Pattern.GroupHead) {
+                Pattern.GroupHead head = (Pattern.GroupHead)node;
+                Pattern.GroupTail tail = head.tail;
+                print(head, "Group.head " + (tail.groupIndex / 2), depth);
+                walk(head.next, depth);
+                print(tail, "/Group.tail " + (tail.groupIndex / 2), depth);
+                node = tail;
+            } else if (node instanceof Pattern.GroupTail) {
+                return;  // stopper
+            } else if (node instanceof Pattern.Ques) {
+                print(node, "Ques " + ((Pattern.Ques)node).type, depth);
+                walk(((Pattern.Ques)node).atom, depth);
+                print("/Ques", depth);
+            } else if (node instanceof Pattern.Branch) {
+                Pattern.Branch b = (Pattern.Branch)node;
+                print(b, name, depth);
+                int i = 0;
+                while (true) {
+                    if (b.atoms[i] != null) {
+                        walk(b.atoms[i], depth);
+                    } else {
+                        print("  (accepted)", depth);
+                    }
+                    if (++i == b.size)
+                        break;
+                    print("-branch.separator-", depth);
+                }
+                node = b.conn;
+                print(node, "/Branch", depth);
+            } else if (node instanceof Pattern.BranchConn) {
+                return;
+            } else if (node instanceof Pattern.CharProperty) {
+                str = pmap.get(((Pattern.CharProperty)node).predicate);
+                if (str == null)
+                    str = toString(node);
+                else
+                    str = "Single \"" + str + "\"";
+                print(node, str, depth);
+            } else if (node instanceof Pattern.SliceNode) {
+                str = name + "  \"" +
+                      toStringCPS(((Pattern.SliceNode)node).buffer) + "\"";
+                print(node, str, depth);
+            } else if (node instanceof Pattern.CharPropertyGreedy) {
+                Pattern.CharPropertyGreedy gcp = (Pattern.CharPropertyGreedy)node;
+                String pstr = pmap.get(gcp.predicate);
+                if (pstr == null)
+                    pstr = gcp.predicate.toString();
+                else
+                    pstr = "Single \"" + pstr + "\"";
+                str = name + " " + pstr + ((gcp.cmin == 0) ? "*" : "+");
+                print(node, str, depth);
+            } else if (node instanceof Pattern.BackRef) {
+                str = "GroupBackRef " + ((Pattern.BackRef)node).groupIndex / 2;
+                print(node, str, depth);
+            } else if (node instanceof Pattern.LastNode) {
+                print(node, "END", depth);
+            } else if (node == Pattern.accept) {
+                return;
+            } else {
+                print(node, name, depth);
+            }
+            node = node.next;
+        }
+    }
+
+    public static void main(String[] args) {
+        Pattern p = Pattern.compile(args[0]);
+        System.out.println("   Pattern: " + p);
+        walk(p.root, 0);
+    }
+}
--- a/jdk/src/java.base/share/classes/java/util/regex/UnicodeProp.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.regex;
-
-import java.util.HashMap;
-import java.util.Locale;
-
-enum UnicodeProp {
-
-    ALPHABETIC {
-        public boolean is(int ch) {
-            return Character.isAlphabetic(ch);
-        }
-    },
-
-    LETTER {
-        public boolean is(int ch) {
-            return Character.isLetter(ch);
-        }
-    },
-
-    IDEOGRAPHIC {
-        public boolean is(int ch) {
-            return Character.isIdeographic(ch);
-        }
-    },
-
-    LOWERCASE {
-        public boolean is(int ch) {
-            return Character.isLowerCase(ch);
-        }
-    },
-
-    UPPERCASE {
-        public boolean is(int ch) {
-            return Character.isUpperCase(ch);
-        }
-    },
-
-    TITLECASE {
-        public boolean is(int ch) {
-            return Character.isTitleCase(ch);
-        }
-    },
-
-    WHITE_SPACE {
-        // \p{Whitespace}
-        public boolean is(int ch) {
-            return ((((1 << Character.SPACE_SEPARATOR) |
-                      (1 << Character.LINE_SEPARATOR) |
-                      (1 << Character.PARAGRAPH_SEPARATOR)) >> Character.getType(ch)) & 1)
-                   != 0 || (ch >= 0x9 && ch <= 0xd) || (ch == 0x85);
-        }
-    },
-
-    CONTROL {
-        // \p{gc=Control}
-        public boolean is(int ch) {
-            return Character.getType(ch) == Character.CONTROL;
-        }
-    },
-
-    PUNCTUATION {
-        // \p{gc=Punctuation}
-        public boolean is(int ch) {
-            return ((((1 << Character.CONNECTOR_PUNCTUATION) |
-                      (1 << Character.DASH_PUNCTUATION) |
-                      (1 << Character.START_PUNCTUATION) |
-                      (1 << Character.END_PUNCTUATION) |
-                      (1 << Character.OTHER_PUNCTUATION) |
-                      (1 << Character.INITIAL_QUOTE_PUNCTUATION) |
-                      (1 << Character.FINAL_QUOTE_PUNCTUATION)) >> Character.getType(ch)) & 1)
-                   != 0;
-        }
-    },
-
-    HEX_DIGIT {
-        // \p{gc=Decimal_Number}
-        // \p{Hex_Digit}    -> PropList.txt: Hex_Digit
-        public boolean is(int ch) {
-            return DIGIT.is(ch) ||
-                   (ch >= 0x0030 && ch <= 0x0039) ||
-                   (ch >= 0x0041 && ch <= 0x0046) ||
-                   (ch >= 0x0061 && ch <= 0x0066) ||
-                   (ch >= 0xFF10 && ch <= 0xFF19) ||
-                   (ch >= 0xFF21 && ch <= 0xFF26) ||
-                   (ch >= 0xFF41 && ch <= 0xFF46);
-        }
-    },
-
-    ASSIGNED {
-        public boolean is(int ch) {
-            return Character.getType(ch) != Character.UNASSIGNED;
-        }
-    },
-
-    NONCHARACTER_CODE_POINT {
-        // PropList.txt:Noncharacter_Code_Point
-        public boolean is(int ch) {
-            return (ch & 0xfffe) == 0xfffe || (ch >= 0xfdd0 && ch <= 0xfdef);
-        }
-    },
-
-    DIGIT {
-        // \p{gc=Decimal_Number}
-        public boolean is(int ch) {
-            return Character.isDigit(ch);
-        }
-    },
-
-    ALNUM {
-        // \p{alpha}
-        // \p{digit}
-        public boolean is(int ch) {
-            return ALPHABETIC.is(ch) || DIGIT.is(ch);
-        }
-    },
-
-    BLANK {
-        // \p{Whitespace} --
-        // [\N{LF} \N{VT} \N{FF} \N{CR} \N{NEL}  -> 0xa, 0xb, 0xc, 0xd, 0x85
-        //  \p{gc=Line_Separator}
-        //  \p{gc=Paragraph_Separator}]
-        public boolean is(int ch) {
-            return Character.getType(ch) == Character.SPACE_SEPARATOR ||
-                   ch == 0x9; // \N{HT}
-        }
-    },
-
-    GRAPH {
-        // [^
-        //  \p{space}
-        //  \p{gc=Control}
-        //  \p{gc=Surrogate}
-        //  \p{gc=Unassigned}]
-        public boolean is(int ch) {
-            return ((((1 << Character.SPACE_SEPARATOR) |
-                      (1 << Character.LINE_SEPARATOR) |
-                      (1 << Character.PARAGRAPH_SEPARATOR) |
-                      (1 << Character.CONTROL) |
-                      (1 << Character.SURROGATE) |
-                      (1 << Character.UNASSIGNED)) >> Character.getType(ch)) & 1)
-                   == 0;
-        }
-    },
-
-    PRINT {
-        // \p{graph}
-        // \p{blank}
-        // -- \p{cntrl}
-        public boolean is(int ch) {
-            return (GRAPH.is(ch) || BLANK.is(ch)) && !CONTROL.is(ch);
-        }
-    },
-
-    WORD {
-        //  \p{alpha}
-        //  \p{gc=Mark}
-        //  \p{digit}
-        //  \p{gc=Connector_Punctuation}
-        //  \p{Join_Control}    200C..200D
-
-        public boolean is(int ch) {
-            return ALPHABETIC.is(ch) ||
-                   ((((1 << Character.NON_SPACING_MARK) |
-                      (1 << Character.ENCLOSING_MARK) |
-                      (1 << Character.COMBINING_SPACING_MARK) |
-                      (1 << Character.DECIMAL_DIGIT_NUMBER) |
-                      (1 << Character.CONNECTOR_PUNCTUATION)) >> Character.getType(ch)) & 1)
-                   != 0 ||
-                   JOIN_CONTROL.is(ch);
-        }
-    },
-
-    JOIN_CONTROL {
-        //  200C..200D    PropList.txt:Join_Control
-        public boolean is(int ch) {
-           return (ch == 0x200C || ch == 0x200D);
-        }
-    };
-
-    private static final HashMap<String, String> posix = new HashMap<>();
-    private static final HashMap<String, String> aliases = new HashMap<>();
-    static {
-        posix.put("ALPHA", "ALPHABETIC");
-        posix.put("LOWER", "LOWERCASE");
-        posix.put("UPPER", "UPPERCASE");
-        posix.put("SPACE", "WHITE_SPACE");
-        posix.put("PUNCT", "PUNCTUATION");
-        posix.put("XDIGIT","HEX_DIGIT");
-        posix.put("ALNUM", "ALNUM");
-        posix.put("CNTRL", "CONTROL");
-        posix.put("DIGIT", "DIGIT");
-        posix.put("BLANK", "BLANK");
-        posix.put("GRAPH", "GRAPH");
-        posix.put("PRINT", "PRINT");
-
-        aliases.put("WHITESPACE", "WHITE_SPACE");
-        aliases.put("HEXDIGIT","HEX_DIGIT");
-        aliases.put("NONCHARACTERCODEPOINT", "NONCHARACTER_CODE_POINT");
-        aliases.put("JOINCONTROL", "JOIN_CONTROL");
-    }
-
-    public static UnicodeProp forName(String propName) {
-        propName = propName.toUpperCase(Locale.ENGLISH);
-        String alias = aliases.get(propName);
-        if (alias != null)
-            propName = alias;
-        try {
-            return valueOf (propName);
-        } catch (IllegalArgumentException x) {}
-        return null;
-    }
-
-    public static UnicodeProp forPOSIXName(String propName) {
-        propName = posix.get(propName.toUpperCase(Locale.ENGLISH));
-        if (propName == null)
-            return null;
-        return valueOf (propName);
-    }
-
-    public abstract boolean is(int ch);
-}
--- a/jdk/src/java.base/share/classes/javax/security/auth/callback/UnsupportedCallbackException.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/javax/security/auth/callback/UnsupportedCallbackException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -40,7 +40,7 @@
     private Callback callback;
 
     /**
-     * Constructs a {@code UnsupportedCallbackException}
+     * Constructs an {@code UnsupportedCallbackException}
      * with no detail message.
      *
      * @param callback the unrecognized {@code Callback}.
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java	Wed Jul 05 21:42:16 2017 +0200
@@ -390,10 +390,25 @@
     private static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
 
     /*
-     * Returns the first non-null class loader up the execution stack,
-     * or null if only code from the null class loader is on the stack.
+     * Returns the first user-defined class loader up the execution stack,
+     * or the platform class loader if only code from the platform or
+     * bootstrap class loader is on the stack.
      */
-    public static native ClassLoader latestUserDefinedLoader();
+    public static ClassLoader latestUserDefinedLoader() {
+        ClassLoader loader = latestUserDefinedLoader0();
+        return loader != null ? loader : ClassLoader.getPlatformClassLoader();
+    }
+
+    /*
+     * Returns the first user-defined class loader up the execution stack,
+     * or null if only code from the platform or bootstrap class loader is
+     * on the stack.  VM does not keep a reference of platform loader and so
+     * it returns null.
+     *
+     * This method should be replaced with StackWalker::walk and then we can
+     * remove the logic in the VM.
+     */
+    private static native ClassLoader latestUserDefinedLoader0();
 
     /**
      * Returns {@code true} if we are in a set UID program.
--- a/jdk/src/java.base/share/classes/sun/net/ftp/FtpClient.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/net/ftp/FtpClient.java	Wed Jul 05 21:42:16 2017 +0200
@@ -784,7 +784,7 @@
      *
      * @param path the pathname of the directory to list or {@code null}
      *        for the current working directoty.
-     * @return a {@code Iterator} of files or {@code null} if the
+     * @return an {@code Iterator} of files or {@code null} if the
      *         command failed.
      * @throws IOException if an error occurred during the transmission
      * @see #setDirParser(FtpDirParser)
--- a/jdk/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java	Wed Jul 05 21:42:16 2017 +0200
@@ -51,12 +51,9 @@
  * configuration is eagerly called to set up parameters, and instantiation
  * is lazily called only when nextBytes or reseed is called.
  * <p>
- * Synchronized keyword should be added to all externally callable engine
- * methods including {@link #engineReseed}, {@link #engineSetSeed}, and
- * {@link #engineNextBytes} (but not {@link #engineGenerateSeed}).
- * Internal methods like {@link #configure} and {@link #instantiateAlgorithm}
- * are not synchronized. They will either be called in a constructor or
- * in another synchronized method.
+ * SecureRandom methods like reseed and nextBytes are not thread-safe.
+ * An implementation is required to protect shared access to instantiate states
+ * (instantiated, nonce) and DRBG states (v, c, key, reseedCounter).
  */
 public abstract class AbstractDrbg extends SecureRandomSpi {
 
@@ -78,8 +75,10 @@
      * Reseed counter of a DRBG instance. A mechanism should increment it
      * after each random bits generation and reset it in reseed. A mechanism
      * does <em>not</em> need to compare it to {@link #reseedInterval}.
+     *
+     * Volatile, will be used in a double checked locking.
      */
-    protected transient int reseedCounter = 0;
+    protected transient volatile int reseedCounter = 0;
 
     // Mech features. If not same as below, must be redefined in constructor.
 
@@ -268,10 +267,9 @@
      * {@code DEFAULT_STRENGTH} is 128) for HashDRBG:
      * <pre>
      * requested             effective
-     * (SHA-1, -1)           (SHA-1,128)
-     * (SHA-1, 112)          (SHA-1,112)
-     * (SHA-1, 192)          IAE
+     * (SHA-224, 256)        IAE
      * (SHA-256, -1)         (SHA-256,128)
+     * (SHA-256, 112)        (SHA-256,112)
      * (SHA-256, 128)        (SHA-256,128)
      * (SHA-3, -1)           IAE
      * (null, -1)            (SHA-256,128)
@@ -383,9 +381,14 @@
             instantiateIfNecessary(null);
 
             // Step 7: Auto reseed
+            // Double checked locking, safe because reseedCounter is volatile
             if (reseedCounter > reseedInterval || pr) {
-                reseedAlgorithm(getEntropyInput(pr), ai);
-                ai = null;
+                synchronized (this) {
+                    if (reseedCounter > reseedInterval || pr) {
+                        reseedAlgorithm(getEntropyInput(pr), ai);
+                        ai = null;
+                    }
+                }
             }
 
             // Step 8, 10: Generate_algorithm
@@ -615,8 +618,7 @@
      * @throws IllegalArgumentException if {@code params} is
      *         inappropriate for this SecureRandom.
      */
-    protected final synchronized void configure(
-            SecureRandomParameters params) {
+    protected final void configure(SecureRandomParameters params) {
         if (debug != null) {
             debug.println(this, "configure " + this + " with " + params);
         }
--- a/jdk/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java	Wed Jul 05 21:42:16 2017 +0200
@@ -39,8 +39,6 @@
 
     private static int alg2strength(String algorithm) {
         switch (algorithm.toUpperCase(Locale.ROOT)) {
-            case "SHA-1":
-                return 128;
             case "SHA-224":
             case "SHA-512/224":
                 return 192;
@@ -82,10 +80,6 @@
             this.securityStrength = tryStrength;
         }
         switch (algorithm.toUpperCase(Locale.ROOT)) {
-            case "SHA-1":
-                this.seedLen = 440 / 8;
-                this.outLen = 160 / 8;
-                break;
             case "SHA-224":
             case "SHA-512/224":
                 this.seedLen = 440 / 8;
--- a/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -441,17 +441,89 @@
             (outOfs < 0) || ((out.length - outOfs) < len)) {
             throw new ArrayIndexOutOfBoundsException();
         }
-        len += outOfs;
-        while (outOfs < len) {
-            long i = in[inOfs++];
-            out[outOfs++] = (byte)(i >> 56);
-            out[outOfs++] = (byte)(i >> 48);
-            out[outOfs++] = (byte)(i >> 40);
-            out[outOfs++] = (byte)(i >> 32);
-            out[outOfs++] = (byte)(i >> 24);
-            out[outOfs++] = (byte)(i >> 16);
-            out[outOfs++] = (byte)(i >>  8);
-            out[outOfs++] = (byte)(i      );
+        if (littleEndianUnaligned) {
+            outOfs += byteArrayOfs;
+            len += outOfs;
+            while (outOfs < len) {
+                unsafe.putLong(out, (long)outOfs, reverseBytes(in[inOfs++]));
+                outOfs += 8;
+            }
+        } else {
+            len += outOfs;
+            while (outOfs < len) {
+                long i = in[inOfs++];
+                out[outOfs++] = (byte)(i >> 56);
+                out[outOfs++] = (byte)(i >> 48);
+                out[outOfs++] = (byte)(i >> 40);
+                out[outOfs++] = (byte)(i >> 32);
+                out[outOfs++] = (byte)(i >> 24);
+                out[outOfs++] = (byte)(i >> 16);
+                out[outOfs++] = (byte)(i >>  8);
+                out[outOfs++] = (byte)(i      );
+            }
+        }
+    }
+
+    /**
+     * byte[] to long[] conversion, little endian byte order
+     */
+    static void b2lLittle(byte[] in, int inOfs, long[] out, int outOfs, int len) {
+        if ((inOfs < 0) || ((in.length - inOfs) < len) ||
+            ((outOfs < 0) || (out.length - outOfs) < len/8)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (littleEndianUnaligned) {
+            inOfs += byteArrayOfs;
+            len += inOfs;
+            while (inOfs < len) {
+                out[outOfs++] = unsafe.getLong(in, (long)inOfs);
+                inOfs += 8;
+            }
+       } else {
+            len += inOfs;
+            while (inOfs < len) {
+                out[outOfs++] = ((in[inOfs    ] & 0xffL)
+                   | ((in[inOfs + 1] & 0xffL) <<  8)
+                   | ((in[inOfs + 2] & 0xffL) << 16)
+                   | ((in[inOfs + 3] & 0xffL) << 24)
+                   | ((in[inOfs + 4] & 0xffL) << 32)
+                   | ((in[inOfs + 5] & 0xffL) << 40)
+                   | ((in[inOfs + 6] & 0xffL) << 48)
+                   | ((in[inOfs + 7] & 0xffL) << 56));
+                inOfs += 8;
+            }
+        }
+    }
+
+
+    /**
+     * long[] to byte[] conversion, little endian byte order
+     */
+    static void l2bLittle(long[] in, int inOfs, byte[] out, int outOfs, int len) {
+        if ((inOfs < 0) || ((in.length - inOfs) < len/8) ||
+            (outOfs < 0) || ((out.length - outOfs) < len)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (littleEndianUnaligned) {
+            outOfs += byteArrayOfs;
+            len += outOfs;
+            while (outOfs < len) {
+                unsafe.putLong(out, (long)outOfs, in[inOfs++]);
+                outOfs += 8;
+            }
+        } else {
+            len += outOfs;
+            while (outOfs < len) {
+                long i = in[inOfs++];
+                out[outOfs++] = (byte)(i      );
+                out[outOfs++] = (byte)(i >>  8);
+                out[outOfs++] = (byte)(i >> 16);
+                out[outOfs++] = (byte)(i >> 24);
+                out[outOfs++] = (byte)(i >> 32);
+                out[outOfs++] = (byte)(i >> 40);
+                out[outOfs++] = (byte)(i >> 48);
+                out[outOfs++] = (byte)(i >> 56);
+            }
         }
     }
 }
--- a/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java	Wed Jul 05 21:42:16 2017 +0200
@@ -27,7 +27,6 @@
 
 import javax.crypto.Cipher;
 import javax.crypto.NoSuchPaddingException;
-import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 import java.io.IOException;
 import java.security.*;
@@ -68,11 +67,6 @@
 
     private static int alg2strength(String algorithm) {
         switch (algorithm.toUpperCase(Locale.ROOT)) {
-            case "TDEA":
-            case "3KEYTDEA":
-            case "3 KEY TDEA":
-            case "DESEDE":
-                return 112;
             case "AES-128":
                 return 128;
             case "AES-192":
@@ -120,16 +114,6 @@
             this.securityStrength = tryStrength;
         }
         switch (algorithm.toUpperCase(Locale.ROOT)) {
-            case "TDEA":
-            case "3KEYTDEA":
-            case "3 KEY TDEA":
-            case "DESEDE":
-                algorithm = "DESede";
-                this.keyAlg = "DESede";
-                this.cipherAlg = "DESede/ECB/NoPadding";
-                this.blockLen = 64 / 8;
-                this.keyLen = 168 / 8;
-                break;
             case "AES-128":
             case "AES-192":
             case "AES-256":
@@ -224,7 +208,7 @@
                 // Step 2.1. Increment
                 addOne(v, ctrLen);
                 // Step 2.2. Block_Encrypt
-                cipher.init(Cipher.ENCRYPT_MODE, getKey(keyAlg, k));
+                cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(k, keyAlg));
                 // Step 2.3. Encrypt into right position, no need to cat
                 cipher.doFinal(v, 0, blockLen, temp, i * blockLen);
             }
@@ -316,7 +300,7 @@
 
         for (int i = 0; i * blockLen < seedLen; i++) {
             try {
-                cipher.init(Cipher.ENCRYPT_MODE, getKey(keyAlg, k));
+                cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(k, keyAlg));
                 int tailLen = temp.length - blockLen*i;
                 if (tailLen > blockLen) {
                     tailLen = blockLen;
@@ -340,7 +324,7 @@
                 inputBlock[j] ^= chain[j];
             }
             try {
-                cipher.init(Cipher.ENCRYPT_MODE, getKey(keyAlg, k));
+                cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(k, keyAlg));
                 chain = cipher.doFinal(inputBlock);
             } catch (GeneralSecurityException e) {
                 throw new InternalError(e);
@@ -350,7 +334,7 @@
     }
 
     @Override
-    protected void reseedAlgorithm(
+    protected synchronized void reseedAlgorithm(
             byte[] ei,
             byte[] additionalInput) {
         if (usedf) {
@@ -456,7 +440,7 @@
             addOne(v, ctrLen);
             try {
                 // Step 4.2. Encrypt
-                cipher.init(Cipher.ENCRYPT_MODE, getKey(keyAlg, k));
+                cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(k, keyAlg));
                 byte[] out = cipher.doFinal(v);
 
                 // Step 4.3 and 5. Cat bytes and leftmost
@@ -479,43 +463,6 @@
         // Step 8. Return
     }
 
-    private static void des7to8(
-            byte[] key56, int off56, byte[] key64, int off64) {
-        key64[off64 + 0] = (byte)
-                (key56[off56 + 0] & 0xFE); // << 0
-        key64[off64 + 1] = (byte)
-                ((key56[off56 + 0] << 7) | ((key56[off56 + 1] & 0xFF) >>> 1));
-        key64[off64 + 2] = (byte)
-                ((key56[off56 + 1] << 6) | ((key56[off56 + 2] & 0xFF) >>> 2));
-        key64[off64 + 3] = (byte)
-                ((key56[off56 + 2] << 5) | ((key56[off56 + 3] & 0xFF) >>> 3));
-        key64[off64 + 4] = (byte)
-                ((key56[off56 + 3] << 4) | ((key56[off56 + 4] & 0xFF) >>> 4));
-        key64[off64 + 5] = (byte)
-                ((key56[off56 + 4] << 3) | ((key56[off56 + 5] & 0xFF) >>> 5));
-        key64[off64 + 6] = (byte)
-                ((key56[off56 + 5] << 2) | ((key56[off56 + 6] & 0xFF) >>> 6));
-        key64[off64 + 7] = (byte)
-                (key56[off56 + 6] << 1);
-
-        for (int i = 0; i < 8; i++) {
-            // if even # bits, make uneven, XOR with 1 (uneven & 1)
-            // for uneven # bits, make even, XOR with 0 (even & 1)
-            key64[off64 + i] ^= Integer.bitCount(key64[off64 + i] ^ 1) & 1;
-        }
-    }
-
-    private static SecretKey getKey(String keyAlg, byte[] k) {
-        if (keyAlg.equals("DESede")) {
-            byte[] k2 = new byte[24];
-            des7to8(k, 0, k2, 0);
-            des7to8(k, 7, k2, 8);
-            des7to8(k, 14, k2, 16);
-            k = k2;
-        }
-        return new SecretKeySpec(k, keyAlg);
-    }
-
     private void readObject(java.io.ObjectInputStream s)
             throws IOException, ClassNotFoundException {
         s.defaultReadObject ();
--- a/jdk/src/java.base/share/classes/sun/security/provider/HashDrbg.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/HashDrbg.java	Wed Jul 05 21:42:16 2017 +0200
@@ -115,7 +115,7 @@
 
     // This method is used by both instantiation and reseeding.
     @Override
-    protected final void hashReseedInternal(byte[] input) {
+    protected final synchronized void hashReseedInternal(byte[] input) {
 
         // 800-90Ar1 10.1.1.2: Instantiate Process.
         // 800-90Ar1 10.1.1.3: Reseed Process.
--- a/jdk/src/java.base/share/classes/sun/security/provider/HmacDrbg.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/HmacDrbg.java	Wed Jul 05 21:42:16 2017 +0200
@@ -115,7 +115,7 @@
 
     // This method is used by both instantiation and reseeding.
     @Override
-    protected final void hashReseedInternal(byte[] input) {
+    protected final synchronized void hashReseedInternal(byte[] input) {
 
         // 800-90Ar1 10.1.2.3: Instantiate Process.
         // 800-90Ar1 10.1.2.4: Reseed Process.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SHA3.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.provider;
+
+import static sun.security.provider.ByteArrayAccess.*;
+import java.nio.*;
+import java.util.*;
+import java.security.*;
+
+/**
+ * This class implements the Secure Hash Algorithm SHA-3 developed by
+ * the National Institute of Standards and Technology along with the
+ * National Security Agency as defined in FIPS PUB 202.
+ *
+ * <p>It implements java.security.MessageDigestSpi, and can be used
+ * through Java Cryptography Architecture (JCA), as a pluggable
+ * MessageDigest implementation.
+ *
+ * @since       9
+ * @author      Valerie Peng
+ */
+abstract class SHA3 extends DigestBase {
+
+    private static final int WIDTH = 200; // in bytes, e.g. 1600 bits
+    private static final int DM = 5; // dimension of lanes
+
+    private static final int NR = 24; // number of rounds
+
+    // precomputed round constants needed by the step mapping Iota
+    private static final long[] RC_CONSTANTS = {
+        0x01L, 0x8082L, 0x800000000000808aL,
+        0x8000000080008000L, 0x808bL, 0x80000001L,
+        0x8000000080008081L, 0x8000000000008009L, 0x8aL,
+        0x88L, 0x80008009L, 0x8000000aL,
+        0x8000808bL, 0x800000000000008bL, 0x8000000000008089L,
+        0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L,
+        0x800aL, 0x800000008000000aL, 0x8000000080008081L,
+        0x8000000000008080L, 0x80000001L, 0x8000000080008008L,
+    };
+
+    private byte[] state;
+
+    /**
+     * Creates a new SHA-3 object.
+     */
+    SHA3(String name, int digestLength) {
+        super(name, digestLength, (WIDTH - (2 * digestLength)));
+        implReset();
+    }
+
+    /**
+     * Core compression function. Processes blockSize bytes at a time
+     * and updates the state of this object.
+     */
+    void implCompress(byte[] b, int ofs) {
+        for (int i = 0; i < buffer.length; i++) {
+            state[i] ^= b[ofs++];
+        }
+        state = keccak(state);
+    }
+
+    /**
+     * Return the digest. Subclasses do not need to reset() themselves,
+     * DigestBase calls implReset() when necessary.
+     */
+    void implDigest(byte[] out, int ofs) {
+        int numOfPadding =
+            setPaddingBytes(buffer, (int)(bytesProcessed % buffer.length));
+        if (numOfPadding < 1) {
+            throw new ProviderException("Incorrect pad size: " + numOfPadding);
+        }
+        for (int i = 0; i < buffer.length; i++) {
+            state[i] ^= buffer[i];
+        }
+        state = keccak(state);
+        System.arraycopy(state, 0, out, ofs, engineGetDigestLength());
+    }
+
+    /**
+     * Resets the internal state to start a new hash.
+     */
+    void implReset() {
+        state = new byte[WIDTH];
+    }
+
+    /**
+     * Utility function for circular shift the specified long
+     * value to the left for n bits.
+     */
+    private static long circularShiftLeft(long lane, int n) {
+        return ((lane << n) | (lane >>> (64 - n)));
+    }
+
+    /**
+     * Utility function for padding the specified data based on the
+     * pad10*1 algorithm (section 5.1) and the 2-bit suffix "01" required
+     * for SHA-3 hash (section 6.1).
+     */
+    private static int setPaddingBytes(byte[] in, int len) {
+        if (len != in.length) {
+            // erase leftover values
+            Arrays.fill(in, len, in.length, (byte)0);
+            // directly store the padding bytes into the input
+            // as the specified buffer is allocated w/ size = rateR
+            in[len] |= (byte) 0x06;
+            in[in.length - 1] |= (byte) 0x80;
+        }
+        return (in.length - len);
+    }
+
+    /**
+     * Utility function for transforming the specified state from
+     * the byte array format into array of lanes as defined in
+     * section 3.1.2.
+     */
+    private static long[][] bytes2Lanes(byte[] s) {
+        if (s.length != WIDTH) {
+            throw new ProviderException("Error: incorrect input size " +
+                s.length);
+        }
+        // The conversion traverses along x-axis before y-axis. So, y is the
+        // first dimension and x is the second dimension.
+        long[][] s2 = new long[DM][DM];
+        int sOfs = 0;
+        for (int y = 0; y < DM; y++, sOfs += 40) {
+            b2lLittle(s, sOfs, s2[y], 0, 40);
+        }
+        return s2;
+    }
+
+    /**
+     * Utility function for transforming the specified arrays of
+     * lanes into a byte array as defined in section 3.1.3.
+     */
+    private static byte[] lanes2Bytes(long[][] m) {
+        byte[] s = new byte[WIDTH];
+        int sOfs = 0;
+        // The conversion traverses along x-axis before y-axis. So, y is the
+        // first dimension and x is the second dimension.
+        for (int y = 0; y < DM; y++, sOfs += 40) {
+            l2bLittle(m[y], 0, s, sOfs, 40);
+        }
+        return s;
+    }
+
+    /**
+     * Step mapping Theta as defined in section 3.2.1 .
+     */
+    private static long[][] smTheta(long[][] a) {
+        long[] c = new long[DM];
+        for (int i = 0; i < DM; i++) {
+            c[i] = a[0][i]^a[1][i]^a[2][i]^a[3][i]^a[4][i];
+        }
+        long[] d = new long[DM];
+        for (int i = 0; i < DM; i++) {
+            long c1 = c[(i + 4) % DM];
+            // left shift and wrap the leftmost bit into the rightmost bit
+            long c2 = circularShiftLeft(c[(i + 1) % DM], 1);
+            d[i] = c1^c2;
+        }
+        for (int y = 0; y < DM; y++) {
+            for (int x = 0; x < DM; x++) {
+                a[y][x] ^= d[x];
+            }
+        }
+        return a;
+    }
+
+    /**
+     * Step mapping Rho as defined in section 3.2.2.
+     */
+    private static long[][] smRho(long[][] a) {
+        long[][] a2 = new long[DM][DM];
+        a2[0][0] = a[0][0];
+        int xNext, yNext;
+        for (int t = 0, x = 1, y = 0; t <= 23; t++, x = xNext, y = yNext) {
+            int numberOfShift = ((t + 1)*(t + 2)/2) % 64;
+            a2[y][x] = circularShiftLeft(a[y][x], numberOfShift);
+            xNext = y;
+            yNext = (2 * x + 3 * y) % DM;
+        }
+        return a2;
+    }
+
+    /**
+     * Step mapping Pi as defined in section 3.2.3.
+     */
+    private static long[][] smPi(long[][] a) {
+        long[][] a2 = new long[DM][DM];
+        for (int y = 0; y < DM; y++) {
+            for (int x = 0; x < DM; x++) {
+                a2[y][x] = a[x][(x + 3 * y) % DM];
+            }
+        }
+        return a2;
+    }
+
+    /**
+     * Step mapping Chi as defined in section 3.2.4.
+     */
+    private static long[][] smChi(long[][] a) {
+        long[][] a2 = new long[DM][DM];
+        for (int y = 0; y < DM; y++) {
+            for (int x = 0; x < DM; x++) {
+                a2[y][x] = a[y][x] ^
+                    ((a[y][(x + 1) % DM] ^ 0xFFFFFFFFFFFFFFFFL) &
+                     a[y][(x + 2) % DM]);
+            }
+        }
+        return a2;
+    }
+
+    /**
+     * Step mapping Iota as defined in section 3.2.5.
+     *
+     * @return the processed state array
+     * @param state the state array to be processed
+     */
+    private static long[][] smIota(long[][] a, int rndIndex) {
+        a[0][0] ^= RC_CONSTANTS[rndIndex];
+        return a;
+    }
+
+    /**
+     * The function Keccak as defined in section 5.2 with
+     * rate r = 1600 and capacity c = (digest length x 2).
+     */
+    private static byte[] keccak(byte[] state) {
+        long[][] lanes = bytes2Lanes(state);
+        for (int ir = 0; ir < NR; ir++) {
+            lanes = smIota(smChi(smPi(smRho(smTheta(lanes)))), ir);
+        }
+        return lanes2Bytes(lanes);
+    }
+
+    public Object clone() throws CloneNotSupportedException {
+        SHA3 copy = (SHA3) super.clone();
+        copy.state = copy.state.clone();
+        return copy;
+    }
+
+    /**
+     * SHA3-224 implementation class.
+     */
+    public static final class SHA224 extends SHA3 {
+        public SHA224() {
+            super("SHA3-224", 28);
+        }
+    }
+
+    /**
+     * SHA3-256 implementation class.
+     */
+    public static final class SHA256 extends SHA3 {
+        public SHA256() {
+            super("SHA3-256", 32);
+        }
+    }
+
+    /**
+     * SHAs-384 implementation class.
+     */
+    public static final class SHA384 extends SHA3 {
+        public SHA384() {
+            super("SHA3-384", 48);
+        }
+    }
+
+    /**
+     * SHA3-512 implementation class.
+     */
+    public static final class SHA512 extends SHA3 {
+        public SHA512() {
+            super("SHA3-512", 64);
+        }
+    }
+}
--- a/jdk/src/java.base/share/classes/sun/security/provider/SecureRandom.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SecureRandom.java	Wed Jul 05 21:42:16 2017 +0200
@@ -156,6 +156,7 @@
             }
         }
         state = digest.digest(seed);
+        remCount = 0;
     }
 
     private static void updateState(byte[] state, byte[] output) {
--- a/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java	Wed Jul 05 21:42:16 2017 +0200
@@ -211,6 +211,25 @@
         map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.6",
                 "SHA-512/256");
 
+        map.put("MessageDigest.SHA3-224", "sun.security.provider.SHA3$SHA224");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.7", "SHA3-224");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.7",
+                "SHA3-224");
+
+        map.put("MessageDigest.SHA3-256", "sun.security.provider.SHA3$SHA256");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.8", "SHA3-256");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.8",
+                "SHA3-256");
+        map.put("MessageDigest.SHA3-384", "sun.security.provider.SHA3$SHA384");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.9", "SHA3-384");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.9",
+                "SHA3-384");
+        map.put("MessageDigest.SHA3-512", "sun.security.provider.SHA3$SHA512");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.10", "SHA3-512");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.10",
+                "SHA3-512");
+
+
         /*
          * Algorithm Parameter Generator engines
          */
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPNonceExtension.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPNonceExtension.java	Wed Jul 05 21:42:16 2017 +0200
@@ -51,7 +51,7 @@
     private byte[] nonceData = null;
 
     /**
-     * Create a {@code OCSPNonceExtension} by providing the nonce length.
+     * Create an {@code OCSPNonceExtension} by providing the nonce length.
      * The criticality is set to false, and the OID for the extension will
      * be the value defined by "id-pkix-ocsp-nonce" from RFC 6960.
      *
@@ -66,7 +66,7 @@
     }
 
     /**
-     * Create a {@code OCSPNonceExtension} by providing the nonce length and
+     * Create an {@code OCSPNonceExtension} by providing the nonce length and
      * criticality setting.  The OID for the extension will
      * be the value defined by "id-pkix-ocsp-nonce" from RFC 6960.
      *
@@ -96,7 +96,7 @@
     }
 
     /**
-     * Create a {@code OCSPNonceExtension} by providing a nonce value.
+     * Create an {@code OCSPNonceExtension} by providing a nonce value.
      * The criticality is set to false, and the OID for the extension will
      * be the value defined by "id-pkix-ocsp-nonce" from RFC 6960.
      *
@@ -114,7 +114,7 @@
     }
 
     /**
-     * Create a {@code OCSPNonceExtension} by providing a nonce value and
+     * Create an {@code OCSPNonceExtension} by providing a nonce value and
      * criticality setting.  The OID for the extension will
      * be the value defined by "id-pkix-ocsp-nonce" from RFC 6960.
      *
--- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -108,7 +108,7 @@
      * a hash for the certificate verify message is required.
      */
     HandshakeHash(boolean needCertificateVerify) {
-        clonesNeeded = needCertificateVerify ? 3 : 2;
+        clonesNeeded = needCertificateVerify ? 4 : 3;
     }
 
     void reserve(ByteBuffer input) {
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java	Wed Jul 05 21:42:16 2017 +0200
@@ -123,7 +123,7 @@
                  */
                 //
                 // Short header is using here.  We reverse the code here
-                // in case it it used in the future.
+                // in case it is used in the future.
                 //
                 // int mask = (isShort ? 0x7F : 0x3F);
                 // len = ((byteZero & mask) << 8) +
--- a/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java	Wed Jul 05 21:42:16 2017 +0200
@@ -552,58 +552,61 @@
             return AlgorithmId.sha512WithECDSA_oid;
         }
 
-        // See if any of the installed providers supply a mapping from
-        // the given algorithm name to an OID string
-        String oidString;
-        if (!initOidTable) {
-            Provider[] provs = Security.getProviders();
-            for (int i=0; i<provs.length; i++) {
-                for (Enumeration<Object> enum_ = provs[i].keys();
-                     enum_.hasMoreElements(); ) {
-                    String alias = (String)enum_.nextElement();
-                    String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH);
-                    int index;
-                    if (upperCaseAlias.startsWith("ALG.ALIAS") &&
-                            (index=upperCaseAlias.indexOf("OID.", 0)) != -1) {
-                        index += "OID.".length();
-                        if (index == alias.length()) {
-                            // invalid alias entry
-                            break;
-                        }
-                        if (oidTable == null) {
-                            oidTable = new HashMap<>();
-                        }
-                        oidString = alias.substring(index);
-                        String stdAlgName = provs[i].getProperty(alias);
-                        if (stdAlgName != null) {
-                            stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH);
-                        }
-                        if (stdAlgName != null &&
-                                oidTable.get(stdAlgName) == null) {
-                            oidTable.put(stdAlgName,
-                                         new ObjectIdentifier(oidString));
-                        }
-                    }
-                }
-            }
-
-            if (oidTable == null) {
-                oidTable = Collections.<String,ObjectIdentifier>emptyMap();
-            }
-            initOidTable = true;
-        }
-
-        return oidTable.get(name.toUpperCase(Locale.ENGLISH));
+        return oidTable().get(name.toUpperCase(Locale.ENGLISH));
     }
 
     private static ObjectIdentifier oid(int ... values) {
         return ObjectIdentifier.newInternal(values);
     }
 
-    private static boolean initOidTable = false;
-    private static Map<String,ObjectIdentifier> oidTable;
+    private static volatile Map<String,ObjectIdentifier> oidTable;
     private static final Map<ObjectIdentifier,String> nameTable;
 
+    /** Returns the oidTable, lazily initializing it on first access. */
+    private static Map<String,ObjectIdentifier> oidTable()
+        throws IOException {
+        // Double checked locking; safe because oidTable is volatile
+        Map<String,ObjectIdentifier> tab;
+        if ((tab = oidTable) == null) {
+            synchronized (AlgorithmId.class) {
+                if ((tab = oidTable) == null)
+                    oidTable = tab = computeOidTable();
+            }
+        }
+        return tab;
+    }
+
+    /** Collects the algorithm names from the installed providers. */
+    private static HashMap<String,ObjectIdentifier> computeOidTable()
+        throws IOException {
+        HashMap<String,ObjectIdentifier> tab = new HashMap<>();
+        for (Provider provider : Security.getProviders()) {
+            for (Object key : provider.keySet()) {
+                String alias = (String)key;
+                String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH);
+                int index;
+                if (upperCaseAlias.startsWith("ALG.ALIAS") &&
+                    (index=upperCaseAlias.indexOf("OID.", 0)) != -1) {
+                    index += "OID.".length();
+                    if (index == alias.length()) {
+                        // invalid alias entry
+                        break;
+                    }
+                    String oidString = alias.substring(index);
+                    String stdAlgName = provider.getProperty(alias);
+                    if (stdAlgName != null) {
+                        stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH);
+                    }
+                    if (stdAlgName != null &&
+                        tab.get(stdAlgName) == null) {
+                        tab.put(stdAlgName, new ObjectIdentifier(oidString));
+                    }
+                }
+            }
+        }
+        return tab;
+    }
+
     /*****************************************************************/
 
     /*
--- a/jdk/src/java.base/share/conf/security/java.security	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/conf/security/java.security	Wed Jul 05 21:42:16 2017 +0200
@@ -206,16 +206,15 @@
 #     "Hash_DRBG" | "HMAC_DRBG" | "CTR_DRBG"
 #
 #   // The DRBG algorithm name. The "SHA-***" names are for Hash_DRBG and
-#   // HMAC_DRBG, default "SHA-256". "3KeyTDEA" and "AES-***" names are for
-#   // CTR_DRBG, default "AES-128" when using the limited cryptographic
-#   // or "AES-256" when using the unlimited.
+#   // HMAC_DRBG, default "SHA-256". The "AES-***" names are for CTR_DRBG,
+#   // default "AES-128" when using the limited cryptographic or "AES-256"
+#   // when using the unlimited.
 #   algorithm_name:
-#     "SHA-1" | "SHA-224" | "SHA-512/224" | "SHA-256" |
+#     "SHA-224" | "SHA-512/224" | "SHA-256" |
 #     "SHA-512/256" | "SHA-384" | "SHA-512" |
-#     "3KeyTDEA" | "AES-128" | "AES-192" | "AES-256"
+#     "AES-128" | "AES-192" | "AES-256"
 #
-#   // Security strength requested. Default "128", or "112"
-#   // if mech_name is CTR_DRBG and algorithm_name is "3KeyTDEA"
+#   // Security strength requested. Default "128"
 #   strength:
 #     "112" | "128" | "192" | "256"
 #
@@ -234,7 +233,7 @@
 #     "use_df" | "no_df"
 #
 # Examples,
-#   securerandom.drbg.config=Hash_DRBG,SHA-1,112,none
+#   securerandom.drbg.config=Hash_DRBG,SHA-224,112,none
 #   securerandom.drbg.config=CTR_DRBG,AES-256,192,pr_and_reseed,use_df
 #
 # The default value is an empty string, which is equivalent to
--- a/jdk/src/java.base/share/native/libjava/VM.c	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/share/native/libjava/VM.c	Wed Jul 05 21:42:16 2017 +0200
@@ -36,7 +36,7 @@
 };
 
 JNIEXPORT jobject JNICALL
-Java_jdk_internal_misc_VM_latestUserDefinedLoader(JNIEnv *env, jclass cls) {
+Java_jdk_internal_misc_VM_latestUserDefinedLoader0(JNIEnv *env, jclass cls) {
     return JVM_LatestUserDefinedLoader(env);
 }
 
--- a/jdk/src/java.base/unix/classes/sun/security/provider/NativePRNG.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/unix/classes/sun/security/provider/NativePRNG.java	Wed Jul 05 21:42:16 2017 +0200
@@ -469,7 +469,8 @@
                     try {
                         seedOut.write(seed);
                     } catch (IOException e) {
-                        throw new ProviderException("setSeed() failed", e);
+                        // Ignored. On Mac OS X, /dev/urandom can be opened
+                        // for write, but actual write is not permitted.
                     }
                 }
                 getMixRandom().engineSetSeed(seed);
--- a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, 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
@@ -23,7 +23,6 @@
  * questions.
  */
 
-
 #include <errno.h>
 #include <strings.h>
 #if defined(_ALLBSD_SOURCE) && defined(__OpenBSD__)
@@ -38,14 +37,14 @@
 #include <net/if.h>
 #include <net/if_arp.h>
 
-#ifdef __solaris__
+#if defined(__solaris__)
 #include <sys/dlpi.h>
 #include <fcntl.h>
 #include <stropts.h>
 #include <sys/sockio.h>
 #endif
 
-#ifdef __linux__
+#if defined(__linux__)
 #include <sys/ioctl.h>
 #include <bits/ioctls.h>
 #include <sys/utsname.h>
@@ -59,10 +58,6 @@
 #include <sys/kinfo.h>
 #endif
 
-#ifdef __linux__
-#define _PATH_PROCNET_IFINET6           "/proc/net/if_inet6"
-#endif
-
 #if defined(_ALLBSD_SOURCE)
 #include <sys/param.h>
 #include <sys/ioctl.h>
@@ -80,6 +75,10 @@
 #include "jni_util.h"
 #include "net_util.h"
 
+#if defined(__linux__)
+#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
+#endif
+
 typedef struct _netaddr  {
     struct sockaddr *addr;
     struct sockaddr *brdcast;
@@ -135,29 +134,32 @@
 static netif  *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
 #endif
 
-static netif  *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix);
+static netif  *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
+                     struct sockaddr *ifr_addrP, int family, short prefix);
 static void    freeif(netif *ifs);
 
 static int     openSocket(JNIEnv *env, int proto);
 static int     openSocketWithFallback(JNIEnv *env, const char *ifname);
 
 
-static struct  sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, struct sockaddr *brdcast_store);
+static struct  sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name,
+                                      struct sockaddr *brdcast_store);
 static short   getSubnet(JNIEnv *env, int sock, const char *ifname);
 static int     getIndex(int sock, const char *ifname);
 
 static int     getFlags(int sock, const char *ifname, int *flags);
-static int     getMacAddress(JNIEnv *env, int sock,  const char* ifname, const struct in_addr* addr, unsigned char *buf);
+static int     getMacAddress(JNIEnv *env, int sock,  const char *ifname,
+                             const struct in_addr *addr, unsigned char *buf);
 static int     getMTU(JNIEnv *env, int sock, const char *ifname);
 
 
-
-#ifdef __solaris__
-static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
-static int    getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf);
+#if defined(__solaris__)
+static netif  *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
+static int     getMacFromDevice(JNIEnv *env, const char *ifname,
+                                unsigned char *retbuf);
 
 #ifndef SIOCGLIFHWADDR
-#define SIOCGLIFHWADDR  _IOWR('i', 192, struct lifreq)
+#define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
 #endif
 
 #endif
@@ -169,27 +171,33 @@
  * Method:    init
  * Signature: ()V
  */
-JNIEXPORT void JNICALL
-Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls) {
-    ni_class = (*env)->FindClass(env,"java/net/NetworkInterface");
+JNIEXPORT void JNICALL Java_java_net_NetworkInterface_init
+  (JNIEnv *env, jclass cls)
+{
+    ni_class = (*env)->FindClass(env, "java/net/NetworkInterface");
     CHECK_NULL(ni_class);
     ni_class = (*env)->NewGlobalRef(env, ni_class);
     CHECK_NULL(ni_class);
-    ni_nameID = (*env)->GetFieldID(env, ni_class,"name", "Ljava/lang/String;");
+    ni_nameID = (*env)->GetFieldID(env, ni_class, "name", "Ljava/lang/String;");
     CHECK_NULL(ni_nameID);
     ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");
     CHECK_NULL(ni_indexID);
-    ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");
+    ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs",
+                                    "[Ljava/net/InetAddress;");
     CHECK_NULL(ni_addrsID);
-    ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");
+    ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings",
+                                    "[Ljava/net/InterfaceAddress;");
     CHECK_NULL(ni_bindsID);
-    ni_descID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");
+    ni_descID = (*env)->GetFieldID(env, ni_class, "displayName",
+                                   "Ljava/lang/String;");
     CHECK_NULL(ni_descID);
     ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z");
     CHECK_NULL(ni_virutalID);
-    ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");
+    ni_childsID = (*env)->GetFieldID(env, ni_class, "childs",
+                                     "[Ljava/net/NetworkInterface;");
     CHECK_NULL(ni_childsID);
-    ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", "Ljava/net/NetworkInterface;");
+    ni_parentID = (*env)->GetFieldID(env, ni_class, "parent",
+                                     "Ljava/net/NetworkInterface;");
     CHECK_NULL(ni_parentID);
     ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
     CHECK_NULL(ni_ctrID);
@@ -199,27 +207,28 @@
     CHECK_NULL(ni_ibcls);
     ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
     CHECK_NULL(ni_ibctrID);
-    ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
+    ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address",
+                                        "Ljava/net/InetAddress;");
     CHECK_NULL(ni_ibaddressID);
-    ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
+    ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast",
+                                           "Ljava/net/Inet4Address;");
     CHECK_NULL(ni_ib4broadcastID);
     ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
     CHECK_NULL(ni_ib4maskID);
-    ni_defaultIndexID = (*env)->GetStaticFieldID(env, ni_class, "defaultIndex", "I");
+    ni_defaultIndexID = (*env)->GetStaticFieldID(env, ni_class, "defaultIndex",
+                                                 "I");
     CHECK_NULL(ni_defaultIndexID);
-
     initInetAddressIDs(env);
 }
 
-
 /*
  * Class:     java_net_NetworkInterface
  * Method:    getByName0
  * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
  */
 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
-    (JNIEnv *env, jclass cls, jstring name) {
-
+  (JNIEnv *env, jclass cls, jstring name)
+{
     netif *ifs, *curr;
     jboolean isCopy;
     const char* name_utf;
@@ -236,9 +245,8 @@
            JNU_ThrowOutOfMemoryError(env, NULL);
        return NULL;
     }
-    /*
-     * Search the list of interface based on name
-     */
+
+    // Search the list of interface based on name
     curr = ifs;
     while (curr != NULL) {
         if (strcmp(name_utf, curr->name) == 0) {
@@ -247,27 +255,26 @@
         curr = curr->next;
     }
 
-    /* if found create a NetworkInterface */
+    // if found create a NetworkInterface
     if (curr != NULL) {;
         obj = createNetworkInterface(env, curr);
     }
 
-    /* release the UTF string and interface list */
+    // release the UTF string and interface list
     (*env)->ReleaseStringUTFChars(env, name, name_utf);
     freeif(ifs);
 
     return obj;
 }
 
-
 /*
  * Class:     java_net_NetworkInterface
  * Method:    getByIndex0
  * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
  */
 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
-    (JNIEnv *env, jclass cls, jint index) {
-
+  (JNIEnv *env, jclass cls, jint index)
+{
     netif *ifs, *curr;
     jobject obj = NULL;
 
@@ -279,9 +286,7 @@
         return NULL;
     }
 
-    /*
-     * Search the list of interface based on index
-     */
+    // Search the list of interface based on index
     curr = ifs;
     while (curr != NULL) {
         if (index == curr->index) {
@@ -290,7 +295,7 @@
         curr = curr->next;
     }
 
-    /* if found create a NetworkInterface */
+    // if found create a NetworkInterface
     if (curr != NULL) {;
         obj = createNetworkInterface(env, curr);
     }
@@ -305,8 +310,8 @@
  * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
  */
 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
-    (JNIEnv *env, jclass cls, jobject iaObj) {
-
+  (JNIEnv *env, jclass cls, jobject iaObj)
+{
     netif *ifs, *curr;
 
 #ifdef AF_INET6
@@ -327,14 +332,13 @@
     while (curr != NULL) {
         netaddr *addrP = curr->addr;
 
-        /*
-         * Iterate through each address on the interface
-         */
+        // Iterate through each address on the interface
         while (addrP != NULL) {
 
             if (family == addrP->family) {
                 if (family == AF_INET) {
-                    int address1 = htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr);
+                    int address1 = htonl(
+                        ((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr);
                     int address2 = getInetAddress_addr(env, iaObj);
 
                     if (address1 == address2) {
@@ -345,7 +349,8 @@
 
 #ifdef AF_INET6
                 if (family == AF_INET6) {
-                    jbyte *bytes = (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr);
+                    jbyte *bytes = (jbyte *)&(
+                        ((struct sockaddr_in6*)addrP->addr)->sin6_addr);
                     jbyte caddr[16];
                     int i;
                     getInet6Address_ipaddress(env, iaObj, (char *)caddr);
@@ -362,7 +367,6 @@
                     }
                 }
 #endif
-
             }
 
             if (match) {
@@ -377,7 +381,7 @@
         curr = curr->next;
     }
 
-    /* if found create a NetworkInterface */
+    // if found create a NetworkInterface
     if (match) {;
         obj = createNetworkInterface(env, curr);
     }
@@ -386,15 +390,14 @@
     return obj;
 }
 
-
 /*
  * Class:     java_net_NetworkInterface
  * Method:    getAll
  * Signature: ()[Ljava/net/NetworkInterface;
  */
 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
-    (JNIEnv *env, jclass cls) {
-
+  (JNIEnv *env, jclass cls)
+{
     netif *ifs, *curr;
     jobjectArray netIFArr;
     jint arr_index, ifCount;
@@ -404,7 +407,7 @@
         return NULL;
     }
 
-    /* count the interface */
+    // count the interface
     ifCount = 0;
     curr = ifs;
     while (curr != NULL) {
@@ -412,17 +415,15 @@
         curr = curr->next;
     }
 
-    /* allocate a NetworkInterface array */
+    // allocate a NetworkInterface array
     netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL);
     if (netIFArr == NULL) {
         freeif(ifs);
         return NULL;
     }
 
-    /*
-     * Iterate through the interfaces, create a NetworkInterface instance
-     * for each array element and populate the object.
-     */
+    // Iterate through the interfaces, create a NetworkInterface instance
+    // for each array element and populate the object.
     curr = ifs;
     arr_index = 0;
     while (curr != NULL) {
@@ -434,7 +435,7 @@
             return NULL;
         }
 
-        /* put the NetworkInterface into the array */
+        // put the NetworkInterface into the array
         (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
 
         curr = curr->next;
@@ -444,13 +445,14 @@
     return netIFArr;
 }
 
-
 /*
  * Class:     java_net_NetworkInterface
  * Method:    isUp0
  * Signature: (Ljava/lang/String;I)Z
  */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0(JNIEnv *env, jclass cls, jstring name, jint index) {
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
+  (JNIEnv *env, jclass cls, jstring name, jint index)
+{
     int ret = getFlags0(env, name);
     return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE :  JNI_FALSE;
 }
@@ -460,7 +462,9 @@
  * Method:    isP2P0
  * Signature: (Ljava/lang/String;I)Z
  */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0(JNIEnv *env, jclass cls, jstring name, jint index) {
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0
+  (JNIEnv *env, jclass cls, jstring name, jint index)
+{
     int ret = getFlags0(env, name);
     return (ret & IFF_POINTOPOINT) ? JNI_TRUE :  JNI_FALSE;
 }
@@ -470,7 +474,9 @@
  * Method:    isLoopback0
  * Signature: (Ljava/lang/String;I)Z
  */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0(JNIEnv *env, jclass cls, jstring name, jint index) {
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0
+  (JNIEnv *env, jclass cls, jstring name, jint index)
+{
     int ret = getFlags0(env, name);
     return (ret & IFF_LOOPBACK) ? JNI_TRUE :  JNI_FALSE;
 }
@@ -480,7 +486,9 @@
  * Method:    supportsMulticast0
  * Signature: (Ljava/lang/String;I)Z
  */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0(JNIEnv *env, jclass cls, jstring name, jint index) {
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0
+  (JNIEnv *env, jclass cls, jstring name, jint index)
+{
     int ret = getFlags0(env, name);
     return (ret & IFF_MULTICAST) ? JNI_TRUE :  JNI_FALSE;
 }
@@ -490,7 +498,9 @@
  * Method:    getMacAddr0
  * Signature: ([bLjava/lang/String;I)[b
  */
-JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
+JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0
+  (JNIEnv *env, jclass cls, jbyteArray addrArray, jstring name, jint index)
+{
     jint addr;
     jbyte caddr[4];
     struct in_addr iaddr;
@@ -507,12 +517,11 @@
            JNU_ThrowOutOfMemoryError(env, NULL);
        return NULL;
     }
-    if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
+    if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
        (*env)->ReleaseStringUTFChars(env, name, name_utf);
        return JNI_FALSE;
     }
 
-
     if (!IS_NULL(addrArray)) {
        (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
        addr = ((caddr[0]<<24) & 0xff000000);
@@ -522,7 +531,7 @@
        iaddr.s_addr = htonl(addr);
        len = getMacAddress(env, sock, name_utf, &iaddr, mac);
     } else {
-       len = getMacAddress(env, sock, name_utf,NULL, mac);
+       len = getMacAddress(env, sock, name_utf, NULL, mac);
     }
     if (len > 0) {
        ret = (*env)->NewByteArray(env, len);
@@ -530,10 +539,10 @@
           /* we may have memory to free at the end of this */
           goto fexit;
        }
-       (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
+       (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *)(mac));
     }
  fexit:
-   /* release the UTF string and interface list */
+   // release the UTF string and interface list
    (*env)->ReleaseStringUTFChars(env, name, name_utf);
 
    close(sock);
@@ -545,8 +554,9 @@
  * Method:      getMTU0
  * Signature:   ([bLjava/lang/String;I)I
  */
-
-JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
+JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0
+  (JNIEnv *env, jclass cls, jstring name, jint index)
+{
     jboolean isCopy;
     int ret = -1;
     int sock;
@@ -564,7 +574,7 @@
        return ret;
     }
 
-    if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
+    if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
        (*env)->ReleaseStringUTFChars(env, name, name_utf);
        return JNI_FALSE;
     }
@@ -608,19 +618,17 @@
     (*env)->ReleaseStringUTFChars(env, name, name_utf);
 
     if (ret < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGLIFFLAGS failed");
         return -1;
     }
 
     return flags;
 }
 
-
-
-
 /*
- * Create a NetworkInterface object, populate the name and index, and
- * populate the InetAddress array based on the IP addresses for this
+ * Creates a NetworkInterface object, populates the name, the index, and
+ * populates the InetAddress array based on the IP addresses for this
  * interface.
  */
 jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
@@ -636,9 +644,7 @@
     netif *childP;
     jobject tmp;
 
-    /*
-     * Create a NetworkInterface object and populate it
-     */
+    // Create a NetworkInterface object and populate it
     netifObj = (*env)->NewObject(env, ni_class, ni_ctrID);
     CHECK_NULL_RETURN(netifObj, NULL);
     name = (*env)->NewStringUTF(env, ifs->name);
@@ -646,11 +652,10 @@
     (*env)->SetObjectField(env, netifObj, ni_nameID, name);
     (*env)->SetObjectField(env, netifObj, ni_descID, name);
     (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
-    (*env)->SetBooleanField(env, netifObj, ni_virutalID, ifs->virtual ? JNI_TRUE : JNI_FALSE);
+    (*env)->SetBooleanField(env, netifObj, ni_virutalID,
+                            ifs->virtual ? JNI_TRUE : JNI_FALSE);
 
-    /*
-     * Count the number of address on this interface
-     */
+    //Count the number of address on this interface
     addr_count = 0;
     addrP = ifs->addr;
     while (addrP != NULL) {
@@ -658,9 +663,7 @@
         addrP = addrP->next;
     }
 
-    /*
-     * Create the array of InetAddresses
-     */
+    // Create the array of InetAddresses
     addrArr = (*env)->NewObjectArray(env, addr_count,  ia_class, NULL);
     if (addrArr == NULL) {
         return NULL;
@@ -680,7 +683,8 @@
         if (addrP->family == AF_INET) {
             iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
             if (iaObj) {
-                 setInetAddress_addr(env, iaObj, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
+                 setInetAddress_addr(env, iaObj, htonl(
+                     ((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
             } else {
                 return NULL;
             }
@@ -691,7 +695,8 @@
                     jobject ia2Obj = NULL;
                     ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
                     if (ia2Obj) {
-                       setInetAddress_addr(env, ia2Obj, htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
+                       setInetAddress_addr(env, ia2Obj, htonl(
+                           ((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
                        (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
                     } else {
                         return NULL;
@@ -709,7 +714,8 @@
             int scope=0;
             iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
             if (iaObj) {
-                jboolean ret = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
+                jboolean ret = setInet6Address_ipaddress(env, iaObj,
+                    (char *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
                 if (ret == JNI_FALSE) {
                     return NULL;
                 }
@@ -738,9 +744,7 @@
         addrP = addrP->next;
     }
 
-    /*
-     * See if there is any virtual interface attached to this one.
-     */
+    // See if there is any virtual interface attached to this one.
     child_count = 0;
     childP = ifs->childs;
     while (childP) {
@@ -753,10 +757,7 @@
         return NULL;
     }
 
-    /*
-     * Create the NetworkInterface instances for the sub-interfaces as
-     * well.
-     */
+    // Create the NetworkInterface instances for the sub-interfaces as well.
     child_index = 0;
     childP = ifs->childs;
     while(childP) {
@@ -772,7 +773,7 @@
     (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
     (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
 
-    /* return the NetworkInterface */
+    // return the NetworkInterface
     return netifObj;
 }
 
@@ -783,10 +784,7 @@
     netif *ifs;
     int sock;
 
-    /*
-     * Enumerate IPv4 addresses
-     */
-
+    // Enumerate IPv4 addresses
     sock = openSocket(env, AF_INET);
     if (sock < 0 && (*env)->ExceptionOccurred(env)) {
         return NULL;
@@ -799,19 +797,16 @@
         return NULL;
     }
 
-    /* return partial list if an exception occurs in the middle of process ???*/
+    // return partial list if an exception occurs in the middle of process ???
 
-    /*
-     * If IPv6 is available then enumerate IPv6 addresses.
-     */
+    // If IPv6 is available then enumerate IPv6 addresses.
 #ifdef AF_INET6
 
-        /* User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
-         * so we have to call ipv6_available()
-         */
+        // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
+        // so we have to call ipv6_available()
         if (ipv6_available()) {
 
-           sock =  openSocket(env, AF_INET6);
+           sock = openSocket(env, AF_INET6);
            if (sock < 0 && (*env)->ExceptionOccurred(env)) {
                freeif(ifs);
                return NULL;
@@ -831,18 +826,18 @@
     return ifs;
 }
 
-#define CHECKED_MALLOC3(_pointer,_type,_size) \
-       do{ \
-        _pointer = (_type)malloc( _size ); \
+#define CHECKED_MALLOC3(_pointer, _type, _size) \
+    do { \
+        _pointer = (_type)malloc(_size); \
         if (_pointer == NULL) { \
             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
             return ifs; /* return untouched list */ \
         } \
-       } while(0)
+    } while(0)
 
 
 /*
- * Free an interface list (including any attached addresses)
+ * Frees an interface list (including any attached addresses)
  */
 void freeif(netif *ifs) {
     netif *currif = ifs;
@@ -854,24 +849,21 @@
             netaddr *next = addrP->next;
             free(addrP);
             addrP = next;
-         }
+        }
 
-            /*
-            * Don't forget to free the sub-interfaces.
-            */
-          if (currif->childs != NULL) {
-                freeif(currif->childs);
-          }
+        // Don't forget to free the sub-interfaces.
+        if (currif->childs != NULL) {
+            freeif(currif->childs);
+        }
 
-          ifs = currif->next;
-          free(currif);
-          currif = ifs;
+        ifs = currif->next;
+        free(currif);
+        currif = ifs;
     }
 }
 
-netif *addif(JNIEnv *env, int sock, const char * if_name,
-             netif *ifs, struct sockaddr* ifr_addrP, int family,
-             short prefix)
+netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
+             struct sockaddr *ifr_addrP, int family, short prefix)
 {
     netif *currif = ifs, *parent;
     netaddr *addrP;
@@ -884,37 +876,34 @@
     char name[IFNAMSIZ], vname[IFNAMSIZ];
 #endif
 
-    char  *name_colonP;
+    char *name_colonP;
     int mask;
     int isVirtual = 0;
     int addr_size;
     int flags = 0;
 
-    /*
-     * If the interface name is a logical interface then we
-     * remove the unit number so that we have the physical
-     * interface (eg: hme0:1 -> hme0). NetworkInterface
-     * currently doesn't have any concept of physical vs.
-     * logical interfaces.
-     */
+    // If the interface name is a logical interface then we remove the unit
+    // number so that we have the physical interface (eg: hme0:1 -> hme0).
+    // NetworkInterface currently doesn't have any concept of physical vs.
+    // logical interfaces.
     strncpy(name, if_name, ifnam_size);
     name[ifnam_size - 1] = '\0';
     *vname = 0;
 
-    /*
-     * Create and populate the netaddr node. If allocation fails
-     * return an un-updated list.
-     */
-    /*Allocate for addr and brdcast at once*/
+     // Create and populate the netaddr node. If allocation fails
+     // return an un-updated list.
+
+     // Allocate for addr and brdcast at once
 
 #ifdef AF_INET6
-    addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
+    addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in)
+                                    : sizeof(struct sockaddr_in6);
 #else
     addr_size = sizeof(struct sockaddr_in);
 #endif
 
-    CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size);
-    addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) );
+    CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr) + 2 * addr_size);
+    addrP->addr = (struct sockaddr *)((char *)addrP + sizeof(netaddr));
     memcpy(addrP->addr, ifr_addrP, addr_size);
 
     addrP->family = family;
@@ -923,8 +912,9 @@
     addrP->next = 0;
     if (family == AF_INET) {
        // Deal with broadcast addr & subnet mask
-       struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size);
-       addrP->brdcast = getBroadcast(env, sock, name,  brdcast_to );
+       struct sockaddr *brdcast_to =
+              (struct sockaddr *) ((char *)addrP + sizeof(netaddr) + addr_size);
+       addrP->brdcast = getBroadcast(env, sock, name, brdcast_to);
        if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
            return ifs;
        }
@@ -935,36 +925,28 @@
        }
      }
 
-    /**
-     * Deal with virtual interface with colon notation e.g. eth0:1
-     */
+    // Deal with virtual interface with colon notation e.g. eth0:1
     name_colonP = strchr(name, ':');
     if (name_colonP != NULL) {
-      /**
-       * This is a virtual interface. If we are able to access the parent
-       * we need to create a new entry if it doesn't exist yet *and* update
-       * the 'parent' interface with the new records.
-       */
+        // This is a virtual interface. If we are able to access the parent
+        // we need to create a new entry if it doesn't exist yet *and* update
+        // the 'parent' interface with the new records.
         *name_colonP = 0;
         if (getFlags(sock, name, &flags) < 0 || flags < 0) {
-            // failed to access parent interface do not create parent.
-            // We are a virtual interface with no parent.
-            isVirtual = 1;
-            *name_colonP = ':';
-        }
-        else{
-           // Got access to parent, so create it if necessary.
-           // Save original name to vname and truncate name by ':'
-            memcpy(vname, name, sizeof(vname) );
-            vname[name_colonP - name] = ':';
+             // failed to access parent interface do not create parent.
+             // We are a virtual interface with no parent.
+             isVirtual = 1;
+             *name_colonP = ':';
+        } else {
+             // Got access to parent, so create it if necessary.
+             // Save original name to vname and truncate name by ':'
+             memcpy(vname, name, sizeof(vname) );
+             vname[name_colonP - name] = ':';
         }
     }
 
-    /*
-     * Check if this is a "new" interface. Use the interface
-     * name for matching because index isn't supported on
-     * Solaris 2.6 & 7.
-     */
+    // Check if this is a "new" interface. Use the interface name for
+    // matching because index isn't supported on Solaris 2.6 & 7.
     while (currif != NULL) {
         if (strcmp(name, currif->name) == 0) {
             break;
@@ -972,13 +954,10 @@
         currif = currif->next;
     }
 
-    /*
-     * If "new" then create an netif structure and
-     * insert it onto the list.
-     */
+    // If "new" then create an netif structure and insert it into the list.
     if (currif == NULL) {
          CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
-         currif->name = (char *) currif+sizeof(netif);
+         currif->name = (char *)currif + sizeof(netif);
          strncpy(currif->name, name, ifnam_size);
          currif->name[ifnam_size - 1] = '\0';
          currif->index = getIndex(sock, name);
@@ -989,17 +968,13 @@
          ifs = currif;
     }
 
-    /*
-     * Finally insert the address on the interface
-     */
+    // Finally insert the address on the interface
     addrP->next = currif->addr;
     currif->addr = addrP;
 
     parent = currif;
 
-    /**
-     * Let's deal with the virtual interface now.
-     */
+    // Deal with the virtual interface now.
     if (vname[0]) {
         netaddr *tmpaddr;
 
@@ -1014,27 +989,29 @@
 
         if (currif == NULL) {
             CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
-            currif->name = (char *) currif + sizeof(netif);
+            currif->name = (char *)currif + sizeof(netif);
             strncpy(currif->name, vname, ifnam_size);
             currif->name[ifnam_size - 1] = '\0';
             currif->index = getIndex(sock, vname);
             currif->addr = NULL;
-           /* Need to duplicate the addr entry? */
+            // Need to duplicate the addr entry?
             currif->virtual = 1;
             currif->childs = NULL;
             currif->next = parent->childs;
             parent->childs = currif;
         }
 
-        CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr)+2*addr_size);
+        CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr) + 2 * addr_size);
         memcpy(tmpaddr, addrP, sizeof(netaddr));
         if (addrP->addr != NULL) {
-            tmpaddr->addr = (struct sockaddr *) ( (char*)tmpaddr + sizeof(netaddr) ) ;
+            tmpaddr->addr = (struct sockaddr *)
+                ((char*)tmpaddr + sizeof(netaddr));
             memcpy(tmpaddr->addr, addrP->addr, addr_size);
         }
 
         if (addrP->brdcast != NULL) {
-            tmpaddr->brdcast = (struct sockaddr *) ((char *) tmpaddr + sizeof(netaddr)+addr_size);
+            tmpaddr->brdcast = (struct sockaddr *)
+                ((char *)tmpaddr + sizeof(netaddr) + addr_size);
             memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
         }
 
@@ -1045,19 +1022,18 @@
     return ifs;
 }
 
-/* Open socket for further ioct calls
- * proto is AF_INET/AF_INET6
+/*
+ * Opens a socket for further ioct calls. proto is one of AF_INET or AF_INET6.
  */
-static int  openSocket(JNIEnv *env, int proto){
+static int openSocket(JNIEnv *env, int proto) {
     int sock;
 
     if ((sock = socket(proto, SOCK_DGRAM, 0)) < 0) {
-        /*
-         * If EPROTONOSUPPORT is returned it means we don't have
-         * support  for this proto so don't throw an exception.
-         */
+        // If EPROTONOSUPPORT is returned it means we don't have
+        // support for this proto so don't throw an exception.
         if (errno != EPROTONOSUPPORT) {
-            NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed");
+            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                         "Socket creation failed");
         }
         return -1;
     }
@@ -1068,37 +1044,38 @@
 
 /** Linux, AIX **/
 #if defined(__linux__) || defined(_AIX)
-/* Open socket for further ioct calls, try v4 socket first and
- * if it falls return v6 socket
- */
 
 #ifdef AF_INET6
+/*
+ * Opens a socket for further ioct calls. Tries AF_INET socket first and
+ * if it falls return AF_INET6 socket.
+ */
 // unused arg ifname and struct if2
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     int sock;
     struct ifreq if2;
 
-     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-         if (errno == EPROTONOSUPPORT){
-              if ( (sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
-                 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
-                 return -1;
-              }
-         }
-         else{ // errno is not NOSUPPORT
-             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
-             return -1;
-         }
-   }
+    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+        if (errno == EPROTONOSUPPORT) {
+            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                             "IPV6 Socket creation failed");
+                return -1;
+            }
+        } else { // errno is not NOSUPPORT
+            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                         "IPV4 Socket creation failed");
+            return -1;
+        }
+    }
 
-     /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
-        of address of an interface */
-
-       return sock;
+    // Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or
+    // IPv6 socket regardless of type of address of an interface.
+    return sock;
 }
 
 #else
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     return openSocket(env,AF_INET);
 }
 #endif
@@ -1111,52 +1088,48 @@
     unsigned i;
     int siocgifconfRequest = SIOCGIFCONF;
 
-
 #if defined(__linux__)
-    /* need to do a dummy SIOCGIFCONF to determine the buffer size.
-     * SIOCGIFCOUNT doesn't work
-     */
+    // need to do a dummy SIOCGIFCONF to determine the buffer size.
+    // SIOCGIFCOUNT doesn't work
     ifc.ifc_buf = NULL;
     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGIFCONF failed");
         return ifs;
     }
 #elif defined(_AIX)
     ifc.ifc_buf = NULL;
     if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGSIZIFCONF failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGSIZIFCONF failed");
         return ifs;
     }
 #endif /* __linux__ */
 
-    CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
+    CHECKED_MALLOC3(buf, char *, ifc.ifc_len);
 
     ifc.ifc_buf = buf;
 #if defined(_AIX)
     siocgifconfRequest = CSIOCGIFCONF;
 #endif
     if (ioctl(sock, siocgifconfRequest, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
-        (void) free(buf);
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGIFCONF failed");
+        free(buf);
         return ifs;
     }
 
-    /*
-     * Iterate through each interface
-     */
+    // Iterate through each interface
     ifreqP = ifc.ifc_req;
-    for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
+    for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++, ifreqP++) {
 #if defined(_AIX)
         if (ifreqP->ifr_addr.sa_family != AF_INET) continue;
 #endif
-        /*
-         * Add to the list
-         */
-        ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
+        // Add to the list
+        ifs = addif(env, sock, ifreqP->ifr_name, ifs,
+                    (struct sockaddr *)&(ifreqP->ifr_addr), AF_INET, 0);
 
-        /*
-         * If an exception occurred then free the list
-         */
+        // If an exception occurred then free the list
         if ((*env)->ExceptionOccurred(env)) {
             free(buf);
             freeif(ifs);
@@ -1164,37 +1137,37 @@
         }
     }
 
-    /*
-     * Free socket and buffer
-     */
+    // Free socket and buffer
     free(buf);
     return ifs;
 }
 
 
+#if defined(AF_INET6) && defined(__linux__)
+
 /*
- * Enumerates and returns all IPv6 interfaces on Linux
+ * Enumerates and returns all IPv6 interfaces on Linux.
  */
-
-#if defined(AF_INET6) && defined(__linux__)
 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
     FILE *f;
     char addr6[40], devname[21];
     char addr6p[8][5];
-    int plen, scope, dad_status, if_idx;
+    int prefix, scope, dad_status, if_idx;
     uint8_t ipv6addr[16];
 
     if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
         while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
-                         addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
-                         &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
+                      addr6p[0], addr6p[1], addr6p[2], addr6p[3],
+                      addr6p[4], addr6p[5], addr6p[6], addr6p[7],
+                      &if_idx, &prefix, &scope, &dad_status, devname) != EOF) {
 
             struct netif *ifs_ptr = NULL;
             struct netif *last_ptr = NULL;
             struct sockaddr_in6 addr;
 
             sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
-                           addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
+                    addr6p[0], addr6p[1], addr6p[2], addr6p[3],
+                    addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
             inet_pton(AF_INET6, addr6, ipv6addr);
 
             memset(&addr, 0, sizeof(struct sockaddr_in6));
@@ -1202,12 +1175,10 @@
 
             addr.sin6_scope_id = if_idx;
 
-            ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
-
+            ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr,
+                        AF_INET6, (short)prefix);
 
-            /*
-             * If an exception occurred then return the list as is.
-             */
+            // If an exception occurred then return the list as is.
             if ((*env)->ExceptionOccurred(env)) {
                 fclose(f);
                 return ifs;
@@ -1220,11 +1191,11 @@
 #endif
 
 
+#if defined(AF_INET6) && defined(_AIX)
+
 /*
- * Enumerates and returns all IPv6 interfaces on AIX
+ * Enumerates and returns all IPv6 interfaces on AIX.
  */
-
-#if defined(AF_INET6) && defined(_AIX)
 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
     struct ifconf ifc;
     struct ifreq *ifreqP;
@@ -1234,12 +1205,12 @@
     unsigned bufsize;
     char *cp, *cplimit;
 
-    /* use SIOCGSIZIFCONF to get size for  SIOCGIFCONF */
+    // use SIOCGSIZIFCONF to get size for  SIOCGIFCONF
 
     ifc.ifc_buf = NULL;
     if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                        "ioctl SIOCGSIZIFCONF failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                    "ioctl SIOCGSIZIFCONF failed");
         return ifs;
     }
     bufsize = ifc.ifc_len;
@@ -1252,29 +1223,27 @@
     ifc.ifc_len = bufsize;
     ifc.ifc_buf = buf;
     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                       "ioctl CSIOCGIFCONF failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl CSIOCGIFCONF failed");
         free(buf);
         return ifs;
     }
 
-    /*
-     * Iterate through each interface
-     */
+    // Iterate through each interface
     ifreqP = ifc.ifc_req;
     cp = (char *)ifc.ifc_req;
     cplimit = cp + ifc.ifc_len;
 
-    for ( ; cp < cplimit; cp += (sizeof(ifreqP->ifr_name) + MAX((ifreqP->ifr_addr).sa_len, sizeof(ifreqP->ifr_addr)))) {
+    for (; cp < cplimit;
+        cp += (sizeof(ifreqP->ifr_name) +
+               MAX((ifreqP->ifr_addr).sa_len, sizeof(ifreqP->ifr_addr))))
+    {
         ifreqP = (struct ifreq *)cp;
         struct ifreq if2;
-
         memset((char *)&if2, 0, sizeof(if2));
-        strcpy(if2.ifr_name, ifreqP->ifr_name);
+        strncpy(if2.ifr_name, ifreqP->ifr_name, sizeof(if2.ifr_name) - 1);
 
-        /*
-         * Skip interface that aren't UP
-         */
+        // Skip interface that aren't UP
         if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
             if (!(if2.ifr_flags & IFF_UP)) {
                 continue;
@@ -1289,16 +1258,11 @@
             s6->sin6_scope_id = if2.ifr_site6;
         }
 
-        /*
-         * Add to the list
-         */
+        // Add to the list
         ifs = addif(env, sock, ifreqP->ifr_name, ifs,
-                    (struct sockaddr *)&(ifreqP->ifr_addr),
-                    AF_INET6, 0);
+                    (struct sockaddr *)&(ifreqP->ifr_addr), AF_INET6, 0);
 
-        /*
-         * If an exception occurred then free the list
-         */
+        // If an exception occurred then free the list
         if ((*env)->ExceptionOccurred(env)) {
             free(buf);
             freeif(ifs);
@@ -1306,24 +1270,21 @@
         }
     }
 
-    /*
-     * Free socket and buffer
-     */
+    // Free socket and buffer
     free(buf);
     return ifs;
 }
 #endif
 
 
-static int getIndex(int sock, const char *name){
-     /*
-      * Try to get the interface index
-      */
+static int getIndex(int sock, const char *name) {
+     // Try to get the interface index
 #if defined(_AIX)
     return if_nametoindex(name);
 #else
     struct ifreq if2;
-    strcpy(if2.ifr_name, name);
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.ifr_name, name, sizeof(if2.ifr_name) - 1);
 
     if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
         return -1;
@@ -1333,38 +1294,41 @@
 #endif
 }
 
-/**
+/*
  * Returns the IPv4 broadcast address of a named interface, if it exists.
  * Returns 0 if it doesn't have one.
  */
-static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
-  struct sockaddr *ret = NULL;
-  struct ifreq if2;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
-
-  /* Let's make sure the interface does have a broadcast address */
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2)  < 0) {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGIFFLAGS failed");
-      return ret;
-  }
+static struct sockaddr *getBroadcast
+  (JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store)
+{
+    struct sockaddr *ret = NULL;
+    struct ifreq if2;
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
 
-  if (if2.ifr_flags & IFF_BROADCAST) {
-      /* It does, let's retrieve it*/
-      if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
-          NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
-          return ret;
-      }
+    // Let's make sure the interface does have a broadcast address.
+    if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2)  < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGIFFLAGS failed");
+        return ret;
+    }
 
-      ret = brdcast_store;
-      memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
-  }
+    if (if2.ifr_flags & IFF_BROADCAST) {
+        // It does, let's retrieve it
+        if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
+            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                         "ioctl SIOCGIFBRDADDR failed");
+            return ret;
+        }
 
-  return ret;
+        ret = brdcast_store;
+        memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
+    }
+
+    return ret;
 }
 
-/**
+/*
  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
  * interface, if it has one, otherwise return -1.
  */
@@ -1372,12 +1336,12 @@
     unsigned int mask;
     short ret;
     struct ifreq if2;
-
-    memset((char *) &if2, 0, sizeof(if2));
-    strcpy(if2.ifr_name, ifname);
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
 
     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGIFNETMASK failed");
         return -1;
     }
 
@@ -1391,12 +1355,15 @@
     return ret;
 }
 
-/**
- * Get the Hardware address (usually MAC address) for the named interface.
- * return puts the data in buf, and returns the length, in byte, of the
+/*
+ * Gets the Hardware address (usually MAC address) for the named interface.
+ * On return puts the data in buf, and returns the length, in byte, of the
  * MAC address. Returns -1 if there is no hardware address on that interface.
  */
-static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
+static int getMacAddress
+  (JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr,
+   unsigned char *buf)
+{
 #if defined (_AIX)
     int size;
     struct kinfo_ndd *nddp;
@@ -1415,7 +1382,8 @@
     nddp = (struct kinfo_ndd *)malloc(size);
 
     if (!nddp) {
-        JNU_ThrowOutOfMemoryError(env, "Network interface getMacAddress native buffer allocation failed");
+        JNU_ThrowOutOfMemoryError(env,
+            "Network interface getMacAddress native buffer allocation failed");
         return -1;
     }
 
@@ -1436,22 +1404,20 @@
     }
 
     return -1;
-
 #elif defined(__linux__)
     static struct ifreq ifr;
     int i;
-
-    strcpy(ifr.ifr_name, ifname);
+    memset((char *)&ifr, 0, sizeof(ifr));
+    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
     if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGIFHWADDR failed");
         return -1;
     }
 
     memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
 
-   /*
-    * All bytes to 0 means no hardware address.
-    */
+    // All bytes to 0 means no hardware address.
 
     for (i = 0; i < IFHWADDRLEN; i++) {
         if (buf[i] != 0)
@@ -1464,17 +1430,18 @@
 
 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
     struct ifreq if2;
-    memset((char *) &if2, 0, sizeof(if2));
+    memset((char *)&if2, 0, sizeof(if2));
 
     if (ifname != NULL) {
-        strcpy(if2.ifr_name, ifname);
+        strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
     } else {
         JNU_ThrowNullPointerException(env, "network interface name is NULL");
         return -1;
     }
 
     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGIFMTU failed");
         return -1;
     }
 
@@ -1483,11 +1450,10 @@
 
 static int getFlags(int sock, const char *ifname, int *flags) {
   struct ifreq if2;
+  memset((char *)&if2, 0, sizeof(if2));
+  strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
 
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
-
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
+  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
       return -1;
   }
 
@@ -1499,53 +1465,54 @@
   return 0;
 }
 
-#endif
+#endif  /* defined(__linux__) || defined(_AIX) */
 
 /** Solaris **/
-#ifdef __solaris__
-/* Open socket for further ioct calls, try v4 socket first and
- * if it falls return v6 socket
+#if defined(__solaris__)
+
+/*
+ * Opens a socket for further ioct calls. Tries AF_INET socket first and
+ * if it falls return AF_INET6 socket.
  */
-
 #ifdef AF_INET6
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     int sock, alreadyV6 = 0;
     struct lifreq if2;
 
-     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-         if (errno == EPROTONOSUPPORT){
-              if ( (sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
-                 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
-                 return -1;
-              }
+    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+        if (errno == EPROTONOSUPPORT) {
+            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                             "IPV6 Socket creation failed");
+                return -1;
+            }
 
-              alreadyV6=1;
-         }
-         else{ // errno is not NOSUPPORT
-             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
-             return -1;
-         }
-   }
+            alreadyV6=1;
+        } else { // errno is not NOSUPPORT
+            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                         "IPV4 Socket creation failed");
+            return -1;
+        }
+    }
+
 
-     /**
-      * Solaris requires that we have an IPv6 socket to query an
-      * interface without an IPv4 address - check it here.
-      * POSIX 1 require the kernel to return ENOTTY if the call is
-      * inappropriate for a device e.g. the NETMASK for a device having IPv6
-      * only address but not all devices follow the standard so
-      * fall back on any error. It's not an ecologically friendly gesture
-      * but more reliable.
-      */
+    // Solaris requires that we have an IPv6 socket to query an  interface
+    // without an IPv4 address - check it here. POSIX 1 require the kernel to
+    // return ENOTTY if the call is inappropriate for a device e.g. the NETMASK
+    // for a device having IPv6 only address but not all devices follow the
+    // standard so fall back on any error. It's not an ecologically friendly
+    // gesture but more reliable.
 
-    if (! alreadyV6 ){
-        memset((char *) &if2, 0, sizeof(if2));
-        strcpy(if2.lifr_name, ifname);
+    if (!alreadyV6) {
+        memset((char *)&if2, 0, sizeof(if2));
+        strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
         if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
-                close(sock);
-                if ( (sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
-                      NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
-                      return -1;
-                }
+            close(sock);
+            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                             "IPV6 Socket creation failed");
+                return -1;
+            }
         }
     }
 
@@ -1553,18 +1520,16 @@
 }
 
 #else
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     return openSocket(env,AF_INET);
 }
 #endif
 
 /*
- * Enumerates and returns all IPv4 interfaces
- * (linux verision)
+ * Enumerates and returns all IPv4 interfaces.
  */
-
 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
-     return enumIPvXInterfaces(env,sock, ifs, AF_INET);
+    return enumIPvXInterfaces(env,sock, ifs, AF_INET);
 }
 
 #ifdef AF_INET6
@@ -1574,8 +1539,8 @@
 #endif
 
 /*
-   Enumerates and returns all interfaces on Solaris
-   use the same code for IPv4 and IPv6
+ * Enumerates and returns all interfaces on Solaris.
+ * Uses the same code for IPv4 and IPv6.
  */
 static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
     struct lifconf ifc;
@@ -1585,19 +1550,16 @@
     struct lifnum numifs;
     unsigned bufsize;
 
-    /*
-     * Get the interface count
-     */
+    // Get the interface count
     numifs.lifn_family = family;
     numifs.lifn_flags = 0;
     if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGLIFNUM failed");
         return ifs;
     }
 
-    /*
-     *  Enumerate the interface configurations
-     */
+    //  Enumerate the interface configurations
     bufsize = numifs.lifn_count * sizeof (struct lifreq);
     CHECKED_MALLOC3(buf, char *, bufsize);
 
@@ -1606,22 +1568,19 @@
     ifc.lifc_len = bufsize;
     ifc.lifc_buf = buf;
     if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGLIFCONF failed");
         free(buf);
         return ifs;
     }
 
-    /*
-     * Iterate through each interface
-     */
+    // Iterate through each interface
     ifr = ifc.lifc_req;
     for (n=0; n<numifs.lifn_count; n++, ifr++) {
         int index = -1;
         struct lifreq if2;
 
-        /*
-        * Ignore either IPv4 or IPv6 addresses
-        */
+        // Ignore either IPv4 or IPv6 addresses
         if (ifr->lifr_addr.ss_family != family) {
             continue;
         }
@@ -1633,12 +1592,12 @@
         }
 #endif
 
-        /* add to the list */
-        ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr),family, (short) ifr->lifr_addrlen);
+        // add to the list
+        ifs = addif(env, sock,ifr->lifr_name, ifs,
+                    (struct sockaddr *)&(ifr->lifr_addr), family,
+                    (short)ifr->lifr_addrlen);
 
-        /*
-        * If an exception occurred we return immediately
-        */
+        // If an exception occurred we return immediately
         if ((*env)->ExceptionOccurred(env)) {
             free(buf);
             return ifs;
@@ -1650,13 +1609,11 @@
     return ifs;
 }
 
-static int getIndex(int sock, const char *name){
-   /*
-    * Try to get the interface index
-    * (Not supported on Solaris 2.6 or 7)
-    */
+static int getIndex(int sock, const char *name) {
+    // Try to get the interface index.  (Not supported on Solaris 2.6 or 7)
     struct lifreq if2;
-    strcpy(if2.lifr_name, name);
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.lifr_name, name, sizeof(if2.lifr_name) - 1);
 
     if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
         return -1;
@@ -1665,27 +1622,30 @@
     return if2.lifr_index;
 }
 
-/**
+/*
  * Returns the IPv4 broadcast address of a named interface, if it exists.
  * Returns 0 if it doesn't have one.
  */
-static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
+static struct sockaddr *getBroadcast
+  (JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store)
+{
     struct sockaddr *ret = NULL;
     struct lifreq if2;
-
-    memset((char *) &if2, 0, sizeof(if2));
-    strcpy(if2.lifr_name, ifname);
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
 
-    /* Let's make sure the interface does have a broadcast address */
+    // Let's make sure the interface does have a broadcast address
     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2)  < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGLIFFLAGS failed");
         return ret;
     }
 
     if (if2.lifr_flags & IFF_BROADCAST) {
-        /* It does, let's retrieve it*/
+        // It does, let's retrieve it
         if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFBRDADDR failed");
+            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                         "ioctl SIOCGLIFBRDADDR failed");
             return ret;
         }
 
@@ -1696,7 +1656,7 @@
     return ret;
 }
 
-/**
+/*
  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
  * interface, if it has one, otherwise return -1.
  */
@@ -1704,12 +1664,12 @@
     unsigned int mask;
     short ret;
     struct lifreq if2;
-
-    memset((char *) &if2, 0, sizeof(if2));
-    strcpy(if2.lifr_name, ifname);
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
 
     if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFNETMASK failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGLIFNETMASK failed");
         return -1;
     }
 
@@ -1725,15 +1685,16 @@
 }
 
 
-
 #define DEV_PREFIX  "/dev/"
 
-/**
+/*
  * Solaris specific DLPI code to get hardware address from a device.
  * Unfortunately, at least up to Solaris X, you have to have special
  * privileges (i.e. be root).
  */
-static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) {
+static int getMacFromDevice
+  (JNIEnv *env, const char* ifname, unsigned char* retbuf)
+{
     char style1dev[MAXPATHLEN];
     int fd;
     dl_phys_addr_req_t dlpareq;
@@ -1742,17 +1703,12 @@
     char buf[128];
     int flags = 0;
 
-   /**
-    * Device is in /dev
-    * e.g.: /dev/bge0
-    */
+    // Device is in /dev.  e.g.: /dev/bge0
     strcpy(style1dev, DEV_PREFIX);
     strcat(style1dev, ifname);
     if ((fd = open(style1dev, O_RDWR)) < 0) {
-        /*
-         * Can't open it. We probably are missing the privilege.
-         * We'll have to try something else
-         */
+         // Can't open it. We probably are missing the privilege.
+         // We'll have to try something else
          return 0;
     }
 
@@ -1763,7 +1719,8 @@
     msg.len = DL_PHYS_ADDR_REQ_SIZE;
 
     if (putmsg(fd, &msg, NULL, 0) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "putmsg failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "putmsg failed");
         return -1;
     }
 
@@ -1773,12 +1730,14 @@
     msg.len = 0;
     msg.maxlen = sizeof (buf);
     if (getmsg(fd, &msg, NULL, &flags) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "getmsg failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "getmsg failed");
         return -1;
     }
 
     if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Couldn't obtain phys addr\n");
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                        "Couldn't obtain phys addr\n");
         return -1;
     }
 
@@ -1786,21 +1745,23 @@
     return dlpaack->dl_addr_length;
 }
 
-/**
- * Get the Hardware address (usually MAC address) for the named interface.
- * return puts the data in buf, and returns the length, in byte, of the
+/*
+ * Gets the Hardware address (usually MAC address) for the named interface.
+ * On return puts the data in buf, and returns the length, in byte, of the
  * MAC address. Returns -1 if there is no hardware address on that interface.
  */
-static int getMacAddress(JNIEnv *env, int sock, const char *ifname,  const struct in_addr* addr, unsigned char *buf) {
+static int getMacAddress
+  (JNIEnv *env, int sock, const char *ifname, const struct in_addr* addr,
+   unsigned char *buf)
+{
     struct arpreq arpreq;
     struct sockaddr_in* sin;
     struct sockaddr_in ipAddr;
     int len, i;
     struct lifreq lif;
 
-    /* First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
-     * try the old way.
-     */
+    // First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
+    // try the old way.
     memset(&lif, 0, sizeof(lif));
     strlcpy(lif.lifr_name, ifname, sizeof(lif.lifr_name));
 
@@ -1811,18 +1772,14 @@
         return sp->sdl_alen;
     }
 
-   /**
-    * On Solaris we have to use DLPI, but it will only work if we have
-    * privileged access (i.e. root). If that fails, we try a lookup
-    * in the ARP table, which requires an IPv4 address.
-    */
+    // On Solaris we have to use DLPI, but it will only work if we have
+    // privileged access (i.e. root). If that fails, we try a lookup
+    // in the ARP table, which requires an IPv4 address.
     if ((len = getMacFromDevice(env, ifname, buf))  == 0) {
-        /*DLPI failed - trying to do arp lookup*/
+        // DLPI failed - trying to do arp lookup
 
         if (addr == NULL) {
-            /**
-             * No IPv4 address for that interface, so can't do an ARP lookup.
-             */
+             // No IPv4 address for that interface, so can't do an ARP lookup.
              return -1;
          }
 
@@ -1843,10 +1800,7 @@
          memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
     }
 
-    /*
-     * All bytes to 0 means no hardware address.
-     */
-
+    // All bytes to 0 means no hardware address.
     for (i = 0; i < len; i++) {
       if (buf[i] != 0)
          return len;
@@ -1857,56 +1811,58 @@
 
 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
     struct lifreq if2;
-
-    memset((char *) &if2, 0, sizeof(if2));
-    strcpy(if2.lifr_name, ifname);
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
 
     if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFMTU failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                    "ioctl SIOCGLIFMTU failed");
         return -1;
     }
 
-    return  if2.lifr_mtu;
+    return if2.lifr_mtu;
+}
+
+static int getFlags(int sock, const char *ifname, int *flags) {
+    struct lifreq if2;
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
+
+    if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
+         return -1;
+    }
+
+    *flags = if2.lifr_flags;
+    return 0;
 }
 
 
-static int getFlags(int sock, const char *ifname, int *flags) {
-     struct   lifreq lifr;
-     memset((caddr_t)&lifr, 0, sizeof(lifr));
-     strcpy((caddr_t)&(lifr.lifr_name), ifname);
-
-     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
-         return -1;
-     }
-
-     *flags = lifr.lifr_flags;
-     return 0;
-}
-
-
-#endif
+#endif  /* __solaris__ */
 
 
 /** BSD **/
 #ifdef _ALLBSD_SOURCE
-/* Open socket for further ioct calls, try v4 socket first and
- * if it falls return v6 socket
+
+/*
+ * Opens a socket for further ioct calls. Tries AF_INET socket first and
+ * if it falls return AF_INET6 socket.
  */
-
 #ifdef AF_INET6
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     int sock;
     struct ifreq if2;
 
      if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-         if (errno == EPROTONOSUPPORT){
-              if ( (sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
-                 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+         if (errno == EPROTONOSUPPORT) {
+              if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                              "IPV6 Socket creation failed");
                  return -1;
               }
          }
          else{ // errno is not NOSUPPORT
-             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
+             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                          "IPV4 Socket creation failed");
              return -1;
          }
    }
@@ -1915,39 +1871,33 @@
 }
 
 #else
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     return openSocket(env,AF_INET);
 }
 #endif
 
 /*
- * Enumerates and returns all IPv4 interfaces
+ * Enumerates and returns all IPv4 interfaces.
  */
 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
     struct ifaddrs *ifa, *origifa;
 
     if (getifaddrs(&origifa) != 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "getifaddrs() function failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "getifaddrs() function failed");
         return ifs;
     }
 
     for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
 
-        /*
-         * Skip non-AF_INET entries.
-         */
+        // Skip non-AF_INET entries.
         if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET)
             continue;
 
-        /*
-         * Add to the list.
-         */
+        // Add to the list.
         ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET, 0);
 
-        /*
-         * If an exception occurred then free the list.
-         */
+        // If an exception occurred then free the list.
         if ((*env)->ExceptionOccurred(env)) {
             freeifaddrs(origifa);
             freeif(ifs);
@@ -1955,33 +1905,25 @@
         }
     }
 
-    /*
-     * Free socket and buffer
-     */
+    // Free socket and buffer
     freeifaddrs(origifa);
     return ifs;
 }
 
-
-/*
- * Enumerates and returns all IPv6 interfaces on Linux
- */
-
 #ifdef AF_INET6
 /*
  * Determines the prefix on BSD for IPv6 interfaces.
  */
-static
-int prefix(void *val, int size) {
+static int prefix(void *val, int size) {
     u_char *name = (u_char *)val;
-    int byte, bit, plen = 0;
+    int byte, bit, prefix = 0;
 
-    for (byte = 0; byte < size; byte++, plen += 8)
+    for (byte = 0; byte < size; byte++, prefix += 8)
         if (name[byte] != 0xff)
             break;
     if (byte == size)
-        return (plen);
-    for (bit = 7; bit != 0; bit--, plen++)
+        return prefix;
+    for (bit = 7; bit != 0; bit--, prefix++)
         if (!(name[byte] & (1 << bit)))
             break;
     for (; bit != 0; bit--)
@@ -1991,11 +1933,11 @@
     for (; byte < size; byte++)
         if (name[byte])
             return (0);
-    return (plen);
+    return prefix;
 }
 
 /*
- * Enumerates and returns all IPv6 interfaces on BSD
+ * Enumerates and returns all IPv6 interfaces on BSD.
  */
 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
     struct ifaddrs *ifa, *origifa;
@@ -2003,37 +1945,36 @@
     struct in6_ifreq ifr6;
 
     if (getifaddrs(&origifa) != 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "getifaddrs() function failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "getifaddrs() function failed");
         return ifs;
     }
 
     for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
 
-        /*
-         * Skip non-AF_INET6 entries.
-         */
+        // Skip non-AF_INET6 entries.
         if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6)
             continue;
 
         memset(&ifr6, 0, sizeof(ifr6));
         strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
-        memcpy(&ifr6.ifr_addr, ifa->ifa_addr, MIN(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len));
+        memcpy(&ifr6.ifr_addr, ifa->ifa_addr,
+               MIN(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len));
 
         if (ioctl(sock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) {
-            NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                             "ioctl SIOCGIFNETMASK_IN6 failed");
+            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                         "ioctl SIOCGIFNETMASK_IN6 failed");
             freeifaddrs(origifa);
             freeif(ifs);
             return NULL;
         }
 
-        /* Add to the list.  */
+        // Add to the list.
         sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
         ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET6,
-                    prefix(&sin6->sin6_addr, sizeof(struct in6_addr)));
+            (short)prefix(&sin6->sin6_addr, sizeof(struct in6_addr)));
 
-        /* If an exception occurred then free the list.  */
+        // If an exception occurred then free the list.
         if ((*env)->ExceptionOccurred(env)) {
             freeifaddrs(origifa);
             freeif(ifs);
@@ -2041,22 +1982,19 @@
         }
     }
 
-    /*
-     * Free socket and ifaddrs buffer
-     */
+    // Free socket and ifaddrs buffer
     freeifaddrs(origifa);
     return ifs;
 }
 #endif
 
-static int getIndex(int sock, const char *name){
+static int getIndex(int sock, const char *name) {
 #ifdef __FreeBSD__
-     /*
-      * Try to get the interface index
-      * (Not supported on Solaris 2.6 or 7)
-      */
+    // Try to get the interface index
+    // (Not supported on Solaris 2.6 or 7)
     struct ifreq if2;
-    strcpy(if2.ifr_name, name);
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.ifr_name, name, sizeof(if2.ifr_name) - 1);
 
     if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
         return -1;
@@ -2064,46 +2002,47 @@
 
     return if2.ifr_index;
 #else
-    /*
-     * Try to get the interface index using BSD specific if_nametoindex
-     */
+    // Try to get the interface index using BSD specific if_nametoindex
     int index = if_nametoindex(name);
     return (index == 0) ? -1 : index;
 #endif
 }
 
-/**
+/*
  * Returns the IPv4 broadcast address of a named interface, if it exists.
  * Returns 0 if it doesn't have one.
  */
-static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
-  struct sockaddr *ret = NULL;
-  struct ifreq if2;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
-
-  /* Let's make sure the interface does have a broadcast address */
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed");
-      return ret;
-  }
+static struct sockaddr *getBroadcast
+  (JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store)
+{
+    struct sockaddr *ret = NULL;
+    struct ifreq if2;
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
 
-  if (if2.ifr_flags & IFF_BROADCAST) {
-      /* It does, let's retrieve it*/
-      if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
-          NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
-          return ret;
-      }
+    // Make sure the interface does have a broadcast address
+    if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGIFFLAGS failed");
+        return ret;
+    }
 
-      ret = brdcast_store;
-      memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
-  }
+    if (if2.ifr_flags & IFF_BROADCAST) {
+        // It does, let's retrieve it
+        if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
+            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                         "ioctl SIOCGIFBRDADDR failed");
+            return ret;
+        }
 
-  return ret;
+        ret = brdcast_store;
+        memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
+    }
+
+    return ret;
 }
 
-/**
+/*
  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
  * interface, if it has one, otherwise return -1.
  */
@@ -2111,12 +2050,12 @@
     unsigned int mask;
     short ret;
     struct ifreq if2;
-
-    memset((char *) &if2, 0, sizeof(if2));
-    strcpy(if2.ifr_name, ifname);
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
 
     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGIFNETMASK failed");
         return -1;
     }
 
@@ -2130,25 +2069,28 @@
     return ret;
 }
 
-/**
- * Get the Hardware address (usually MAC address) for the named interface.
+/*
+ * Gets the Hardware address (usually MAC address) for the named interface.
  * return puts the data in buf, and returns the length, in byte, of the
  * MAC address. Returns -1 if there is no hardware address on that interface.
  */
-static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
+static int getMacAddress
+  (JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr,
+   unsigned char *buf)
+{
     struct ifaddrs *ifa0, *ifa;
     struct sockaddr *saddr;
     int i;
 
-    /* Grab the interface list */
+    // Grab the interface list
     if (!getifaddrs(&ifa0)) {
-        /* Cycle through the interfaces */
+        // Cycle through the interfaces
         for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) {
             saddr = ifa->ifa_addr;
-            /* Link layer contains the MAC address */
+            // Link layer contains the MAC address
             if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) {
                 struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr;
-                /* Check the address is the correct length */
+                // Check the address is the correct length
                 if (sadl->sdl_alen == ETHER_ADDR_LEN) {
                     memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
                     freeifaddrs(ifa0);
@@ -2164,12 +2106,12 @@
 
 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
     struct ifreq if2;
-
-    memset((char *) &if2, 0, sizeof(if2));
-    strcpy(if2.ifr_name, ifname);
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
 
     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "ioctl SIOCGIFMTU failed");
         return -1;
     }
 
@@ -2177,22 +2119,20 @@
 }
 
 static int getFlags(int sock, const char *ifname, int *flags) {
-  struct ifreq if2;
-  int ret = -1;
+    struct ifreq if2;
+    int ret = -1;
+    memset((char *)&if2, 0, sizeof(if2));
+    strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
 
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
-
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
-      return -1;
-  }
+    if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
+        return -1;
+    }
 
-  if (sizeof(if2.ifr_flags) == sizeof(short)) {
-    *flags = (if2.ifr_flags & 0xffff);
-  } else {
-    *flags = if2.ifr_flags;
-  }
-  return 0;
+    if (sizeof(if2.ifr_flags) == sizeof(short)) {
+        *flags = (if2.ifr_flags & 0xffff);
+    } else {
+        *flags = if2.ifr_flags;
+    }
+    return 0;
 }
-
-#endif
+#endif /* __ALLBSD_SOURCE__ */
--- a/jdk/src/java.httpclient/share/classes/java/net/http/CharsetToolkit.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +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
- */
-package java.net.http;
-
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-// The purpose of this class is to separate charset-related tasks from the main
-// WebSocket logic, simplifying where possible.
-//
-//     * Coders hide the differences between coding and flushing stages on the
-//       API level
-//     * Verifier abstracts the way the verification is performed
-//       (spoiler: it's a decoding into a throw-away buffer)
-//
-// Coding methods throw exceptions instead of returning coding result denoting
-// errors, since any kind of handling and recovery is not expected.
-final class CharsetToolkit {
-
-    private CharsetToolkit() { }
-
-    static final class Verifier {
-
-        private final CharsetDecoder decoder = UTF_8.newDecoder();
-        // A buffer used to check validity of UTF-8 byte stream by decoding it.
-        // The contents of this buffer are never used.
-        // The size is arbitrary, though it should probably be chosen from the
-        // performance perspective since it affects the total number of calls to
-        // decoder.decode() and amount of work in each of these calls
-        private final CharBuffer blackHole = CharBuffer.allocate(1024);
-
-        void verify(ByteBuffer in, boolean endOfInput)
-                throws CharacterCodingException {
-            while (true) {
-                // Since decoder.flush() cannot produce an error, it's not
-                // helpful for verification. Therefore this step is skipped.
-                CoderResult r = decoder.decode(in, blackHole, endOfInput);
-                if (r.isOverflow()) {
-                    blackHole.clear();
-                } else if (r.isUnderflow()) {
-                    break;
-                } else if (r.isError()) {
-                    r.throwException();
-                } else {
-                    // Should not happen
-                    throw new InternalError();
-                }
-            }
-        }
-
-        Verifier reset() {
-            decoder.reset();
-            return this;
-        }
-    }
-
-    static final class Encoder {
-
-        private final CharsetEncoder encoder = UTF_8.newEncoder();
-        private boolean coding = true;
-
-        CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput)
-                throws CharacterCodingException {
-
-            if (coding) {
-                CoderResult r = encoder.encode(in, out, endOfInput);
-                if (r.isOverflow()) {
-                    return r;
-                } else if (r.isUnderflow()) {
-                    if (endOfInput) {
-                        coding = false;
-                    } else {
-                        return r;
-                    }
-                } else if (r.isError()) {
-                    r.throwException();
-                } else {
-                    // Should not happen
-                    throw new InternalError();
-                }
-            }
-            assert !coding;
-            return encoder.flush(out);
-        }
-
-        Encoder reset() {
-            coding = true;
-            encoder.reset();
-            return this;
-        }
-    }
-
-    static CharBuffer decode(ByteBuffer in) throws CharacterCodingException {
-        return UTF_8.newDecoder().decode(in);
-    }
-
-    static final class Decoder {
-
-        private final CharsetDecoder decoder = UTF_8.newDecoder();
-        private boolean coding = true; // Either coding or flushing
-
-        CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput)
-                throws CharacterCodingException {
-
-            if (coding) {
-                CoderResult r = decoder.decode(in, out, endOfInput);
-                if (r.isOverflow()) {
-                    return r;
-                } else if (r.isUnderflow()) {
-                    if (endOfInput) {
-                        coding = false;
-                    } else {
-                        return r;
-                    }
-                } else if (r.isError()) {
-                    r.throwException();
-                } else {
-                    // Should not happen
-                    throw new InternalError();
-                }
-            }
-            assert !coding;
-            return decoder.flush(out);
-        }
-
-        Decoder reset() {
-            coding = true;
-            decoder.reset();
-            return this;
-        }
-    }
-}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java	Wed Jul 05 21:42:16 2017 +0200
@@ -39,18 +39,22 @@
 
     private final HttpClientImpl client;
     private final HttpConnection connection;
-    private volatile boolean closed;
 
     private interface RawEvent {
 
-        /** must return the selector interest op flags OR'd. */
+        /**
+         * must return the selector interest op flags OR'd.
+         */
         int interestOps();
 
-        /** called when event occurs. */
+        /**
+         * called when event occurs.
+         */
         void handle();
     }
 
-    interface NonBlockingEvent extends RawEvent { }
+    interface NonBlockingEvent extends RawEvent {
+    }
 
     RawChannel(HttpClientImpl client, HttpConnection connection) {
         this.client = client;
@@ -127,12 +131,11 @@
 
     @Override
     public boolean isOpen() {
-        return !closed;
+        return connection.isOpen();
     }
 
     @Override
     public void close() throws IOException {
-        closed = true;
         connection.close();
     }
 
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java	Wed Jul 05 21:42:16 2017 +0200
@@ -32,6 +32,9 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.function.BiFunction;
 import java.util.function.LongConsumer;
 
@@ -409,13 +412,20 @@
     @Override
     HttpResponseImpl getResponse() throws IOException {
         try {
-            return getResponseAsync(null).join();
-        } catch (Throwable e) {
+            if (request.timeval() > 0) {
+                return getResponseAsync(null).get(
+                        request.timeval(), TimeUnit.MILLISECONDS);
+            } else {
+                return getResponseAsync(null).join();
+            }
+        } catch (TimeoutException e) {
+            throw new HttpTimeoutException("Response timed out");
+        } catch (InterruptedException | ExecutionException e) {
             Throwable t = e.getCause();
             if (t instanceof IOException) {
                 throw (IOException)t;
             }
-            throw e;
+            throw new IOException(e);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WS.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.io.IOException;
+import java.net.ProtocolException;
+import java.net.http.WSOpeningHandshake.Result;
+import java.nio.ByteBuffer;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import static java.lang.System.Logger.Level.ERROR;
+import static java.lang.System.Logger.Level.WARNING;
+import static java.net.http.WSUtils.logger;
+import static java.util.Objects.requireNonNull;
+
+/*
+ * A WebSocket client.
+ *
+ * Consists of two independent parts; a transmitter responsible for sending
+ * messages, and a receiver which notifies the listener of incoming messages.
+ */
+final class WS implements WebSocket {
+
+    private final String subprotocol;
+    private final RawChannel channel;
+    private final WSTransmitter transmitter;
+    private final WSReceiver receiver;
+    private final Listener listener;
+    private final Object stateLock = new Object();
+    private volatile State state = State.CONNECTED;
+    private final CompletableFuture<Void> whenClosed = new CompletableFuture<>();
+
+    static CompletableFuture<WebSocket> newInstanceAsync(WSBuilder b) {
+        CompletableFuture<Result> result = new WSOpeningHandshake(b).performAsync();
+        Listener listener = b.getListener();
+        Executor executor = b.getClient().executorService();
+        return result.thenApply(r -> {
+            WS ws = new WS(listener, r.subprotocol, r.channel, executor);
+            ws.start();
+            return ws;
+        });
+    }
+
+    private WS(Listener listener, String subprotocol, RawChannel channel,
+               Executor executor) {
+        this.listener = wrapListener(listener);
+        this.channel = channel;
+        this.subprotocol = subprotocol;
+        Consumer<Throwable> errorHandler = error -> {
+            if (error == null) {
+                throw new InternalError();
+            }
+            // If the channel is closed, we need to update the state, to denote
+            // there's no point in trying to continue using WebSocket
+            if (!channel.isOpen()) {
+                synchronized (stateLock) {
+                    tryChangeState(State.ERROR);
+                }
+            }
+        };
+        transmitter = new WSTransmitter(executor, channel, errorHandler);
+        receiver = new WSReceiver(this.listener, this, executor, channel);
+    }
+
+    private void start() {
+        receiver.start();
+    }
+
+    @Override
+    public CompletableFuture<Void> sendText(ByteBuffer message, boolean isLast) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override
+    public CompletableFuture<Void> sendText(CharSequence message, boolean isLast) {
+        requireNonNull(message, "message");
+        synchronized (stateLock) {
+            checkState();
+            return transmitter.sendText(message, isLast);
+        }
+    }
+
+    @Override
+    public CompletableFuture<Void> sendText(Stream<? extends CharSequence> message) {
+        requireNonNull(message, "message");
+        synchronized (stateLock) {
+            checkState();
+            return transmitter.sendText(message);
+        }
+    }
+
+    @Override
+    public CompletableFuture<Void> sendBinary(ByteBuffer message, boolean isLast) {
+        requireNonNull(message, "message");
+        synchronized (stateLock) {
+            checkState();
+            return transmitter.sendBinary(message, isLast);
+        }
+    }
+
+    @Override
+    public CompletableFuture<Void> sendPing(ByteBuffer message) {
+        requireNonNull(message, "message");
+        synchronized (stateLock) {
+            checkState();
+            return transmitter.sendPing(message);
+        }
+    }
+
+    @Override
+    public CompletableFuture<Void> sendPong(ByteBuffer message) {
+        requireNonNull(message, "message");
+        synchronized (stateLock) {
+            checkState();
+            return transmitter.sendPong(message);
+        }
+    }
+
+    @Override
+    public CompletableFuture<Void> sendClose(CloseCode code, CharSequence reason) {
+        requireNonNull(code, "code");
+        requireNonNull(reason, "reason");
+        synchronized (stateLock) {
+            return doSendClose(() -> transmitter.sendClose(code, reason));
+        }
+    }
+
+    @Override
+    public CompletableFuture<Void> sendClose() {
+        synchronized (stateLock) {
+            return doSendClose(() -> transmitter.sendClose());
+        }
+    }
+
+    private CompletableFuture<Void> doSendClose(Supplier<CompletableFuture<Void>> s) {
+        checkState();
+        boolean closeChannel = false;
+        synchronized (stateLock) {
+            if (state == State.CLOSED_REMOTELY) {
+                closeChannel = tryChangeState(State.CLOSED);
+            } else {
+                tryChangeState(State.CLOSED_LOCALLY);
+            }
+        }
+        CompletableFuture<Void> sent = s.get();
+        if (closeChannel) {
+            sent.whenComplete((v, t) -> {
+                try {
+                    channel.close();
+                } catch (IOException e) {
+                    logger.log(ERROR, "Error transitioning to state " + State.CLOSED, e);
+                }
+            });
+        }
+        return sent;
+    }
+
+    @Override
+    public long request(long n) {
+        if (n < 0L) {
+            throw new IllegalArgumentException("The number must not be negative: " + n);
+        }
+        return receiver.request(n);
+    }
+
+    @Override
+    public String getSubprotocol() {
+        return subprotocol;
+    }
+
+    @Override
+    public boolean isClosed() {
+        return state.isTerminal();
+    }
+
+    @Override
+    public void abort() throws IOException {
+        synchronized (stateLock) {
+            tryChangeState(State.ABORTED);
+        }
+        channel.close();
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "[" + state + "]";
+    }
+
+    private void checkState() {
+        if (state.isTerminal() || state == State.CLOSED_LOCALLY) {
+            throw new IllegalStateException("WebSocket is closed [" + state + "]");
+        }
+    }
+
+    /*
+     * Wraps the user's listener passed to the constructor into own listener to
+     * intercept transitions to terminal states (onClose and onError) and to act
+     * upon exceptions and values from the user's listener.
+     */
+    private Listener wrapListener(Listener listener) {
+        return new Listener() {
+
+            // Listener's method MUST be invoked in a happen-before order
+            private final Object visibilityLock = new Object();
+
+            @Override
+            public void onOpen(WebSocket webSocket) {
+                synchronized (visibilityLock) {
+                    listener.onOpen(webSocket);
+                }
+            }
+
+            @Override
+            public CompletionStage<?> onText(WebSocket webSocket, Text message,
+                                             MessagePart part) {
+                synchronized (visibilityLock) {
+                    return listener.onText(webSocket, message, part);
+                }
+            }
+
+            @Override
+            public CompletionStage<?> onBinary(WebSocket webSocket, ByteBuffer message,
+                                               MessagePart part) {
+                synchronized (visibilityLock) {
+                    return listener.onBinary(webSocket, message, part);
+                }
+            }
+
+            @Override
+            public CompletionStage<?> onPing(WebSocket webSocket, ByteBuffer message) {
+                synchronized (visibilityLock) {
+                    return listener.onPing(webSocket, message);
+                }
+            }
+
+            @Override
+            public CompletionStage<?> onPong(WebSocket webSocket, ByteBuffer message) {
+                synchronized (visibilityLock) {
+                    return listener.onPong(webSocket, message);
+                }
+            }
+
+            @Override
+            public void onClose(WebSocket webSocket, Optional<CloseCode> code, String reason) {
+                synchronized (stateLock) {
+                    if (state == State.CLOSED_REMOTELY || state.isTerminal()) {
+                        throw new InternalError("Unexpected onClose in state " + state);
+                    } else if (state == State.CLOSED_LOCALLY) {
+                        try {
+                            channel.close();
+                        } catch (IOException e) {
+                            logger.log(ERROR, "Error transitioning to state " + State.CLOSED, e);
+                        }
+                        tryChangeState(State.CLOSED);
+                    } else if (state == State.CONNECTED) {
+                        tryChangeState(State.CLOSED_REMOTELY);
+                    }
+                }
+                synchronized (visibilityLock) {
+                    listener.onClose(webSocket, code, reason);
+                }
+            }
+
+            @Override
+            public void onError(WebSocket webSocket, Throwable error) {
+                // An error doesn't necessarily mean the connection must be
+                // closed automatically
+                if (!channel.isOpen()) {
+                    synchronized (stateLock) {
+                        tryChangeState(State.ERROR);
+                    }
+                } else if (error instanceof ProtocolException
+                        && error.getCause() instanceof WSProtocolException) {
+                    WSProtocolException cause = (WSProtocolException) error.getCause();
+                    logger.log(WARNING, "Failing connection {0}, reason: ''{1}''",
+                            webSocket, cause.getMessage());
+                    CloseCode cc = cause.getCloseCode();
+                    transmitter.sendClose(cc, "").whenComplete((v, t) -> {
+                        synchronized (stateLock) {
+                            tryChangeState(State.ERROR);
+                        }
+                        try {
+                            channel.close();
+                        } catch (IOException e) {
+                            logger.log(ERROR, e);
+                        }
+                    });
+                }
+                synchronized (visibilityLock) {
+                    listener.onError(webSocket, error);
+                }
+            }
+        };
+    }
+
+    private boolean tryChangeState(State newState) {
+        assert Thread.holdsLock(stateLock);
+        if (state.isTerminal()) {
+            return false;
+        }
+        state = newState;
+        if (newState.isTerminal()) {
+            whenClosed.complete(null);
+        }
+        return true;
+    }
+
+    CompletionStage<Void> whenClosed() {
+        return whenClosed;
+    }
+
+    /*
+     * WebSocket connection internal state.
+     */
+    private enum State {
+
+        /*
+         * Initial WebSocket state. The WebSocket is connected (i.e. remains in
+         * this state) unless proven otherwise. For example, by reading or
+         * writing operations on the channel.
+         */
+        CONNECTED,
+
+        /*
+         * A Close message has been received by the client. No more messages
+         * will be received.
+         */
+        CLOSED_REMOTELY,
+
+        /*
+         * A Close message has been sent by the client. No more messages can be
+         * sent.
+         */
+        CLOSED_LOCALLY,
+
+        /*
+         * Close messages has been both sent and received (closing handshake)
+         * and TCP connection closed. Closed _cleanly_ in terms of RFC 6455.
+         */
+        CLOSED,
+
+        /*
+         * The connection has been aborted by the client. Closed not _cleanly_
+         * in terms of RFC 6455.
+         */
+        ABORTED,
+
+        /*
+         * The connection has been terminated due to a protocol or I/O error.
+         * Might happen during sending or receiving.
+         */
+        ERROR;
+
+        /*
+         * Returns `true` if this state is terminal. If WebSocket has transited
+         * to such a state, if remains in it forever.
+         */
+        boolean isTerminal() {
+            return this == CLOSED || this == ABORTED || this == ERROR;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSBuilder.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+
+final class WSBuilder implements WebSocket.Builder {
+
+    private static final Set<String> FORBIDDEN_HEADERS =
+            new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+
+    static {
+        List<String> headers = List.of("Connection", "Upgrade",
+                "Sec-WebSocket-Accept", "Sec-WebSocket-Extensions",
+                "Sec-WebSocket-Key", "Sec-WebSocket-Protocol",
+                "Sec-WebSocket-Version");
+        FORBIDDEN_HEADERS.addAll(headers);
+    }
+
+    private final URI uri;
+    private final HttpClient client;
+    private final LinkedHashMap<String, List<String>> headers = new LinkedHashMap<>();
+    private final WebSocket.Listener listener;
+    private Collection<String> subprotocols = Collections.emptyList();
+    private long timeout;
+    private TimeUnit timeUnit;
+
+    WSBuilder(URI uri, HttpClient client, WebSocket.Listener listener) {
+        checkURI(requireNonNull(uri, "uri"));
+        requireNonNull(client, "client");
+        requireNonNull(listener, "listener");
+        this.uri = uri;
+        this.listener = listener;
+        this.client = client;
+    }
+
+    @Override
+    public WebSocket.Builder header(String name, String value) {
+        requireNonNull(name, "name");
+        requireNonNull(value, "value");
+        if (FORBIDDEN_HEADERS.contains(name)) {
+            throw new IllegalArgumentException(
+                    format("Header '%s' is used in the WebSocket Protocol", name));
+        }
+        List<String> values = headers.computeIfAbsent(name, n -> new LinkedList<>());
+        values.add(value);
+        return this;
+    }
+
+    @Override
+    public WebSocket.Builder subprotocols(String mostPreferred, String... lesserPreferred) {
+        requireNonNull(mostPreferred, "mostPreferred");
+        requireNonNull(lesserPreferred, "lesserPreferred");
+        this.subprotocols = checkSubprotocols(mostPreferred, lesserPreferred);
+        return this;
+    }
+
+    @Override
+    public WebSocket.Builder connectTimeout(long timeout, TimeUnit unit) {
+        if (timeout < 0) {
+            throw new IllegalArgumentException("Negative timeout: " + timeout);
+        }
+        requireNonNull(unit, "unit");
+        this.timeout = timeout;
+        this.timeUnit = unit;
+        return this;
+    }
+
+    @Override
+    public CompletableFuture<WebSocket> buildAsync() {
+        return WS.newInstanceAsync(this);
+    }
+
+    private static URI checkURI(URI uri) {
+        String s = uri.getScheme();
+        if (!("ws".equalsIgnoreCase(s) || "wss".equalsIgnoreCase(s))) {
+            throw new IllegalArgumentException
+                    ("URI scheme not ws or wss (RFC 6455 3.): " + s);
+        }
+        String fragment = uri.getFragment();
+        if (fragment != null) {
+            throw new IllegalArgumentException(format
+                    ("Fragment not allowed in a WebSocket URI (RFC 6455 3.): '%s'",
+                            fragment));
+        }
+        return uri;
+    }
+
+    URI getUri() { return uri; }
+
+    HttpClient getClient() { return client; }
+
+    Map<String, List<String>> getHeaders() {
+        LinkedHashMap<String, List<String>> copy = new LinkedHashMap<>(headers.size());
+        headers.forEach((name, values) -> copy.put(name, new LinkedList<>(values)));
+        return copy;
+    }
+
+    WebSocket.Listener getListener() { return listener; }
+
+    Collection<String> getSubprotocols() {
+        return new ArrayList<>(subprotocols);
+    }
+
+    long getTimeout() { return timeout; }
+
+    TimeUnit getTimeUnit() { return timeUnit; }
+
+    private static Collection<String> checkSubprotocols(String mostPreferred,
+                                                        String... lesserPreferred) {
+        checkSubprotocolSyntax(mostPreferred, "mostPreferred");
+        LinkedHashSet<String> sp = new LinkedHashSet<>(1 + lesserPreferred.length);
+        sp.add(mostPreferred);
+        for (int i = 0; i < lesserPreferred.length; i++) {
+            String p = lesserPreferred[i];
+            String location = format("lesserPreferred[%s]", i);
+            requireNonNull(p, location);
+            checkSubprotocolSyntax(p, location);
+            if (!sp.add(p)) {
+                throw new IllegalArgumentException(format(
+                        "Duplicate subprotocols (RFC 6455 4.1.): '%s'", p));
+            }
+        }
+        return sp;
+    }
+
+    private static void checkSubprotocolSyntax(String subprotocol, String location) {
+        if (subprotocol.isEmpty()) {
+            throw new IllegalArgumentException
+                    ("Subprotocol name is empty (RFC 6455 4.1.): " + location);
+        }
+        if (!subprotocol.chars().allMatch(c -> 0x21 <= c && c <= 0x7e)) {
+            throw new IllegalArgumentException
+                    ("Subprotocol name contains illegal characters (RFC 6455 4.1.): "
+                            + location);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSCharsetToolkit.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,126 @@
+/*
+ * 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
+ */
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
+
+import static java.lang.System.Logger.Level.WARNING;
+import static java.net.http.WSUtils.EMPTY_BYTE_BUFFER;
+import static java.net.http.WSUtils.logger;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/*
+ * A collection of tools for UTF-8 coding.
+ */
+final class WSCharsetToolkit {
+
+    private WSCharsetToolkit() { }
+
+    static final class Encoder {
+
+        private final CharsetEncoder encoder = UTF_8.newEncoder();
+
+        ByteBuffer encode(CharBuffer in) throws CharacterCodingException {
+            return encoder.encode(in);
+        }
+
+        // TODO:
+        // ByteBuffer[] encode(CharBuffer in) throws CharacterCodingException {
+        //     return encoder.encode(in);
+        // }
+    }
+
+    static CharBuffer decode(ByteBuffer in) throws CharacterCodingException {
+        return UTF_8.newDecoder().decode(in);
+    }
+
+    static final class Decoder {
+
+        private final CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
+
+        {
+            decoder.onMalformedInput(CodingErrorAction.REPORT);
+            decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        }
+
+        private ByteBuffer leftovers = EMPTY_BYTE_BUFFER;
+
+        WSShared<CharBuffer> decode(WSShared<ByteBuffer> in, boolean endOfInput)
+                throws CharacterCodingException {
+            ByteBuffer b;
+            int rem = leftovers.remaining();
+            if (rem != 0) {
+                // TODO: We won't need this wasteful allocation & copying when
+                // JDK-8155222 has been resolved
+                b = ByteBuffer.allocate(rem + in.remaining());
+                b.put(leftovers).put(in.buffer()).flip();
+            } else {
+                b = in.buffer();
+            }
+            CharBuffer out = CharBuffer.allocate(b.remaining());
+            CoderResult r = decoder.decode(b, out, endOfInput);
+            if (r.isError()) {
+                r.throwException();
+            }
+            if (b.hasRemaining()) {
+                leftovers = ByteBuffer.allocate(b.remaining()).put(b).flip();
+            } else {
+                leftovers = EMPTY_BYTE_BUFFER;
+            }
+            // Since it's UTF-8, the assumption is leftovers.remaining() < 4
+            // (i.e. small). Otherwise a shared buffer should be used
+            if (!(leftovers.remaining() < 4)) {
+                logger.log(WARNING,
+                        "The size of decoding leftovers is greater than expected: {0}",
+                        leftovers.remaining());
+            }
+            b.position(b.limit()); // As if we always read to the end
+            in.dispose();
+            // Decoder promises that in the case of endOfInput == true:
+            // "...any remaining undecoded input will be treated as being
+            // malformed"
+            assert !(endOfInput && leftovers.hasRemaining()) : endOfInput + ", " + leftovers;
+            if (endOfInput) {
+                r = decoder.flush(out);
+                decoder.reset();
+                if (r.isOverflow()) {
+                    // FIXME: for now I know flush() does nothing. But the
+                    // implementation of UTF8 decoder might change. And if now
+                    // flush() is a no-op, it is not guaranteed to remain so in
+                    // the future
+                    throw new InternalError("Not yet implemented");
+                }
+            }
+            out.flip();
+            return WSShared.wrap(out);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposable.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+interface WSDisposable {
+
+    void dispose();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposableText.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+final class WSDisposableText implements WebSocket.Text, WSDisposable {
+
+    private final WSShared<CharBuffer> text;
+
+    WSDisposableText(WSShared<CharBuffer> text) {
+        this.text = text;
+    }
+
+    @Override
+    public int length() {
+        return text.buffer().length();
+    }
+
+    @Override
+    public char charAt(int index) {
+        return text.buffer().charAt(index);
+    }
+
+    @Override
+    public CharSequence subSequence(int start, int end) {
+        return text.buffer().subSequence(start, end);
+    }
+
+    @Override
+    public ByteBuffer asByteBuffer() {
+        throw new UnsupportedOperationException("To be removed from the API");
+    }
+
+    @Override
+    public String toString() {
+        return text.buffer().toString();
+    }
+
+    @Override
+    public void dispose() {
+        text.dispose();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSFrame.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,486 @@
+/*
+ * 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  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.nio.ByteBuffer;
+
+import static java.lang.String.format;
+import static java.net.http.WSFrame.Opcode.ofCode;
+import static java.net.http.WSUtils.dump;
+
+/*
+ * A collection of utilities for reading, writing, and masking frames.
+ */
+final class WSFrame {
+
+    private WSFrame() { }
+
+    static final int MAX_HEADER_SIZE_BYTES = 2 + 8 + 4;
+
+    enum Opcode {
+
+        CONTINUATION   (0x0),
+        TEXT           (0x1),
+        BINARY         (0x2),
+        NON_CONTROL_0x3(0x3),
+        NON_CONTROL_0x4(0x4),
+        NON_CONTROL_0x5(0x5),
+        NON_CONTROL_0x6(0x6),
+        NON_CONTROL_0x7(0x7),
+        CLOSE          (0x8),
+        PING           (0x9),
+        PONG           (0xA),
+        CONTROL_0xB    (0xB),
+        CONTROL_0xC    (0xC),
+        CONTROL_0xD    (0xD),
+        CONTROL_0xE    (0xE),
+        CONTROL_0xF    (0xF);
+
+        private static final Opcode[] opcodes;
+
+        static {
+            Opcode[] values = values();
+            opcodes = new Opcode[values.length];
+            for (Opcode c : values) {
+                assert opcodes[c.code] == null
+                        : WSUtils.dump(c, c.code, opcodes[c.code]);
+                opcodes[c.code] = c;
+            }
+        }
+
+        private final byte code;
+        private final char shiftedCode;
+        private final String description;
+
+        Opcode(int code) {
+            this.code = (byte) code;
+            this.shiftedCode = (char) (code << 8);
+            this.description = format("%x (%s)", code, name());
+        }
+
+        boolean isControl() {
+            return (code & 0x8) != 0;
+        }
+
+        static Opcode ofCode(int code) {
+            return opcodes[code & 0xF];
+        }
+
+        @Override
+        public String toString() {
+            return description;
+        }
+    }
+
+    /*
+     * A utility to mask payload data.
+     */
+    static final class Masker {
+
+        private final ByteBuffer acc = ByteBuffer.allocate(8);
+        private final int[] maskBytes = new int[4];
+        private int offset;
+        private long maskLong;
+
+        /*
+         * Sets up the mask.
+         */
+        Masker mask(int value) {
+            acc.clear().putInt(value).putInt(value).flip();
+            for (int i = 0; i < maskBytes.length; i++) {
+                maskBytes[i] = acc.get(i);
+            }
+            offset = 0;
+            maskLong = acc.getLong(0);
+            return this;
+        }
+
+        /*
+         * Reads as many bytes as possible from the given input buffer, writing
+         * the resulting masked bytes to the given output buffer.
+         *
+         * src.remaining() <= dst.remaining() // TODO: do we need this restriction?
+         * 'src' and 'dst' can be the same ByteBuffer
+         */
+        Masker applyMask(ByteBuffer src, ByteBuffer dst) {
+            if (src.remaining() > dst.remaining()) {
+                throw new IllegalArgumentException(dump(src, dst));
+            }
+            begin(src, dst);
+            loop(src, dst);
+            end(src, dst);
+            return this;
+        }
+
+        // Applying the remaining of the mask (strictly not more than 3 bytes)
+        // byte-wise
+        private void begin(ByteBuffer src, ByteBuffer dst) {
+            if (offset > 0) {
+                for (int i = src.position(), j = dst.position();
+                     offset < 4 && i <= src.limit() - 1 && j <= dst.limit() - 1;
+                     i++, j++, offset++) {
+                    dst.put(j, (byte) (src.get(i) ^ maskBytes[offset]));
+                    dst.position(j + 1);
+                    src.position(i + 1);
+                }
+                offset &= 3;
+            }
+        }
+
+        private void loop(ByteBuffer src, ByteBuffer dst) {
+            int i = src.position();
+            int j = dst.position();
+            final int srcLim = src.limit() - 8;
+            final int dstLim = dst.limit() - 8;
+            for (; i <= srcLim && j <= dstLim; i += 8, j += 8) {
+                dst.putLong(j, (src.getLong(i) ^ maskLong));
+            }
+            if (i > src.limit()) {
+                src.position(i - 8);
+            } else {
+                src.position(i);
+            }
+            if (j > dst.limit()) {
+                dst.position(j - 8);
+            } else {
+                dst.position(j);
+            }
+        }
+
+        // Applying the mask to the remaining bytes byte-wise (don't make any
+        // assumptions on how many, hopefully not more than 7 for 64bit arch)
+        private void end(ByteBuffer src, ByteBuffer dst) {
+            for (int i = src.position(), j = dst.position();
+                 i <= src.limit() - 1 && j <= dst.limit() - 1;
+                 i++, j++, offset = (offset + 1) & 3) { // offset cycle through 0..3
+                dst.put(j, (byte) (src.get(i) ^ maskBytes[offset]));
+                src.position(i + 1);
+                dst.position(j + 1);
+            }
+        }
+    }
+
+    /*
+     * A builder of frame headers, capable of writing to a given buffer.
+     *
+     * The builder does not enforce any protocol-level rules, it simply writes
+     * a header structure to the buffer. The order of calls to intermediate
+     * methods is not significant.
+     */
+    static final class HeaderBuilder {
+
+        private char firstChar;
+        private long payloadLen;
+        private int maskingKey;
+        private boolean mask;
+
+        HeaderBuilder fin(boolean value) {
+            if (value) {
+                firstChar |=  0b10000000_00000000;
+            } else {
+                firstChar &= ~0b10000000_00000000;
+            }
+            return this;
+        }
+
+        HeaderBuilder rsv1(boolean value) {
+            if (value) {
+                firstChar |=  0b01000000_00000000;
+            } else {
+                firstChar &= ~0b01000000_00000000;
+            }
+            return this;
+        }
+
+        HeaderBuilder rsv2(boolean value) {
+            if (value) {
+                firstChar |=  0b00100000_00000000;
+            } else {
+                firstChar &= ~0b00100000_00000000;
+            }
+            return this;
+        }
+
+        HeaderBuilder rsv3(boolean value) {
+            if (value) {
+                firstChar |=  0b00010000_00000000;
+            } else {
+                firstChar &= ~0b00010000_00000000;
+            }
+            return this;
+        }
+
+        HeaderBuilder opcode(Opcode value) {
+            firstChar = (char) ((firstChar & 0xF0FF) | value.shiftedCode);
+            return this;
+        }
+
+        HeaderBuilder payloadLen(long value) {
+            payloadLen = value;
+            firstChar &= 0b11111111_10000000; // Clear previous payload length leftovers
+            if (payloadLen < 126) {
+                firstChar |= payloadLen;
+            } else if (payloadLen < 65535) {
+                firstChar |= 126;
+            } else {
+                firstChar |= 127;
+            }
+            return this;
+        }
+
+        HeaderBuilder mask(int value) {
+            firstChar |= 0b00000000_10000000;
+            maskingKey = value;
+            mask = true;
+            return this;
+        }
+
+        HeaderBuilder noMask() {
+            firstChar &= ~0b00000000_10000000;
+            mask = false;
+            return this;
+        }
+
+        /*
+         * Writes the header to the given buffer.
+         *
+         * The buffer must have at least MAX_HEADER_SIZE_BYTES remaining. The
+         * buffer's position is incremented by the number of bytes written.
+         */
+        void build(ByteBuffer buffer) {
+            buffer.putChar(firstChar);
+            if (payloadLen >= 126) {
+                if (payloadLen < 65535) {
+                    buffer.putChar((char) payloadLen);
+                } else {
+                    buffer.putLong(payloadLen);
+                }
+            }
+            if (mask) {
+                buffer.putInt(maskingKey);
+            }
+        }
+    }
+
+    /*
+     * A consumer of frame parts.
+     *
+     * Guaranteed to be called in the following order by the Frame.Reader:
+     *
+     *     fin rsv1 rsv2 rsv3 opcode mask payloadLength maskingKey? payloadData+ endFrame
+     */
+    interface Consumer {
+
+        void fin(boolean value);
+
+        void rsv1(boolean value);
+
+        void rsv2(boolean value);
+
+        void rsv3(boolean value);
+
+        void opcode(Opcode value);
+
+        void mask(boolean value);
+
+        void payloadLen(long value);
+
+        void maskingKey(int value);
+
+        /*
+         * Called when a part of the payload is ready to be consumed.
+         *
+         * Though may not yield a complete payload in a single invocation, i.e.
+         *
+         *     data.remaining() < payloadLen
+         *
+         * the sum of `data.remaining()` passed to all invocations of this
+         * method will be equal to 'payloadLen', reported in
+         * `void payloadLen(long value)`
+         *
+         * No unmasking is done.
+         */
+        void payloadData(WSShared<ByteBuffer> data, boolean isLast);
+
+        void endFrame(); // TODO: remove (payloadData(isLast=true)) should be enough
+    }
+
+    /*
+     * A Reader of Frames.
+     *
+     * No protocol-level rules are enforced, only frame structure.
+     */
+    static final class Reader {
+
+        private static final int AWAITING_FIRST_BYTE  =  1;
+        private static final int AWAITING_SECOND_BYTE =  2;
+        private static final int READING_16_LENGTH    =  4;
+        private static final int READING_64_LENGTH    =  8;
+        private static final int READING_MASK         = 16;
+        private static final int READING_PAYLOAD      = 32;
+
+        // A private buffer used to simplify multi-byte integers reading
+        private final ByteBuffer accumulator = ByteBuffer.allocate(8);
+        private int state = AWAITING_FIRST_BYTE;
+        private boolean mask;
+        private long payloadLength;
+
+        /*
+         * Reads at most one frame from the given buffer invoking the consumer's
+         * methods corresponding to the frame elements found.
+         *
+         * As much of the frame's payload, if any, is read. The buffers position
+         * is updated to reflect the number of bytes read.
+         *
+         * Throws WSProtocolException if the frame is malformed.
+         */
+        void readFrame(WSShared<ByteBuffer> shared, Consumer consumer) {
+            ByteBuffer input = shared.buffer();
+            loop:
+            while (true) {
+                byte b;
+                switch (state) {
+                    case AWAITING_FIRST_BYTE:
+                        if (!input.hasRemaining()) {
+                            break loop;
+                        }
+                        b = input.get();
+                        consumer.fin( (b & 0b10000000) != 0);
+                        consumer.rsv1((b & 0b01000000) != 0);
+                        consumer.rsv2((b & 0b00100000) != 0);
+                        consumer.rsv3((b & 0b00010000) != 0);
+                        consumer.opcode(ofCode(b));
+                        state = AWAITING_SECOND_BYTE;
+                        continue loop;
+                    case AWAITING_SECOND_BYTE:
+                        if (!input.hasRemaining()) {
+                            break loop;
+                        }
+                        b = input.get();
+                        consumer.mask(mask = (b & 0b10000000) != 0);
+                        byte p1 = (byte) (b & 0b01111111);
+                        if (p1 < 126) {
+                            assert p1 >= 0 : p1;
+                            consumer.payloadLen(payloadLength = p1);
+                            state = mask ? READING_MASK : READING_PAYLOAD;
+                        } else if (p1 < 127) {
+                            state = READING_16_LENGTH;
+                        } else {
+                            state = READING_64_LENGTH;
+                        }
+                        continue loop;
+                    case READING_16_LENGTH:
+                        if (!input.hasRemaining()) {
+                            break loop;
+                        }
+                        b = input.get();
+                        if (accumulator.put(b).position() < 2) {
+                            continue loop;
+                        }
+                        payloadLength = accumulator.flip().getChar();
+                        if (payloadLength < 126) {
+                            throw notMinimalEncoding(payloadLength, 2);
+                        }
+                        consumer.payloadLen(payloadLength);
+                        accumulator.clear();
+                        state = mask ? READING_MASK : READING_PAYLOAD;
+                        continue loop;
+                    case READING_64_LENGTH:
+                        if (!input.hasRemaining()) {
+                            break loop;
+                        }
+                        b = input.get();
+                        if (accumulator.put(b).position() < 8) {
+                            continue loop;
+                        }
+                        payloadLength = accumulator.flip().getLong();
+                        if (payloadLength < 0) {
+                            throw negativePayload(payloadLength);
+                        } else if (payloadLength < 65535) {
+                            throw notMinimalEncoding(payloadLength, 8);
+                        }
+                        consumer.payloadLen(payloadLength);
+                        accumulator.clear();
+                        state = mask ? READING_MASK : READING_PAYLOAD;
+                        continue loop;
+                    case READING_MASK:
+                        if (!input.hasRemaining()) {
+                            break loop;
+                        }
+                        b = input.get();
+                        if (accumulator.put(b).position() != 4) {
+                            continue loop;
+                        }
+                        consumer.maskingKey(accumulator.flip().getInt());
+                        accumulator.clear();
+                        state = READING_PAYLOAD;
+                        continue loop;
+                    case READING_PAYLOAD:
+                        // This state does not require any bytes to be available
+                        // in the input buffer in order to proceed
+                        boolean fullyRead;
+                        int limit;
+                        if (payloadLength <= input.remaining()) {
+                            limit = input.position() + (int) payloadLength;
+                            payloadLength = 0;
+                            fullyRead = true;
+                        } else {
+                            limit = input.limit();
+                            payloadLength -= input.remaining();
+                            fullyRead = false;
+                        }
+                        // FIXME: consider a case where payloadLen != 0,
+                        // but input.remaining() == 0
+                        //
+                        // There shouldn't be an invocation of payloadData with
+                        // an empty buffer, as it would be an artifact of
+                        // reading
+                        consumer.payloadData(shared.share(input.position(), limit), fullyRead);
+                        // Update the position manually, since reading the
+                        // payload doesn't advance buffer's position
+                        input.position(limit);
+                        if (fullyRead) {
+                            consumer.endFrame();
+                            state = AWAITING_FIRST_BYTE;
+                        }
+                        break loop;
+                    default:
+                        throw new InternalError(String.valueOf(state));
+                }
+            }
+        }
+
+        private static WSProtocolException negativePayload(long payloadLength) {
+            return new WSProtocolException
+                    ("5.2.", format("Negative 64-bit payload length %s", payloadLength));
+        }
+
+        private static WSProtocolException notMinimalEncoding(long payloadLength, int numBytes) {
+            return new WSProtocolException
+                    ("5.2.", format("Payload length (%s) is not encoded with minimal number (%s) of bytes",
+                            payloadLength, numBytes));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,289 @@
+/*
+ * 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 java.net.http;
+
+import java.net.http.WSFrame.Opcode;
+import java.net.http.WebSocket.MessagePart;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static java.lang.String.format;
+import static java.lang.System.Logger.Level.TRACE;
+import static java.net.http.WSUtils.dump;
+import static java.net.http.WSUtils.logger;
+import static java.net.http.WebSocket.CloseCode.NOT_CONSISTENT;
+import static java.net.http.WebSocket.CloseCode.of;
+import static java.util.Objects.requireNonNull;
+
+/*
+ * Consumes frame parts and notifies a message consumer, when there is
+ * sufficient data to produce a message, or part thereof.
+ *
+ * Data consumed but not yet translated is accumulated until it's sufficient to
+ * form a message.
+ */
+final class WSFrameConsumer implements WSFrame.Consumer {
+
+    private final AtomicInteger invocationOrder = new AtomicInteger();
+
+    private final WSMessageConsumer output;
+    private final WSCharsetToolkit.Decoder decoder = new WSCharsetToolkit.Decoder();
+    private boolean fin;
+    private Opcode opcode, originatingOpcode;
+    private MessagePart part = MessagePart.WHOLE;
+    private long payloadLen;
+    private WSShared<ByteBuffer> binaryData;
+
+    WSFrameConsumer(WSMessageConsumer output) {
+        this.output = requireNonNull(output);
+    }
+
+    @Override
+    public void fin(boolean value) {
+        assert invocationOrder.compareAndSet(0, 1) : dump(invocationOrder, value);
+        if (logger.isLoggable(TRACE)) {
+            // Checked for being loggable because of autoboxing of 'value'
+            logger.log(TRACE, "Reading fin: {0}", value);
+        }
+        fin = value;
+    }
+
+    @Override
+    public void rsv1(boolean value) {
+        assert invocationOrder.compareAndSet(1, 2) : dump(invocationOrder, value);
+        if (logger.isLoggable(TRACE)) {
+            logger.log(TRACE, "Reading rsv1: {0}", value);
+        }
+        if (value) {
+            throw new WSProtocolException("5.2.", "rsv1 bit is set unexpectedly");
+        }
+    }
+
+    @Override
+    public void rsv2(boolean value) {
+        assert invocationOrder.compareAndSet(2, 3) : dump(invocationOrder, value);
+        if (logger.isLoggable(TRACE)) {
+            logger.log(TRACE, "Reading rsv2: {0}", value);
+        }
+        if (value) {
+            throw new WSProtocolException("5.2.", "rsv2 bit is set unexpectedly");
+        }
+    }
+
+    @Override
+    public void rsv3(boolean value) {
+        assert invocationOrder.compareAndSet(3, 4) : dump(invocationOrder, value);
+        if (logger.isLoggable(TRACE)) {
+            logger.log(TRACE, "Reading rsv3: {0}", value);
+        }
+        if (value) {
+            throw new WSProtocolException("5.2.", "rsv3 bit is set unexpectedly");
+        }
+    }
+
+    @Override
+    public void opcode(Opcode v) {
+        assert invocationOrder.compareAndSet(4, 5) : dump(invocationOrder, v);
+        logger.log(TRACE, "Reading opcode: {0}", v);
+        if (v == Opcode.PING || v == Opcode.PONG || v == Opcode.CLOSE) {
+            if (!fin) {
+                throw new WSProtocolException("5.5.", "A fragmented control frame " + v);
+            }
+            opcode = v;
+        } else if (v == Opcode.TEXT || v == Opcode.BINARY) {
+            if (originatingOpcode != null) {
+                throw new WSProtocolException
+                        ("5.4.", format("An unexpected frame %s (fin=%s)", v, fin));
+            }
+            opcode = v;
+            if (!fin) {
+                originatingOpcode = v;
+            }
+        } else if (v == Opcode.CONTINUATION) {
+            if (originatingOpcode == null) {
+                throw new WSProtocolException
+                        ("5.4.", format("An unexpected frame %s (fin=%s)", v, fin));
+            }
+            opcode = v;
+        } else {
+            throw new WSProtocolException("5.2.", "An unknown opcode " + v);
+        }
+    }
+
+    @Override
+    public void mask(boolean value) {
+        assert invocationOrder.compareAndSet(5, 6) : dump(invocationOrder, value);
+        if (logger.isLoggable(TRACE)) {
+            logger.log(TRACE, "Reading mask: {0}", value);
+        }
+        if (value) {
+            throw new WSProtocolException
+                    ("5.1.", "Received a masked frame from the server");
+        }
+    }
+
+    @Override
+    public void payloadLen(long value) {
+        assert invocationOrder.compareAndSet(6, 7) : dump(invocationOrder, value);
+        if (logger.isLoggable(TRACE)) {
+            logger.log(TRACE, "Reading payloadLen: {0}", value);
+        }
+        if (opcode.isControl()) {
+            if (value > 125) {
+                throw new WSProtocolException
+                        ("5.5.", format("A control frame %s has a payload length of %s",
+                                opcode, value));
+            }
+            assert Opcode.CLOSE.isControl();
+            if (opcode == Opcode.CLOSE && value == 1) {
+                throw new WSProtocolException
+                        ("5.5.1.", "A Close frame's status code is only 1 byte long");
+            }
+        }
+        payloadLen = value;
+    }
+
+    @Override
+    public void maskingKey(int value) {
+        assert false : dump(invocationOrder, value);
+    }
+
+    @Override
+    public void payloadData(WSShared<ByteBuffer> data, boolean isLast) {
+        assert invocationOrder.compareAndSet(7, isLast ? 8 : 7)
+                : dump(invocationOrder, data, isLast);
+        if (logger.isLoggable(TRACE)) {
+            logger.log(TRACE, "Reading payloadData: data={0}, isLast={1}", data, isLast);
+        }
+        if (opcode.isControl()) {
+            if (binaryData != null) {
+                binaryData.put(data);
+                data.dispose();
+            } else if (!isLast) {
+                // The first chunk of the message
+                int remaining = data.remaining();
+                // It shouldn't be 125, otherwise the next chunk will be of size
+                // 0, which is not what Reader promises to deliver (eager
+                // reading)
+                assert remaining < 125 : dump(remaining);
+                WSShared<ByteBuffer> b = WSShared.wrap(ByteBuffer.allocate(125)).put(data);
+                data.dispose();
+                binaryData = b; // Will be disposed by the user
+            } else {
+                // The only chunk; will be disposed by the user
+                binaryData = data.position(data.limit()); // FIXME: remove this hack
+            }
+        } else {
+            part = determinePart(isLast);
+            boolean text = opcode == Opcode.TEXT || originatingOpcode == Opcode.TEXT;
+            if (!text) {
+                output.onBinary(part, data);
+            } else {
+                boolean binaryNonEmpty = data.hasRemaining();
+                WSShared<CharBuffer> textData;
+                try {
+                    textData = decoder.decode(data, part.isLast());
+                } catch (CharacterCodingException e) {
+                    throw new WSProtocolException
+                            ("5.6.", "Invalid UTF-8 sequence in frame " + opcode, NOT_CONSISTENT, e);
+                }
+                if (!(binaryNonEmpty && !textData.hasRemaining())) {
+                    // If there's a binary data, that result in no text, then we
+                    // don't deliver anything
+                    output.onText(part, new WSDisposableText(textData));
+                }
+            }
+        }
+    }
+
+    @Override
+    public void endFrame() {
+        assert invocationOrder.compareAndSet(8, 0) : dump(invocationOrder);
+        if (opcode.isControl()) {
+            binaryData.flip();
+        }
+        switch (opcode) {
+            case CLOSE:
+                WebSocket.CloseCode cc;
+                String reason;
+                if (payloadLen == 0) {
+                    cc = null;
+                    reason = "";
+                } else {
+                    ByteBuffer b = binaryData.buffer();
+                    int len = b.remaining();
+                    assert 2 <= len && len <= 125 : dump(len, payloadLen);
+                    try {
+                        cc = of(b.getChar());
+                        reason = WSCharsetToolkit.decode(b).toString();
+                    } catch (IllegalArgumentException e) {
+                        throw new WSProtocolException
+                                ("5.5.1", "Incorrect status code", e);
+                    } catch (CharacterCodingException e) {
+                        throw new WSProtocolException
+                                ("5.5.1", "Close reason is a malformed UTF-8 sequence", e);
+                    }
+                }
+                binaryData.dispose(); // Manual dispose
+                output.onClose(cc, reason);
+                break;
+            case PING:
+                output.onPing(binaryData);
+                binaryData = null;
+                break;
+            case PONG:
+                output.onPong(binaryData);
+                binaryData = null;
+                break;
+            default:
+                assert opcode == Opcode.TEXT || opcode == Opcode.BINARY
+                        || opcode == Opcode.CONTINUATION : dump(opcode);
+                if (fin) {
+                    // It is always the last chunk:
+                    // either TEXT(FIN=TRUE)/BINARY(FIN=TRUE) or CONT(FIN=TRUE)
+                    originatingOpcode = null;
+                }
+                break;
+        }
+        payloadLen = 0;
+        opcode = null;
+    }
+
+    private MessagePart determinePart(boolean isLast) {
+        boolean lastChunk = fin && isLast;
+        switch (part) {
+            case LAST:
+            case WHOLE:
+                return lastChunk ? MessagePart.WHOLE : MessagePart.FIRST;
+            case FIRST:
+            case PART:
+                return lastChunk ? MessagePart.LAST : MessagePart.PART;
+            default:
+                throw new InternalError(String.valueOf(part));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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 java.net.http;
+
+import java.net.http.WebSocket.CloseCode;
+import java.net.http.WebSocket.MessagePart;
+import java.nio.ByteBuffer;
+
+interface WSMessageConsumer {
+
+    void onText(MessagePart part, WSDisposableText data);
+
+    void onBinary(MessagePart part, WSShared<ByteBuffer> data);
+
+    void onPing(WSShared<ByteBuffer> data);
+
+    void onPong(WSShared<ByteBuffer> data);
+
+    void onClose(CloseCode code, CharSequence reason);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageSender.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,189 @@
+/*
+ * 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  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.net.http.WSFrame.HeaderBuilder;
+import java.net.http.WSFrame.Masker;
+import java.net.http.WSOutgoingMessage.Binary;
+import java.net.http.WSOutgoingMessage.Close;
+import java.net.http.WSOutgoingMessage.Ping;
+import java.net.http.WSOutgoingMessage.Pong;
+import java.net.http.WSOutgoingMessage.StreamedText;
+import java.net.http.WSOutgoingMessage.Text;
+import java.net.http.WSOutgoingMessage.Visitor;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.security.SecureRandom;
+import java.util.function.Consumer;
+
+import static java.net.http.WSFrame.MAX_HEADER_SIZE_BYTES;
+import static java.net.http.WSFrame.Opcode.BINARY;
+import static java.net.http.WSFrame.Opcode.CLOSE;
+import static java.net.http.WSFrame.Opcode.CONTINUATION;
+import static java.net.http.WSFrame.Opcode.PING;
+import static java.net.http.WSFrame.Opcode.PONG;
+import static java.net.http.WSFrame.Opcode.TEXT;
+import static java.util.Objects.requireNonNull;
+
+/*
+ * A Sender of outgoing messages.  Given a message,
+ *
+ *     1) constructs the frame
+ *     2) initiates the channel write
+ *     3) notifies when the message has been sent
+ */
+final class WSMessageSender {
+
+    private final Visitor frameBuilderVisitor;
+    private final Consumer<Throwable> completionEventConsumer;
+    private final WSWriter writer;
+    private final ByteBuffer[] buffers = new ByteBuffer[2];
+
+    WSMessageSender(RawChannel channel, Consumer<Throwable> completionEventConsumer) {
+        // Single reusable buffer that holds a header
+        this.buffers[0] = ByteBuffer.allocateDirect(MAX_HEADER_SIZE_BYTES);
+        this.frameBuilderVisitor = new FrameBuilderVisitor();
+        this.completionEventConsumer = completionEventConsumer;
+        this.writer = new WSWriter(channel, this.completionEventConsumer);
+    }
+
+    /*
+     * Tries to send the given message fully. Invoked once per message.
+     */
+    boolean trySendFully(WSOutgoingMessage m) {
+        requireNonNull(m);
+        synchronized (this) {
+            try {
+                return sendNow(m);
+            } catch (Exception e) {
+                completionEventConsumer.accept(e);
+                return false;
+            }
+        }
+    }
+
+    private boolean sendNow(WSOutgoingMessage m) {
+        buffers[0].clear();
+        m.accept(frameBuilderVisitor);
+        buffers[0].flip();
+        return writer.tryWriteFully(buffers);
+    }
+
+    /*
+     * Builds and initiates a write of a frame, from a given message.
+     */
+    class FrameBuilderVisitor implements Visitor {
+
+        private final SecureRandom random = new SecureRandom();
+        private final WSCharsetToolkit.Encoder encoder = new WSCharsetToolkit.Encoder();
+        private final Masker masker = new Masker();
+        private final HeaderBuilder headerBuilder = new HeaderBuilder();
+        private boolean previousIsLast = true;
+
+        @Override
+        public void visit(Text message) {
+            try {
+                buffers[1] = encoder.encode(CharBuffer.wrap(message.characters));
+            } catch (CharacterCodingException e) {
+                completionEventConsumer.accept(e);
+                return;
+            }
+            int mask = random.nextInt();
+            maskAndRewind(buffers[1], mask);
+            headerBuilder
+                    .fin(message.isLast)
+                    .opcode(previousIsLast ? TEXT : CONTINUATION)
+                    .payloadLen(buffers[1].remaining())
+                    .mask(mask)
+                    .build(buffers[0]);
+            previousIsLast = message.isLast;
+        }
+
+        @Override
+        public void visit(StreamedText streamedText) {
+            throw new IllegalArgumentException("Not yet implemented");
+        }
+
+        @Override
+        public void visit(Binary message) {
+            buffers[1] = message.bytes;
+            int mask = random.nextInt();
+            maskAndRewind(buffers[1], mask);
+            headerBuilder
+                    .fin(message.isLast)
+                    .opcode(previousIsLast ? BINARY : CONTINUATION)
+                    .payloadLen(message.bytes.remaining())
+                    .mask(mask)
+                    .build(buffers[0]);
+            previousIsLast = message.isLast;
+        }
+
+        @Override
+        public void visit(Ping message) {
+            buffers[1] = message.bytes;
+            int mask = random.nextInt();
+            maskAndRewind(buffers[1], mask);
+            headerBuilder
+                    .fin(true)
+                    .opcode(PING)
+                    .payloadLen(message.bytes.remaining())
+                    .mask(mask)
+                    .build(buffers[0]);
+        }
+
+        @Override
+        public void visit(Pong message) {
+            buffers[1] = message.bytes;
+            int mask = random.nextInt();
+            maskAndRewind(buffers[1], mask);
+            headerBuilder
+                    .fin(true)
+                    .opcode(PONG)
+                    .payloadLen(message.bytes.remaining())
+                    .mask(mask)
+                    .build(buffers[0]);
+        }
+
+        @Override
+        public void visit(Close message) {
+            buffers[1] = message.bytes;
+            int mask = random.nextInt();
+            maskAndRewind(buffers[1], mask);
+            headerBuilder
+                    .fin(true)
+                    .opcode(CLOSE)
+                    .payloadLen(buffers[1].remaining())
+                    .mask(mask)
+                    .build(buffers[0]);
+        }
+
+        private void maskAndRewind(ByteBuffer b, int mask) {
+            int oldPos = b.position();
+            masker.mask(mask).applyMask(b, b);
+            b.position(oldPos);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static java.lang.String.format;
+import static java.lang.System.Logger.Level.TRACE;
+import static java.net.http.WSUtils.logger;
+import static java.net.http.WSUtils.webSocketSpecViolation;
+
+final class WSOpeningHandshake {
+
+    private static final String HEADER_CONNECTION = "Connection";
+    private static final String HEADER_UPGRADE = "Upgrade";
+    private static final String HEADER_ACCEPT = "Sec-WebSocket-Accept";
+    private static final String HEADER_EXTENSIONS = "Sec-WebSocket-Extensions";
+    private static final String HEADER_KEY = "Sec-WebSocket-Key";
+    private static final String HEADER_PROTOCOL = "Sec-WebSocket-Protocol";
+    private static final String HEADER_VERSION = "Sec-WebSocket-Version";
+    private static final String VALUE_VERSION = "13"; // WebSocket's lucky number
+
+    private static final SecureRandom srandom = new SecureRandom();
+
+    private final MessageDigest sha1;
+
+    {
+        try {
+            sha1 = MessageDigest.getInstance("SHA-1");
+        } catch (NoSuchAlgorithmException e) {
+            // Shouldn't happen:
+            // SHA-1 must be available in every Java platform implementation
+            throw new InternalError("Minimum platform requirements are not met", e);
+        }
+    }
+
+    private final HttpRequest request;
+    private final Collection<String> subprotocols;
+    private final String nonce;
+
+    WSOpeningHandshake(WSBuilder b) {
+        URI httpURI = createHttpUri(b.getUri());
+        HttpRequest.Builder requestBuilder = b.getClient().request(httpURI);
+        if (b.getTimeUnit() != null) {
+            requestBuilder.timeout(b.getTimeUnit(), b.getTimeout());
+        }
+        Collection<String> s = b.getSubprotocols();
+        if (!s.isEmpty()) {
+            String p = s.stream().collect(Collectors.joining(", "));
+            requestBuilder.header(HEADER_PROTOCOL, p);
+        }
+        requestBuilder.header(HEADER_VERSION, VALUE_VERSION);
+        this.nonce = createNonce();
+        requestBuilder.header(HEADER_KEY, this.nonce);
+        this.request = requestBuilder.GET();
+        HttpRequestImpl r = (HttpRequestImpl) this.request;
+        r.isWebSocket(true);
+        r.setSystemHeader(HEADER_UPGRADE, "websocket");
+        r.setSystemHeader(HEADER_CONNECTION, "Upgrade");
+        this.subprotocols = s;
+    }
+
+    private URI createHttpUri(URI webSocketUri) {
+        // FIXME: check permission for WebSocket URI and translate it into http/https permission
+        logger.log(TRACE, "->createHttpUri(''{0}'')", webSocketUri);
+        String httpScheme = webSocketUri.getScheme().equalsIgnoreCase("ws")
+                ? "http"
+                : "https";
+        try {
+            URI uri = new URI(httpScheme,
+                    webSocketUri.getUserInfo(),
+                    webSocketUri.getHost(),
+                    webSocketUri.getPort(),
+                    webSocketUri.getPath(),
+                    webSocketUri.getQuery(),
+                    null);
+            logger.log(TRACE, "<-createHttpUri: ''{0}''", uri);
+            return uri;
+        } catch (URISyntaxException e) {
+            // Shouldn't happen: URI invariant
+            throw new InternalError("Error translating WebSocket URI to HTTP URI", e);
+        }
+    }
+
+    CompletableFuture<Result> performAsync() {
+        // The whole dancing with thenCompose instead of thenApply is because
+        // WebSocketHandshakeException is a checked exception
+        return request.responseAsync()
+                .thenCompose(response -> {
+                    try {
+                        Result result = handleResponse(response);
+                        return CompletableFuture.completedFuture(result);
+                    } catch (WebSocketHandshakeException e) {
+                        return CompletableFuture.failedFuture(e);
+                    }
+                });
+    }
+
+    private Result handleResponse(HttpResponse response) throws WebSocketHandshakeException {
+        // By this point all redirects, authentications, etc. (if any) must have
+        // been done by the httpClient used by the WebSocket; so only 101 is
+        // expected
+        int statusCode = response.statusCode();
+        if (statusCode != 101) {
+            String m = webSocketSpecViolation("1.3.",
+                    "Unable to complete handshake; HTTP response status code "
+                            + statusCode
+            );
+            throw new WebSocketHandshakeException(m, response);
+        }
+        HttpHeaders h = response.headers();
+        checkHeader(h, response, HEADER_UPGRADE, v -> v.equalsIgnoreCase("websocket"));
+        checkHeader(h, response, HEADER_CONNECTION, v -> v.equalsIgnoreCase("Upgrade"));
+        checkVersion(response, h);
+        checkAccept(response, h);
+        checkExtensions(response, h);
+        String subprotocol = checkAndReturnSubprotocol(response, h);
+        RawChannel channel = ((HttpResponseImpl) response).rawChannel();
+        return new Result(subprotocol, channel);
+    }
+
+    private void checkExtensions(HttpResponse response, HttpHeaders headers)
+            throws WebSocketHandshakeException {
+        List<String> ext = headers.allValues(HEADER_EXTENSIONS);
+        if (!ext.isEmpty()) {
+            String m = webSocketSpecViolation("4.1.",
+                    "Server responded with extension(s) though none were requested "
+                            + Arrays.toString(ext.toArray())
+            );
+            throw new WebSocketHandshakeException(m, response);
+        }
+    }
+
+    private String checkAndReturnSubprotocol(HttpResponse response, HttpHeaders headers)
+            throws WebSocketHandshakeException {
+        assert response.statusCode() == 101 : response.statusCode();
+        List<String> sp = headers.allValues(HEADER_PROTOCOL);
+        int size = sp.size();
+        if (size == 0) {
+            // In this case the subprotocol requested (if any) by the client
+            // doesn't matter. If there is no such header in the response, then
+            // the server doesn't want to use any subprotocol
+            return null;
+        } else if (size > 1) {
+            // We don't know anything about toString implementation of this
+            // list, so let's create an array
+            String m = webSocketSpecViolation("4.1.",
+                    "Server responded with multiple subprotocols: "
+                            + Arrays.toString(sp.toArray())
+            );
+            throw new WebSocketHandshakeException(m, response);
+        } else {
+            String selectedSubprotocol = sp.get(0);
+            if (this.subprotocols.contains(selectedSubprotocol)) {
+                return selectedSubprotocol;
+            } else {
+                String m = webSocketSpecViolation("4.1.",
+                        format("Server responded with a subprotocol " +
+                                        "not among those requested: '%s'",
+                                selectedSubprotocol));
+                throw new WebSocketHandshakeException(m, response);
+            }
+        }
+    }
+
+    private void checkAccept(HttpResponse response, HttpHeaders headers)
+            throws WebSocketHandshakeException {
+        assert response.statusCode() == 101 : response.statusCode();
+        String x = nonce + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+        sha1.update(x.getBytes(StandardCharsets.ISO_8859_1));
+        String expected = Base64.getEncoder().encodeToString(sha1.digest());
+        checkHeader(headers, response, HEADER_ACCEPT, actual -> actual.trim().equals(expected));
+    }
+
+    private void checkVersion(HttpResponse response, HttpHeaders headers)
+            throws WebSocketHandshakeException {
+        assert response.statusCode() == 101 : response.statusCode();
+        List<String> versions = headers.allValues(HEADER_VERSION);
+        if (versions.isEmpty()) { // That's normal and expected
+            return;
+        }
+        String m = webSocketSpecViolation("4.4.",
+                "Server responded with version(s) "
+                        + Arrays.toString(versions.toArray()));
+        throw new WebSocketHandshakeException(m, response);
+    }
+
+    //
+    // Checks whether there's only one value for the header with the given name
+    // and the value satisfies the predicate.
+    //
+    private static void checkHeader(HttpHeaders headers,
+                                    HttpResponse response,
+                                    String headerName,
+                                    Predicate<? super String> valuePredicate)
+            throws WebSocketHandshakeException {
+        assert response.statusCode() == 101 : response.statusCode();
+        List<String> values = headers.allValues(headerName);
+        if (values.isEmpty()) {
+            String m = webSocketSpecViolation("4.1.",
+                    format("Server response field '%s' is missing", headerName)
+            );
+            throw new WebSocketHandshakeException(m, response);
+        } else if (values.size() > 1) {
+            String m = webSocketSpecViolation("4.1.",
+                    format("Server response field '%s' has multiple values", headerName)
+            );
+            throw new WebSocketHandshakeException(m, response);
+        }
+        if (!valuePredicate.test(values.get(0))) {
+            String m = webSocketSpecViolation("4.1.",
+                    format("Server response field '%s' is incorrect", headerName)
+            );
+            throw new WebSocketHandshakeException(m, response);
+        }
+    }
+
+    private static String createNonce() {
+        byte[] bytes = new byte[16];
+        srandom.nextBytes(bytes);
+        return Base64.getEncoder().encodeToString(bytes);
+    }
+
+    static final class Result {
+
+        final String subprotocol;
+        final RawChannel channel;
+
+        private Result(String subprotocol, RawChannel channel) {
+            this.subprotocol = subprotocol;
+            this.channel = channel;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSOutgoingMessage.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.util.stream.Stream;
+
+abstract class WSOutgoingMessage {
+
+    interface Visitor {
+        void visit(Text message);
+        void visit(StreamedText message);
+        void visit(Binary message);
+        void visit(Ping message);
+        void visit(Pong message);
+        void visit(Close message);
+    }
+
+    abstract void accept(Visitor visitor);
+
+    private WSOutgoingMessage() { }
+
+    static final class Text extends WSOutgoingMessage {
+
+        public final boolean isLast;
+        public final CharSequence characters;
+
+        Text(boolean isLast, CharSequence characters) {
+            this.isLast = isLast;
+            this.characters = characters;
+        }
+
+        @Override
+        void accept(Visitor visitor) {
+            visitor.visit(this);
+        }
+
+        @Override
+        public String toString() {
+            return WSUtils.toStringSimple(this) + "[isLast=" + isLast
+                    + ", characters=" + WSUtils.toString(characters) + "]";
+        }
+    }
+
+    static final class StreamedText extends WSOutgoingMessage {
+
+        public final Stream<? extends CharSequence> characters;
+
+        StreamedText(Stream<? extends CharSequence> characters) {
+            this.characters = characters;
+        }
+
+        @Override
+        void accept(Visitor visitor) {
+            visitor.visit(this);
+        }
+
+        @Override
+        public String toString() {
+            return WSUtils.toStringSimple(this) + "[characters=" + characters + "]";
+        }
+    }
+
+    static final class Binary extends WSOutgoingMessage {
+
+        public final boolean isLast;
+        public final ByteBuffer bytes;
+
+        Binary(boolean isLast, ByteBuffer bytes) {
+            this.isLast = isLast;
+            this.bytes = bytes;
+        }
+
+        @Override
+        void accept(Visitor visitor) {
+            visitor.visit(this);
+        }
+
+        @Override
+        public String toString() {
+            return WSUtils.toStringSimple(this) + "[isLast=" + isLast
+                    + ", bytes=" + WSUtils.toString(bytes) + "]";
+        }
+    }
+
+    static final class Ping extends WSOutgoingMessage {
+
+        public final ByteBuffer bytes;
+
+        Ping(ByteBuffer bytes) {
+            this.bytes = bytes;
+        }
+
+        @Override
+        void accept(Visitor visitor) {
+            visitor.visit(this);
+        }
+
+        @Override
+        public String toString() {
+            return WSUtils.toStringSimple(this) + "[" + WSUtils.toString(bytes) + "]";
+        }
+    }
+
+    static final class Pong extends WSOutgoingMessage {
+
+        public final ByteBuffer bytes;
+
+        Pong(ByteBuffer bytes) {
+            this.bytes = bytes;
+        }
+
+        @Override
+        void accept(Visitor visitor) {
+            visitor.visit(this);
+        }
+
+        @Override
+        public String toString() {
+            return WSUtils.toStringSimple(this) + "[" + WSUtils.toString(bytes) + "]";
+        }
+    }
+
+    static final class Close extends WSOutgoingMessage {
+
+        public final ByteBuffer bytes;
+
+        Close(ByteBuffer bytes) {
+            this.bytes = bytes;
+        }
+
+        @Override
+        void accept(Visitor visitor) {
+            visitor.visit(this);
+        }
+
+        @Override
+        public String toString() {
+            return WSUtils.toStringSimple(this) + "[" + WSUtils.toString(bytes) + "]";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSProtocolException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,68 @@
+package java.net.http;
+
+import java.net.http.WebSocket.CloseCode;
+
+import static java.net.http.WebSocket.CloseCode.PROTOCOL_ERROR;
+import static java.util.Objects.requireNonNull;
+
+//
+// Special kind of exception closed from the outside world.
+//
+// Used as a "marker exception" for protocol issues in the incoming data, so the
+// implementation could close the connection and specify an appropriate status
+// code.
+//
+// A separate 'section' argument makes it more uncomfortable to be lazy and to
+// leave a relevant spec reference empty :-) As a bonus all messages have the
+// same style.
+//
+final class WSProtocolException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+    private final CloseCode closeCode;
+    private final String section;
+
+    WSProtocolException(String section, String detail) {
+        this(section, detail, PROTOCOL_ERROR);
+    }
+
+    WSProtocolException(String section, String detail, Throwable cause) {
+        this(section, detail, PROTOCOL_ERROR, cause);
+    }
+
+    private WSProtocolException(String section, String detail, CloseCode code) {
+        super(formatMessage(section, detail));
+        this.closeCode = requireNonNull(code);
+        this.section = section;
+    }
+
+    WSProtocolException(String section, String detail, CloseCode code,
+                        Throwable cause) {
+        super(formatMessage(section, detail), cause);
+        this.closeCode = requireNonNull(code);
+        this.section = section;
+    }
+
+    private static String formatMessage(String section, String detail) {
+        if (requireNonNull(section).isEmpty()) {
+            throw new IllegalArgumentException();
+        }
+        if (requireNonNull(detail).isEmpty()) {
+            throw new IllegalArgumentException();
+        }
+        return WSUtils.webSocketSpecViolation(section, detail);
+    }
+
+    CloseCode getCloseCode() {
+        return closeCode;
+    }
+
+    public String getSection() {
+        return section;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "[" + closeCode + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,275 @@
+/*
+ * 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 java.net.http;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.ProtocolException;
+import java.net.http.WebSocket.Listener;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.util.Optional;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Supplier;
+
+import static java.lang.System.Logger.Level.ERROR;
+import static java.net.http.WSUtils.EMPTY_BYTE_BUFFER;
+import static java.net.http.WSUtils.logger;
+
+/*
+ * Receives incoming data from the channel and converts it into a sequence of
+ * messages, which are then passed to the listener.
+ */
+final class WSReceiver {
+
+    private final Listener listener;
+    private final WebSocket webSocket;
+    private final Supplier<WSShared<ByteBuffer>> buffersSupplier =
+            new WSSharedPool<>(() -> ByteBuffer.allocateDirect(32768), 2);
+    private final RawChannel channel;
+    private final RawChannel.NonBlockingEvent channelEvent;
+    private final WSSignalHandler handler;
+    private final AtomicLong demand = new AtomicLong();
+    private final AtomicBoolean readable = new AtomicBoolean();
+    private boolean started;
+    private volatile boolean closed;
+    private final WSFrame.Reader reader = new WSFrame.Reader();
+    private final WSFrameConsumer frameConsumer;
+    private WSShared<ByteBuffer> buf = WSShared.wrap(EMPTY_BYTE_BUFFER);
+    private WSShared<ByteBuffer> data; // TODO: initialize with leftovers from the RawChannel
+
+    WSReceiver(Listener listener, WebSocket webSocket, Executor executor,
+               RawChannel channel) {
+        this.listener = listener;
+        this.webSocket = webSocket;
+        this.channel = channel;
+        handler = new WSSignalHandler(executor, this::react);
+        channelEvent = createChannelEvent();
+        this.frameConsumer = new WSFrameConsumer(new MessageConsumer());
+    }
+
+    private void react() {
+        synchronized (this) {
+            while (demand.get() > 0 && !closed) {
+                try {
+                    if (data == null) {
+                        if (!getData()) {
+                            break;
+                        }
+                    }
+                    reader.readFrame(data, frameConsumer);
+                    if (!data.hasRemaining()) {
+                        data.dispose();
+                        data = null;
+                    }
+                    // In case of exception we don't need to clean any state,
+                    // since it's the terminal condition anyway. Nothing will be
+                    // retried.
+                } catch (WSProtocolException e) {
+                    // Translate into ProtocolException
+                    closeExceptionally(new ProtocolException().initCause(e));
+                } catch (Exception e) {
+                    closeExceptionally(e);
+                }
+            }
+        }
+    }
+
+    long request(long n) {
+        long newDemand = demand.accumulateAndGet(n, (p, i) -> p + i < 0 ? Long.MAX_VALUE : p + i);
+        handler.signal();
+        assert newDemand >= 0 : newDemand;
+        return newDemand;
+    }
+
+    private boolean getData() throws IOException {
+        if (!readable.get()) {
+            return false;
+        }
+        if (!buf.hasRemaining()) {
+            buf.dispose();
+            buf = buffersSupplier.get();
+            assert buf.hasRemaining() : buf;
+        }
+        int oldPosition = buf.position();
+        int oldLimit = buf.limit();
+        int numRead = channel.read(buf.buffer());
+        if (numRead > 0) {
+            data = buf.share(oldPosition, oldPosition + numRead);
+            buf.select(buf.limit(), oldLimit); // Move window to the free region
+            return true;
+        } else if (numRead == 0) {
+            readable.set(false);
+            channel.registerEvent(channelEvent);
+            return false;
+        } else {
+            assert numRead < 0 : numRead;
+            throw new WSProtocolException
+                    ("7.2.1.", "Stream ended before a Close frame has been received");
+        }
+    }
+
+    void start() {
+        synchronized (this) {
+            if (started) {
+                throw new IllegalStateException("Already started");
+            }
+            started = true;
+            try {
+                channel.registerEvent(channelEvent);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+            try {
+                listener.onOpen(webSocket);
+            } catch (Exception e) {
+                closeExceptionally(new RuntimeException("onOpen threw an exception", e));
+            }
+        }
+    }
+
+    private void close() { // TODO: move to WS.java
+        closed = true;
+    }
+
+    private void closeExceptionally(Throwable error) {  // TODO: move to WS.java
+        close();
+        try {
+            listener.onError(webSocket, error);
+        } catch (Exception e) {
+            logger.log(ERROR, "onError threw an exception", e);
+        }
+    }
+
+    private final class MessageConsumer implements WSMessageConsumer {
+
+        @Override
+        public void onText(WebSocket.MessagePart part, WSDisposableText data) {
+            decrementDemand();
+            CompletionStage<?> cs;
+            try {
+                cs = listener.onText(webSocket, data, part);
+            } catch (Exception e) {
+                closeExceptionally(new RuntimeException("onText threw an exception", e));
+                return;
+            }
+            follow(cs, data, "onText");
+        }
+
+        @Override
+        public void onBinary(WebSocket.MessagePart part, WSShared<ByteBuffer> data) {
+            decrementDemand();
+            CompletionStage<?> cs;
+            try {
+                cs = listener.onBinary(webSocket, data.buffer(), part);
+            } catch (Exception e) {
+                closeExceptionally(new RuntimeException("onBinary threw an exception", e));
+                return;
+            }
+            follow(cs, data, "onBinary");
+        }
+
+        @Override
+        public void onPing(WSShared<ByteBuffer> data) {
+            decrementDemand();
+            CompletionStage<?> cs;
+            try {
+                cs = listener.onPing(webSocket, data.buffer());
+            } catch (Exception e) {
+                closeExceptionally(new RuntimeException("onPing threw an exception", e));
+                return;
+            }
+            follow(cs, data, "onPing");
+        }
+
+        @Override
+        public void onPong(WSShared<ByteBuffer> data) {
+            decrementDemand();
+            CompletionStage<?> cs;
+            try {
+                cs = listener.onPong(webSocket, data.buffer());
+            } catch (Exception e) {
+                closeExceptionally(new RuntimeException("onPong threw an exception", e));
+                return;
+            }
+            follow(cs, data, "onPong");
+        }
+
+        @Override
+        public void onClose(WebSocket.CloseCode code, CharSequence reason) {
+            decrementDemand();
+            try {
+                close();
+                listener.onClose(webSocket, Optional.ofNullable(code), reason.toString());
+            } catch (Exception e) {
+                logger.log(ERROR, "onClose threw an exception", e);
+            }
+        }
+    }
+
+    private void follow(CompletionStage<?> cs, WSDisposable d, String source) {
+        if (cs == null) {
+            d.dispose();
+        } else {
+            cs.whenComplete((whatever, error) -> {
+                if (error != null) {
+                    String m = "CompletionStage returned by " + source + " completed exceptionally";
+                    closeExceptionally(new RuntimeException(m, error));
+                }
+                d.dispose();
+            });
+        }
+    }
+
+    private void decrementDemand() {
+        long newDemand = demand.decrementAndGet();
+        assert newDemand >= 0 : newDemand;
+    }
+
+    private RawChannel.NonBlockingEvent createChannelEvent() {
+        return new RawChannel.NonBlockingEvent() {
+
+            @Override
+            public int interestOps() {
+                return SelectionKey.OP_READ;
+            }
+
+            @Override
+            public void handle() {
+                boolean wasNotReadable = readable.compareAndSet(false, true);
+                assert wasNotReadable;
+                handler.signal();
+            }
+
+            @Override
+            public String toString() {
+                return "Read readiness event [" + channel + "]";
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSShared.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,202 @@
+/*
+ * 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  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+//
+//  +-----------+---------------+------------ ~ ------+
+//  |  shared#1 |    shared#2   | non-shared          |
+//  +-----------+---------------+------------ ~ ------+
+//  |                                                 |
+//  |<------------------  shared0  ---------- ~ ----->|
+//
+//
+// Objects of the type are not thread-safe. It's the responsibility of the
+// client to access shared buffers safely between threads.
+//
+// It would be perfect if we could extend java.nio.Buffer, but it's not an
+// option since Buffer and all its descendants have package-private
+// constructors.
+//
+abstract class WSShared<T extends Buffer> implements WSDisposable {
+
+    protected final AtomicBoolean disposed = new AtomicBoolean();
+    protected final T buffer;
+
+    protected WSShared(T buffer) {
+        this.buffer = Objects.requireNonNull(buffer);
+    }
+
+    static <T extends Buffer> WSShared<T> wrap(T buffer) {
+        return new WSShared<>(buffer) {
+            @Override
+            WSShared<T> share(int pos, int limit) {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    // TODO: should be a terminal operation as after it returns the buffer might
+    //       have escaped (we can't protect it any more)
+    public T buffer() {
+        checkDisposed();
+        return buffer;
+    }
+
+    abstract WSShared<T> share(final int pos, final int limit);
+
+    WSShared<T> select(final int pos, final int limit) {
+        checkRegion(pos, limit, buffer());
+        select(pos, limit, buffer());
+        return this;
+    }
+
+    @Override
+    public void dispose() {
+        if (!disposed.compareAndSet(false, true)) {
+            throw new IllegalStateException("Has been disposed previously");
+        }
+    }
+
+    int limit() {
+        return buffer().limit();
+    }
+
+    WSShared<T> limit(int newLimit) {
+        buffer().limit(newLimit);
+        return this;
+    }
+
+    int position() {
+        return buffer().position();
+    }
+
+    WSShared<T> position(int newPosition) {
+        buffer().position(newPosition);
+        return this;
+    }
+
+    int remaining() {
+        return buffer().remaining();
+    }
+
+    boolean hasRemaining() {
+        return buffer().hasRemaining();
+    }
+
+    WSShared<T> flip() {
+        buffer().flip();
+        return this;
+    }
+
+    WSShared<T> rewind() {
+        buffer().rewind();
+        return this;
+    }
+
+    WSShared<T> put(WSShared<? extends T> src) {
+        put(this.buffer(), src.buffer());
+        return this;
+    }
+
+    static void checkRegion(int position, int limit, Buffer buffer) {
+        if (position < 0 || position > buffer.capacity()) {
+            throw new IllegalArgumentException("position: " + position);
+        }
+        if (limit < 0 || limit > buffer.capacity()) {
+            throw new IllegalArgumentException("limit: " + limit);
+        }
+        if (limit < position) {
+            throw new IllegalArgumentException
+                    ("limit < position: limit=" + limit + ", position=" + position);
+        }
+    }
+
+    void select(int newPos, int newLim, Buffer buffer) {
+        int oldPos = buffer.position();
+        int oldLim = buffer.limit();
+        assert 0 <= oldPos && oldPos <= oldLim && oldLim <= buffer.capacity();
+        if (oldLim <= newPos) {
+            buffer().limit(newLim).position(newPos);
+        } else {
+            buffer.position(newPos).limit(newLim);
+        }
+    }
+
+    // The same as dst.put(src)
+    static <T extends Buffer> T put(T dst, T src) {
+        if (dst instanceof ByteBuffer) {
+            ((ByteBuffer) dst).put((ByteBuffer) src);
+        } else if (dst instanceof CharBuffer) {
+            ((CharBuffer) dst).put((CharBuffer) src);
+        } else {
+            // We don't work with buffers of other types
+            throw new IllegalArgumentException();
+        }
+        return dst;
+    }
+
+    // TODO: Remove when JDK-8150785 has been done
+    @SuppressWarnings("unchecked")
+    static <T extends Buffer> T slice(T buffer) {
+        if (buffer instanceof ByteBuffer) {
+            return (T) ((ByteBuffer) buffer).slice();
+        } else if (buffer instanceof CharBuffer) {
+            return (T) ((CharBuffer) buffer).slice();
+        } else {
+            // We don't work with buffers of other types
+            throw new IllegalArgumentException();
+        }
+    }
+
+    // TODO: Remove when JDK-8150785 has been done
+    @SuppressWarnings("unchecked")
+    static <T extends Buffer> T duplicate(T buffer) {
+        if (buffer instanceof ByteBuffer) {
+            return (T) ((ByteBuffer) buffer).duplicate();
+        } else if (buffer instanceof CharBuffer) {
+            return (T) ((CharBuffer) buffer).duplicate();
+        } else {
+            // We don't work with buffers of other types
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "[" + WSUtils.toString(buffer()) + "]";
+    }
+
+    private void checkDisposed() {
+        if (disposed.get()) {
+            throw new IllegalStateException("Has been disposed previously");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSSharedPool.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,148 @@
+/*
+ * 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  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.nio.Buffer;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
+
+import static java.lang.System.Logger.Level.TRACE;
+import static java.net.http.WSShared.duplicate;
+import static java.net.http.WSUtils.logger;
+import static java.util.Objects.requireNonNull;
+
+final class WSSharedPool<T extends Buffer> implements Supplier<WSShared<T>> {
+
+    private final Supplier<T> factory;
+    private final BlockingQueue<T> queue;
+
+    WSSharedPool(Supplier<T> factory, int maxPoolSize) {
+        this.factory = requireNonNull(factory);
+        this.queue = new LinkedBlockingQueue<>(maxPoolSize);
+    }
+
+    @Override
+    public Pooled get() {
+        T b = queue.poll();
+        if (b == null) {
+            logger.log(TRACE, "Pool {0} contains no free buffers", this);
+            b = requireNonNull(factory.get());
+        }
+        Pooled buf = new Pooled(new AtomicInteger(1), b, duplicate(b));
+        logger.log(TRACE, "Pool {0} created new buffer {1}", this, buf);
+        return buf;
+    }
+
+    private void put(Pooled b) {
+        assert b.disposed.get() && b.refCount.get() == 0
+                : WSUtils.dump(b.disposed, b.refCount, b);
+        b.shared.clear();
+        boolean accepted = queue.offer(b.getShared());
+        if (logger.isLoggable(TRACE)) {
+            if (accepted) {
+                logger.log(TRACE, "Pool {0} accepted {1}", this, b);
+            } else {
+                logger.log(TRACE, "Pool {0} discarded {1}", this, b);
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "[queue.size=" + queue.size() + "]";
+    }
+
+    private final class Pooled extends WSShared<T> {
+
+        private final AtomicInteger refCount;
+        private final T shared;
+
+        private Pooled(AtomicInteger refCount, T shared, T region) {
+            super(region);
+            this.refCount = refCount;
+            this.shared = shared;
+        }
+
+        private T getShared() {
+            return shared;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Pooled share(final int pos, final int limit) {
+            synchronized (this) {
+                T buffer = buffer();
+                checkRegion(pos, limit, buffer);
+                final int oldPos = buffer.position();
+                final int oldLimit = buffer.limit();
+                select(pos, limit, buffer);
+                T slice = WSShared.slice(buffer);
+                select(oldPos, oldLimit, buffer);
+                referenceAndGetCount();
+                Pooled buf = new Pooled(refCount, shared, slice);
+                logger.log(TRACE, "Shared {0} from {1}", buf, this);
+                return buf;
+            }
+        }
+
+        @Override
+        public void dispose() {
+            logger.log(TRACE, "Disposed {0}", this);
+            super.dispose();
+            if (dereferenceAndGetCount() == 0) {
+                WSSharedPool.this.put(this);
+            }
+        }
+
+        private int referenceAndGetCount() {
+            return refCount.updateAndGet(n -> {
+                if (n != Integer.MAX_VALUE) {
+                    return n + 1;
+                } else {
+                    throw new IllegalArgumentException
+                            ("Too many references: " + this);
+                }
+            });
+        }
+
+        private int dereferenceAndGetCount() {
+            return refCount.updateAndGet(n -> {
+                if (n > 0) {
+                    return n - 1;
+                } else {
+                    throw new InternalError();
+                }
+            });
+        }
+
+        @Override
+        public String toString() {
+            return WSUtils.toStringSimple(this) + "[" + WSUtils.toString(buffer)
+                    + "[refCount=" + refCount + ", disposed=" + disposed + "]]";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSSignalHandler.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,137 @@
+/*
+ * 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  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static java.util.Objects.requireNonNull;
+
+//
+// The problem:
+// ------------
+//   1. For every invocation of 'signal()' there must be at least
+//      1 invocation of 'handler.run()' that goes after
+//   2. There must be no more than 1 thread running the 'handler.run()'
+//      at any given time
+//
+// For example, imagine each signal increments (+1) some number. Then the
+// handler responds (eventually) the way that makes the number 0.
+//
+// For each signal there's a response. Several signals may be handled by a
+// single response.
+//
+final class WSSignalHandler {
+
+    // In this state the task is neither submitted nor running.
+    // No one is handling signals. If a new signal has been received, the task
+    // has to be submitted to the executor in order to handle this signal.
+    private static final int DONE    = 0;
+
+    // In this state the task is running.
+    // * If the signaller has found the task in this state it will try to change
+    //   the state to RERUN in order to make the already running task to handle
+    //   the new signal before exiting.
+    // * If the task has found itself in this state it will exit.
+    private static final int RUNNING = 1;
+
+    // A signal to the task, that it must rerun on the spot (without being
+    // resubmitted to the executor).
+    // If the task has found itself in this state it resets the state to
+    // RUNNING and repeats the pass.
+    private static final int RERUN   = 2;
+
+    private final AtomicInteger state = new AtomicInteger(DONE);
+
+    private final Executor executor;
+    private final Runnable task;
+
+    WSSignalHandler(Executor executor, Runnable handler) {
+        this.executor = requireNonNull(executor);
+        requireNonNull(handler);
+
+        task = () -> {
+            while (!Thread.currentThread().isInterrupted()) {
+
+                try {
+                    handler.run();
+                } catch (Exception e) {
+                    // Sorry, the task won't be automatically retried;
+                    // hope next signals (if any) will kick off the handling
+                    state.set(DONE);
+                    throw e;
+                }
+
+                int prev = state.getAndUpdate(s -> {
+                    if (s == RUNNING) {
+                        return DONE;
+                    } else {
+                        return RUNNING;
+                    }
+                });
+
+                // Can't be DONE, since only the task itself may transit state
+                // into DONE (with one exception: RejectedExecution in signal();
+                // but in that case we couldn't be here at all)
+                assert prev == RUNNING || prev == RERUN;
+
+                if (prev == RUNNING) {
+                    break;
+                }
+            }
+        };
+    }
+
+    // Invoked by outer code to signal
+    void signal() {
+
+        int prev = state.getAndUpdate(s -> {
+            switch (s) {
+                case RUNNING:
+                    return RERUN;
+                case DONE:
+                    return RUNNING;
+                case RERUN:
+                    return RERUN;
+                default:
+                    throw new InternalError(String.valueOf(s));
+            }
+        });
+
+        if (prev != DONE) {
+            // Nothing to do! piggybacking on previous signal
+            return;
+        }
+        try {
+            executor.execute(task);
+        } catch (RejectedExecutionException e) {
+            // Sorry some signal() invocations may have been accepted, but won't
+            // be done, since the 'task' couldn't be submitted
+            state.set(DONE);
+            throw e;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSTransmitter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,176 @@
+/*
+ * 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  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.net.http.WSOutgoingMessage.Binary;
+import java.net.http.WSOutgoingMessage.Close;
+import java.net.http.WSOutgoingMessage.Ping;
+import java.net.http.WSOutgoingMessage.Pong;
+import java.net.http.WSOutgoingMessage.StreamedText;
+import java.net.http.WSOutgoingMessage.Text;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CoderResult;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+import static java.lang.String.format;
+import static java.net.http.Pair.pair;
+
+/*
+ * Prepares outgoing messages for transmission.  Verifies the WebSocket state,
+ * places the message on the outbound queue, and notifies the signal handler.
+ */
+final class WSTransmitter {
+
+    private final BlockingQueue<Pair<WSOutgoingMessage, CompletableFuture<Void>>>
+            backlog = new LinkedBlockingQueue<>();
+    private final WSMessageSender sender;
+    private final WSSignalHandler handler;
+    private boolean previousMessageSent = true;
+    private boolean canSendBinary = true;
+    private boolean canSendText = true;
+
+    WSTransmitter(Executor executor, RawChannel channel, Consumer<Throwable> errorHandler) {
+        this.handler = new WSSignalHandler(executor, this::handleSignal);
+        Consumer<Throwable> sendCompletion = (error) -> {
+            synchronized (this) {
+                if (error == null) {
+                    previousMessageSent = true;
+                    handler.signal();
+                } else {
+                    errorHandler.accept(error);
+                    backlog.forEach(p -> p.second.completeExceptionally(error));
+                    backlog.clear();
+                }
+            }
+        };
+        this.sender = new WSMessageSender(channel, sendCompletion);
+    }
+
+    CompletableFuture<Void> sendText(CharSequence message, boolean isLast) {
+        checkAndUpdateText(isLast);
+        return acceptMessage(new Text(isLast, message));
+    }
+
+    CompletableFuture<Void> sendText(Stream<? extends CharSequence> message) {
+        checkAndUpdateText(true);
+        return acceptMessage(new StreamedText(message));
+    }
+
+    CompletableFuture<Void> sendBinary(ByteBuffer message, boolean isLast) {
+        checkAndUpdateBinary(isLast);
+        return acceptMessage(new Binary(isLast, message));
+    }
+
+    CompletableFuture<Void> sendPing(ByteBuffer message) {
+        checkSize(message.remaining(), 125);
+        return acceptMessage(new Ping(message));
+    }
+
+    CompletableFuture<Void> sendPong(ByteBuffer message) {
+        checkSize(message.remaining(), 125);
+        return acceptMessage(new Pong(message));
+    }
+
+    CompletableFuture<Void> sendClose(WebSocket.CloseCode code, CharSequence reason) {
+        return acceptMessage(createCloseMessage(code, reason));
+    }
+
+    CompletableFuture<Void> sendClose() {
+        return acceptMessage(new Close(ByteBuffer.allocate(0)));
+    }
+
+    private CompletableFuture<Void> acceptMessage(WSOutgoingMessage m) {
+        CompletableFuture<Void> cf = new CompletableFuture<>();
+        synchronized (this) {
+            backlog.offer(pair(m, cf));
+        }
+        handler.signal();
+        return cf;
+    }
+
+    /* Callback for pulling messages from the queue, and initiating the send. */
+    private void handleSignal() {
+        synchronized (this) {
+            while (!backlog.isEmpty() && previousMessageSent) {
+                previousMessageSent = false;
+                Pair<WSOutgoingMessage, CompletableFuture<Void>> p = backlog.peek();
+                boolean sent = sender.trySendFully(p.first);
+                if (sent) {
+                    backlog.remove();
+                    p.second.complete(null);
+                    previousMessageSent = true;
+                }
+            }
+        }
+    }
+
+    private Close createCloseMessage(WebSocket.CloseCode code, CharSequence reason) {
+        // TODO: move to construction of CloseDetail (JDK-8155621)
+        ByteBuffer b = ByteBuffer.allocateDirect(125).putChar((char) code.getCode());
+        CoderResult result = StandardCharsets.UTF_8.newEncoder()
+                .encode(CharBuffer.wrap(reason), b, true);
+        if (result.isError()) {
+            try {
+                result.throwException();
+            } catch (CharacterCodingException e) {
+                throw new IllegalArgumentException("Reason is a malformed UTF-16 sequence", e);
+            }
+        } else if (result.isOverflow()) {
+            throw new IllegalArgumentException("Reason is too long");
+        }
+        return new Close(b.flip());
+    }
+
+    private void checkSize(int size, int maxSize) {
+        if (size > maxSize) {
+            throw new IllegalArgumentException(
+                    format("The message is too long: %s;" +
+                            " expected not longer than %s", size, maxSize)
+            );
+        }
+    }
+
+    private void checkAndUpdateText(boolean isLast) {
+        if (!canSendText) {
+            throw new IllegalStateException("Unexpected text message");
+        }
+        canSendBinary = isLast;
+    }
+
+    private void checkAndUpdateBinary(boolean isLast) {
+        if (!canSendBinary) {
+            throw new IllegalStateException("Unexpected binary message");
+        }
+        canSendText = isLast;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSUtils.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+final class WSUtils {
+
+    private WSUtils() { }
+
+    static final System.Logger logger = System.getLogger("java.net.http.WebSocket");
+    static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocate(0);
+
+    //
+    // Helps to trim long names (packages, nested/inner types) in logs/toString
+    //
+    static String toStringSimple(Object o) {
+        return o.getClass().getSimpleName() + "@" +
+                Integer.toHexString(System.identityHashCode(o));
+    }
+
+    //
+    // 1. It adds a number of remaining bytes;
+    // 2. Standard Buffer-type toString for CharBuffer (since it adheres to the
+    // contract of java.lang.CharSequence.toString() which is both not too
+    // useful and not too private)
+    //
+    static String toString(Buffer b) {
+        return toStringSimple(b)
+                + "[pos=" + b.position()
+                + " lim=" + b.limit()
+                + " cap=" + b.capacity()
+                + " rem=" + b.remaining() + "]";
+    }
+
+    static String toString(CharSequence s) {
+        return s == null
+                ? "null"
+                : toStringSimple(s) + "[len=" + s.length() + "]";
+    }
+
+    static String dump(Object... objects) {
+        return Arrays.toString(objects);
+    }
+
+    static String webSocketSpecViolation(String section, String detail) {
+        return "RFC 6455 " + section + " " + detail;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSWriter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,134 @@
+/*
+ * 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  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  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  License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.util.function.Consumer;
+
+import static java.util.Objects.requireNonNull;
+
+/*
+ * Writes ByteBuffer[] to the channel in a non-blocking, asynchronous fashion.
+ *
+ * A client attempts to write data by calling
+ *
+ *     boolean tryWriteFully(ByteBuffer[] buffers)
+ *
+ * If the attempt was successful and all the data has been written, then the
+ * method returns `true`.
+ *
+ * If the data has been written partially, then the method returns `false`, and
+ * the writer (this object) attempts to complete the write asynchronously by
+ * calling, possibly more than once
+ *
+ *     boolean tryCompleteWrite()
+ *
+ * in its own threads.
+ *
+ * When the write has been completed asynchronously, the callback is signalled
+ * with `null`.
+ *
+ * If an error occurs in any of these stages it will NOT be thrown from the
+ * method. Instead `false` will be returned and the exception will be signalled
+ * to the callback. This is done in order to handle all exceptions in a single
+ * place.
+ */
+final class WSWriter {
+
+    private final RawChannel channel;
+    private final RawChannel.NonBlockingEvent writeReadinessHandler;
+    private final Consumer<Throwable> completionCallback;
+    private ByteBuffer[] buffers;
+    private int offset;
+
+    WSWriter(RawChannel channel, Consumer<Throwable> completionCallback) {
+        this.channel = channel;
+        this.completionCallback = completionCallback;
+        this.writeReadinessHandler = createHandler();
+    }
+
+    boolean tryWriteFully(ByteBuffer[] buffers) {
+        synchronized (this) {
+            this.buffers = requireNonNull(buffers);
+            this.offset = 0;
+        }
+        return tryCompleteWrite();
+    }
+
+    private final boolean tryCompleteWrite() {
+        try {
+            return writeNow();
+        } catch (IOException e) {
+            completionCallback.accept(e);
+            return false;
+        }
+    }
+
+    private boolean writeNow() throws IOException {
+        synchronized (this) {
+            for (; offset != -1; offset = nextUnwrittenIndex(buffers, offset)) {
+                long bytesWritten = channel.write(buffers, offset, buffers.length - offset);
+                if (bytesWritten == 0) {
+                    channel.registerEvent(writeReadinessHandler);
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    private static int nextUnwrittenIndex(ByteBuffer[] buffers, int offset) {
+        for (int i = offset; i < buffers.length; i++) {
+            if (buffers[i].hasRemaining()) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private RawChannel.NonBlockingEvent createHandler() {
+        return new RawChannel.NonBlockingEvent() {
+
+            @Override
+            public int interestOps() {
+                return SelectionKey.OP_WRITE;
+            }
+
+            @Override
+            public void handle() {
+                if (tryCompleteWrite()) {
+                    completionCallback.accept(null);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "Write readiness event [" + channel + "]";
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,1288 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+import java.io.IOException;
+import java.net.ProtocolException;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
+
+/**
+ * A WebSocket client conforming to RFC&nbsp;6455.
+ *
+ * <p> A {@code WebSocket} provides full-duplex communication over a TCP
+ * connection.
+ *
+ * <p> To create a {@code WebSocket} use a {@linkplain #newBuilder(URI, Listener)
+ * builder}. Once a {@code WebSocket} is obtained, it's ready to send and
+ * receive messages. When the {@code WebSocket} is no longer
+ * needed it must be closed: a Close message must both be {@linkplain
+ * #sendClose() sent} and {@linkplain Listener#onClose(WebSocket, Optional,
+ * String) received}. Or to close abruptly, {@link #abort()} is called. Once
+ * closed it remains closed, cannot be reopened.
+ *
+ * <p> Messages of type {@code X} are sent through the {@code WebSocket.sendX}
+ * methods and received through {@link WebSocket.Listener}{@code .onX} methods
+ * asynchronously. Each of the methods begins the operation and returns a {@link
+ * CompletionStage} which completes when the operation has completed.
+ *
+ * <p> Messages are received only if {@linkplain #request(long) requested}.
+ *
+ * <p> One outstanding send operation is permitted: if another send operation is
+ * initiated before the previous one has completed, an {@link
+ * IllegalStateException IllegalStateException} will be thrown. When sending, a
+ * message should not be modified until the returned {@code CompletableFuture}
+ * completes (either normally or exceptionally).
+ *
+ * <p> Messages can be sent and received as a whole or in parts. A whole message
+ * is a sequence of one or more messages in which the last message is marked
+ * when it is sent or received.
+ *
+ * <p> If the message is contained in a {@link ByteBuffer}, bytes are considered
+ * arranged from the {@code buffer}'s {@link ByteBuffer#position() position} to
+ * the {@code buffer}'s {@link ByteBuffer#limit() limit}.
+ *
+ * <p> All message exchange is run by the threads belonging to the {@linkplain
+ * HttpClient#executorService() executor service} of {@code WebSocket}'s {@link
+ * HttpClient}.
+ *
+ * <p> Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method of this type will cause a {@link NullPointerException
+ * NullPointerException} to be thrown.
+ *
+ * @since 9
+ */
+public interface WebSocket {
+
+    /**
+     * Creates a builder of {@code WebSocket}s connected to the given URI and
+     * receiving events with the given {@code Listener}.
+     *
+     * <p> Equivalent to:
+     * <pre>{@code
+     *     WebSocket.newBuilder(uri, HttpClient.getDefault())
+     * }</pre>
+     *
+     * @param uri
+     *         the WebSocket URI as defined in the WebSocket Protocol
+     *         (with "ws" or "wss" scheme)
+     *
+     * @param listener
+     *         the listener
+     *
+     * @throws IllegalArgumentException
+     *         if the {@code uri} is not a WebSocket URI
+     * @throws SecurityException
+     *         if running under a security manager and the caller does
+     *         not have permission to access the
+     *         {@linkplain HttpClient#getDefault() default HttpClient}
+     *
+     * @return a builder
+     */
+    static Builder newBuilder(URI uri, Listener listener) {
+        return newBuilder(uri, HttpClient.getDefault(), listener);
+    }
+
+    /**
+     * Creates a builder of {@code WebSocket}s connected to the given URI and
+     * receiving events with the given {@code Listener}.
+     *
+     * <p> Providing a custom {@code client} allows for finer control over the
+     * opening handshake.
+     *
+     * <p> <b>Example</b>
+     * <pre>{@code
+     *     HttpClient client = HttpClient.create()
+     *             .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
+     *             .build();
+     *     ...
+     *     WebSocket.newBuilder(URI.create("ws://websocket.example.com"), client, listener)...
+     * }</pre>
+     *
+     * @param uri
+     *         the WebSocket URI as defined in the WebSocket Protocol
+     *         (with "ws" or "wss" scheme)
+     *
+     * @param client
+     *         the HttpClient
+     * @param listener
+     *         the listener
+     *
+     * @throws IllegalArgumentException
+     *         if the uri is not a WebSocket URI
+     *
+     * @return a builder
+     */
+    static Builder newBuilder(URI uri, HttpClient client, Listener listener) {
+        return new WSBuilder(uri, client, listener);
+    }
+
+    /**
+     * A builder for creating {@code WebSocket} instances.
+     *
+     * <p> To build a {@code WebSocket}, instantiate a builder, configure it
+     * as required by calling intermediate methods (the ones that return the
+     * builder itself), then finally call {@link #buildAsync()} to get a {@link
+     * CompletableFuture} with resulting {@code WebSocket}.
+     *
+     * <p> If an intermediate method has not been called, an appropriate
+     * default value (or behavior) will be used. Unless otherwise noted, a
+     * repeated call to an intermediate method overwrites the previous value (or
+     * overrides the previous behaviour), if no exception is thrown.
+     *
+     * <p> Instances of {@code Builder} may not be safe for use by multiple
+     * threads.
+     *
+     * @since 9
+     */
+    interface Builder {
+
+        /**
+         * Adds the given name-value pair to the list of additional headers for
+         * the opening handshake.
+         *
+         * <p> Headers defined in WebSocket Protocol are not allowed to be added.
+         *
+         * @param name
+         *         the header name
+         * @param value
+         *         the header value
+         *
+         * @return this builder
+         *
+         * @throws IllegalArgumentException
+         *         if the {@code name} is a WebSocket defined header name
+         */
+        Builder header(String name, String value);
+
+        /**
+         * Includes a request for the given subprotocols during the opening
+         * handshake.
+         *
+         * <p> Among the requested subprotocols at most one will be chosen by
+         * the server. When the {@code WebSocket} is connected, the subprotocol
+         * in use is available from {@link WebSocket#getSubprotocol}.
+         * Subprotocols may be specified in the order of preference.
+         *
+         * <p> Each of the given subprotocols must conform to the relevant
+         * rules defined in the WebSocket Protocol.
+         *
+         * @param mostPreferred
+         *         the most preferred subprotocol
+         * @param lesserPreferred
+         *         the lesser preferred subprotocols, with the least preferred
+         *         at the end
+         *
+         * @return this builder
+         *
+         * @throws IllegalArgumentException
+         *         if any of the WebSocket Protocol rules relevant to
+         *         subprotocols are violated
+         */
+        Builder subprotocols(String mostPreferred, String... lesserPreferred);
+
+        /**
+         * Sets a timeout for the opening handshake.
+         *
+         * <p> If the opening handshake is not finished within the specified
+         * timeout then {@link #buildAsync()} completes exceptionally with a
+         * {@code HttpTimeoutException}.
+         *
+         * <p> If the timeout is not specified then it's deemed infinite.
+         *
+         * @param timeout
+         *         the maximum time to wait
+         * @param unit
+         *         the time unit of the timeout argument
+         *
+         * @return this builder
+         *
+         * @throws IllegalArgumentException
+         *         if the {@code timeout} is negative
+         */
+        Builder connectTimeout(long timeout, TimeUnit unit);
+
+        /**
+         * Builds a {@code WebSocket}.
+         *
+         * <p> Returns immediately with a {@code CompletableFuture<WebSocket>}
+         * which completes with the {@code WebSocket} when it is connected, or
+         * completes exceptionally if an error occurs.
+         *
+         * <p> {@code CompletableFuture} may complete exceptionally with the
+         * following errors:
+         * <ul>
+         * <li> {@link IOException}
+         *          if an I/O error occurs
+         * <li> {@link InterruptedException}
+         *          if the operation was interrupted
+         * <li> {@link SecurityException}
+         *          if a security manager is set, and the caller does not
+         *          have a {@link java.net.URLPermission} for the WebSocket URI
+         * <li> {@link WebSocketHandshakeException}
+         *          if the opening handshake fails
+         * </ul>
+         *
+         * @return a {@code CompletableFuture} of {@code WebSocket}
+         */
+        CompletableFuture<WebSocket> buildAsync();
+    }
+
+    /**
+     * A listener for events and messages on a {@code WebSocket}.
+     *
+     * <p> Each method below corresponds to a type of event.
+     * <ul>
+     * <li> {@link #onOpen onOpen} <br>
+     * This method is always the first to be invoked.
+     * <li> {@link #onText(WebSocket, WebSocket.Text, WebSocket.MessagePart)
+     * onText}, {@link #onBinary(WebSocket, ByteBuffer, WebSocket.MessagePart)
+     * onBinary}, {@link #onPing(WebSocket, ByteBuffer) onPing} and {@link
+     * #onPong(WebSocket, ByteBuffer) onPong} <br>
+     * These methods are invoked zero or more times after {@code onOpen}.
+     * <li> {@link #onClose(WebSocket, Optional, String) onClose}, {@link
+     * #onError(WebSocket, Throwable) onError} <br>
+     * Only one of these methods is invoked, and that method is invoked last and
+     * at most once.
+     * </ul>
+     *
+     * <pre><code>
+     *     onOpen (onText|onBinary|onPing|onPong)* (onClose|onError)?
+     * </code></pre>
+     *
+     * <p> Messages received by the {@code Listener} conform to the WebSocket
+     * Protocol, otherwise {@code onError} with a {@link ProtocolException} is
+     * invoked.
+     *
+     * <p> If a whole message is received, then the corresponding method
+     * ({@code onText} or {@code onBinary}) will be invoked with {@link
+     * WebSocket.MessagePart#WHOLE WHOLE} marker. Otherwise the method will be
+     * invoked with {@link WebSocket.MessagePart#FIRST FIRST}, zero or more
+     * times with {@link WebSocket.MessagePart#FIRST PART} and, finally, with
+     * {@link WebSocket.MessagePart#LAST LAST} markers.
+     *
+     * <pre><code>
+     *     WHOLE|(FIRST PART* LAST)
+     * </code></pre>
+     *
+     * <p> All methods are invoked in a sequential (and
+     * <a href="../../../java/util/concurrent/package-summary.html#MemoryVisibility">
+     * happens-before</a>) order, one after another, possibly by different
+     * threads. If any of the methods above throws an exception, {@code onError}
+     * is then invoked with that exception. Exceptions thrown from {@code
+     * onError} or {@code onClose} are ignored.
+     *
+     * <p> When the method returns, the message is deemed received. After this
+     * another messages may be received.
+     *
+     * <p> These invocations begin asynchronous processing which might not end
+     * with the invocation. To provide coordination, methods of {@code
+     * Listener} return a {@link CompletionStage CompletionStage}. The {@code
+     * CompletionStage} signals the {@code WebSocket} that the
+     * processing of a message has ended. For
+     * convenience, methods may return {@code null}, which means
+     * the same as returning an already completed {@code CompletionStage}. If
+     * the returned {@code CompletionStage} completes exceptionally, then {@link
+     * #onError(WebSocket, Throwable) onError} will be invoked with the
+     * exception.
+     *
+     * <p> Control of the message passes to the {@code Listener} with the
+     * invocation of the method. Control of the message returns to the {@code
+     * WebSocket} at the earliest of, either returning {@code null} from the
+     * method, or the completion of the {@code CompletionStage} returned from
+     * the method. The {@code WebSocket} does not access the message while it's
+     * not in its control. The {@code Listener} must not access the message
+     * after its control has been returned to the {@code WebSocket}.
+     *
+     * <p> It is the responsibility of the listener to make additional
+     * {@linkplain WebSocket#request(long) message requests}, when ready, so
+     * that messages are received eventually.
+     *
+     * <p> Methods above are never invoked with {@code null}s as their
+     * arguments.
+     *
+     * @since 9
+     */
+    interface Listener {
+
+        /**
+         * Notifies the {@code Listener} that it is connected to the provided
+         * {@code WebSocket}.
+         *
+         * <p> The {@code onOpen} method does not correspond to any message
+         * from the WebSocket Protocol. It is a synthetic event. It is the first
+         * {@code Listener}'s method to be invoked. No other {@code Listener}'s
+         * methods are invoked before this one. The method is usually used to
+         * make an initial {@linkplain WebSocket#request(long) request} for
+         * messages.
+         *
+         * <p> If an exception is thrown from this method then {@link
+         * #onError(WebSocket, Throwable) onError} will be invoked with the
+         * exception.
+         *
+         * @implSpec The default implementation {@linkplain WebSocket#request(long)
+         * requests one message}.
+         *
+         * @param webSocket
+         *         the WebSocket
+         */
+        default void onOpen(WebSocket webSocket) { webSocket.request(1); }
+
+        /**
+         * Receives a Text message.
+         *
+         * <p> The {@code onText} method is invoked zero or more times between
+         * {@code onOpen} and ({@code onClose} or {@code onError}).
+         *
+         * <p> This message may be a partial UTF-16 sequence. However, the
+         * concatenation of all messages through the last will be a whole UTF-16
+         * sequence.
+         *
+         * <p> If an exception is thrown from this method or the returned {@code
+         * CompletionStage} completes exceptionally, then {@link
+         * #onError(WebSocket, Throwable) onError} will be invoked with the
+         * exception.
+         *
+         * @implSpec The default implementation {@linkplain WebSocket#request(long)
+         * requests one more message}.
+         *
+         * @param webSocket
+         *         the WebSocket
+         * @param message
+         *         the message
+         * @param part
+         *         the part
+         *
+         * @return a CompletionStage that completes when the message processing
+         * is done; or {@code null} if already done
+         */
+        default CompletionStage<?> onText(WebSocket webSocket,
+                                          Text message,
+                                          MessagePart part) {
+            webSocket.request(1);
+            return null;
+        }
+
+        /**
+         * Receives a Binary message.
+         *
+         * <p> The {@code onBinary} method is invoked zero or more times
+         * between {@code onOpen} and ({@code onClose} or {@code onError}).
+         *
+         * <p> If an exception is thrown from this method or the returned {@code
+         * CompletionStage} completes exceptionally, then {@link
+         * #onError(WebSocket, Throwable) onError} will be invoked with this
+         * exception.
+         *
+         * @implSpec The default implementation {@linkplain WebSocket#request(long)
+         * requests one more message}.
+         *
+         * @param webSocket
+         *         the WebSocket
+         * @param message
+         *         the message
+         * @param part
+         *         the part
+         *
+         * @return a CompletionStage that completes when the message processing
+         * is done; or {@code null} if already done
+         */
+        default CompletionStage<?> onBinary(WebSocket webSocket,
+                                            ByteBuffer message,
+                                            MessagePart part) {
+            webSocket.request(1);
+            return null;
+        }
+
+        /**
+         * Receives a Ping message.
+         *
+         * <p> A Ping message may be sent or received by either client or
+         * server. It may serve either as a keepalive or as a means to verify
+         * that the remote endpoint is still responsive.
+         *
+         * <p> The message will consist of not more than {@code 125} bytes:
+         * {@code message.remaining() <= 125}.
+         *
+         * <p> The {@code onPing} is invoked zero or more times in between
+         * {@code onOpen} and ({@code onClose} or {@code onError}).
+         *
+         * <p> If an exception is thrown from this method or the returned {@code
+         * CompletionStage} completes exceptionally, then {@link
+         * #onError(WebSocket, Throwable) onError} will be invoked with this
+         * exception.
+         *
+         * @implNote
+         *
+         * <p> Replies with a Pong message and requests one more message when
+         * the Pong has been sent.
+         *
+         * @param webSocket
+         *         the WebSocket
+         * @param message
+         *         the message
+         *
+         * @return a CompletionStage that completes when the message processing
+         * is done; or {@code null} if already done
+         */
+        default CompletionStage<?> onPing(WebSocket webSocket,
+                                          ByteBuffer message) {
+            return webSocket.sendPong(message).thenRun(() -> webSocket.request(1));
+        }
+
+        /**
+         * Receives a Pong message.
+         *
+         * <p> A Pong message may be unsolicited or may be received in response
+         * to a previously sent Ping. In the latter case, the contents of the
+         * Pong is identical to the originating Ping.
+         *
+         * <p> The message will consist of not more than {@code 125} bytes:
+         * {@code message.remaining() <= 125}.
+         *
+         * <p> The {@code onPong} method is invoked zero or more times in
+         * between {@code onOpen} and ({@code onClose} or {@code onError}).
+         *
+         * <p> If an exception is thrown from this method or the returned {@code
+         * CompletionStage} completes exceptionally, then {@link
+         * #onError(WebSocket, Throwable) onError} will be invoked with this
+         * exception.
+         *
+         * @implSpec The default implementation {@linkplain WebSocket#request(long)
+         * requests one more message}.
+         *
+         * @param webSocket
+         *         the WebSocket
+         * @param message
+         *         the message
+         *
+         * @return a CompletionStage that completes when the message processing
+         * is done; or {@code null} if already done
+         */
+        default CompletionStage<?> onPong(WebSocket webSocket,
+                                          ByteBuffer message) {
+            webSocket.request(1);
+            return null;
+        }
+
+        /**
+         * Receives a Close message.
+         *
+         * <p> Once a Close message is received, the server will not send any
+         * more messages.
+         *
+         * <p> A Close message may consist of a close code and a reason for
+         * closing. The reason will have a UTF-8 representation not longer than
+         * {@code 123} bytes. The reason may be useful for debugging or passing
+         * information relevant to the connection but is not necessarily human
+         * readable.
+         *
+         * <p> {@code onClose} is the last invocation on the {@code Listener}.
+         * It is invoked at most once, but after {@code onOpen}. If an exception
+         * is thrown from this method, it is ignored.
+         *
+         * @implSpec The default implementation does nothing.
+         *
+         * @param webSocket
+         *         the WebSocket
+         * @param code
+         *         an {@code Optional} describing the close code, or
+         *         an empty {@code Optional} if the message doesn't contain it
+         * @param reason
+         *         the reason of close; can be empty
+         */
+        default void onClose(WebSocket webSocket, Optional<CloseCode> code,
+                             String reason) { }
+
+        /**
+         * Notifies an I/O or protocol error has occurred on the {@code
+         * WebSocket}.
+         *
+         * <p> The {@code onError} method does not correspond to any message
+         * from the WebSocket Protocol. It is a synthetic event. {@code onError}
+         * is the last invocation on the {@code Listener}. It is invoked at most
+         * once but after {@code onOpen}. If an exception is thrown from this
+         * method, it is ignored.
+         *
+         * <p> The WebSocket Protocol requires some errors occurs in the
+         * incoming destination must be fatal to the connection. In such cases
+         * the implementation takes care of closing the {@code WebSocket}. By
+         * the time {@code onError} is invoked, no more messages can be sent on
+         * this {@code WebSocket}.
+         *
+         * @apiNote Errors associated with send operations ({@link
+         * WebSocket#sendText(CharSequence, boolean) sendText}, {@link
+         * #sendBinary(ByteBuffer, boolean) sendBinary}, {@link
+         * #sendPing(ByteBuffer) sendPing}, {@link #sendPong(ByteBuffer)
+         * sendPong} and {@link #sendClose(CloseCode, CharSequence) sendClose})
+         * are reported to the {@code CompletionStage} operations return.
+         *
+         * @implSpec The default implementation does nothing.
+         *
+         * @param webSocket
+         *         the WebSocket
+         * @param error
+         *         the error
+         */
+        default void onError(WebSocket webSocket, Throwable error) { }
+    }
+
+    /**
+     * A marker used by {@link WebSocket.Listener} for partial message
+     * receiving.
+     *
+     * @since 9
+     */
+    enum MessagePart {
+
+        /**
+         * The first part of a message in a sequence.
+         */
+        FIRST,
+
+        /**
+         * A middle part of a message in a sequence.
+         */
+        PART,
+
+        /**
+         * The last part of a message in a sequence.
+         */
+        LAST,
+
+        /**
+         * A whole message. The message consists of a single part.
+         */
+        WHOLE;
+
+        /**
+         * Tells whether a part of a message received with this marker is the
+         * last part.
+         *
+         * @return {@code true} if LAST or WHOLE, {@code false} otherwise
+         */
+        public boolean isLast() {
+            return this == LAST || this == WHOLE;
+        }
+    }
+
+    /**
+     * Sends a Text message with bytes from the given {@code ByteBuffer}.
+     *
+     * <p> Returns immediately with a {@code CompletableFuture<Void>} which
+     * completes normally when the message has been sent, or completes
+     * exceptionally if an error occurs.
+     *
+     * <p> This message may be a partial UTF-8 sequence. However, the
+     * concatenation of all messages through the last must be a whole UTF-8
+     * sequence.
+     *
+     * <p> The {@code ByteBuffer} should not be modified until the returned
+     * {@code CompletableFuture} completes (either normally or exceptionally).
+     *
+     * <p> The returned {@code CompletableFuture} can complete exceptionally
+     * with:
+     * <ul>
+     * <li> {@link IOException}
+     *          if an I/O error occurs during this operation; or the
+     *          {@code WebSocket} closes while this operation is in progress;
+     *          or the {@code message} is a malformed UTF-8 sequence
+     * </ul>
+     *
+     * @param message
+     *         the message
+     * @param isLast
+     *         {@code true} if this is the final part of the message,
+     *         {@code false} otherwise
+     *
+     * @return a CompletableFuture of Void
+     *
+     * @throws IllegalStateException
+     *         if the WebSocket is closed
+     * @throws IllegalStateException
+     *         if a Close message has been sent already
+     * @throws IllegalStateException
+     *         if there is an outstanding send operation
+     * @throws IllegalStateException
+     *         if a previous Binary message
+     *         was not sent with {@code isLast == true}
+     */
+    CompletableFuture<Void> sendText(ByteBuffer message, boolean isLast);
+
+    /**
+     * Sends a Text message with characters from the given {@code
+     * CharSequence}.
+     *
+     * <p> Returns immediately with a {@code CompletableFuture<Void>} which
+     * completes normally when the message has been sent, or completes
+     * exceptionally if an error occurs.
+     *
+     * <p> This message may be a partial UTF-16 sequence. However, the
+     * concatenation of all messages through the last must be a whole UTF-16
+     * sequence.
+     *
+     * <p> The {@code CharSequence} should not be modified until the returned
+     * {@code CompletableFuture} completes (either normally or exceptionally).
+     *
+     * <p> The returned {@code CompletableFuture} can complete exceptionally
+     * with:
+     * <ul>
+     * <li> {@link IOException}
+     *          if an I/O error occurs during this operation; or the
+     *          {@code WebSocket} closes while this operation is in progress;
+     *          or the {@code message} is a malformed UTF-16 sequence
+     * </ul>
+     *
+     * @param message
+     *         the message
+     * @param isLast
+     *         {@code true} if this is the final part of the message
+     *         {@code false} otherwise
+     *
+     * @return a CompletableFuture of Void
+     *
+     * @throws IllegalStateException
+     *         if the WebSocket is closed
+     * @throws IllegalStateException
+     *         if a Close message has been already sent
+     * @throws IllegalStateException
+     *         if there is an outstanding send operation
+     * @throws IllegalStateException
+     *         if a previous Binary message was not sent
+     *         with {@code isLast == true}
+     */
+    CompletableFuture<Void> sendText(CharSequence message, boolean isLast);
+
+    /**
+     * Sends a whole Text message with characters from the given {@code
+     * CharSequence}.
+     *
+     * <p> This is a convenience method. For the general case, use {@link
+     * #sendText(CharSequence, boolean)}.
+     *
+     * <p> Returns immediately with a {@code CompletableFuture<Void>} which
+     * completes normally when the message has been sent, or completes
+     * exceptionally if an error occurs.
+     *
+     * <p> The {@code CharSequence} should not be modified until the returned
+     * {@code CompletableFuture} completes (either normally or exceptionally).
+     *
+     * <p> The returned {@code CompletableFuture} can complete exceptionally
+     * with:
+     * <ul>
+     * <li> {@link IOException}
+     *          if an I/O error occurs during this operation; or the
+     *          {@code WebSocket} closes while this operation is in progress;
+     *          or the message is a malformed UTF-16 sequence
+     * </ul>
+     *
+     * @param message
+     *         the message
+     *
+     * @return a CompletableFuture of Void
+     *
+     * @throws IllegalStateException
+     *         if the WebSocket is closed
+     * @throws IllegalStateException
+     *         if a Close message has been already sent
+     * @throws IllegalStateException
+     *         if there is an outstanding send operation
+     * @throws IllegalStateException
+     *         if a previous Binary message was not sent
+     *         with {@code isLast == true}
+     */
+    default CompletableFuture<Void> sendText(CharSequence message) {
+        return sendText(message, true);
+    }
+
+    /**
+     * Sends a whole Text message with characters from {@code
+     * CharacterSequence}s provided by the given {@code Stream}.
+     *
+     * <p> This is a convenience method. For the general case use {@link
+     * #sendText(CharSequence, boolean)}.
+     *
+     * <p> Returns immediately with a {@code CompletableFuture<Void>} which
+     * completes normally when the message has been sent, or completes
+     * exceptionally if an error occurs.
+     *
+     * <p> Streamed character sequences should not be modified until the
+     * returned {@code CompletableFuture} completes (either normally or
+     * exceptionally).
+     *
+     * <p> The returned {@code CompletableFuture} can complete exceptionally
+     * with:
+     * <ul>
+     * <li> {@link IOException}
+     *          if an I/O error occurs during this operation; or the
+     *          {@code WebSocket} closes while this operation is in progress;
+     *          or the message is a malformed UTF-16 sequence
+     * </ul>
+     *
+     * @param message
+     *         the message
+     *
+     * @return a CompletableFuture of Void
+     *
+     * @throws IllegalStateException
+     *         if the WebSocket is closed
+     * @throws IllegalStateException
+     *         if a Close message has been already sent
+     * @throws IllegalStateException
+     *         if there is an outstanding send operation
+     * @throws IllegalStateException
+     *         if a previous Binary message was not sent
+     *         with {@code isLast == true}
+     */
+    CompletableFuture<Void> sendText(Stream<? extends CharSequence> message);
+
+    /**
+     * Sends a Binary message with bytes from the given {@code ByteBuffer}.
+     *
+     * <p> Returns immediately with a {@code CompletableFuture<Void>} which
+     * completes normally when the message has been sent, or completes
+     * exceptionally if an error occurs.
+     *
+     * <p> The returned {@code CompletableFuture} can complete exceptionally
+     * with:
+     * <ul>
+     * <li> {@link IOException}
+     *          if an I/O error occurs during this operation or the
+     *          {@code WebSocket} closes while this operation is in progress
+     * </ul>
+     *
+     * @param message
+     *         the message
+     * @param isLast
+     *         {@code true} if this is the final part of the message,
+     *         {@code false} otherwise
+     *
+     * @return a CompletableFuture of Void
+     *
+     * @throws IllegalStateException
+     *         if the WebSocket is closed
+     * @throws IllegalStateException
+     *         if a Close message has been already sent
+     * @throws IllegalStateException
+     *         if there is an outstanding send operation
+     * @throws IllegalStateException
+     *         if a previous Text message was not sent
+     *         with {@code isLast == true}
+     */
+    CompletableFuture<Void> sendBinary(ByteBuffer message, boolean isLast);
+
+    /**
+     * Sends a Binary message with bytes from the given {@code byte[]}.
+     *
+     * <p> Returns immediately with a {@code CompletableFuture<Void>} which
+     * completes normally when the message has been sent, or completes
+     * exceptionally if an error occurs.
+     *
+     * <p> The returned {@code CompletableFuture} can complete exceptionally
+     * with:
+     * <ul>
+     * <li> {@link IOException}
+     *          if an I/O error occurs during this operation or the
+     *          {@code WebSocket} closes while this operation is in progress
+     * </ul>
+     *
+     * @implSpec This is equivalent to:
+     * <pre>{@code
+     *     sendBinary(ByteBuffer.wrap(message), isLast)
+     * }</pre>
+     *
+     * @param message
+     *         the message
+     * @param isLast
+     *         {@code true} if this is the final part of the message,
+     *         {@code false} otherwise
+     *
+     * @return a CompletableFuture of Void
+     *
+     * @throws IllegalStateException
+     *         if the WebSocket is closed
+     * @throws IllegalStateException
+     *         if a Close message has been already sent
+     * @throws IllegalStateException
+     *         if there is an outstanding send operation
+     * @throws IllegalStateException
+     *         if a previous Text message was not sent
+     *         with {@code isLast == true}
+     */
+    default CompletableFuture<Void> sendBinary(byte[] message, boolean isLast) {
+        Objects.requireNonNull(message, "message");
+        return sendBinary(ByteBuffer.wrap(message), isLast);
+    }
+
+    /**
+     * Sends a Ping message.
+     *
+     * <p> Returns immediately with a {@code CompletableFuture<Void>} which
+     * completes normally when the message has been sent, or completes
+     * exceptionally if an error occurs.
+     *
+     * <p> A Ping message may be sent or received by either client or server.
+     * It may serve either as a keepalive or as a means to verify that the
+     * remote endpoint is still responsive.
+     *
+     * <p> The message must consist of not more than {@code 125} bytes: {@code
+     * message.remaining() <= 125}.
+     *
+     * <p> The returned {@code CompletableFuture} can complete exceptionally
+     * with:
+     * <ul>
+     * <li> {@link IOException}
+     *          if an I/O error occurs during this operation or the
+     *          {@code WebSocket} closes while this operation is in progress
+     * </ul>
+     *
+     * @param message
+     *         the message
+     *
+     * @return a CompletableFuture of Void
+     *
+     * @throws IllegalStateException
+     *         if the WebSocket is closed
+     * @throws IllegalStateException
+     *         if a Close message has been already sent
+     * @throws IllegalStateException
+     *         if there is an outstanding send operation
+     * @throws IllegalArgumentException
+     *         if {@code message.remaining() > 125}
+     */
+    CompletableFuture<Void> sendPing(ByteBuffer message);
+
+    /**
+     * Sends a Pong message.
+     *
+     * <p> Returns immediately with a {@code CompletableFuture<Void>} which
+     * completes normally when the message has been sent, or completes
+     * exceptionally if an error occurs.
+     *
+     * <p> A Pong message may be unsolicited or may be sent in response to a
+     * previously received Ping. In latter case the contents of the Pong is
+     * identical to the originating Ping.
+     *
+     * <p> The message must consist of not more than {@code 125} bytes: {@code
+     * message.remaining() <= 125}.
+     *
+     * <p> The returned {@code CompletableFuture} can complete exceptionally
+     * with:
+     * <ul>
+     * <li> {@link IOException}
+     *          if an I/O error occurs during this operation or the
+     *          {@code WebSocket} closes while this operation is in progress
+     * </ul>
+     *
+     * @param message
+     *         the message
+     *
+     * @return a CompletableFuture of Void
+     *
+     * @throws IllegalStateException
+     *         if the WebSocket is closed
+     * @throws IllegalStateException
+     *         if a Close message has been already sent
+     * @throws IllegalStateException
+     *         if there is an outstanding send operation
+     * @throws IllegalArgumentException
+     *         if {@code message.remaining() > 125}
+     */
+    CompletableFuture<Void> sendPong(ByteBuffer message);
+
+    /**
+     * Sends a Close message with the given close code and the reason.
+     *
+     * <p> Returns immediately with a {@code CompletableFuture<Void>} which
+     * completes normally when the message has been sent, or completes
+     * exceptionally if an error occurs.
+     *
+     * <p> A Close message may consist of a close code and a reason for closing.
+     * The reason must have a valid UTF-8 representation not longer than {@code
+     * 123} bytes. The reason may be useful for debugging or passing information
+     * relevant to the connection but is not necessarily human readable.
+     *
+     * <p> The returned {@code CompletableFuture} can complete exceptionally
+     * with:
+     * <ul>
+     * <li> {@link IOException}
+     *          if an I/O error occurs during this operation or the
+     *          {@code WebSocket} closes while this operation is in progress
+     * </ul>
+     *
+     * @param code
+     *         the close code
+     * @param reason
+     *         the reason; can be empty
+     *
+     * @return a CompletableFuture of Void
+     *
+     * @throws IllegalStateException
+     *         if the WebSocket is closed
+     * @throws IllegalStateException
+     *         if a Close message has been already sent
+     * @throws IllegalStateException
+     *         if there is an outstanding send operation
+     * @throws IllegalArgumentException
+     *         if the {@code reason} doesn't have a valid UTF-8
+     *         representation not longer than {@code 123} bytes
+     */
+    CompletableFuture<Void> sendClose(CloseCode code, CharSequence reason);
+
+    /**
+     * Sends an empty Close message.
+     *
+     * <p> Returns immediately with a {@code CompletableFuture<Void>} which
+     * completes normally when the message has been sent, or completes
+     * exceptionally if an error occurs.
+     *
+     * <p> The returned {@code CompletableFuture} can complete exceptionally
+     * with:
+     * <ul>
+     * <li> {@link IOException}
+     *          if an I/O error occurs during this operation or the
+     *          {@code WebSocket} closes while this operation is in progress
+     * </ul>
+     *
+     * @return a CompletableFuture of Void
+     *
+     * @throws IllegalStateException
+     *         if the WebSocket is closed
+     * @throws IllegalStateException
+     *         if a Close message has been already sent
+     * @throws IllegalStateException
+     *         if there is an outstanding send operation
+     */
+    CompletableFuture<Void> sendClose();
+
+    /**
+     * Requests {@code n} more messages to be received by the {@link Listener
+     * Listener}.
+     *
+     * <p> The actual number might be fewer if either of the endpoints decide to
+     * close the connection before that or an error occurs.
+     *
+     * <p> A {@code WebSocket} that has just been created, hasn't requested
+     * anything yet. Usually the initial request for messages is done in {@link
+     * Listener#onOpen(java.net.http.WebSocket) Listener.onOpen}.
+     *
+     * If all requested messages have been received, and the server sends more,
+     * then these messages are queued.
+     *
+     * @implNote This implementation does not distinguish between partial and
+     * whole messages, because it's not known beforehand how a message will be
+     * received.
+     * <p> If a server sends more messages than requested, the implementation
+     * queues up these messages on the TCP connection and may eventually force
+     * the sender to stop sending through TCP flow control.
+     *
+     * @param n
+     *         the number of messages
+     *
+     * @throws IllegalArgumentException
+     *         if {@code n < 0}
+     *
+     * @return resulting unfulfilled demand with this request taken into account
+     */
+    // TODO return void as it's breaking encapsulation (leaking info when exactly something deemed delivered)
+    // or demand behaves after LONG.MAX_VALUE
+    long request(long n);
+
+    /**
+     * Returns a {@linkplain Builder#subprotocols(String, String...) subprotocol}
+     * in use.
+     *
+     * @return a subprotocol, or {@code null} if there is none
+     */
+    String getSubprotocol();
+
+    /**
+     * Tells whether the {@code WebSocket} is closed.
+     *
+     * <p> A {@code WebSocket} deemed closed when either the underlying socket
+     * is closed or the closing handshake is completed.
+     *
+     * @return {@code true} if the {@code WebSocket} is closed,
+     *         {@code false} otherwise
+     */
+    boolean isClosed();
+
+    /**
+     * Closes the {@code WebSocket} abruptly.
+     *
+     * <p> This method closes the underlying TCP connection. If the {@code
+     * WebSocket} is already closed then invoking this method has no effect.
+     *
+     * @throws IOException
+     *         if an I/O error occurs
+     */
+    void abort() throws IOException;
+
+    /**
+     * A {@code WebSocket} close status code.
+     *
+     * <p> Some codes <a href="https://tools.ietf.org/html/rfc6455#section-7.4">
+     * specified</a> in the WebSocket Protocol are defined as named constants
+     * here. Others can be {@linkplain #of(int) retrieved on demand}.
+     *
+     * <p> This is a
+     * <a href="../../lang/doc-files/ValueBased.html">value-based</a> class;
+     * use of identity-sensitive operations (including reference equality
+     * ({@code ==}), identity hash code, or synchronization) on instances of
+     * {@code CloseCode} may have unpredictable results and should be avoided.
+     *
+     * @since 9
+     */
+    final class CloseCode {
+
+        /**
+         * Indicates a normal close, meaning that the purpose for which the
+         * connection was established has been fulfilled.
+         *
+         * <p> Numerical representation: {@code 1000}
+         */
+        public static final CloseCode NORMAL_CLOSURE
+                = new CloseCode(1000, "NORMAL_CLOSURE");
+
+        /**
+         * Indicates that an endpoint is "going away", such as a server going
+         * down or a browser having navigated away from a page.
+         *
+         * <p> Numerical representation: {@code 1001}
+         */
+        public static final CloseCode GOING_AWAY
+                = new CloseCode(1001, "GOING_AWAY");
+
+        /**
+         * Indicates that an endpoint is terminating the connection due to a
+         * protocol error.
+         *
+         * <p> Numerical representation: {@code 1002}
+         */
+        public static final CloseCode PROTOCOL_ERROR
+                = new CloseCode(1002, "PROTOCOL_ERROR");
+
+        /**
+         * Indicates that an endpoint is terminating the connection because it
+         * has received a type of data it cannot accept (e.g., an endpoint that
+         * understands only text data MAY send this if it receives a binary
+         * message).
+         *
+         * <p> Numerical representation: {@code 1003}
+         */
+        public static final CloseCode CANNOT_ACCEPT
+                = new CloseCode(1003, "CANNOT_ACCEPT");
+
+        /**
+         * Indicates that an endpoint is terminating the connection because it
+         * has received data within a message that was not consistent with the
+         * type of the message (e.g., non-UTF-8 [RFC3629] data within a text
+         * message).
+         *
+         * <p> Numerical representation: {@code 1007}
+         */
+        public static final CloseCode NOT_CONSISTENT
+                = new CloseCode(1007, "NOT_CONSISTENT");
+
+        /**
+         * Indicates that an endpoint is terminating the connection because it
+         * has received a message that violates its policy. This is a generic
+         * status code that can be returned when there is no other more suitable
+         * status code (e.g., {@link #CANNOT_ACCEPT} or {@link #TOO_BIG}) or if
+         * there is a need to hide specific details about the policy.
+         *
+         * <p> Numerical representation: {@code 1008}
+         */
+        public static final CloseCode VIOLATED_POLICY
+                = new CloseCode(1008, "VIOLATED_POLICY");
+
+        /**
+         * Indicates that an endpoint is terminating the connection because it
+         * has received a message that is too big for it to process.
+         *
+         * <p> Numerical representation: {@code 1009}
+         */
+        public static final CloseCode TOO_BIG
+                = new CloseCode(1009, "TOO_BIG");
+
+        /**
+         * Indicates that an endpoint is terminating the connection because it
+         * encountered an unexpected condition that prevented it from fulfilling
+         * the request.
+         *
+         * <p> Numerical representation: {@code 1011}
+         */
+        public static final CloseCode UNEXPECTED_CONDITION
+                = new CloseCode(1011, "UNEXPECTED_CONDITION");
+
+        private static final Map<Integer, CloseCode> cached = Map.ofEntries(
+                entry(NORMAL_CLOSURE),
+                entry(GOING_AWAY),
+                entry(PROTOCOL_ERROR),
+                entry(CANNOT_ACCEPT),
+                entry(NOT_CONSISTENT),
+                entry(VIOLATED_POLICY),
+                entry(TOO_BIG),
+                entry(UNEXPECTED_CONDITION)
+        );
+
+        /**
+         * Returns a {@code CloseCode} from its numerical representation.
+         *
+         * <p> The given {@code code} should be in the range {@code 1000 <= code
+         * <= 4999}, and should not be equal to any of the following codes:
+         * {@code 1004}, {@code 1005}, {@code 1006} and {@code 1015}.
+         *
+         * @param code
+         *         numerical representation
+         *
+         * @return a close code corresponding to the provided numerical value
+         *
+         * @throws IllegalArgumentException
+         *         if {@code code} violates any of the requirements above
+         */
+        public static CloseCode of(int code) {
+            if (code < 1000 || code > 4999) {
+                throw new IllegalArgumentException("Out of range: " + code);
+            }
+            if (code == 1004 || code == 1005 || code == 1006 || code == 1015) {
+                throw new IllegalArgumentException("Reserved: " + code);
+            }
+            CloseCode closeCode = cached.get(code);
+            return closeCode != null ? closeCode : new CloseCode(code, "");
+        }
+
+        private final int code;
+        private final String description;
+
+        private CloseCode(int code, String description) {
+            assert description != null;
+            this.code = code;
+            this.description = description;
+        }
+
+        /**
+         * Returns a numerical representation of this close code.
+         *
+         * @return a numerical representation
+         */
+        public int getCode() {
+            return code;
+        }
+
+        /**
+         * Compares this close code to the specified object.
+         *
+         * @param o
+         *         the object to compare this {@code CloseCode} against
+         *
+         * @return {@code true} iff the argument is a close code with the same
+         * {@linkplain #getCode() numerical representation} as this one
+         */
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (!(o instanceof CloseCode)) {
+                return false;
+            }
+            CloseCode that = (CloseCode) o;
+            return code == that.code;
+        }
+
+        @Override
+        public int hashCode() {
+            return code;
+        }
+
+        /**
+         * Returns a human-readable representation of this close code.
+         *
+         * @apiNote The representation is not designed to be parsed; the format
+         * may change unexpectedly.
+         *
+         * @return a string representation
+         */
+        @Override
+        public String toString() {
+            return code + (description.isEmpty() ? "" : (": " + description));
+        }
+
+        private static Map.Entry<Integer, CloseCode> entry(CloseCode cc) {
+            return Map.entry(cc.getCode(), cc);
+        }
+    }
+
+    /**
+     * A character sequence that provides access to the characters UTF-8 decoded
+     * from a message in a {@code ByteBuffer}.
+     *
+     * @since 9
+     */
+    interface Text extends CharSequence {
+
+        // Methods from the CharSequence below are mentioned explicitly for the
+        // purpose of documentation, so when looking at javadoc it immediately
+        // obvious what methods Text has
+
+        @Override
+        int length();
+
+        @Override
+        char charAt(int index);
+
+        @Override
+        CharSequence subSequence(int start, int end);
+
+        /**
+         * Returns a string containing the characters in this sequence in the
+         * same order as this sequence. The length of the string will be the
+         * length of this sequence.
+         *
+         * @return a string consisting of exactly this sequence of characters
+         */
+        @Override
+        // TODO: remove the explicit javadoc above when:
+        // (JDK-8144034 has been resolved) AND (the comment is still identical
+        // to CharSequence#toString)
+        String toString();
+
+        /**
+         * Returns a read-only {@code ByteBuffer} containing the message encoded
+         * in UTF-8.
+         *
+         * @return a read-only ByteBuffer
+         */
+        ByteBuffer asByteBuffer();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WebSocketHandshakeException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.net.http;
+
+/**
+ * An exception used to signal the opening handshake failed.
+ *
+ * @since 9
+ */
+public final class WebSocketHandshakeException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+    private final transient HttpResponse response;
+
+    WebSocketHandshakeException(HttpResponse response) {
+        this(null, response);
+    }
+
+    WebSocketHandshakeException(String message, HttpResponse response) {
+        super(statusCodeOrFullMessage(message, response));
+        this.response = response;
+    }
+
+    /**
+     * // FIXME: terrible toString (+ not always status should be displayed I guess)
+     */
+    private static String statusCodeOrFullMessage(String m, HttpResponse response) {
+        return (m == null || m.isEmpty())
+                ? String.valueOf(response.statusCode())
+                : response.statusCode() + ": " + m;
+    }
+
+    /**
+     * Returns a HTTP response from the server.
+     *
+     * <p> The value may be unavailable ({@code null}) if this exception has
+     * been serialized and then read back in.
+     *
+     * @return server response
+     */
+    public HttpResponse getResponse() {
+        return response;
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java	Wed Jul 05 21:42:16 2017 +0200
@@ -33,6 +33,7 @@
  *    <li>{@link java.net.http.HttpClient}</li>
  *    <li>{@link java.net.http.HttpRequest}</li>
  *    <li>{@link java.net.http.HttpResponse}</li>
+ *    <li>{@link java.net.http.WebSocket}</li>
  * </ul>
  *
  * @since 9
--- a/jdk/src/java.management/share/classes/javax/management/AttributeList.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.management/share/classes/javax/management/AttributeList.java	Wed Jul 05 21:42:16 2017 +0200
@@ -148,7 +148,7 @@
      * <p>If this method has ever been called on a given
      * {@code AttributeList} instance, a subsequent attempt to add
      * an object to that instance which is not an {@code Attribute}
-     * will fail with a {@code IllegalArgumentException}. For compatibility
+     * will fail with an {@code IllegalArgumentException}. For compatibility
      * reasons, an {@code AttributeList} on which this method has never
      * been called does allow objects other than {@code Attribute}s to
      * be added.</p>
--- a/jdk/src/java.management/share/classes/javax/management/MBeanFeatureInfo.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.management/share/classes/javax/management/MBeanFeatureInfo.java	Wed Jul 05 21:42:16 2017 +0200
@@ -215,7 +215,7 @@
      *    <ul>
      *    <li>1. The method {@link ObjectInputStream#readObject readObject()}
      *       is called twice to obtain the field names (a {@code String[]}) and
-     *       the field values (a {@code Object[]}) of the {@code descriptor}.
+     *       the field values (an {@code Object[]}) of the {@code descriptor}.
      *       The two obtained values then are used to construct
      *       an {@link ImmutableDescriptor} instance for the field
      *       {@code descriptor};</li>
--- a/jdk/src/java.management/share/classes/javax/management/MBeanInfo.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.management/share/classes/javax/management/MBeanInfo.java	Wed Jul 05 21:42:16 2017 +0200
@@ -670,7 +670,7 @@
      *    <ul>
      *    <li>1. The method {@link ObjectInputStream#readObject readObject()}
      *       is called twice to obtain the field names (a {@code String[]}) and
-     *       the field values (a {@code Object[]}) of the {@code descriptor}.
+     *       the field values (an {@code Object[]}) of the {@code descriptor}.
      *       The two obtained values then are used to construct
      *       an {@link ImmutableDescriptor} instance for the field
      *       {@code descriptor};</li>
--- a/jdk/src/java.management/share/classes/sun/management/Sensor.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.management/share/classes/sun/management/Sensor.java	Wed Jul 05 21:42:16 2017 +0200
@@ -34,7 +34,7 @@
  * An abstract sensor.
  *
  * <p>
- * A {@code AbstractSensor} object consists of two attributes:
+ * An {@code AbstractSensor} object consists of two attributes:
  * <ul>
  *   <li>{@code on} is a boolean flag indicating if a sensor is
  *       triggered. This flag will be set or cleared by the
--- a/jdk/src/java.management/share/classes/sun/management/counter/perf/InstrumentationException.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.management/share/classes/sun/management/counter/perf/InstrumentationException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -27,14 +27,14 @@
 
 public class InstrumentationException extends RuntimeException {
     /**
-     * Constructs a {@code InstrumentationException} with no
+     * Constructs an {@code InstrumentationException} with no
      * detail message.
      */
      public InstrumentationException() {
      }
 
     /**
-     * Constructs a {@code InstrumentationException} with a specified
+     * Constructs an {@code InstrumentationException} with a specified
      * detail message.
      *
      * @param message the detail message
--- a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/EventQueue.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/EventQueue.java	Wed Jul 05 21:42:16 2017 +0200
@@ -78,7 +78,7 @@
      *        {@code UnsolicitedNotificationEvent}.
      * If it is a subclass of {@code NamingEvent}, all listeners must implement
      * the corresponding subinterface of {@code NamingListener}.
-     * For example, for a {@code ObjectAddedEvent}, all listeners <em>must</em>
+     * For example, for an {@code ObjectAddedEvent}, all listeners <em>must</em>
      * implement the {@code ObjectAddedListener} interface.
      * <em>The current implementation does not check this before dispatching
      * the event.</em>
--- a/jdk/src/java.naming/share/classes/javax/naming/event/EventContext.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.naming/share/classes/javax/naming/event/EventContext.java	Wed Jul 05 21:42:16 2017 +0200
@@ -56,7 +56,7 @@
  *{@code NameNotFoundException}).
  *<p>
  * An application can use the method {@code targetMustExist()} to check
- * whether a {@code EventContext} supports registration
+ * whether an {@code EventContext} supports registration
  * of nonexistent targets.
  *
  *<h1>Event Source</h1>
@@ -92,7 +92,7 @@
  * which it invoked {@code addNamingListener()} (just as
  * it needs to keep a reference to the listener in order to remove it
  * later). It cannot expect to do a {@code lookup()} and get another instance of
- * a {@code EventContext} on which to perform the deregistration.
+ * an {@code EventContext} on which to perform the deregistration.
  *<h1>Lifetime of Registration</h1>
  * A registered listener becomes deregistered when:
  *<ul>
@@ -102,7 +102,7 @@
  *<li>{@code Context.close()} is invoked on the {@code EventContext}
  * instance with which it has registered.
  </ul>
- * Until that point, a {@code EventContext} instance that has outstanding
+ * Until that point, an {@code EventContext} instance that has outstanding
  * listeners will continue to exist and be maintained by the service provider.
  *
  *<h1>Listener Implementations</h1>
--- a/jdk/src/java.naming/share/classes/javax/naming/event/NamingListener.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.naming/share/classes/javax/naming/event/NamingListener.java	Wed Jul 05 21:42:16 2017 +0200
@@ -40,7 +40,7 @@
   * from the {@code EventContext} with which it has registered.
   *<p>
   * For example, suppose a listener implements {@code ObjectChangeListener} and
-  * registers with a {@code EventContext}.
+  * registers with an {@code EventContext}.
   * Then, if the connection to the server is subsequently broken,
   * the listener will receive a {@code NamingExceptionEvent} and may
   * take some corrective action, such as notifying the user of the application.
--- a/jdk/src/java.naming/share/classes/javax/naming/ldap/UnsolicitedNotificationListener.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.naming/share/classes/javax/naming/ldap/UnsolicitedNotificationListener.java	Wed Jul 05 21:42:16 2017 +0200
@@ -32,7 +32,7 @@
  * "Unsolicited notification" is defined in
  * <A HREF="http://www.ietf.org/rfc/rfc2251.txt">RFC 2251</A>.
  * It allows the server to send unsolicited notifications to the client.
- * A {@code UnsolicitedNotificationListener} must:
+ * An {@code UnsolicitedNotificationListener} must:
  *<ol>
  * <li>Implement this interface and its method
  * <li>Implement {@code NamingListener.namingExceptionThrown()} so
@@ -41,7 +41,7 @@
  * <li>Register with the context using one of the {@code addNamingListener()}
  * methods from {@code EventContext} or {@code EventDirContext}.
  * Only the {@code NamingListener} argument of these methods are applicable;
- * the rest are ignored for a {@code UnsolicitedNotificationListener}.
+ * the rest are ignored for an {@code UnsolicitedNotificationListener}.
  * (These arguments might be applicable to the listener if it implements
  * other listener interfaces).
  *</ol>
--- a/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -35,21 +35,8 @@
  * request that the RMI runtime use its socket factory instance
  * instead of the default implementation.
  *
- * <p>The default socket factory implementation performs a
- * three-tiered approach to creating client sockets. First, a direct
- * socket connection to the remote VM is attempted.  If that fails
- * (due to a firewall), the runtime uses HTTP with the explicit port
- * number of the server.  If the firewall does not allow this type of
- * communication, then HTTP to a cgi-bin script on the server is used
- * to POST the RMI call. The HTTP tunneling mechanisms are disabled by
- * default. This behavior is controlled by the {@code java.rmi.server.disableHttp}
- * property, whose default value is {@code true}. Setting this property's
- * value to {@code false} will enable the HTTP tunneling mechanisms.
- *
- * <p><strong>Deprecated: HTTP Tunneling.</strong> <em>The HTTP tunneling mechanisms
- * described above, specifically HTTP with an explicit port and HTTP to a
- * cgi-bin script, are deprecated. These HTTP tunneling mechanisms are
- * subject to removal in a future release of the platform.</em>
+ * <p>The default socket factory implementation creates a direct
+ * socket connection to the remote host.
  *
  * <p>The default socket factory implementation creates server sockets that
  * are bound to the wildcard address, which accepts requests from all network
@@ -181,7 +168,7 @@
     public synchronized static RMISocketFactory getDefaultSocketFactory() {
         if (defaultSocketFactory == null) {
             defaultSocketFactory =
-                new sun.rmi.transport.proxy.RMIMasterSocketFactory();
+                new sun.rmi.transport.tcp.TCPDirectSocketFactory();
         }
         return defaultSocketFactory;
     }
--- a/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java	Wed Jul 05 21:42:16 2017 +0200
@@ -194,7 +194,7 @@
         /*
          * Unless we were told to skip this consideration, choose the
          * "default loader" to simulate the default ObjectInputStream
-         * resolveClass mechanism (that is, choose the first non-null
+         * resolveClass mechanism (that is, choose the first non-platform
          * loader on the execution stack) to maximize the likelihood of
          * type compatibility with calling code.  (This consideration
          * is skipped during server parameter unmarshalling using the 1.2
@@ -268,8 +268,9 @@
     }
 
     /*
-     * Returns the first non-null class loader up the execution stack, or null
-     * if only code from the null class loader is on the stack.
+     * Returns the first non-platform class loader up the execution stack,
+     * or platform class loader if only code from the platform class loader or null
+     * is on the stack.
      */
     private static ClassLoader latestUserDefinedLoader() {
         return jdk.internal.misc.VM.latestUserDefinedLoader();
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,423 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.rmi.transport.proxy;
-
-import java.io.*;
-import java.net.*;
-import java.util.Hashtable;
-
-/**
- * CGIClientException is thrown when an error is detected
- * in a client's request.
- */
-class CGIClientException extends Exception {
-    private static final long serialVersionUID = 8147981687059865216L;
-
-    public CGIClientException(String s) {
-        super(s);
-    }
-
-    public CGIClientException(String s, Throwable cause) {
-        super(s, cause);
-    }
-}
-
-/**
- * CGIServerException is thrown when an error occurs here on the server.
- */
-class CGIServerException extends Exception {
-
-    private static final long serialVersionUID = 6928425456704527017L;
-
-    public CGIServerException(String s) {
-        super(s);
-    }
-
-    public CGIServerException(String s, Throwable cause) {
-        super(s, cause);
-    }
-}
-
-/**
- * CGICommandHandler is the interface to an object that handles a
- * particular supported command.
- */
-interface CGICommandHandler {
-
-    /**
-     * Return the string form of the command
-     * to be recognized in the query string.
-     */
-    public String getName();
-
-    /**
-     * Execute the command with the given string as parameter.
-     */
-    public void execute(String param) throws CGIClientException, CGIServerException;
-}
-
-/**
- * The CGIHandler class contains methods for executing as a CGI program.
- * The main function interprets the query string as a command of the form
- * "{@code <command>=<parameters>}".
- *
- * This class depends on the CGI 1.0 environment variables being set as
- * properties of the same name in this Java VM.
- *
- * All data and methods of this class are static because they are specific
- * to this particular CGI process.
- */
-public final class CGIHandler {
-
-    /* get CGI parameters that we need */
-    static int ContentLength;
-    static String QueryString;
-    static String RequestMethod;
-    static String ServerName;
-    static int ServerPort;
-
-    static {
-        java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Void>() {
-            public Void run() {
-                ContentLength =
-                    Integer.getInteger("CONTENT_LENGTH", 0).intValue();
-                QueryString = System.getProperty("QUERY_STRING", "");
-                RequestMethod = System.getProperty("REQUEST_METHOD", "");
-                ServerName = System.getProperty("SERVER_NAME", "");
-                ServerPort = Integer.getInteger("SERVER_PORT", 0).intValue();
-                return null;
-            }
-        });
-    }
-
-    /* list of handlers for supported commands */
-    private static CGICommandHandler commands[] = {
-        new CGIForwardCommand(),
-        new CGIGethostnameCommand(),
-        new CGIPingCommand(),
-        new CGITryHostnameCommand()
-    };
-
-    /* construct table mapping command strings to handlers */
-    private static Hashtable<String, CGICommandHandler> commandLookup;
-    static {
-        commandLookup = new Hashtable<>();
-        for (int i = 0; i < commands.length; ++ i)
-            commandLookup.put(commands[i].getName(), commands[i]);
-    }
-
-    /* prevent instantiation of this class */
-    private CGIHandler() {}
-
-    /**
-     * Execute command given in query string on URL.  The string before
-     * the first '=' is interpreted as the command name, and the string
-     * after the first '=' is the parameters to the command.
-     */
-    public static void main(String args[])
-    {
-        try {
-            String command, param;
-            int delim = QueryString.indexOf('=');
-            if (delim == -1) {
-                command = QueryString;
-                param = "";
-            }
-            else {
-                command = QueryString.substring(0, delim);
-                param = QueryString.substring(delim + 1);
-            }
-            CGICommandHandler handler =
-                commandLookup.get(command);
-            if (handler != null)
-                try {
-                    handler.execute(param);
-                } catch (CGIClientException e) {
-                    e.printStackTrace();
-                    returnClientError(e.getMessage());
-                } catch (CGIServerException e) {
-                    e.printStackTrace();
-                    returnServerError(e.getMessage());
-                }
-            else
-                returnClientError("invalid command.");
-        } catch (Exception e) {
-            e.printStackTrace();
-            returnServerError("internal error: " + e.getMessage());
-        }
-        System.exit(0);
-    }
-
-    /**
-     * Return an HTML error message indicating there was error in
-     * the client's request.
-     */
-    private static void returnClientError(String message)
-    {
-        System.out.println("Status: 400 Bad Request: " + message);
-        System.out.println("Content-type: text/html");
-        System.out.println("");
-        System.out.println("<HTML>" +
-                           "<HEAD><TITLE>Java RMI Client Error" +
-                           "</TITLE></HEAD>" +
-                           "<BODY>");
-        System.out.println("<H1>Java RMI Client Error</H1>");
-        System.out.println("");
-        System.out.println(message);
-        System.out.println("</BODY></HTML>");
-        System.exit(1);
-    }
-
-    /**
-     * Return an HTML error message indicating an error occurred
-     * here on the server.
-     */
-    private static void returnServerError(String message)
-    {
-        System.out.println("Status: 500 Server Error: " + message);
-        System.out.println("Content-type: text/html");
-        System.out.println("");
-        System.out.println("<HTML>" +
-                           "<HEAD><TITLE>Java RMI Server Error" +
-                           "</TITLE></HEAD>" +
-                           "<BODY>");
-        System.out.println("<H1>Java RMI Server Error</H1>");
-        System.out.println("");
-        System.out.println(message);
-        System.out.println("</BODY></HTML>");
-        System.exit(1);
-    }
-}
-
-/**
- * "forward" command: Forward request body to local port on the server,
- * and send response back to client.
- */
-final class CGIForwardCommand implements CGICommandHandler {
-
-    public String getName() {
-        return "forward";
-    }
-
-    @SuppressWarnings("deprecation")
-    private String getLine (DataInputStream socketIn) throws IOException {
-        return socketIn.readLine();
-    }
-
-    public void execute(String param) throws CGIClientException, CGIServerException
-    {
-        if (!CGIHandler.RequestMethod.equals("POST"))
-            throw new CGIClientException("can only forward POST requests");
-
-        int port;
-        try {
-            port = Integer.parseInt(param);
-        } catch (NumberFormatException e) {
-            throw new CGIClientException("invalid port number.", e);
-        }
-        if (port <= 0 || port > 0xFFFF)
-            throw new CGIClientException("invalid port: " + port);
-        if (port < 1024)
-            throw new CGIClientException("permission denied for port: " +
-                                         port);
-
-        byte buffer[];
-        Socket socket;
-        try {
-            socket = new Socket(InetAddress.getLocalHost(), port);
-        } catch (IOException e) {
-            throw new CGIServerException("could not connect to local port", e);
-        }
-
-        /*
-         * read client's request body
-         */
-        DataInputStream clientIn = new DataInputStream(System.in);
-        buffer = new byte[CGIHandler.ContentLength];
-        try {
-            clientIn.readFully(buffer);
-        } catch (EOFException e) {
-            throw new CGIClientException("unexpected EOF reading request body", e);
-        } catch (IOException e) {
-            throw new CGIClientException("error reading request body", e);
-        }
-
-        /*
-         * send to local server in HTTP
-         */
-        try {
-            DataOutputStream socketOut =
-                new DataOutputStream(socket.getOutputStream());
-            socketOut.writeBytes("POST / HTTP/1.0\r\n");
-            socketOut.writeBytes("Content-length: " +
-                                 CGIHandler.ContentLength + "\r\n\r\n");
-            socketOut.write(buffer);
-            socketOut.flush();
-        } catch (IOException e) {
-            throw new CGIServerException("error writing to server", e);
-        }
-
-        /*
-         * read response
-         */
-        DataInputStream socketIn;
-        try {
-            socketIn = new DataInputStream(socket.getInputStream());
-        } catch (IOException e) {
-            throw new CGIServerException("error reading from server", e);
-        }
-        String key = "Content-length:".toLowerCase();
-        boolean contentLengthFound = false;
-        String line;
-        int responseContentLength = -1;
-        do {
-            try {
-                line = getLine(socketIn);
-            } catch (IOException e) {
-                throw new CGIServerException("error reading from server", e);
-            }
-            if (line == null)
-                throw new CGIServerException(
-                    "unexpected EOF reading server response");
-
-            if (line.toLowerCase().startsWith(key)) {
-                if (contentLengthFound) {
-                    throw new CGIServerException(
-                            "Multiple Content-length entries found.");
-                } else {
-                    responseContentLength =
-                        Integer.parseInt(line.substring(key.length()).trim());
-                    contentLengthFound = true;
-                }
-            }
-        } while ((line.length() != 0) &&
-                 (line.charAt(0) != '\r') && (line.charAt(0) != '\n'));
-
-        if (!contentLengthFound || responseContentLength < 0)
-            throw new CGIServerException(
-                "missing or invalid content length in server response");
-        buffer = new byte[responseContentLength];
-        try {
-            socketIn.readFully(buffer);
-        } catch (EOFException e) {
-            throw new CGIServerException(
-                "unexpected EOF reading server response", e);
-        } catch (IOException e) {
-            throw new CGIServerException("error reading from server", e);
-        }
-
-        /*
-         * send response back to client
-         */
-        System.out.println("Status: 200 OK");
-        System.out.println("Content-type: application/octet-stream");
-        System.out.println("");
-        try {
-            System.out.write(buffer);
-        } catch (IOException e) {
-            throw new CGIServerException("error writing response", e);
-        }
-        System.out.flush();
-    }
-}
-
-/**
- * "gethostname" command: Return the host name of the server as the
- * response body
- */
-final class CGIGethostnameCommand implements CGICommandHandler {
-
-    public String getName() {
-        return "gethostname";
-    }
-
-    public void execute(String param)
-    {
-        System.out.println("Status: 200 OK");
-        System.out.println("Content-type: application/octet-stream");
-        System.out.println("Content-length: " +
-                           CGIHandler.ServerName.length());
-        System.out.println("");
-        System.out.print(CGIHandler.ServerName);
-        System.out.flush();
-    }
-}
-
-/**
- * "ping" command: Return an OK status to indicate that connection
- * was successful.
- */
-final class CGIPingCommand implements CGICommandHandler {
-
-    public String getName() {
-        return "ping";
-    }
-
-    public void execute(String param)
-    {
-        System.out.println("Status: 200 OK");
-        System.out.println("Content-type: application/octet-stream");
-        System.out.println("Content-length: 0");
-        System.out.println("");
-    }
-}
-
-/**
- * "tryhostname" command: Return a human readable message describing
- * what host name is available to local Java VMs.
- */
-final class CGITryHostnameCommand implements CGICommandHandler {
-
-    public String getName() {
-        return "tryhostname";
-    }
-
-    public void execute(String param)
-    {
-        System.out.println("Status: 200 OK");
-        System.out.println("Content-type: text/html");
-        System.out.println("");
-        System.out.println("<HTML>" +
-                           "<HEAD><TITLE>Java RMI Server Hostname Info" +
-                           "</TITLE></HEAD>" +
-                           "<BODY>");
-        System.out.println("<H1>Java RMI Server Hostname Info</H1>");
-        System.out.println("<H2>Local host name available to Java VM:</H2>");
-        System.out.print("<P>InetAddress.getLocalHost().getHostName()");
-        try {
-            String localHostName = InetAddress.getLocalHost().getHostName();
-
-            System.out.println(" = " + localHostName);
-        } catch (UnknownHostException e) {
-            System.out.println(" threw java.net.UnknownHostException");
-        }
-
-        System.out.println("<H2>Server host information obtained through CGI interface from HTTP server:</H2>");
-        System.out.println("<P>SERVER_NAME = " + CGIHandler.ServerName);
-        System.out.println("<P>SERVER_PORT = " + CGIHandler.ServerPort);
-        System.out.println("</BODY></HTML>");
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 1996, 2005, 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.rmi.transport.proxy;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
-import sun.rmi.runtime.Log;
-
-/**
- * The HttpAwareServerSocket class extends the java.net.ServerSocket
- * class.  It behaves like a ServerSocket, except that if
- * the first four bytes of an accepted socket are the letters "POST",
- * then it returns an HttpReceiveSocket instead of a java.net.Socket.
- * This means that the accept method blocks until four bytes have been
- * read from the new socket's input stream.
- */
-class HttpAwareServerSocket extends ServerSocket {
-
-    /**
-     * Create a server socket on a specified port.
-     * @param port the port
-     * @exception IOException IO error when opening the socket.
-     */
-    public HttpAwareServerSocket(int port) throws IOException
-    {
-        super(port);
-    }
-
-    /**
-     * Create a server socket, bind it to the specified local port
-     * and listen to it.  You can connect to an annonymous port by
-     * specifying the port number to be 0.  <i>backlog</i> specifies
-     * how many connection requests the system will queue up while waiting
-     * for the ServerSocket to execute accept().
-     * @param port the specified port
-     * @param backlog the number of queued connect requests pending accept
-     */
-    public HttpAwareServerSocket(int port, int backlog) throws IOException
-    {
-        super(port, backlog);
-    }
-
-    /**
-     * Accept a connection. This method will block until the connection
-     * is made and four bytes can be read from the input stream.
-     * If the first four bytes are "POST", then an HttpReceiveSocket is
-     * returned, which will handle the HTTP protocol wrapping.
-     * Otherwise, a WrappedSocket is returned.  The input stream will be
-     * reset to the beginning of the transmission.
-     * In either case, a BufferedInputStream will already be on top of
-     * the underlying socket's input stream.
-     * @exception IOException IO error when waiting for the connection.
-     */
-    public Socket accept() throws IOException
-    {
-        Socket socket = super.accept();
-        BufferedInputStream in =
-            new BufferedInputStream(socket.getInputStream());
-
-        RMIMasterSocketFactory.proxyLog.log(Log.BRIEF,
-            "socket accepted (checking for POST)");
-
-        in.mark(4);
-        boolean isHttp = (in.read() == 'P') &&
-                         (in.read() == 'O') &&
-                         (in.read() == 'S') &&
-                         (in.read() == 'T');
-        in.reset();
-
-        if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) {
-            RMIMasterSocketFactory.proxyLog.log(Log.BRIEF,
-                (isHttp ? "POST found, HTTP socket returned" :
-                          "POST not found, direct socket returned"));
-        }
-
-        if (isHttp)
-            return new HttpReceiveSocket(socket, in, null);
-        else
-            return new WrappedSocket(socket, in, null);
-    }
-
-    /**
-     * Return the implementation address and implementation port of
-     * the HttpAwareServerSocket as a String.
-     */
-    public String toString()
-    {
-        return "HttpAware" + super.toString();
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 1996, 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 sun.rmi.transport.proxy;
-
-import java.io.*;
-
-import sun.rmi.runtime.Log;
-
-/**
- * The HttpInputStream class assists the HttpSendSocket and HttpReceiveSocket
- * classes by filtering out the header for the message as well as any
- * data after its proper content length.
- */
-class HttpInputStream extends FilterInputStream {
-
-    /** bytes remaining to be read from proper content of message */
-    protected int bytesLeft;
-
-    /** bytes remaining to be read at time of last mark */
-    protected int bytesLeftAtMark;
-
-    /**
-     * Create new filter on a given input stream.
-     * @param in the InputStream to filter from
-     */
-    @SuppressWarnings("deprecation")
-    public HttpInputStream(InputStream in) throws IOException
-    {
-        super(in);
-
-        if (in.markSupported())
-            in.mark(0); // prevent resetting back to old marks
-
-        // pull out header, looking for content length
-
-        DataInputStream dis = new DataInputStream(in);
-        String key = "Content-length:".toLowerCase();
-        boolean contentLengthFound = false;
-        String line;
-        do {
-            line = dis.readLine();
-
-            if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) {
-                RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE,
-                    "received header line: \"" + line + "\"");
-            }
-
-            if (line == null)
-                throw new EOFException();
-
-            if (line.toLowerCase().startsWith(key)) {
-                if (contentLengthFound) {
-                    throw new IOException(
-                            "Multiple Content-length entries found.");
-                } else {
-                    bytesLeft =
-                        Integer.parseInt(line.substring(key.length()).trim());
-                    contentLengthFound = true;
-                }
-            }
-
-            // The idea here is to go past the first blank line.
-            // Some DataInputStream.readLine() documentation specifies that
-            // it does include the line-terminating character(s) in the
-            // returned string, but it actually doesn't, so we'll cover
-            // all cases here...
-        } while ((line.length() != 0) &&
-                 (line.charAt(0) != '\r') && (line.charAt(0) != '\n'));
-
-        if (!contentLengthFound || bytesLeft < 0) {
-            // This really shouldn't happen, but if it does, shoud we fail??
-            // For now, just give up and let a whole lot of bytes through...
-            bytesLeft = Integer.MAX_VALUE;
-        }
-        bytesLeftAtMark = bytesLeft;
-
-        if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) {
-            RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE,
-                "content length: " + bytesLeft);
-        }
-    }
-
-    /**
-     * Returns the number of bytes that can be read with blocking.
-     * Make sure that this does not exceed the number of bytes remaining
-     * in the proper content of the message.
-     */
-    public int available() throws IOException
-    {
-        int bytesAvailable = in.available();
-        if (bytesAvailable > bytesLeft)
-            bytesAvailable = bytesLeft;
-
-        return bytesAvailable;
-    }
-
-    /**
-     * Read a byte of data from the stream.  Make sure that one is available
-     * from the proper content of the message, else -1 is returned to
-     * indicate to the user that the end of the stream has been reached.
-     */
-    public int read() throws IOException
-    {
-        if (bytesLeft > 0) {
-            int data = in.read();
-            if (data != -1)
-                -- bytesLeft;
-
-            if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) {
-                RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE,
-                   "received byte: '" +
-                    ((data & 0x7F) < ' ' ? " " : String.valueOf((char) data)) +
-                    "' " + data);
-            }
-
-            return data;
-        }
-        else {
-            RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE,
-                                                "read past content length");
-
-            return -1;
-        }
-    }
-
-    public int read(byte b[], int off, int len) throws IOException
-    {
-        if (bytesLeft == 0 && len > 0) {
-            RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE,
-                                                "read past content length");
-
-            return -1;
-        }
-        if (len > bytesLeft)
-            len = bytesLeft;
-        int bytesRead = in.read(b, off, len);
-        bytesLeft -= bytesRead;
-
-        if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) {
-            RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE,
-                "read " + bytesRead + " bytes, " + bytesLeft + " remaining");
-        }
-
-        return bytesRead;
-    }
-
-    /**
-     * Mark the current position in the stream (for future calls to reset).
-     * Remember where we are within the proper content of the message, so
-     * that a reset method call can recreate our state properly.
-     * @param readlimit how many bytes can be read before mark becomes invalid
-     */
-    public void mark(int readlimit)
-    {
-        in.mark(readlimit);
-        if (in.markSupported())
-            bytesLeftAtMark = bytesLeft;
-    }
-
-    /**
-     * Repositions the stream to the last marked position.  Make sure to
-     * adjust our position within the proper content accordingly.
-     */
-    public void reset() throws IOException
-    {
-        in.reset();
-        bytesLeft = bytesLeftAtMark;
-    }
-
-    /**
-     * Skips bytes of the stream.  Make sure to adjust our
-     * position within the proper content accordingly.
-     * @param n number of bytes to be skipped
-     */
-    public long skip(long n) throws IOException
-    {
-        if (n > bytesLeft)
-            n = bytesLeft;
-        long bytesSkipped = in.skip(n);
-        bytesLeft -= bytesSkipped;
-        return bytesSkipped;
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 1996, 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.rmi.transport.proxy;
-
-import java.io.*;
-
-/**
- * The HttpOutputStream class assists the HttpSendSocket and HttpReceiveSocket
- * classes by providing an output stream that buffers its entire input until
- * closed, and then it sends the complete transmission prefixed by the end of
- * an HTTP header that specifies the content length.
- */
-class HttpOutputStream extends ByteArrayOutputStream {
-
-    /** the output stream to send response to */
-    protected OutputStream out;
-
-    /** true if HTTP response has been sent */
-    boolean responseSent = false;
-
-    /**
-     * Begin buffering new HTTP response to be sent to a given stream.
-     * @param out the OutputStream to send response to
-     */
-    public HttpOutputStream(OutputStream out) {
-        super();
-        this.out = out;
-    }
-
-    /**
-     * On close, send HTTP-packaged response.
-     */
-    public synchronized void close() throws IOException {
-        if (!responseSent) {
-            /*
-             * If response would have zero content length, then make it
-             * have some arbitrary data so that certain clients will not
-             * fail because the "document contains no data".
-             */
-            if (size() == 0)
-                write(emptyData);
-
-            DataOutputStream dos = new DataOutputStream(out);
-            dos.writeBytes("Content-type: application/octet-stream\r\n");
-            dos.writeBytes("Content-length: " + size() + "\r\n");
-            dos.writeBytes("\r\n");
-            writeTo(dos);
-            dos.flush();
-            // Do not close the underlying stream here, because that would
-            // close the underlying socket and prevent reading a response.
-            reset(); // reset byte array
-            responseSent = true;
-        }
-    }
-
-    /** data to send if the response would otherwise be empty */
-    private static byte[] emptyData = { 0 };
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 1996, 2000, 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.rmi.transport.proxy;
-
-import java.io.*;
-import java.net.Socket;
-import java.net.InetAddress;
-
-/**
- * The HttpReceiveSocket class extends the WrappedSocket class
- * by removing the HTTP protocol packaging from the input stream and
- * formatting the output stream as an HTTP response.
- *
- * NOTES:
- *
- * The output stream must be explicitly closed for the output to be
- * sent, since the HttpResponseOutputStream needs to buffer the entire
- * transmission to be able to fill in the content-length field of
- * the HTTP header.  Closing this socket will do this.
- *
- * The constructor blocks until the HTTP protocol header
- * is received.  This could be fixed, but I don't think it should be a
- * problem because this object would not be created unless the
- * HttpAwareServerSocket has detected the beginning of the header
- * anyway, so the rest should be there.
- *
- * This socket can only be used to process one POST and reply to it.
- * Another message would be received on a newly accepted socket anyway.
- */
-public class HttpReceiveSocket extends WrappedSocket implements RMISocketInfo {
-
-    /** true if the HTTP header has pushed through the output stream yet */
-    private boolean headerSent = false;
-
-    /**
-     * Layer on top of a pre-existing Socket object, and use specified
-     * input and output streams.
-     * @param socket the pre-existing socket to use
-     * @param in the InputStream to use for this socket (can be null)
-     * @param out the OutputStream to use for this socket (can be null)
-     */
-    public HttpReceiveSocket(Socket socket, InputStream in, OutputStream out)
-        throws IOException
-    {
-        super(socket, in, out);
-
-        this.in = new HttpInputStream(in != null ? in :
-                                                   socket.getInputStream());
-        this.out = (out != null ? out :
-                    socket.getOutputStream());
-    }
-
-    /**
-     * Indicate that this socket is not reusable.
-     */
-    public boolean isReusable()
-    {
-        return false;
-    }
-
-    /**
-     * Get the address to which this socket is connected.  "null" is always
-     * returned (to indicate an unknown address) because the originating
-     * host's IP address cannot be reliably determined: both because the
-     * request probably went through a proxy server, and because if it was
-     * delivered by a local forwarder (CGI script or servlet), we do NOT
-     * want it to appear as if the call is coming from the local host (in
-     * case the remote object makes access control decisions based on the
-     * "client host" of a remote call; see bugid 4399040).
-     */
-    public InetAddress getInetAddress() {
-        return null;
-    }
-
-    /**
-     * Get an OutputStream for this socket.
-     */
-    public OutputStream getOutputStream() throws IOException
-    {
-        if (!headerSent) { // could this be done in constructor??
-            DataOutputStream dos = new DataOutputStream(out);
-            dos.writeBytes("HTTP/1.0 200 OK\r\n");
-            dos.flush();
-            headerSent = true;
-            out = new HttpOutputStream(out);
-        }
-        return out;
-    }
-
-    /**
-     * Close the socket.
-     */
-    public synchronized void close() throws IOException
-    {
-        getOutputStream().close(); // make sure response is sent
-        socket.close();
-    }
-
-    /**
-     * Return string representation of the socket.
-     */
-    public String toString()
-    {
-        return "HttpReceive" + socket.toString();
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 1996, 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.rmi.transport.proxy;
-
-import java.io.*;
-
-/**
- * The HttpSendInputStream class is used by the HttpSendSocket class as
- * a layer on the top of the InputStream it returns so that it can be
- * notified of attempts to read from it.  This allows the HttpSendSocket
- * to know when it should push across its output message.
- */
-class HttpSendInputStream extends FilterInputStream {
-
-    /** the HttpSendSocket object that is providing this stream */
-    HttpSendSocket owner;
-
-    /**
-     * Create new filter on a given input stream.
-     * @param in the InputStream to filter from
-     * @param owner the HttpSendSocket that is providing this stream
-     */
-    public HttpSendInputStream(InputStream in, HttpSendSocket owner)
-        throws IOException
-    {
-        super(in);
-
-        this.owner = owner;
-    }
-
-    /**
-     * Mark this stream as inactive for its owner socket, so the next time
-     * a read is attempted, the owner will be notified and a new underlying
-     * input stream obtained.
-     */
-    public void deactivate()
-    {
-        in = null;
-    }
-
-    /**
-     * Read a byte of data from the stream.
-     */
-    public int read() throws IOException
-    {
-        if (in == null)
-            in = owner.readNotify();
-        return in.read();
-    }
-
-    /**
-     * Read into an array of bytes.
-     * @param b the buffer into which the data is to be read
-     * @param off the start offset of the data
-     * @param len the maximum number of bytes to read
-     */
-    public int read(byte b[], int off, int len) throws IOException
-    {
-        if (len == 0)
-            return 0;
-        if (in == null)
-            in = owner.readNotify();
-        return in.read(b, off, len);
-    }
-
-    /**
-     * Skip bytes of input.
-     * @param n the number of bytes to be skipped
-     */
-    public long skip(long n) throws IOException
-    {
-        if (n == 0)
-            return 0;
-        if (in == null)
-            in = owner.readNotify();
-        return in.skip(n);
-    }
-
-    /**
-     * Return the number of bytes that can be read without blocking.
-     */
-    public int available() throws IOException
-    {
-        if (in == null)
-            in = owner.readNotify();
-        return in.available();
-    }
-
-    /**
-     * Close the stream.
-     */
-    public void close() throws IOException
-    {
-        owner.close();
-    }
-
-    /**
-     * Mark the current position in the stream.
-     * @param readlimit how many bytes can be read before mark becomes invalid
-     */
-    public synchronized void mark(int readlimit)
-    {
-        if (in == null) {
-            try {
-                in = owner.readNotify();
-            }
-            catch (IOException e) {
-                return;
-            }
-        }
-        in.mark(readlimit);
-    }
-
-    /**
-     * Reposition the stream to the last marked position.
-     */
-    public synchronized void reset() throws IOException
-    {
-        if (in == null)
-            in = owner.readNotify();
-        in.reset();
-    }
-
-    /**
-     * Return true if this stream type supports mark/reset.
-     */
-    public boolean markSupported()
-    {
-        if (in == null) {
-            try {
-                in = owner.readNotify();
-            }
-            catch (IOException e) {
-                return false;
-            }
-        }
-        return in.markSupported();
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 1996, 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.rmi.transport.proxy;
-
-import java.io.*;
-
-/**
- * The HttpSendOutputStream class is used by the HttpSendSocket class as
- * a layer on the top of the OutputStream it returns so that it can be
- * notified of attempts to write to it.  This allows the HttpSendSocket
- * to know when it should construct a new message.
- */
-class HttpSendOutputStream extends FilterOutputStream {
-
-    /** the HttpSendSocket object that is providing this stream */
-    HttpSendSocket owner;
-
-    /**
-     * Create new filter on a given output stream.
-     * @param out the OutputStream to filter from
-     * @param owner the HttpSendSocket that is providing this stream
-     */
-    public HttpSendOutputStream(OutputStream out, HttpSendSocket owner)
-        throws IOException
-    {
-        super(out);
-
-        this.owner = owner;
-    }
-
-    /**
-     * Mark this stream as inactive for its owner socket, so the next time
-     * a write is attempted, the owner will be notified and a new underlying
-     * output stream obtained.
-     */
-    public void deactivate()
-    {
-        out = null;
-    }
-
-    /**
-     * Write a byte of data to the stream.
-     */
-    public void write(int b) throws IOException
-    {
-        if (out == null)
-            out = owner.writeNotify();
-        out.write(b);
-    }
-
-    /**
-     * Write a subarray of bytes.
-     * @param b the buffer from which the data is to be written
-     * @param off the start offset of the data
-     * @param len the number of bytes to be written
-     */
-    public void write(byte b[], int off, int len) throws IOException
-    {
-        if (len == 0)
-            return;
-        if (out == null)
-            out = owner.writeNotify();
-        out.write(b, off, len);
-    }
-
-    /**
-     * Flush the stream.
-     */
-    public void flush() throws IOException
-    {
-        if (out != null)
-            out.flush();
-    }
-
-    /**
-     * Close the stream.
-     */
-    public void close() throws IOException
-    {
-        flush();
-        owner.close();
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, 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.rmi.transport.proxy;
-
-import java.io.*;
-import java.net.*;
-import java.security.PrivilegedAction;
-
-import sun.rmi.runtime.Log;
-
-/**
- * The HttpSendSocket class extends the java.net.Socket class
- * by enclosing the data output stream in, then extracting the input
- * stream from, an HTTP protocol transmission.
- *
- * NOTES:
- *
- * Since the length of the output request must be known before the
- * HTTP header can be completed, all of the output is buffered by
- * an HttpOutputStream object until either an attempt is made to
- * read from this socket, or the socket is explicitly closed.
- *
- * On the first read attempt to read from this socket, the buffered
- * output is sent to the destination as the body of an HTTP POST
- * request.  All reads will then acquire data from the body of
- * the response.  A subsequent attempt to write to this socket will
- * throw an IOException.
- */
-class HttpSendSocket extends Socket implements RMISocketInfo {
-
-    /** the host to connect to */
-    protected String host;
-
-    /** the port to connect to */
-    protected int port;
-
-    /** the URL to forward through */
-    protected URL url;
-
-    /** the object managing this connection through the URL */
-    protected URLConnection conn = null;
-
-    /** internal input stream for this socket */
-    protected InputStream in = null;
-
-    /** internal output stream for this socket */
-    protected OutputStream out = null;
-
-    /** the notifying input stream returned to users */
-    protected HttpSendInputStream inNotifier;
-
-    /** the notifying output stream returned to users */
-    protected HttpSendOutputStream outNotifier;
-
-    /**
-     * Line separator string.  This is the value of the line.separator
-     * property at the moment that the socket was created.
-     */
-    private String lineSeparator =
-        java.security.AccessController.doPrivileged(
-            (PrivilegedAction<String>) () -> System.getProperty("line.separator"));
-
-    /**
-     * Create a stream socket and connect it to the specified port on
-     * the specified host.
-     * @param host the host
-     * @param port the port
-     */
-    public HttpSendSocket(String host, int port, URL url) throws IOException
-    {
-        super((SocketImpl)null);        // no underlying SocketImpl for this object
-
-        if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) {
-            RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE,
-                "host = " + host + ", port = " + port + ", url = " + url);
-        }
-
-        this.host = host;
-        this.port = port;
-        this.url = url;
-
-        inNotifier = new HttpSendInputStream(null, this);
-        outNotifier = new HttpSendOutputStream(writeNotify(), this);
-    }
-
-    /**
-     * Create a stream socket and connect it to the specified port on
-     * the specified host.
-     * @param host the host
-     * @param port the port
-     */
-    public HttpSendSocket(String host, int port) throws IOException
-    {
-        this(host, port, new URL("http", host, port, "/"));
-    }
-
-    /**
-     * Create a stream socket and connect it to the specified address on
-     * the specified port.
-     * @param address the address
-     * @param port the port
-     */
-    public HttpSendSocket(InetAddress address, int port) throws IOException
-    {
-        this(address.getHostName(), port);
-    }
-
-    /**
-     * Indicate that this socket is not reusable.
-     */
-    public boolean isReusable()
-    {
-        return false;
-    }
-
-    /**
-     * Create a new socket connection to host (or proxy), and prepare to
-     * send HTTP transmission.
-     */
-    public synchronized OutputStream writeNotify() throws IOException
-    {
-        if (conn != null) {
-            throw new IOException("attempt to write on HttpSendSocket after " +
-                                  "request has been sent");
-        }
-
-        conn = url.openConnection();
-        conn.setDoOutput(true);
-        conn.setUseCaches(false);
-        conn.setRequestProperty("Content-type", "application/octet-stream");
-
-        inNotifier.deactivate();
-        in = null;
-
-        return out = conn.getOutputStream();
-    }
-
-    /**
-     * Send HTTP output transmission and prepare to receive response.
-     */
-    public synchronized InputStream readNotify() throws IOException
-    {
-        RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE,
-            "sending request and activating input stream");
-
-        outNotifier.deactivate();
-        out.close();
-        out = null;
-
-        try {
-            in = conn.getInputStream();
-        } catch (IOException e) {
-            RMIMasterSocketFactory.proxyLog.log(Log.BRIEF,
-                "failed to get input stream, exception: ", e);
-
-            throw new IOException("HTTP request failed");
-        }
-
-        /*
-         * If an HTTP error response is returned, sometimes an IOException
-         * is thrown, which is handled above, and other times it isn't, and
-         * the error response body will be available for reading.
-         * As a safety net to catch any such unexpected HTTP behavior, we
-         * verify that the content type of the response is what the
-         * HttpOutputStream generates: "application/octet-stream".
-         * (Servers' error responses will generally be "text/html".)
-         * Any error response body is printed to the log.
-         */
-        String contentType = conn.getContentType();
-        if (contentType == null ||
-            !conn.getContentType().equals("application/octet-stream"))
-        {
-            if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) {
-                String message;
-                if (contentType == null) {
-                    message = "missing content type in response" +
-                        lineSeparator;
-                } else {
-                    message = "invalid content type in response: " +
-                        contentType + lineSeparator;
-                }
-
-                message += "HttpSendSocket.readNotify: response body: ";
-                try {
-                    BufferedReader din = new BufferedReader(new InputStreamReader(in));
-                    String line;
-                    while ((line = din.readLine()) != null)
-                        message += line + lineSeparator;
-                } catch (IOException e) {
-                }
-                RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, message);
-            }
-
-            throw new IOException("HTTP request failed");
-        }
-
-        return in;
-    }
-
-    /**
-     * Get the address to which the socket is connected.
-     */
-    public InetAddress getInetAddress()
-    {
-        try {
-            return InetAddress.getByName(host);
-        } catch (UnknownHostException e) {
-            return null;        // null if couldn't resolve destination host
-        }
-    }
-
-    /**
-     * Get the local address to which the socket is bound.
-     */
-    public InetAddress getLocalAddress()
-    {
-        try {
-            return InetAddress.getLocalHost();
-        } catch (UnknownHostException e) {
-            return null;        // null if couldn't determine local host
-        }
-    }
-
-    /**
-     * Get the remote port to which the socket is connected.
-     */
-    public int getPort()
-    {
-        return port;
-    }
-
-    /**
-     * Get the local port to which the socket is connected.
-     */
-    public int getLocalPort()
-    {
-        return -1;      // request not applicable to this socket type
-    }
-
-    /**
-     * Get an InputStream for this socket.
-     */
-    public InputStream getInputStream() throws IOException
-    {
-        return inNotifier;
-    }
-
-    /**
-     * Get an OutputStream for this socket.
-     */
-    public OutputStream getOutputStream() throws IOException
-    {
-        return outNotifier;
-    }
-
-    /**
-     * Enable/disable TCP_NODELAY.
-     * This operation has no effect for an HttpSendSocket.
-     */
-    public void setTcpNoDelay(boolean on) throws SocketException
-    {
-    }
-
-    /**
-     * Retrieve whether TCP_NODELAY is enabled.
-     */
-    public boolean getTcpNoDelay() throws SocketException
-    {
-        return false;   // imply option is disabled
-    }
-
-    /**
-     * Enable/disable SO_LINGER with the specified linger time.
-     * This operation has no effect for an HttpSendSocket.
-     */
-    public void setSoLinger(boolean on, int val) throws SocketException
-    {
-    }
-
-    /**
-     * Retrive setting for SO_LINGER.
-     */
-    public int getSoLinger() throws SocketException
-    {
-        return -1;      // imply option is disabled
-    }
-
-    /**
-     * Enable/disable SO_TIMEOUT with the specified timeout
-     * This operation has no effect for an HttpSendSocket.
-     */
-    public synchronized void setSoTimeout(int timeout) throws SocketException
-    {
-    }
-
-    /**
-     * Retrive setting for SO_TIMEOUT.
-     */
-    public synchronized int getSoTimeout() throws SocketException
-    {
-        return 0;       // imply option is disabled
-    }
-
-    /**
-     * Close the socket.
-     */
-    public synchronized void close() throws IOException
-    {
-        if (out != null) // push out transmission if not done
-            out.close();
-    }
-
-    /**
-     * Return string representation of this pseudo-socket.
-     */
-    public String toString()
-    {
-        return "HttpSendSocket[host=" + host +
-               ",port=" + port +
-               ",url=" + url + "]";
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 1996, 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.rmi.transport.proxy;
-
-import java.io.IOException;
-import java.net.Socket;
-import java.net.ServerSocket;
-import java.rmi.server.RMISocketFactory;
-
-/**
- * RMIDirectSocketFactory creates a direct socket connection to the
- * specified port on the specified host.
- */
-public class RMIDirectSocketFactory extends RMISocketFactory {
-
-    public Socket createSocket(String host, int port) throws IOException
-    {
-        return new Socket(host, port);
-    }
-
-    public ServerSocket createServerSocket(int port) throws IOException
-    {
-        return new ServerSocket(port);
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1998, 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.rmi.transport.proxy;
-
-import java.io.IOException;
-import java.net.Socket;
-import java.net.ServerSocket;
-import java.net.URL;
-import java.rmi.server.RMISocketFactory;
-
-/**
- * RMIHttpToCGISocketFactory creates a socket connection to the
- * specified host that is comminicated within an HTTP request,
- * forwarded through the default firewall proxy, to the target host's
- * normal HTTP server, to a CGI program which forwards the request to
- * the actual specified port on the socket.
- */
-public class RMIHttpToCGISocketFactory extends RMISocketFactory {
-
-    public Socket createSocket(String host, int port)
-        throws IOException
-    {
-        return new HttpSendSocket(host, port,
-                                  new URL("http", host,
-                                          "/cgi-bin/java-rmi.cgi" +
-                                          "?forward=" + port));
-    }
-
-    public ServerSocket createServerSocket(int port) throws IOException
-    {
-        return new HttpAwareServerSocket(port);
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 1998, 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.rmi.transport.proxy;
-
-import java.io.IOException;
-import java.net.Socket;
-import java.net.ServerSocket;
-import java.net.URL;
-import java.rmi.server.RMISocketFactory;
-
-/**
- * RMIHttpToPortSocketFactory creates a socket connection to the
- * specified host that is communicated within an HTTP request,
- * forwarded through the default firewall proxy, directly to the
- * specified port.
- */
-public class RMIHttpToPortSocketFactory extends RMISocketFactory {
-
-    public Socket createSocket(String host, int port)
-        throws IOException
-    {
-        return new HttpSendSocket(host, port,
-                                  new URL("http", host, port, "/"));
-    }
-
-    public ServerSocket createServerSocket(int port)
-        throws IOException
-    {
-        return new HttpAwareServerSocket(port);
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,468 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.rmi.transport.proxy;
-
-import java.io.*;
-import java.net.*;
-import java.security.*;
-import java.util.*;
-import java.rmi.server.LogStream;
-import java.rmi.server.RMISocketFactory;
-import sun.rmi.runtime.Log;
-import sun.rmi.runtime.NewThreadAction;
-
-/**
- * RMIMasterSocketFactory attempts to create a socket connection to the
- * specified host using successively less efficient mechanisms
- * until one succeeds.  If the host is successfully connected to,
- * the factory for the successful mechanism is stored in an internal
- * hash table keyed by the host name, so that future attempts to
- * connect to the same host will automatically use the same
- * mechanism.
- */
-@SuppressWarnings("deprecation")
-public class RMIMasterSocketFactory extends RMISocketFactory {
-
-    /** "proxy" package log level */
-    static int logLevel = LogStream.parseLevel(getLogLevel());
-
-    private static String getLogLevel() {
-        return java.security.AccessController.doPrivileged(
-            (PrivilegedAction<String>) () -> System.getProperty("sun.rmi.transport.proxy.logLevel"));
-    }
-
-    /* proxy package log */
-    static final Log proxyLog =
-        Log.getLog("sun.rmi.transport.tcp.proxy",
-                   "transport", RMIMasterSocketFactory.logLevel);
-
-    /** timeout for attemping direct socket connections */
-    private static long connectTimeout = getConnectTimeout();
-
-    private static long getConnectTimeout() {
-        return java.security.AccessController.doPrivileged((PrivilegedAction<Long>) () ->
-            Long.getLong("sun.rmi.transport.proxy.connectTimeout", 15000)); // default: 15 seconds
-    }
-
-    /** whether to fallback to HTTP on general connect failures */
-    private static final boolean eagerHttpFallback =
-        java.security.AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
-            Boolean.getBoolean("sun.rmi.transport.proxy.eagerHttpFallback"));
-
-    /** table of hosts successfully connected to and the factory used */
-    private Hashtable<String, RMISocketFactory> successTable =
-        new Hashtable<>();
-
-    /** maximum number of hosts to remember successful connection to */
-    private static final int MaxRememberedHosts = 64;
-
-    /** list of the hosts in successTable in initial connection order */
-    private Vector<String> hostList = new Vector<>(MaxRememberedHosts);
-
-    /** default factory for initial use for direct socket connection */
-    protected RMISocketFactory initialFactory = new RMIDirectSocketFactory();
-
-    /** ordered list of factories to try as alternate connection
-      * mechanisms if a direct socket connections fails */
-    protected Vector<RMISocketFactory> altFactoryList;
-
-    /**
-     * Create a RMIMasterSocketFactory object.  Establish order of
-     * connection mechanisms to attempt on createSocket, if a direct
-     * socket connection fails.
-     */
-    public RMIMasterSocketFactory() {
-        altFactoryList = new Vector<>(2);
-        boolean setFactories = false;
-
-        try {
-            String proxyHost;
-            proxyHost = java.security.AccessController.doPrivileged(
-               (PrivilegedAction<String>) () -> System.getProperty("http.proxyHost"));
-
-            if (proxyHost == null)
-                proxyHost = java.security.AccessController.doPrivileged(
-                    (PrivilegedAction<String>) () -> System.getProperty("proxyHost"));
-
-            boolean disable = java.security.AccessController.doPrivileged(
-                (PrivilegedAction<String>) () -> System.getProperty("java.rmi.server.disableHttp", "true"))
-                .equalsIgnoreCase("true");
-
-            if (!disable && proxyHost != null && proxyHost.length() > 0) {
-                setFactories = true;
-            }
-        } catch (Exception e) {
-            // unable to obtain the properties, so use the default behavior.
-        }
-
-        if (setFactories) {
-            altFactoryList.addElement(new RMIHttpToPortSocketFactory());
-            altFactoryList.addElement(new RMIHttpToCGISocketFactory());
-        }
-    }
-
-    /**
-     * Create a new client socket.  If we remember connecting to this host
-     * successfully before, then use the same factory again.  Otherwise,
-     * try using a direct socket connection and then the alternate factories
-     * in the order specified in altFactoryList.
-     */
-    public Socket createSocket(String host, int port)
-        throws IOException
-    {
-        if (proxyLog.isLoggable(Log.BRIEF)) {
-            proxyLog.log(Log.BRIEF, "host: " + host + ", port: " + port);
-        }
-
-        /*
-         * If we don't have any alternate factories to consult, short circuit
-         * the fallback procedure and delegate to the initial factory.
-         */
-        if (altFactoryList.size() == 0) {
-            return initialFactory.createSocket(host, port);
-        }
-
-        RMISocketFactory factory;
-
-        /*
-         * If we remember successfully connecting to this host before,
-         * use the same factory.
-         */
-        factory = successTable.get(host);
-        if (factory != null) {
-            if (proxyLog.isLoggable(Log.BRIEF)) {
-                proxyLog.log(Log.BRIEF,
-                    "previously successful factory found: " + factory);
-            }
-            return factory.createSocket(host, port);
-        }
-
-        /*
-         * Next, try a direct socket connection.  Open socket in another
-         * thread and only wait for specified timeout, in case the socket
-         * would otherwise spend minutes trying an unreachable host.
-         */
-        Socket initialSocket = null;
-        Socket fallbackSocket = null;
-        final AsyncConnector connector =
-            new AsyncConnector(initialFactory, host, port,
-                AccessController.getContext());
-                // connection must be attempted with
-                // this thread's access control context
-        IOException initialFailure = null;
-
-        try {
-            synchronized (connector) {
-
-                Thread t = java.security.AccessController.doPrivileged(
-                    new NewThreadAction(connector, "AsyncConnector", true));
-                t.start();
-
-                try {
-                    long now = System.currentTimeMillis();
-                    long deadline = now + connectTimeout;
-                    do {
-                        connector.wait(deadline - now);
-                        initialSocket = checkConnector(connector);
-                        if (initialSocket != null)
-                            break;
-                        now = System.currentTimeMillis();
-                    } while (now < deadline);
-                } catch (InterruptedException e) {
-                    throw new InterruptedIOException(
-                        "interrupted while waiting for connector");
-                }
-            }
-
-            // assume no route to host (for now) if no connection yet
-            if (initialSocket == null)
-                throw new NoRouteToHostException(
-                    "connect timed out: " + host);
-
-            proxyLog.log(Log.BRIEF, "direct socket connection successful");
-
-            return initialSocket;
-
-        } catch (UnknownHostException | NoRouteToHostException e) {
-            initialFailure = e;
-        } catch (SocketException e) {
-            if (eagerHttpFallback) {
-                initialFailure = e;
-            } else {
-                throw e;
-            }
-        } finally {
-            if (initialFailure != null) {
-
-                if (proxyLog.isLoggable(Log.BRIEF)) {
-                    proxyLog.log(Log.BRIEF,
-                        "direct socket connection failed: ", initialFailure);
-                }
-
-                // Finally, try any alternate connection mechanisms.
-                for (int i = 0; i < altFactoryList.size(); ++ i) {
-                    factory = altFactoryList.elementAt(i);
-                    if (proxyLog.isLoggable(Log.BRIEF)) {
-                        proxyLog.log(Log.BRIEF,
-                            "trying with factory: " + factory);
-                    }
-                    try (Socket testSocket =
-                            factory.createSocket(host, port)) {
-                        // For HTTP connections, the output (POST request) must
-                        // be sent before we verify a successful connection.
-                        // So, sacrifice a socket for the sake of testing...
-                        // The following sequence should verify a successful
-                        // HTTP connection if no IOException is thrown.
-                        InputStream in = testSocket.getInputStream();
-                        int b = in.read(); // probably -1 for EOF...
-                    } catch (IOException ex) {
-                        if (proxyLog.isLoggable(Log.BRIEF)) {
-                            proxyLog.log(Log.BRIEF, "factory failed: ", ex);
-                        }
-
-                        continue;
-                    }
-                    proxyLog.log(Log.BRIEF, "factory succeeded");
-
-                    // factory succeeded, open new socket for caller's use
-                    try {
-                        fallbackSocket = factory.createSocket(host, port);
-                    } catch (IOException ex) {  // if it fails 2nd time,
-                    }                           // just give up
-                    break;
-                }
-            }
-        }
-
-        synchronized (successTable) {
-            try {
-                // check once again to see if direct connection succeeded
-                synchronized (connector) {
-                    initialSocket = checkConnector(connector);
-                }
-                if (initialSocket != null) {
-                    // if we had made another one as well, clean it up...
-                    if (fallbackSocket != null)
-                        fallbackSocket.close();
-                    return initialSocket;
-                }
-                // if connector ever does get socket, it won't be used
-                connector.notUsed();
-            } catch (UnknownHostException | NoRouteToHostException e) {
-                initialFailure = e;
-            } catch (SocketException e) {
-                if (eagerHttpFallback) {
-                    initialFailure = e;
-                } else {
-                    throw e;
-                }
-            }
-            // if we had found an alternate mechanism, go and use it
-            if (fallbackSocket != null) {
-                // remember this successful host/factory pair
-                rememberFactory(host, factory);
-                return fallbackSocket;
-            }
-            throw initialFailure;
-        }
-    }
-
-    /**
-     * Remember a successful factory for connecting to host.
-     * Currently, excess hosts are removed from the remembered list
-     * using a Least Recently Created strategy.
-     */
-    void rememberFactory(String host, RMISocketFactory factory) {
-        synchronized (successTable) {
-            while (hostList.size() >= MaxRememberedHosts) {
-                successTable.remove(hostList.elementAt(0));
-                hostList.removeElementAt(0);
-            }
-            hostList.addElement(host);
-            successTable.put(host, factory);
-        }
-    }
-
-    /**
-     * Check if an AsyncConnector succeeded.  If not, return socket
-     * given to fall back to.
-     */
-    Socket checkConnector(AsyncConnector connector)
-        throws IOException
-    {
-        Exception e = connector.getException();
-        if (e != null) {
-            e.fillInStackTrace();
-            /*
-             * The AsyncConnector implementation guaranteed that the exception
-             * will be either an IOException or a RuntimeException, and we can
-             * only throw one of those, so convince that compiler that it must
-             * be one of those.
-             */
-            if (e instanceof IOException) {
-                throw (IOException) e;
-            } else if (e instanceof RuntimeException) {
-                throw (RuntimeException) e;
-            } else {
-                throw new Error("internal error: " +
-                    "unexpected checked exception: " + e.toString());
-            }
-        }
-        return connector.getSocket();
-    }
-
-    /**
-     * Create a new server socket.
-     */
-    public ServerSocket createServerSocket(int port) throws IOException {
-        //return new HttpAwareServerSocket(port);
-        return initialFactory.createServerSocket(port);
-    }
-
-
-    /**
-     * AsyncConnector is used by RMIMasterSocketFactory to attempt socket
-     * connections on a separate thread.  This allows RMIMasterSocketFactory
-     * to control how long it will wait for the connection to succeed.
-     */
-    private class AsyncConnector implements Runnable {
-
-        /** what factory to use to attempt connection */
-        private RMISocketFactory factory;
-
-        /** the host to connect to */
-        private String host;
-
-        /** the port to connect to */
-        private int port;
-
-        /** access control context to attempt connection within */
-        private AccessControlContext acc;
-
-        /** exception that occurred during connection, if any */
-        private Exception exception = null;
-
-        /** the connected socket, if successful */
-        private Socket socket = null;
-
-        /** socket should be closed after created, if ever */
-        private boolean cleanUp = false;
-
-        /**
-         * Create a new asynchronous connector object.
-         */
-        AsyncConnector(RMISocketFactory factory, String host, int port,
-                       AccessControlContext acc)
-        {
-            this.factory = factory;
-            this.host    = host;
-            this.port    = port;
-            this.acc     = acc;
-            SecurityManager security = System.getSecurityManager();
-            if (security != null) {
-                security.checkConnect(host, port);
-            }
-        }
-
-        /**
-         * Attempt socket connection in separate thread.  If successful,
-         * notify master waiting,
-         */
-        public void run() {
-            try {
-                /*
-                 * Using the privileges of the thread that wants to make the
-                 * connection is tempting, but it will fail with applets with
-                 * the current applet security manager because the applet
-                 * network connection policy is not captured in the permission
-                 * framework of the access control context we have.
-                 *
-                 * java.security.AccessController.beginPrivileged(acc);
-                 */
-                try {
-                    Socket temp = factory.createSocket(host, port);
-                    synchronized (this) {
-                        socket = temp;
-                        notify();
-                    }
-                    rememberFactory(host, factory);
-                    synchronized (this) {
-                        if (cleanUp)
-                          try {
-                              socket.close();
-                          } catch (IOException e) {
-                          }
-                    }
-                } catch (Exception e) {
-                    /*
-                     * Note that the only exceptions which could actually have
-                     * occurred here are IOException or RuntimeException.
-                     */
-                    synchronized (this) {
-                        exception = e;
-                        notify();
-                    }
-                }
-            } finally {
-                /*
-                 * See above comments for matching beginPrivileged() call that
-                 * is also commented out.
-                 *
-                 * java.security.AccessController.endPrivileged();
-                 */
-            }
-        }
-
-        /**
-         * Get exception that occurred during connection attempt, if any.
-         * In the current implementation, this is guaranteed to be either
-         * an IOException or a RuntimeException.
-         */
-        private synchronized Exception getException() {
-            return exception;
-        }
-
-        /**
-         * Get successful socket, if any.
-         */
-        private synchronized Socket getSocket() {
-            return socket;
-        }
-
-        /**
-         * Note that this connector's socket, if ever successfully created,
-         * will not be used, so it should be cleaned up quickly
-         */
-        synchronized void notUsed() {
-            if (socket != null) {
-                try {
-                    socket.close();
-                } catch (IOException e) {
-                }
-            }
-            cleanUp = true;
-        }
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 1996, 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.rmi.transport.proxy;
-
-/**
- * RMISocketInfo is an interface that extensions of the java.net.Socket
- * class may use to provide more information on its capabilities.
- */
-public interface RMISocketInfo {
-
-    /**
-     * Return true if this socket can be used for more than one
-     * RMI call.  If a socket does not implement this interface, then
-     * it is assumed to be reusable.
-     */
-    public boolean isReusable();
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.rmi.transport.proxy;
-
-import java.io.*;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.SocketException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-/**
- * The WrappedSocket class provides a general wrapper for providing an
- * extended implementation of java.net.Socket that can be attached to
- * a pre-existing Socket object.  WrappedSocket itself provides a
- * constructor for specifying alternate input or output streams to be
- * returned than those of the underlying Socket.
- */
-class WrappedSocket extends Socket {
-
-    /** the underlying concrete socket */
-    protected Socket socket;
-
-    /** the input stream to return for socket */
-    protected InputStream in = null;
-
-    /** the output stream to return for socket */
-    protected OutputStream out = null;
-
-    /**
-     * Layer on top of a pre-existing Socket object, and use specified
-     * input and output streams.  This allows the creator of the
-     * underlying socket to peek at the beginning of the input with a
-     * BufferedInputStream and determine which kind of socket
-     * to create, without consuming the input.
-     * @param socket the pre-existing socket to use
-     * @param in the InputStream to return to users (can be null)
-     * @param out the OutputStream to return to users (can be null)
-     */
-    public WrappedSocket(Socket socket, InputStream in, OutputStream out)
-        throws IOException
-    {
-        super((java.net.SocketImpl)null);       // no underlying SocketImpl for this object
-        this.socket = socket;
-        this.in = in;
-        this.out = out;
-    }
-
-    /**
-     * Get the address to which the socket is connected.
-     */
-    public InetAddress getInetAddress()
-    {
-        return socket.getInetAddress();
-    }
-
-    /**
-     * Get the local address to which the socket is bound.
-     */
-    public InetAddress getLocalAddress() {
-        return  AccessController.doPrivileged(
-                        new PrivilegedAction<InetAddress>() {
-                            @Override
-                            public InetAddress run() {
-                                return socket.getLocalAddress();
-
-                            }
-                        });
-    }
-
-    /**
-     * Get the remote port to which the socket is connected.
-     */
-    public int getPort()
-    {
-        return socket.getPort();
-    }
-
-    /**
-     * Get the local port to which the socket is connected.
-     */
-    public int getLocalPort()
-    {
-        return socket.getLocalPort();
-    }
-
-    /**
-     * Get an InputStream for this socket.
-     */
-    public InputStream getInputStream() throws IOException
-    {
-        if (in == null)
-            in = socket.getInputStream();
-        return in;
-    }
-
-    /**
-     * Get an OutputStream for this socket.
-     */
-    public OutputStream getOutputStream() throws IOException
-    {
-        if (out == null)
-            out = socket.getOutputStream();
-        return out;
-    }
-
-    /**
-     * Enable/disable TCP_NODELAY.
-     */
-    public void setTcpNoDelay(boolean on) throws SocketException
-    {
-        socket.setTcpNoDelay(on);
-    }
-
-    /**
-     * Retrieve whether TCP_NODELAY is enabled.
-     */
-    public boolean getTcpNoDelay() throws SocketException
-    {
-        return socket.getTcpNoDelay();
-    }
-
-    /**
-     * Enable/disable SO_LINGER with the specified linger time.
-     */
-    public void setSoLinger(boolean on, int val) throws SocketException
-    {
-        socket.setSoLinger(on, val);
-    }
-
-    /**
-     * Retrive setting for SO_LINGER.
-     */
-    public int getSoLinger() throws SocketException
-    {
-        return socket.getSoLinger();
-    }
-
-    /**
-     * Enable/disable SO_TIMEOUT with the specified timeout
-     */
-    public synchronized void setSoTimeout(int timeout) throws SocketException
-    {
-        socket.setSoTimeout(timeout);
-    }
-
-    /**
-     * Retrive setting for SO_TIMEOUT.
-     */
-    public synchronized int getSoTimeout() throws SocketException
-    {
-        return socket.getSoTimeout();
-    }
-
-    /**
-     * Close the socket.
-     */
-    public synchronized void close() throws IOException
-    {
-        socket.close();
-    }
-
-    /**
-     * Return string representation of the socket.
-     */
-    public String toString()
-    {
-        return "Wrapped" + socket.toString();
-    }
-}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2001, 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
@@ -26,14 +26,10 @@
 package sun.rmi.transport.tcp;
 
 import java.io.*;
-import java.net.InetAddress;
 import java.net.Socket;
-import java.net.SocketException;
 import java.rmi.*;
-import java.rmi.server.RMISocketFactory;
 import sun.rmi.runtime.Log;
 import sun.rmi.transport.*;
-import sun.rmi.transport.proxy.*;
 
 public class TCPConnection implements Connection {
 
@@ -120,10 +116,7 @@
      */
     public boolean isReusable()
     {
-        if ((socket != null) && (socket instanceof RMISocketInfo))
-            return ((RMISocketInfo) socket).isReusable();
-        else
-            return true;
+        return true;
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1996, 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.rmi.transport.tcp;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.ServerSocket;
+import java.rmi.server.RMISocketFactory;
+
+/**
+ * RMIDirectSocketFactory creates a direct socket connection to the
+ * specified port on the specified host.
+ */
+public class TCPDirectSocketFactory extends RMISocketFactory {
+
+    public Socket createSocket(String host, int port) throws IOException
+    {
+        return new Socket(host, port);
+    }
+
+    public ServerSocket createServerSocket(int port) throws IOException
+    {
+        return new ServerSocket(port);
+    }
+}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, 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
@@ -75,7 +75,6 @@
 import sun.rmi.transport.Target;
 import sun.rmi.transport.Transport;
 import sun.rmi.transport.TransportConstants;
-import sun.rmi.transport.proxy.HttpReceiveSocket;
 
 /**
  * TCPTransport is the socket-based implementation of the RMI Transport
@@ -711,35 +710,10 @@
                         ? sockIn
                         : new BufferedInputStream(sockIn);
 
-                // Read magic (or HTTP wrapper)
-                bufIn.mark(4);
+                // Read magic
                 DataInputStream in = new DataInputStream(bufIn);
                 int magic = in.readInt();
 
-                if (magic == POST) {
-                    tcpLog.log(Log.BRIEF, "decoding HTTP-wrapped call");
-
-                    // It's really a HTTP-wrapped request.  Repackage
-                    // the socket in a HttpReceiveSocket, reinitialize
-                    // sockIn and in, and reread magic.
-                    bufIn.reset();      // unread "POST"
-
-                    try {
-                        socket = new HttpReceiveSocket(socket, bufIn, null);
-                        remoteHost = "0.0.0.0";
-                        sockIn = socket.getInputStream();
-                        bufIn = new BufferedInputStream(sockIn);
-                        in = new DataInputStream(bufIn);
-                        magic = in.readInt();
-
-                    } catch (IOException e) {
-                        throw new RemoteException("Error HTTP-unwrapping call",
-                                                  e);
-                    }
-                }
-                // bufIn's mark will invalidate itself when it overflows
-                // so it doesn't have to be turned off
-
                 // read and verify transport header
                 short version = in.readShort();
                 if (magic != TransportConstants.Magic ||
--- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/EncryptionKey.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/EncryptionKey.java	Wed Jul 05 21:42:16 2017 +0200
@@ -61,7 +61,7 @@
     private transient boolean destroyed = false;
 
     /**
-     * Constructs a {@code EncryptionKey} from the given bytes and
+     * Constructs an {@code EncryptionKey} from the given bytes and
      * the key type.
      * <p>
      * The contents of the byte array are copied; subsequent modification of
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/JdbcRowSetImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/JdbcRowSetImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -3799,7 +3799,7 @@
      * Retrieves the column id as {@code int} array that was set using
      * {@code setMatchColumn(int [])} for this rowset.
      *
-     * @return a {@code int} array object that contains the column ids
+     * @return an {@code int} array object that contains the column ids
      *         for the rowset which has this as the match columns.
      *
      * @throws SQLException if an error occurs or column index is not set
@@ -6226,7 +6226,7 @@
 
 
    /**
-    * Sets the designated parameter to a {@code InputStream} object.  The inputstream must contain  the number
+    * Sets the designated parameter to an {@code InputStream} object.  The inputstream must contain  the number
     * of characters specified by length otherwise a {@code SQLException} will be
     * generated when the {@code PreparedStatement} is executed.
     * This method differs from the {@code setBinaryStream (int, InputStream, int)}
@@ -6256,7 +6256,7 @@
    }
 
  /**
-    * Sets the designated parameter to a {@code InputStream} object.
+    * Sets the designated parameter to an {@code InputStream} object.
     * This method differs from the {@code setBinaryStream (int, InputStream)}
     * This method differs from the {@code setBinaryStream (int, InputStream)}
     * method because it informs the driver that the parameter value should be
@@ -6287,7 +6287,7 @@
    }
 
    /**
-    * Sets the designated parameter to a {@code InputStream} object.  The {@code inputstream} must contain  the number
+    * Sets the designated parameter to an {@code InputStream} object.  The {@code inputstream} must contain  the number
     * of characters specified by length, otherwise a {@code SQLException} will be
     * generated when the {@code CallableStatement} is executed.
     * This method differs from the {@code setBinaryStream (int, InputStream, int)}
@@ -6336,7 +6336,7 @@
    }
 
    /**
-    * Sets the designated parameter to a {@code InputStream} object.
+    * Sets the designated parameter to an {@code InputStream} object.
     * This method differs from the {@code setBinaryStream (int, InputStream)}
     * method because it informs the driver that the parameter value should be
     * sent to the server as a {@code BLOB}.  When the {@code setBinaryStream} method is used,
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/SyncResolverImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/SyncResolverImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -4586,7 +4586,7 @@
      * Retrieves the column id as {@code int} array that was set using
      * {@code setMatchColumn(int [])} for this rowset.
      *
-     * @return a {@code int} array object that contains the column ids
+     * @return an {@code int} array object that contains the column ids
      *         for the rowset which has this as the match columns.
      *
      * @throws SQLException if an error occurs or column index is not set
--- a/jdk/src/java.sql/share/classes/java/sql/CallableStatement.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.sql/share/classes/java/sql/CallableStatement.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1882,7 +1882,7 @@
        throws SQLException;
 
     /**
-     * Sets the designated parameter to a {@code InputStream} object.
+     * Sets the designated parameter to an {@code InputStream} object.
      * The <code>Inputstream</code> must contain the number
      * of characters specified by length, otherwise a <code>SQLException</code> will be
      * generated when the <code>CallableStatement</code> is executed.
@@ -2379,7 +2379,7 @@
        throws SQLException;
 
     /**
-     * Sets the designated parameter to a {@code InputStream} object.
+     * Sets the designated parameter to an {@code InputStream} object.
      * This method differs from the <code>setBinaryStream (int, InputStream)</code>
      * method because it informs the driver that the parameter value should be
      * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/encryption/AgreementMethod.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/encryption/AgreementMethod.java	Wed Jul 05 21:42:16 2017 +0200
@@ -101,7 +101,7 @@
     /**
      * Adds additional {@code AgreementMethod} information.
      *
-     * @param info a {@code Element} that represents additional information
+     * @param info an {@code Element} that represents additional information
      * specified by
      *   <pre>{@code
      *     <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
@@ -112,7 +112,7 @@
     /**
      * Removes additional {@code AgreementMethod} information.
      *
-     * @param info a {@code Element} that represents additional information
+     * @param info an {@code Element} that represents additional information
      * specified by
      *   <pre>{@code
      *     <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/LibMDMech.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+/**
+ * Enum for representing the ucrypto mechanisms.
+ *
+ * @since 9
+ */
+public enum LibMDMech {
+
+    MD5(new ServiceDesc[]
+        { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigestMD$MD5")
+        }),
+    SHA_1(new ServiceDesc[]
+        { sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigestMD$SHA1",
+             "SHA-1", "SHA1")
+        }),
+    SHA_256(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigestMD$SHA256",
+             "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1")
+        }),
+    SHA_384(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigestMD$SHA384",
+             "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2")
+        }),
+    SHA_512(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigestMD$SHA512",
+             "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3")
+        });
+
+    ServiceDesc[] serviceDescs;
+
+    private static ServiceDesc sd(String type, String algo, String cn, String... aliases) {
+        return new ServiceDesc(type, algo, cn, aliases);
+    }
+
+    LibMDMech(ServiceDesc[] serviceDescs) {
+        this.serviceDescs = serviceDescs;
+    }
+
+    public ServiceDesc[] getServiceDescriptions() { return serviceDescs; }
+}
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,23 +33,67 @@
 import java.security.*;
 
 /**
- * MessageDigest implementation class. This class currently supports
- * MD5, SHA1, SHA256, SHA384, and SHA512
+ * MessageDigest implementation class using native Ucrypto API.
+ * This class currently supports: MD5, SHA-2 (224, 256, 384, 512)
+ * and SHA-3 (224, 256, 384, 512) digests
  *
  * @since 9
  */
-public abstract class NativeDigest extends MessageDigestSpi
-        implements Cloneable {
+abstract class NativeDigest extends MessageDigestSpi {
 
-    private static final int MECH_MD5 = 1;
-    private static final int MECH_SHA1 = 2;
-    private static final int MECH_SHA256 = 3;
-    private static final int MECH_SHA224 = 4;
-    private static final int MECH_SHA384 = 5;
-    private static final int MECH_SHA512 = 6;
+    public static final class MD5 extends NativeDigest {
+        public MD5() {
+            super(UcryptoMech.CRYPTO_MD5, 16);
+        }
+    }
+    public static final class SHA1 extends NativeDigest {
+        public SHA1() {
+            super(UcryptoMech.CRYPTO_SHA1, 20);
+        }
+    }
+    public static final class SHA224 extends NativeDigest {
+        public SHA224() {
+            super(UcryptoMech.CRYPTO_SHA224, 28);
+        }
+    }
+    public static final class SHA256 extends NativeDigest {
+        public SHA256() {
+            super(UcryptoMech.CRYPTO_SHA256, 32);
+        }
+    }
+    public static final class SHA384 extends NativeDigest {
+        public SHA384() {
+            super(UcryptoMech.CRYPTO_SHA384, 48);
+        }
+    }
+    public static final class SHA512 extends NativeDigest {
+        public SHA512() {
+            super(UcryptoMech.CRYPTO_SHA512, 64);
+        }
+    }
+    public static final class SHA3_224 extends NativeDigest {
+        public SHA3_224() {
+            super(UcryptoMech.CRYPTO_SHA3_224, 28);
+        }
+    }
+    public static final class SHA3_256 extends NativeDigest {
+        public SHA3_256() {
+            super(UcryptoMech.CRYPTO_SHA3_256, 32);
+        }
+    }
+    public static final class SHA3_384 extends NativeDigest {
+        public SHA3_384() {
+            super(UcryptoMech.CRYPTO_SHA3_384, 48);
+        }
+    }
+    public static final class SHA3_512 extends NativeDigest {
+        public SHA3_512() {
+            super(UcryptoMech.CRYPTO_SHA3_512, 64);
+        }
+    }
 
     private final int digestLen;
-    private final int mech;
+    private final UcryptoMech mech;
 
     // field for ensuring native memory is freed
     private DigestContextRef pCtxt = null;
@@ -64,10 +108,9 @@
         // referents are GC'ed so we can do post-mortem processing
         private static Set<DigestContextRef> refList =
             new ConcurrentSkipListSet<DigestContextRef>();
-            //            Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>());
 
         private final long id;
-        private final int mech;
+        private final UcryptoMech mech;
 
         private static void drainRefQueueBounded() {
             while (true) {
@@ -77,7 +120,7 @@
             }
         }
 
-        DigestContextRef(NativeDigest nc, long id, int mech) {
+        DigestContextRef(NativeDigest nc, long id, UcryptoMech mech) {
             super(nc, refQueue);
             this.id = id;
             this.mech = mech;
@@ -98,18 +141,22 @@
             refList.remove(this);
             try {
                 if (needFree) {
-                    UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id);
-                    NativeDigest.nativeFree(mech, id);
-                } else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id);
+                    UcryptoProvider.debug("Resource: free Digest Ctxt " +
+                        this.id);
+                    NativeDigest.nativeFree(mech.value(), id);
+                } else {
+                    UcryptoProvider.debug("Resource: discard Digest Ctxt " +
+                        this.id);
+                }
             } finally {
                 this.clear();
             }
         }
     }
 
-    NativeDigest(int mech, int digestLen) {
+    NativeDigest(UcryptoMech mech, int digestLen) {
+        this.mech = mech;
         this.digestLen = digestLen;
-        this.mech = mech;
     }
 
     // see JCA spec
@@ -153,10 +200,10 @@
         }
 
         if (pCtxt == null) {
-            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+            pCtxt = new DigestContextRef(this, nativeInit(mech.value()), mech);
         }
         try {
-            int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen);
+            int status = nativeDigest(mech.value(), pCtxt.id, out, ofs, digestLen);
             if (status != 0) {
                 throw new DigestException("Internal error: " + status);
             }
@@ -183,64 +230,24 @@
                 + len + ". in.length: " + in.length);
         }
         if (pCtxt == null) {
-            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+            pCtxt = new DigestContextRef(this, nativeInit(mech.value()), mech);
         }
-        nativeUpdate(mech, pCtxt.id, in, ofs, len);
+        nativeUpdate(mech.value(), pCtxt.id, in, ofs, len);
     }
 
     /**
      * Clone this digest.
      */
     public synchronized Object clone() throws CloneNotSupportedException {
-        NativeDigest copy = (NativeDigest) super.clone();
-        // re-work the fields that cannot be copied over
-        if (pCtxt != null) {
-            copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech);
-        }
-        return copy;
+        throw new CloneNotSupportedException("Clone is not supported");
     }
 
     // return pointer to the context
-    protected static native long nativeInit(int mech);
-    // return status code; always 0
-    protected static native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
+    protected static final native long nativeInit(int mech);
     // 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 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);
     // free the specified context
-    private native static void nativeFree(int mech, long id);
-
-
-    public static final class MD5 extends NativeDigest {
-        public MD5() {
-            super(MECH_MD5, 16);
-        }
-    }
-
-    public static final class SHA1 extends NativeDigest {
-        public SHA1() {
-            super(MECH_SHA1, 20);
-        }
-    }
-
-    public static final class SHA256 extends NativeDigest {
-        public SHA256() {
-            super(MECH_SHA256, 32);
-        }
-    }
-
-
-    public static final class SHA384 extends NativeDigest {
-        public SHA384() {
-            super(MECH_SHA384, 48);
-        }
-    }
-
-
-    public static final class SHA512 extends NativeDigest {
-        public SHA512() {
-            super(MECH_SHA512, 64);
-        }
-    }
+    private static final native void nativeFree(int mech, long id);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigestMD.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.lang.ref.*;
+
+import java.io.ByteArrayOutputStream;
+import java.util.*;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.security.*;
+
+/**
+ * MessageDigest implementation class for libMD API. This class currently supports
+ * MD5, SHA1, SHA256, SHA384, and SHA512
+ *
+ * @since 9
+ */
+public abstract class NativeDigestMD extends MessageDigestSpi
+        implements Cloneable {
+
+    private static final int MECH_MD5 = 1;
+    private static final int MECH_SHA1 = 2;
+    private static final int MECH_SHA256 = 3;
+    private static final int MECH_SHA224 = 4;
+    private static final int MECH_SHA384 = 5;
+    private static final int MECH_SHA512 = 6;
+
+    private final int digestLen;
+    private final int mech;
+
+    // field for ensuring native memory is freed
+    private DigestContextRef pCtxt = null;
+
+    private static class DigestContextRef extends PhantomReference<NativeDigestMD>
+        implements Comparable<DigestContextRef> {
+
+        private static ReferenceQueue<NativeDigestMD> refQueue =
+            new ReferenceQueue<NativeDigestMD>();
+
+        // Needed to keep these references from being GC'ed until when their
+        // referents are GC'ed so we can do post-mortem processing
+        private static Set<DigestContextRef> refList =
+            new ConcurrentSkipListSet<DigestContextRef>();
+            //            Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>());
+
+        private final long id;
+        private final int mech;
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                DigestContextRef next = (DigestContextRef) refQueue.poll();
+                if (next == null) break;
+                next.dispose(true);
+            }
+        }
+
+        DigestContextRef(NativeDigestMD nc, long id, int mech) {
+            super(nc, refQueue);
+            this.id = id;
+            this.mech = mech;
+            refList.add(this);
+            UcryptoProvider.debug("Resource: track Digest Ctxt " + this.id);
+            drainRefQueueBounded();
+        }
+
+        public int compareTo(DigestContextRef other) {
+            if (this.id == other.id) {
+                return 0;
+            } else {
+                return (this.id < other.id) ? -1 : 1;
+            }
+        }
+
+        void dispose(boolean needFree) {
+            refList.remove(this);
+            try {
+                if (needFree) {
+                    UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id);
+                    NativeDigestMD.nativeFree(mech, id);
+                } else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id);
+            } finally {
+                this.clear();
+            }
+        }
+    }
+
+    NativeDigestMD(int mech, int digestLen) {
+        this.digestLen = digestLen;
+        this.mech = mech;
+    }
+
+    // see JCA spec
+    protected int engineGetDigestLength() {
+        return digestLen;
+    }
+
+    // see JCA spec
+    protected synchronized void engineReset() {
+        if (pCtxt != null) {
+            pCtxt.dispose(true);
+            pCtxt = null;
+        }
+    }
+
+    // see JCA spec
+    protected synchronized byte[] engineDigest() {
+        byte[] digest = new byte[digestLen];
+        try {
+            int len = engineDigest(digest, 0, digestLen);
+            if (len != digestLen) {
+                throw new UcryptoException("Digest length mismatch." +
+                    " Len: " + len + ". digestLen: " + digestLen);
+            }
+            return digest;
+        } catch (DigestException de) {
+            throw new UcryptoException("Internal error", de);
+        }
+    }
+
+    // see JCA spec
+    protected synchronized int engineDigest(byte[] out, int ofs, int len)
+            throws DigestException {
+        if (len < digestLen) {
+            throw new DigestException("Output buffer must be at least " +
+                          digestLen + " bytes long. Got: " + len);
+        }
+        if ((ofs < 0) || (len < 0) || (ofs > out.length - len)) {
+            throw new DigestException("Buffer too short to store digest. " +
+                "ofs: " + ofs + ". len: " + len + ". out.length: " + out.length);
+        }
+
+        if (pCtxt == null) {
+            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+        }
+        try {
+            int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen);
+            if (status != 0) {
+                throw new DigestException("Internal error: " + status);
+            }
+        } finally {
+            pCtxt.dispose(false);
+            pCtxt = null;
+        }
+        return digestLen;
+    }
+
+    // see JCA spec
+    protected synchronized void engineUpdate(byte in) {
+        byte[] temp = { in };
+        engineUpdate(temp, 0, 1);
+    }
+
+    // see JCA spec
+    protected synchronized void engineUpdate(byte[] in, int ofs, int len) {
+        if (len == 0) {
+            return;
+        }
+        if ((ofs < 0) || (len < 0) || (ofs > in.length - len)) {
+            throw new ArrayIndexOutOfBoundsException("ofs: " + ofs + ". len: "
+                + len + ". in.length: " + in.length);
+        }
+        if (pCtxt == null) {
+            pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+        }
+        nativeUpdate(mech, pCtxt.id, in, ofs, len);
+    }
+
+    /**
+     * Clone this digest.
+     */
+    public synchronized Object clone() throws CloneNotSupportedException {
+        NativeDigestMD copy = (NativeDigestMD) super.clone();
+        // re-work the fields that cannot be copied over
+        if (pCtxt != null) {
+            copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech);
+        }
+        return copy;
+    }
+
+    // return pointer to the context
+    protected static final native long nativeInit(int mech);
+    // return status code; always 0
+    protected static final native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
+    // return status code; always 0
+    protected static final native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
+    // return pointer to the duplicated context
+    protected static final native long nativeClone(int mech, long pCtxt);
+    // free the specified context
+    private static final native void nativeFree(int mech, long id);
+
+
+    public static final class MD5 extends NativeDigestMD {
+        public MD5() {
+            super(MECH_MD5, 16);
+        }
+    }
+
+    public static final class SHA1 extends NativeDigestMD {
+        public SHA1() {
+            super(MECH_SHA1, 20);
+        }
+    }
+
+    public static final class SHA256 extends NativeDigestMD {
+        public SHA256() {
+            super(MECH_SHA256, 32);
+        }
+    }
+
+
+    public static final class SHA384 extends NativeDigestMD {
+        public SHA384() {
+            super(MECH_SHA384, 48);
+        }
+    }
+
+
+    public static final class SHA512 extends NativeDigestMD {
+        public SHA512() {
+            super(MECH_SHA512, 64);
+        }
+    }
+}
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
 
 package com.oracle.security.ucrypto;
 
-import java.util.HashMap;
-
 /**
  * Enum for representing the ucrypto mechanisms.
  *
@@ -35,78 +33,126 @@
 // Check /usr/include/libsoftcrypto.h for updates
 public enum UcryptoMech {
 
-    CRYPTO_AES_ECB(1, new ServiceDesc[]
+    CRYPTO_AES_ECB(new ServiceDesc[]
         { sd("Cipher", "AES/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding"),
           sd("Cipher", "AES/ECB/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesEcbPKCS5",
              "AES"),
-          sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes128EcbNoPadding",
+          sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
              "2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"),
-          sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes192EcbNoPadding",
+          sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
              "2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"),
-          sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes256EcbNoPadding",
+          sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
              "2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41")
         }),
-    CRYPTO_AES_CBC(2, new ServiceDesc[]
+    CRYPTO_AES_CBC(new ServiceDesc[]
         { sd("Cipher", "AES/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding"),
           sd("Cipher", "AES/CBC/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCbcPKCS5"),
-          sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes128CbcNoPadding",
+          sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
              "2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"),
-          sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes192CbcNoPadding",
+          sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
              "2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"),
-          sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes256CbcNoPadding",
+          sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
              "2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42")
         }),
-    CRYPTO_AES_CBC_PAD(3, null), // No support from Solaris yet
-    CRYPTO_AES_CTR(4, new ServiceDesc[]
+//  CRYPTO_AES_CBC_PAD(null), // Support added since S11.1; however we still use CRYPTO_AES_CBC due to known bug
+    CRYPTO_AES_CTR(new ServiceDesc[]
         { sd("Cipher", "AES/CTR/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCtrNoPadding") }),
-    CRYPTO_AES_CCM(5, null), // Cannot support due to lack of Java API which corresponds to CK_AES_CCM_PARAMS
-    CRYPTO_AES_GCM(6, new ServiceDesc[]
+//  CRYPTO_AES_CCM(null), // Need Java API for CK_AES_CCM_PARAMS
+    CRYPTO_AES_GCM(new ServiceDesc[]
         { sd("Cipher", "AES/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding"),
-          sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes128GcmNoPadding",
+          sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
              "2.16.840.1.101.3.4.1.6", "OID.2.16.840.1.101.3.4.1.6"),
-          sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes192GcmNoPadding",
+          sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
              "2.16.840.1.101.3.4.1.26", "OID.2.16.840.1.101.3.4.1.26"),
-          sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes256GcmNoPadding",
+          sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
              "2.16.840.1.101.3.4.1.46", "OID.2.16.840.1.101.3.4.1.46")
         }),
-    CRYPTO_AES_GMAC(7, null), // No support from Solaris yet
-    CRYPTO_AES_CFB128(8, new ServiceDesc[]
+//  CRYPTO_AES_GMAC(null), // No support from Solaris
+    CRYPTO_AES_CFB128(new ServiceDesc[]
         { sd("Cipher", "AES/CFB128/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCfb128NoPadding"),
-          sd("Cipher", "AES/CFB128/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5") }),
-    CRYPTO_RSA_PKCS(31, new ServiceDesc[]
+          sd("Cipher", "AES/CFB128/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5")
+        }),
+
+    CRYPTO_RSA_PKCS(new ServiceDesc[]
         { sd("Cipher", "RSA/ECB/PKCS1Padding", "com.oracle.security.ucrypto.NativeRSACipher$PKCS1Padding",
-             "RSA") }),
-    CRYPTO_RSA_X_509(32, new ServiceDesc[]
+             "RSA")
+        }),
+    CRYPTO_RSA_X_509(new ServiceDesc[]
         { sd("Cipher", "RSA/ECB/NoPadding", "com.oracle.security.ucrypto.NativeRSACipher$NoPadding") }),
-    CRYPTO_MD5_RSA_PKCS(33, new ServiceDesc[]
+    CRYPTO_MD5_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "MD5withRSA", "com.oracle.security.ucrypto.NativeRSASignature$MD5",
-             "1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4") }),
-    CRYPTO_SHA1_RSA_PKCS(34, new ServiceDesc[]
+             "1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4")
+        }),
+    CRYPTO_SHA1_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA1withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA1",
              "1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5",
-             "1.3.14.3.2.29") }),
-    CRYPTO_SHA256_RSA_PKCS(35, new ServiceDesc[]
+             "1.3.14.3.2.29")
+        }),
+    CRYPTO_SHA256_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA256withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA256",
-             "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11") }),
-    CRYPTO_SHA384_RSA_PKCS(36, new ServiceDesc[]
+             "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11")
+        }),
+    CRYPTO_SHA384_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA384withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA384",
-             "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12") }),
-    CRYPTO_SHA512_RSA_PKCS(37, new ServiceDesc[]
+             "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12")
+        }),
+    CRYPTO_SHA512_RSA_PKCS(new ServiceDesc[]
         { sd("Signature", "SHA512withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA512",
-             "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13") });
+             "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13")
+        }),
 
-    private final int mech;
+    CRYPTO_MD5(new ServiceDesc[]
+        { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigest$MD5") }),
+    CRYPTO_SHA1(new ServiceDesc[]
+        { sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigest$SHA1", "SHA-1", "SHA1") }),
+    CRYPTO_SHA224(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-224", "com.oracle.security.ucrypto.NativeDigest$SHA224",
+             "2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4")
+    }),
+    CRYPTO_SHA256(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigest$SHA256",
+             "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1")
+    }),
+    CRYPTO_SHA384(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigest$SHA384",
+             "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2")
+    }),
+    CRYPTO_SHA512(new ServiceDesc[]
+        { sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigest$SHA512",
+             "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3")
+    }),
+    CRYPTO_SHA3_224(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-224", "com.oracle.security.ucrypto.NativeDigest$SHA3_224",
+             "2.16.840.1.101.3.4.2.7", "OID.2.16.840.1.101.3.4.2.7")
+    }),
+    CRYPTO_SHA3_256(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-256", "com.oracle.security.ucrypto.NativeDigest$SHA3_256",
+             "2.16.840.1.101.3.4.2.8", "OID.2.16.840.1.101.3.4.2.8")
+    }),
+    CRYPTO_SHA3_384(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-384", "com.oracle.security.ucrypto.NativeDigest$SHA3_384",
+             "2.16.840.1.101.3.4.2.9", "OID.2.16.840.1.101.3.4.2.9")
+    }),
+    CRYPTO_SHA3_512(new ServiceDesc[]
+        { sd("MessageDigest", "SHA3-512", "com.oracle.security.ucrypto.NativeDigest$SHA3_512",
+             "2.16.840.1.101.3.4.2.10", "OID.2.16.840.1.101.3.4.2.10")
+    });
+
+    private int mech = 0;
     private final ServiceDesc[] serviceDescs;
 
     private static ServiceDesc sd(String type, String algo, String cn, String... aliases) {
         return new ServiceDesc(type, algo, cn, aliases);
     }
 
-    UcryptoMech(int mech, ServiceDesc[] serviceDescs) {
-        this.mech = mech;
+    UcryptoMech(ServiceDesc[] serviceDescs) {
         this.serviceDescs = serviceDescs;
     }
 
+    public void setValue(int nativeMechValue) {
+        this.mech = nativeMechValue;
+    }
+
     public int value() { return mech; }
     public ServiceDesc[] getServiceDescriptions() { return serviceDescs; }
 }
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 
 import java.io.IOException;
 import java.io.File;
+import java.lang.reflect.Constructor;
 import java.util.*;
 import java.security.*;
 
@@ -74,48 +75,52 @@
             if (provProp != null) {
                 boolean[] result = loadLibraries();
                 if (result.length == 2) {
-                    if (result[0]) { // successfully loaded libmd
-                        provProp.put("MessageDigest.MD5",
-                            sd("MessageDigest", "MD5",
-                               "com.oracle.security.ucrypto.NativeDigest$MD5"));
-                        provProp.put("MessageDigest.SHA",
-                            sd("MessageDigest", "SHA",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA1",
-                               "SHA-1", "SHA1"));
-                        provProp.put("MessageDigest.SHA-256",
-                            sd("MessageDigest", "SHA-256",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA256",
-                               "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"));
-
-                        provProp.put("MessageDigest.SHA-384",
-                            sd("MessageDigest", "SHA-384",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA384",
-                               "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"));
-
-                        provProp.put("MessageDigest.SHA-512",
-                            sd("MessageDigest", "SHA-512",
-                               "com.oracle.security.ucrypto.NativeDigest$SHA512",
-                               "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"));
-                    };
-                    if (result[1]) { // successfully loaded libsoftcrypto
+                    // true when libsoftcrypto or libucrypto(S12) has been successfully loaded
+                    if (result[1]) {
                         String supportedMechs = getMechList();
                         debug("Prov: supported mechs = " + supportedMechs);
-                        for (UcryptoMech m : UcryptoMech.values()) {
-                            if (supportedMechs.indexOf(m.name() + ",") != -1) {
+                        StringTokenizer st = new StringTokenizer(supportedMechs, ":,;");
+                        // format: numOfSupportedMechs:[mechName,mechValue;]+
+                        // skip the first one which is numberOfSupportedMechs
+                        st.nextToken();
+                        while (st.hasMoreTokens()) {
+                            String mechName = st.nextToken();
+                            int nativeMechVal = Integer.parseInt(st.nextToken());
+                            try {
+                                UcryptoMech m = Enum.valueOf(UcryptoMech.class, mechName);
+                                m.setValue(nativeMechVal);
                                 ServiceDesc[] services = m.getServiceDescriptions();
-                                // skip unsupported UcryptoMech
-                                if (services == null || services.length == 0) continue;
+                                // defined in UcryptoMech as unsupported
+                                if (services == null || services.length == 0) {
+                                    debug("Skip Unsupported Algorithm: " + mechName);
+                                    continue;
+                                }
                                 for (int p = 0; p < services.length; p++) {
                                     ServiceDesc entry = services[p];
                                     provProp.put(entry.getType() + "." + entry.getAlgorithm(),
                                                  entry);
                                 }
+                            } catch (IllegalArgumentException iae) {
+                                // not defined in UcryptoMech
+                                debug("Skip Unrecognized Algorithm: " + mechName);
                             }
                         }
                         // NOTE: GCM support is only available since jdk 7
                         provProp.put("AlgorithmParameters.GCM",
-                                     sd("AlgorithmParameters", "GCM", "com.oracle.security.ucrypto.GCMParameters"));
+                                     sd("AlgorithmParameters", "GCM",
+                                        "com.oracle.security.ucrypto.GCMParameters"));
                     }
+                    // true when libmd is needed and has been successfully loaded
+                    if (result[0]) {
+                        for (LibMDMech m : LibMDMech.values()) {
+                            ServiceDesc[] services = m.getServiceDescriptions();
+                            for (ServiceDesc entry : services) {
+                                String sKey = entry.getType() + "." + entry.getAlgorithm();
+                                //  only register if none has been registered
+                                provProp.putIfAbsent(sKey, entry);
+                            }
+                        }
+                    };
                 } else {
                     debug("Prov: unexpected ucrypto library loading error, got " + result.length);
                 }
@@ -138,6 +143,7 @@
                   sd.getAliases(), null);
         }
 
+        @SuppressWarnings("deprecation")
         @Override
         public Object newInstance(Object ctrParamObj)
             throws NoSuchAlgorithmException {
@@ -152,53 +158,19 @@
                     int keySize = -1;
                     if (algo.charAt(3) == '_') {
                         keySize = Integer.parseInt(algo.substring(4, 7))/8;
-                        algo = algo.substring(0, 3) + algo.substring(7);
-                    }
-                    if (algo.equals("AES/ECB/NoPadding")) {
-                        return new NativeCipher.AesEcbNoPadding(keySize);
-                    } else if (algo.equals("AES/ECB/PKCS5Padding")) {
-                        return new NativeCipherWithJavaPadding.AesEcbPKCS5();
-                    } else if (algo.equals("AES/CBC/NoPadding")) {
-                        return new NativeCipher.AesCbcNoPadding(keySize);
-                    } else if (algo.equals("AES/CBC/PKCS5Padding")) {
-                        return new NativeCipherWithJavaPadding.AesCbcPKCS5();
-                    } else if (algo.equals("AES/CTR/NoPadding")) {
-                        return new NativeCipher.AesCtrNoPadding();
-                    } else if (algo.equals("AES/GCM/NoPadding")) {
-                        return new NativeGCMCipher.AesGcmNoPadding(keySize);
-                    } else if (algo.equals("AES/CFB128/NoPadding")) {
-                        return new NativeCipher.AesCfb128NoPadding();
-                    } else if (algo.equals("AES/CFB128/PKCS5Padding")) {
-                        return new NativeCipherWithJavaPadding.AesCfb128PKCS5();
-                    } else if (algo.equals("RSA/ECB/NoPadding")) {
-                        return new NativeRSACipher.NoPadding();
-                    } else if (algo.equals("RSA/ECB/PKCS1Padding")) {
-                        return new NativeRSACipher.PKCS1Padding();
                     }
-                } 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();
+                    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("MessageDigest")) {
-                    if (algo.equals("SHA")) {
-                        return new NativeDigest.SHA1();
-                    } else if (algo.equals("SHA-256")) {
-                        return new NativeDigest.SHA256();
-                    } else if (algo.equals("SHA-384")) {
-                        return new NativeDigest.SHA384();
-                    } else if (algo.equals("SHA-512")) {
-                        return new NativeDigest.SHA512();
-                    } else if (algo.equals("MD5")) {
-                        return new NativeDigest.MD5();
-                    }
+                } else if (type.equals("Signature") || type.equals("MessageDigest")) {
+                    String implClass = getClassName();
+                    Class<?> clz = Class.forName(implClass);
+                    return clz.newInstance();
                 } else if (type.equals("AlgorithmParameters")) {
                     if (algo.equals("GCM")) {
                         return new GCMParameters();
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/libsoftcrypto.h	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _LIBSOFTCRYPTO_H
-#define _LIBSOFTCRYPTO_H
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <strings.h>
-
-typedef enum ucrypto_mech {
-    CRYPTO_AES_ECB = 1,
-    CRYPTO_AES_CBC,
-    CRYPTO_AES_CBC_PAD,
-    CRYPTO_AES_CTR,
-    CRYPTO_AES_CCM,
-    CRYPTO_AES_GCM,
-    CRYPTO_AES_GMAC,
-    CRYPTO_AES_CFB128,
-    CRYPTO_RSA_PKCS = 31,
-    CRYPTO_RSA_X_509,
-    CRYPTO_MD5_RSA_PKCS,
-    CRYPTO_SHA1_RSA_PKCS,
-    CRYPTO_SHA256_RSA_PKCS,
-    CRYPTO_SHA384_RSA_PKCS,
-    CRYPTO_SHA512_RSA_PKCS
-} ucrypto_mech_t;
-
-typedef struct crypto_ctx {
-    void *cc_provider;
-    uint_t    cc_session;
-    void            *cc_provider_private;    /* owned by provider */
-    void            *cc_framework_private;    /* owned by framework */
-    uint32_t        cc_flags;        /* flags */
-    void            *cc_opstate;        /* state */
-} crypto_ctx_t;
-
-extern int ucrypto_encrypt_init(crypto_ctx_t *context,
-    ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
-    void *iv, size_t iv_len);
-
-extern int ucrypto_encrypt_update(crypto_ctx_t *context, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-extern int ucrypto_encrypt_final(crypto_ctx_t *context, uchar_t *out,
-    size_t *out_len);
-
-/* Encrypt atomic */
-extern int ucrypto_encrypt(ucrypto_mech_t mech_type, uchar_t *key_str,
-    size_t key_len, void *iv, size_t iv_len, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-/* Decrypt multi-part */
-extern int ucrypto_decrypt_init(crypto_ctx_t *context,
-    ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
-    void *iv, size_t iv_len);
-
-extern int ucrypto_decrypt_update(crypto_ctx_t *context, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-extern int ucrypto_decrypt_final(crypto_ctx_t *context, uchar_t *out,
-    size_t *out_len);
-
-/* Decrypt atomic */
-extern int ucrypto_decrypt(ucrypto_mech_t mech_type, uchar_t *key_str,
-    size_t key_len, void *iv, size_t iv_len, uchar_t *in,
-    size_t in_len, uchar_t *out, size_t *out_len);
-
-/* Sign multi-part */
-extern int ucrypto_sign_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len);
-
-extern int ucrypto_sign_update(crypto_ctx_t *context,
-    uchar_t *data_str, size_t data_len);
-
-extern int ucrypto_sign_final(crypto_ctx_t *context,
-    uchar_t *sig_str, size_t *sig_len);
-
-/* Sign atomic */
-extern int ucrypto_sign(ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len,
-    uchar_t *data_str, size_t data_len, uchar_t *sig_str, size_t *sig_len);
-
-/* Verify multi-part */
-extern int ucrypto_verify_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len);
-
-extern int ucrypto_verify_update(crypto_ctx_t *context,
-    uchar_t *data_str, size_t data_len);
-
-extern int ucrypto_verify_final(crypto_ctx_t *context,
-    uchar_t *sig_str, size_t *sig_len);
-
-/* Verify atomic */
-extern int ucrypto_verify(ucrypto_mech_t mech_type,
-    uchar_t *key_str, size_t key_len, void *iv, size_t iv_len,
-    uchar_t *data_str, size_t data_len, uchar_t *sig, size_t *sig_len);
-
-extern int ucrypto_get_mechlist(char *str);
-
-extern const char *ucrypto_id2mech(ucrypto_mech_t mech_type);
-
-extern ucrypto_mech_t ucrypto_mech2id(const char *str);
-
-extern int ucrypto_version();
-
-typedef struct CK_AES_CTR_PARAMS {
-    ulong_t    ulCounterBits;
-    uint8_t cb[16];
-} CK_AES_CTR_PARAMS;
-
-typedef struct CK_AES_GCM_PARAMS {
-    uchar_t *pIv;
-    ulong_t ulIvLen;
-    ulong_t ulIvBits;
-    uchar_t *pAAD;
-    ulong_t ulAADLen;
-    ulong_t ulTagBits;
-} CK_AES_GCM_PARAMS;
-
-typedef struct crypto_object_attribute {
-    uint64_t    oa_type;    /* attribute type */
-    caddr_t            oa_value;    /* attribute value */
-    ssize_t            oa_value_len;    /* length of attribute value */
-} crypto_object_attribute_t;
-
-/* Attribute types to use for passing a RSA public key or a private key. */
-#define    SUN_CKA_MODULUS            0x00000120
-#define    SUN_CKA_MODULUS_BITS        0x00000121
-#define    SUN_CKA_PUBLIC_EXPONENT        0x00000122
-#define    SUN_CKA_PRIVATE_EXPONENT    0x00000123
-#define    SUN_CKA_PRIME_1            0x00000124
-#define    SUN_CKA_PRIME_2            0x00000125
-#define    SUN_CKA_EXPONENT_1        0x00000126
-#define    SUN_CKA_EXPONENT_2        0x00000127
-#define    SUN_CKA_COEFFICIENT        0x00000128
-#define    SUN_CKA_PRIME            0x00000130
-#define    SUN_CKA_SUBPRIME        0x00000131
-#define    SUN_CKA_BASE            0x00000132
-
-#define    CKK_EC            0x00000003
-#define    CKK_GENERIC_SECRET    0x00000010
-#define    CKK_RC4            0x00000012
-#define    CKK_AES            0x0000001F
-#define    CKK_DES            0x00000013
-#define    CKK_DES2        0x00000014
-#define    CKK_DES3        0x00000015
-
-#define    CKO_PUBLIC_KEY        0x00000002
-#define    CKO_PRIVATE_KEY        0x00000003
-#define    CKA_CLASS        0x00000000
-#define    CKA_VALUE        0x00000011
-#define    CKA_KEY_TYPE        0x00000100
-#define    CKA_VALUE_LEN        0x00000161
-#define    CKA_EC_PARAMS        0x00000180
-#define    CKA_EC_POINT        0x00000181
-
-#endif /* _LIBSOFTCRYPTO_H */
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,22 @@
 /*
  * Dumps out byte array in hex with and name and length info
  */
+void printError(char* header, int mech, int rv) {
+  if (mech != -1) {
+    printf("%s, mech = %d, rv = 0x%0x\n", header, mech, rv);
+  } else {
+    printf("%s, rv = 0x%0x\n", header, rv);
+  }
+  if (*ftab->ucryptoStrerror != NULL) {
+    char * reason = (*ftab->ucryptoStrerror)(rv);
+    printf("\tcause = %s\n", reason);
+    free(reason);
+  }
+}
+
+/*
+ * Dumps out byte array in hex with and name and length info
+ */
 void printBytes(char* header, unsigned char* bytes, int len) {
   int i;
 
@@ -60,6 +76,16 @@
   (*env)->DeleteLocalRef(env, jExClass);
 }
 
+/*
+ * De-allocates all memory associated with crypto_ctx_t
+ */
+void freeContext(crypto_ctx_t *context) {
+  if (ftab->ucryptoFreeContext != NULL) {
+    (*ftab->ucryptoFreeContext)(context);
+  }
+  free(context);
+}
+
 JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
     return JNI_VERSION_1_4;
 }
@@ -203,10 +229,10 @@
   }
   if (encrypt) {
     rv = (*ftab->ucryptoEncryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
-    if (rv != 0 && DEBUG) printf("ucryptoEncryptInit: ret = 0x%x\n", rv);
+    if (rv != 0 && DEBUG) printError("ucryptoEncryptInit", mech, rv);
   } else {
     rv =(*ftab->ucryptoDecryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
-    if (rv != 0 && DEBUG) printf("ucryptoDecryptInit: ret = 0x%x\n", rv);
+    if (rv != 0 && DEBUG) printError("ucryptoDecryptInit", mech, rv);
   }
 
   if (iv != jIv) {
@@ -234,15 +260,15 @@
   }
   if (encrypt) {
     rv = (*ftab->ucryptoEncryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoEncryptUpdate: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoEncryptUpdate", -1, rv);
     } else {
       *outLen = (int)outLength;
     }
   } else {
     rv = (*ftab->ucryptoDecryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoDecryptUpdate: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoDecryptUpdate", -1, rv);
     } else {
       if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
       *outLen = (int)outLength;
@@ -263,16 +289,16 @@
   if (DEBUG) printf("CipherFinal: OutOfs %i, outLen %i\n", outOfs, *outLen);
   if (encrypt) {
     rv = (*ftab->ucryptoEncryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoDecryptFinal", -1, rv);
     } else {
       if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
       *outLen = (int)outLength;
     }
   } else {
     rv = (*ftab->ucryptoDecryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
-    if (rv != 0) {
-      if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv);
+    if (rv) {
+      if (DEBUG) printError("ucryptoDecryptFinal", -1, rv);
     } else {
       if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
       *outLen = (int)outLength;
@@ -285,102 +311,61 @@
 // SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
 ////////////////////////////////////////////////////////
 jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit(jint mech) {
-  void *pContext = NULL;
+  crypto_ctx_t *context = NULL;
+  int rv;
 
-  switch (mech) {
-  case com_oracle_security_ucrypto_NativeDigest_MECH_SHA1:
-    pContext = (SHA1_CTX *) malloc(sizeof(SHA1_CTX));
-    if (pContext != NULL) {
-      (*ftab->sha1Init)((SHA1_CTX *)pContext);
-    }
-    break;
-  case com_oracle_security_ucrypto_NativeDigest_MECH_MD5:
-    pContext = (MD5_CTX *) malloc(sizeof(MD5_CTX));
-    if (pContext != NULL) {
-      (*ftab->md5Init)((MD5_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_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) {
-
-  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);
-  }
-  return 0;
-}
+  crypto_ctx_t *context;
+  jint rv = 0;
+  size_t digest_len = digestLen;
 
-jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone
-  (jint mech, jlong pContext) {
-  void *copy = NULL;
-  size_t len = 0;
+  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);
+  }
 
-  if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
-    len = sizeof(SHA1_CTX);
-  } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
-    len = sizeof(MD5_CTX);
-  } else { // SHA-2 family
-    len = sizeof(SHA2_CTX);
-  }
-  copy = (void*) malloc(len);
-  if (copy != NULL) {
-    bcopy((void *)pContext, copy, len);
-  }
-  return (jlong) copy;
+  return -rv; // use negative value to indicate error
 }
 
 void JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree
   (jint mech, jlong pContext) {
-  if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
-    free((SHA1_CTX*) pContext);
-  } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
-    free((MD5_CTX*) pContext);
-  } else { // SHA-2 family
-    free((SHA2_CTX*) pContext);
-  }
+  crypto_ctx_t *context;
+
+  context = (crypto_ctx_t *) pContext;
+  freeContext(context);
 }
 
 // AES
@@ -395,7 +380,7 @@
     rv = CipherInit(context, encrypt, (ucrypto_mech_t) mech, bufKey, keyLen,
                     bufIv, ivLen, tagLen, bufAad, aadLen);
     if (rv) {
-      free(context);
+      freeContext(context);
       return 0L;
     }
   }
@@ -417,8 +402,7 @@
   context = (crypto_ctx_t *) pContext;
   rv = CipherUpdate(context, encrypt, (unsigned char*)bufIn, inOfs, inLen, (unsigned char*)bufOut, outOfs, &outLen);
   if (rv) {
-    free(context);
-    context = 0;
+    freeContext(context);
     return -rv; // use negative value to indicate error!
   }
 
@@ -443,7 +427,7 @@
     outLen = 0;
   }
   rv = CipherFinal(context, encrypt, bufOut, outOfs, &outLen);
-  free(context);
+  freeContext(context);
   if (rv) {
      return -rv; // use negative value to indicate error!
   }
@@ -451,8 +435,6 @@
   return outLen;
 }
 
-
-
 /*
  * Class:     com_oracle_security_ucrypto_NativeDigest
  * Method:    nativeInit
@@ -475,13 +457,15 @@
 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
   unsigned char *bufIn;
+  jint rv = 0;
+
 
   bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
   if (!(*env)->ExceptionCheck(env)) {
-    JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
+    rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
     free(bufIn);
   }
-  return 0;
+  return rv;
 }
 
 /*
@@ -492,6 +476,7 @@
 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest
   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
   unsigned char *bufOut;
+  jint rv = 0;
 
   bufOut = (unsigned char *) malloc(digestLen);
   if (bufOut == NULL) {
@@ -499,21 +484,12 @@
     return 0;
   }
 
-  JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
-
-  (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
+  rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
+  if (rv == 0) {
+      (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
+  }
   free(bufOut);
-  return 0;
-}
-
-/*
- * Class:     com_oracle_security_ucrypto_NativeDigest
- * Method:    nativeClone
- * Signature: (IJ)J
- */
-JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeClone
-  (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
-  return JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone(mech, pContext);
+  return rv;
 }
 
 /*
@@ -582,7 +558,7 @@
 
 cleanup:
   if ((result == 0L) && (context != NULL)) {
-    free(context);
+    freeContext(context);
   }
   if (bufKey != NULL) {
     (*env)->ReleaseByteArrayElements(env, jKey, (jbyte *)bufKey, 0);
@@ -626,7 +602,7 @@
 
   rv = CipherUpdate(context, encrypt, bufIn, 0, inLen, bufOut, 0, &outLen);
   if (rv) {
-    free(context);
+    freeContext(context);
     free(bufIn);
     free(bufOut);
     return -rv;
@@ -683,6 +659,7 @@
   return rc;
 }
 
+
 /*
  * Class:     com_oracle_security_ucrypto_NativeKey
  * Method:    nativeFree
@@ -984,9 +961,9 @@
   }
 
   if (DEBUG) {
-    printf("RSAPublicKey Init: keyValue=%ld, keyLen=2\n", pKey);
-    printBytes("RSA PublicKey mod: ", (unsigned char*) mod, modLen);
-    printBytes("RSA PublicKey pubExp: ", (unsigned char*) pub, pubLen);
+    printf("RSAPublicKey.nativeInit: keyValue=%ld, keyLen=2\n", pKey);
+    printBytes("\tmod: ", (unsigned char*) mod, modLen);
+    printBytes("\tpubExp: ", (unsigned char*) pub, pubLen);
   }
 
   pKey[0].oa_type = SUN_CKA_MODULUS;
@@ -1062,7 +1039,7 @@
   if (DEBUG) {
     printf("SignatureInit: context=%ld, mech=%d, sign=%d, keyValue=%ld, keyLength=%d\n",
            context, mech, sign, pKey, keyLength);
-    printf("SignatureInit, ret =>  0x%x\n", rv);
+    printError("SignatureInit", mech, rv);
   }
   return rv;
 }
@@ -1083,7 +1060,7 @@
     pKey = (uchar_t *) jKey;
     rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
     if (rv) {
-      free(context);
+      freeContext(context);
       return 0L;
     }
   }
@@ -1105,7 +1082,7 @@
   pKey = (uchar_t *) jKey;
   rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
   if (rv) {
-    free(context);
+    freeContext(context);
     throwUCExceptionUsingRV(env, rv);
     return 0L;
   }
@@ -1125,7 +1102,7 @@
 
   context = (crypto_ctx_t *) pCtxt;
   if (DEBUG) {
-    printf("Signature update: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n",
+    printf("NativeRSASignature.nativeUpdate: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n",
            context, sign, jIn, jInOfs, jInLen);
   }
   if (sign) {
@@ -1133,9 +1110,9 @@
   } else {
     rv = (*ftab->ucryptoVerifyUpdate)(context, (uchar_t *) (jIn + jInOfs), (size_t) jInLen);
   }
-  if (DEBUG) printf("Signature update, ret =>  0x%x\n", rv);
   if (rv) {
-    free(context);
+    freeContext(context);
+    if (DEBUG) printError("NativeRSASignature.nativeUpdate", -1, rv);
     return -rv; // use negative value to indicate error!
   }
 
@@ -1194,9 +1171,9 @@
 
   context = (crypto_ctx_t *) pCtxt;
   if (DEBUG) {
-      printf("Signature final: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n",
+      printf("NativeRSASignature.nativeFinal: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n",
              context, sign, bufSig, sigOfs, jSigLen);
-      printBytes("Before Final: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
+      printBytes("Before: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
   }
   if (sign) {
     rv = (*ftab->ucryptoSignFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
@@ -1204,18 +1181,17 @@
     rv = (*ftab->ucryptoVerifyFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
   }
 
-  if (DEBUG) {
-    printf("Signature nativeFinal, ret =>  0x%x\n", rv);
-    if (sigLength != jSigLen) {
-      printf("SIG actual output len=%d\n", sigLength);
+  freeContext(context);
+  if (rv) {
+    if (DEBUG) {
+      printError("NativeRSASignature.nativeFinal", -1, rv);
+      if (sigLength != jSigLen) {
+        printf("NativeRSASignature.nativeFinal out sig len=%d\n", sigLength);
+      }
+      if (sign) {
+        printBytes("After: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
+      }
     }
-    if (sign) {
-      printBytes("After nativeFinal: ", (unsigned char*) (bufSig + sigOfs), jSigLen);
-    }
-  }
-
-  free(context);
-  if (rv) {
     return -rv;
   } else return 0;
 }
@@ -1273,10 +1249,10 @@
 
   pKey = (uchar_t *) keyValue;
   if (DEBUG) {
-    printf("Cipher nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n",
+    printf("NativeRSACipher.nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n",
            mech, encrypt, pKey, keyLength);
-    printBytes("Before nativeAtomic: in: ", (unsigned char*) bufIn, jInLen);
-    printBytes("Before nativeAtomic: out: ", (unsigned char*) (bufOut + jOutOfs), jOutLen);
+    printBytes("Before: in  = ", (unsigned char*) bufIn, jInLen);
+    printBytes("Before: out = ", (unsigned char*) (bufOut + jOutOfs), jOutLen);
   }
 
   if (encrypt) {
@@ -1289,11 +1265,11 @@
       (uchar_t *)(bufOut + jOutOfs), &outLength);
   }
   if (DEBUG) {
-    printf("Cipher nativeAtomic, ret =>  0x%x\n", rv);
+    printError("NativeRSACipher.nativeAtomic", mech, rv);
     if (outLength != jOutLen) {
-      printf("CIP actual output len=%d\n", outLength);
+      printf("NativeRSACipher.nativeAtomic out len=%d\n", outLength);
     }
-    printBytes("After nativeAtomic: ", (unsigned char*) (bufOut + jOutOfs), outLength);
+    printBytes("After: ", (unsigned char*) (bufOut + jOutOfs), outLength);
   }
 
   if (rv) {
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,18 +29,18 @@
 extern "C" {
 #endif
 
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_MD5
-#define com_oracle_security_ucrypto_NativeDigest_MECH_MD5 1L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA1
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA1 2L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA256
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA256 3L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA224
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA224 4L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA384
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA384 5L
-#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA512
-#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA512 6L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5 1L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1 2L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256 3L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA224
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA224 4L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384 5L
+#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512
+#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512 6L
 
 #define DEBUG 0
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <jni.h>
+#include "jni_util.h"
+#include <libsoftcrypto.h>
+#include "nativeCrypto.h"
+#include "nativeFunc.h"
+
+
+extern void throwOutOfMemoryError(JNIEnv *env, const char *msg);
+extern jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len);
+
+///////////////////////////////////////////////////////
+// SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
+////////////////////////////////////////////////////////
+jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(jint mech) {
+  void *pContext = NULL;
+
+  switch (mech) {
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1:
+    pContext = malloc(sizeof(SHA1_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha1Init)((SHA1_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5:
+    pContext = malloc(sizeof(MD5_CTX));
+    if (pContext != NULL) {
+      (*ftab->md5Init)((MD5_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256:
+    pContext = malloc(sizeof(SHA2_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384:
+    pContext = malloc(sizeof(SHA2_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext);
+    }
+    break;
+  case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512:
+    pContext = malloc(sizeof(SHA2_CTX));
+    if (pContext != NULL) {
+      (*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext);
+    }
+    break;
+  default:
+    if (DEBUG) printf("ERROR: Unsupported mech %i\n", mech);
+  }
+  return (jlong) pContext;
+}
+
+jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
+  (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    (*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    (*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  } else { // SHA-2 family
+    (*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len);
+  }
+  return 0;
+}
+
+// Do digest and free the context immediately
+jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
+  (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
+
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    (*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext);
+    free((SHA1_CTX *)pContext);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    (*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext);
+    free((MD5_CTX *)pContext);
+  } else { // SHA-2 family
+    (*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext);
+    free((SHA2_CTX *)pContext);
+  }
+  return 0;
+}
+
+jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
+  (jint mech, jlong pContext) {
+  void *copy = NULL;
+  size_t len = 0;
+
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    len = sizeof(SHA1_CTX);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    len = sizeof(MD5_CTX);
+  } else { // SHA-2 family
+    len = sizeof(SHA2_CTX);
+  }
+  copy = malloc(len);
+  if (copy != NULL) {
+    bcopy((void *)pContext, copy, len);
+  }
+  return (jlong) copy;
+}
+
+void JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
+  (jint mech, jlong pContext) {
+  if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
+    free((SHA1_CTX*) pContext);
+  } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
+    free((MD5_CTX*) pContext);
+  } else { // SHA-2 family
+    free((SHA2_CTX*) pContext);
+  }
+}
+
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeInit
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit
+  (JNIEnv *env, jclass jcls, jint mech) {
+  jlong result = JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(mech);
+  if (result == NULL) {
+     throwOutOfMemoryError(env, NULL);
+  }
+  return result;
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeUpdate
+ * Signature: (IJ[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
+  unsigned char *bufIn;
+
+  bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
+  if (!(*env)->ExceptionCheck(env)) {
+    JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
+    free(bufIn);
+  }
+  return 0;
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeDigest
+ * Signature: (IJ[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
+  unsigned char *bufOut;
+
+  bufOut = (unsigned char *) malloc(digestLen);
+  if (bufOut == NULL) {
+    throwOutOfMemoryError(env, NULL);
+    return 0;
+  }
+
+  JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
+
+  (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
+  free(bufOut);
+  return 0;
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeClone
+ * Signature: (IJ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
+  return JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone(mech, pContext);
+}
+
+/*
+ * Class:     com_oracle_security_ucrypto_NativeDigestMD
+ * Method:    nativeFree
+ * Signature: (IJ)V
+ */
+JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
+  (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
+  JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree(mech, pContext);
+}
+
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,21 +42,33 @@
 static const char SHA2_FINAL[]                   = "SHA2Final";
 static const char UCRYPTO_VERSION[]              = "ucrypto_version";
 static const char UCRYPTO_GET_MECHLIST[]         = "ucrypto_get_mechlist";
+
 static const char UCRYPTO_ENCRYPT_INIT[]         = "ucrypto_encrypt_init";
 static const char UCRYPTO_ENCRYPT_UPDATE[]       = "ucrypto_encrypt_update";
 static const char UCRYPTO_ENCRYPT_FINAL[]        = "ucrypto_encrypt_final";
 static const char UCRYPTO_ENCRYPT[]              = "ucrypto_encrypt";
+
 static const char UCRYPTO_DECRYPT_INIT[]         = "ucrypto_decrypt_init";
 static const char UCRYPTO_DECRYPT_UPDATE[]       = "ucrypto_decrypt_update";
 static const char UCRYPTO_DECRYPT_FINAL[]        = "ucrypto_decrypt_final";
 static const char UCRYPTO_DECRYPT[]              = "ucrypto_decrypt";
+
 static const char UCRYPTO_SIGN_INIT[]            = "ucrypto_sign_init";
 static const char UCRYPTO_SIGN_UPDATE[]          = "ucrypto_sign_update";
 static const char UCRYPTO_SIGN_FINAL[]           = "ucrypto_sign_final";
+
 static const char UCRYPTO_VERIFY_INIT[]          = "ucrypto_verify_init";
 static const char UCRYPTO_VERIFY_UPDATE[]        = "ucrypto_verify_update";
 static const char UCRYPTO_VERIFY_FINAL[]         = "ucrypto_verify_final";
 
+static const char UCRYPTO_DIGEST_INIT[]          = "ucrypto_digest_init";
+static const char UCRYPTO_DIGEST_UPDATE[]        = "ucrypto_digest_update";
+static const char UCRYPTO_DIGEST_FINAL[]         = "ucrypto_digest_final";
+
+static const char UCRYPTO_FREE_CONTEXT[]         = "ucrypto_free_context";
+
+static const char UCRYPTO_STRERROR[]             = "ucrypto_strerror";
+
 /**
  * Initialize native T4 crypto function pointers
  */
@@ -73,28 +85,6 @@
     return NULL;
   }
 
-  lib = dlopen("libmd.so", RTLD_NOW);
-  if (lib != NULL) {
-    ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT);
-    ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE);
-    ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL);
-    ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT);
-    ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE);
-    ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL);
-    ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT);
-    ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE);
-    ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL);
-    if (ftab->md5Init != NULL && ftab->md5Update != NULL &&
-        ftab->md5Final != NULL && ftab->sha1Init != NULL &&
-        ftab->sha1Update != NULL && ftab->sha1Final != NULL &&
-        ftab->sha2Init != NULL && ftab->sha2Update != NULL &&
-        ftab->sha2Final != NULL) {
-      buf[0] = JNI_TRUE;
-    } else {
-      dlclose(lib);
-    }
-  }
-
   lib = dlopen("libsoftcrypto.so", RTLD_NOW);
   if (lib != NULL) {
     // These APIs aren't available for v0 lib on Solaris 10
@@ -102,7 +92,6 @@
       dlsym(lib, UCRYPTO_VERSION);
     ftab->ucryptoGetMechList = (UCRYPTO_GET_MECHLIST_FN_PTR)
       dlsym(lib, UCRYPTO_GET_MECHLIST);
-    //??
     ftab->ucryptoSignInit = (UCRYPTO_SIGN_INIT_FN_PTR)
       dlsym(lib, UCRYPTO_SIGN_INIT);
     ftab->ucryptoSignUpdate = (UCRYPTO_SIGN_UPDATE_FN_PTR)
@@ -116,6 +105,21 @@
     ftab->ucryptoVerifyFinal = (UCRYPTO_VERIFY_FINAL_FN_PTR)
       dlsym(lib, UCRYPTO_VERIFY_FINAL);
 
+    // These APS are added starting S12
+    ftab->ucryptoDigestInit = (UCRYPTO_DIGEST_INIT_FN_PTR)
+      dlsym(lib, UCRYPTO_DIGEST_INIT);
+    ftab->ucryptoDigestUpdate = (UCRYPTO_DIGEST_UPDATE_FN_PTR)
+      dlsym(lib, UCRYPTO_DIGEST_UPDATE);
+    ftab->ucryptoDigestFinal = (UCRYPTO_DIGEST_FINAL_FN_PTR)
+      dlsym(lib, UCRYPTO_DIGEST_FINAL);
+
+    ftab->ucryptoFreeContext = (UCRYPTO_FREE_CONTEXT_FN_PTR)
+      dlsym(lib, UCRYPTO_FREE_CONTEXT);
+
+    ftab->ucryptoStrerror = (UCRYPTO_STRERROR_FN_PTR)
+      dlsym(lib, UCRYPTO_STRERROR);
+
+
     // These should be avilable for all libsoftcrypto libs
     ftab->ucryptoEncryptInit = (UCRYPTO_ENCRYPT_INIT_FN_PTR)
       dlsym(lib, UCRYPTO_ENCRYPT_INIT);
@@ -147,6 +151,34 @@
     } else {
       dlclose(lib);
     }
+
+    // proceed with libmd when libucrypto does not support digest operations
+    if (ftab->ucryptoDigestInit == NULL ||
+        ftab->ucryptoDigestUpdate == NULL ||
+        ftab->ucryptoDigestFinal == NULL) {
+
+      lib = dlopen("libmd.so", RTLD_NOW);
+      if (lib != NULL) {
+        ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT);
+        ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE);
+        ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL);
+        ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT);
+        ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE);
+        ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL);
+        ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT);
+        ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE);
+        ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL);
+        if (ftab->md5Init != NULL && ftab->md5Update != NULL &&
+            ftab->md5Final != NULL && ftab->sha1Init != NULL &&
+            ftab->sha1Update != NULL && ftab->sha1Final != NULL &&
+            ftab->sha2Init != NULL && ftab->sha2Update != NULL &&
+            ftab->sha2Final != NULL) {
+          buf[0] = JNI_TRUE;
+        } else {
+          dlclose(lib);
+        }
+      }
+    }
   }
 
   return buf;
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,15 +69,12 @@
      (crypto_ctx_t *context, ucrypto_mech_t mech_type,
       uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_ENCRYPT_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *in,
       size_t in_len, uchar_t *out, size_t *out_len);
-
 typedef int (*UCRYPTO_ENCRYPT_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *out,
       size_t *out_len);
-
 typedef int (*UCRYPTO_ENCRYPT_FN_PTR)
      (ucrypto_mech_t mech_type, uchar_t *key_str,
       size_t key_len, void *iv, size_t iv_len, uchar_t *in,
@@ -87,15 +84,12 @@
      (crypto_ctx_t *context,
       ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_DECRYPT_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *in,
       size_t in_len, uchar_t *out, size_t *out_len);
-
 typedef int (*UCRYPTO_DECRYPT_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *out,
       size_t *out_len);
-
 typedef int (*UCRYPTO_DECRYPT_FN_PTR)
      (ucrypto_mech_t mech_type, uchar_t *key_str,
       size_t key_len, void *iv, size_t iv_len, uchar_t *in,
@@ -105,10 +99,8 @@
      (crypto_ctx_t *context, ucrypto_mech_t mech_type,
       uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_SIGN_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *data_str, size_t data_len);
-
 typedef int (*UCRYPTO_SIGN_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len);
 
@@ -116,13 +108,24 @@
      (crypto_ctx_t *context, ucrypto_mech_t mech_type,
       uchar_t *key_str, size_t key_len,
       void *iv, size_t iv_len);
-
 typedef int (*UCRYPTO_VERIFY_UPDATE_FN_PTR)
      (crypto_ctx_t *context, uchar_t *data_str, size_t data_len);
-
 typedef int (*UCRYPTO_VERIFY_FINAL_FN_PTR)
      (crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len);
 
+typedef int (*UCRYPTO_DIGEST_INIT_FN_PTR)
+     (crypto_ctx_t *context, ucrypto_mech_t mech_type,
+      void *param, size_t param_len);
+typedef int (*UCRYPTO_DIGEST_UPDATE_FN_PTR)
+     (crypto_ctx_t *context, const uchar_t *data, size_t data_len);
+typedef int (*UCRYPTO_DIGEST_FINAL_FN_PTR)
+     (crypto_ctx_t *context, uchar_t *digest, size_t *digest_len);
+
+typedef void (*UCRYPTO_FREE_CONTEXT_FN_PTR)
+     (crypto_ctx_t *context);
+
+typedef char* (*UCRYPTO_STRERROR_FN_PTR)(int rv);
+
 
 
 /* dynamically resolved functions from libmd, and libsoftcrypto
@@ -153,6 +156,11 @@
   UCRYPTO_VERIFY_INIT_FN_PTR     ucryptoVerifyInit;
   UCRYPTO_VERIFY_UPDATE_FN_PTR   ucryptoVerifyUpdate;
   UCRYPTO_VERIFY_FINAL_FN_PTR    ucryptoVerifyFinal;
+  UCRYPTO_DIGEST_INIT_FN_PTR     ucryptoDigestInit;
+  UCRYPTO_DIGEST_UPDATE_FN_PTR   ucryptoDigestUpdate;
+  UCRYPTO_DIGEST_FINAL_FN_PTR    ucryptoDigestFinal;
+  UCRYPTO_FREE_CONTEXT_FN_PTR    ucryptoFreeContext;
+  UCRYPTO_STRERROR_FN_PTR        ucryptoStrerror;
 } T4CRYPTO_FUNCTION_TABLE;
 
 typedef T4CRYPTO_FUNCTION_TABLE *T4CRYPTO_FUNCTION_TABLE_PTR;
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InvalidModuleException.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InvalidModuleException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -36,14 +36,14 @@
     private static final long serialVersionUID = 7907359387320658039L;
 
     /**
-     * Constructs a {@code InvalidModuleException} with no detail message.
+     * Constructs an {@code InvalidModuleException} with no detail message.
      */
     public InvalidModuleException() {
         super();
     }
 
     /**
-     * Constructs a {@code InvalidModuleException} with the given detail
+     * Constructs an {@code InvalidModuleException} with the given detail
      * message.
      *
      * @param msg
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginOrderingGraph.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginOrderingGraph.java	Wed Jul 05 21:42:16 2017 +0200
@@ -35,10 +35,6 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.PluginException;
 
-/**
- *
- * @author jdenise
- */
 public class PluginOrderingGraph {
 
     static class Node {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java	Wed Jul 05 21:42:16 2017 +0200
@@ -32,10 +32,6 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.Plugin.PluginType;
 
-/**
- *
- * @author jdenise
- */
 public class Utils {
 
     private Utils() {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.ToIntFunction;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.internal.Utils;
+
+/**
+ *
+ * Order Resources plugin
+ */
+public final class OrderResourcesPlugin implements TransformerPlugin {
+    public static final String NAME = "order-resources";
+    private final List<ToIntFunction<String>> filters;
+    private final Map<String, Integer> orderedPaths;
+
+    public OrderResourcesPlugin() {
+        this.filters = new ArrayList<>();
+        this.orderedPaths = new HashMap<>();
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    static class SortWrapper {
+        private final ModuleData resource;
+        private final int ordinal;
+
+        SortWrapper(ModuleData resource, int ordinal) {
+            this.resource = resource;
+            this.ordinal = ordinal;
+        }
+
+        ModuleData getResource() {
+            return resource;
+        }
+
+        String getPath() {
+            return resource.getPath();
+        }
+
+        int getOrdinal() {
+            return ordinal;
+        }
+    }
+
+    private String stripModule(String path) {
+        if (path.startsWith("/")) {
+            int index = path.indexOf('/', 1);
+
+            if (index != -1) {
+                return path.substring(index + 1);
+            }
+        }
+
+        return path;
+    }
+
+    private int getOrdinal(ModuleData resource) {
+        String path = resource.getPath();
+
+        Integer value = orderedPaths.get(stripModule(path));
+
+        if (value != null) {
+            return value;
+        }
+
+        for (ToIntFunction<String> function : filters) {
+            int ordinal = function.applyAsInt(path);
+
+            if (ordinal != Integer.MAX_VALUE) {
+                return ordinal;
+            }
+        }
+
+        return Integer.MAX_VALUE;
+    }
+
+    private static int compare(SortWrapper wrapper1, SortWrapper wrapper2) {
+        int compare = wrapper1.getOrdinal() - wrapper2.getOrdinal();
+
+        if (compare != 0) {
+            return compare;
+        }
+
+        return wrapper1.getPath().compareTo(wrapper2.getPath());
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        in.getContent().stream()
+                .filter(resource -> resource.getType()
+                        .equals(ModuleDataType.CLASS_OR_RESOURCE))
+                .map((resource) -> new SortWrapper(resource, getOrdinal(resource)))
+                .sorted(OrderResourcesPlugin::compare)
+                .forEach((wrapper) -> out.add(wrapper.getResource()));
+        in.getContent().stream()
+                .filter(other -> !other.getType()
+                        .equals(ModuleDataType.CLASS_OR_RESOURCE))
+                .forEach((other) -> out.add(other));
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.SORTER);
+
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        String val = config.get(NAME);
+        String[] patterns = Utils.listParser.apply(val);
+        int ordinal = 0;
+
+        for (String pattern : patterns) {
+            if (pattern.startsWith("@")) {
+                File file = new File(pattern.substring(1));
+
+                if (file.exists()) {
+                    List<String> lines;
+
+                    try {
+                        lines = Files.readAllLines(file.toPath());
+                    } catch (IOException ex) {
+                        throw new PluginException(ex);
+                    }
+
+                    for (String line : lines) {
+                        if (!line.startsWith("#")) {
+                            orderedPaths.put(line + ".class", ordinal++);
+                        }
+                    }
+                }
+            } else {
+                boolean endsWith = pattern.startsWith("*");
+                boolean startsWith = pattern.endsWith("*");
+                ToIntFunction<String> function;
+                final int result = ordinal++;
+
+                if (startsWith && endsWith) {
+                    final String string = pattern.substring(1, pattern.length() - 1);
+                    function = (path)-> path.contains(string) ? result : Integer.MAX_VALUE;
+                } else if (startsWith) {
+                    final String string = pattern.substring(0, pattern.length() - 1);
+                    function = (path)-> path.startsWith(string) ? result : Integer.MAX_VALUE;
+                } else if (endsWith) {
+                    final String string = pattern.substring(1);
+                    function = (path)-> path.endsWith(string) ? result : Integer.MAX_VALUE;
+                } else {
+                    final String string = pattern;
+                    function = (path)-> path.equals(string) ? result : Integer.MAX_VALUE;
+                }
+
+                filters.add(function);
+            }
+        }
+    }
+}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SortResourcesPlugin.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal.plugins;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-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 java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-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.TransformerPlugin;
-import jdk.tools.jlink.internal.Utils;
-
-/**
- *
- * Sort Resources plugin
- */
-public final class SortResourcesPlugin implements TransformerPlugin {
-
-    public static final String NAME = "sort-resources";
-    private final List<Pattern> filters = new ArrayList<>();
-    private List<String> orderedPaths;
-    private boolean isFile;
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    static class SortWrapper {
-
-        private final ModuleData resource;
-        private final int ordinal;
-
-        SortWrapper(ModuleData resource, int ordinal) {
-            this.resource = resource;
-            this.ordinal = ordinal;
-        }
-
-        ModuleData getResource() {
-            return resource;
-        }
-
-        String getPath() {
-            return resource.getPath();
-        }
-
-        int getOrdinal() {
-            return ordinal;
-        }
-    }
-
-    private int getPatternOrdinal(String path) {
-        int ordinal = -1;
-        for (int i = 0; i < filters.size(); i++) {
-            Matcher m = filters.get(i).matcher(path);
-            if (m.matches()) {
-                ordinal = i;
-                break;
-            }
-        }
-        return ordinal;
-    }
-
-    private int getFileOrdinal(String path) {
-        return orderedPaths.indexOf(path);
-    }
-
-    @Override
-    public void visit(Pool in, Pool out) {
-        in.getContent().stream()
-                .filter(w -> w.getType().equals(ModuleDataType.CLASS_OR_RESOURCE))
-                .map((r) -> new SortWrapper(r, isFile
-                        ? getFileOrdinal(r.getPath())
-                        : getPatternOrdinal(r.getPath())))
-                .sorted((sw1, sw2) -> {
-                    int ordinal1 = sw1.getOrdinal();
-                    int ordinal2 = sw2.getOrdinal();
-
-                    if (ordinal1 >= 0) {
-                        if (ordinal2 >= 0) {
-                            return ordinal1 - ordinal2;
-                        } else {
-                            return -1;
-                        }
-                    } else if (ordinal2 >= 0) {
-                        return 1;
-                    }
-
-                    return sw1.getPath().compareTo(sw2.getPath());
-                }).forEach((sw) -> {
-            try {
-                out.add(sw.getResource());
-            } catch (Exception ex) {
-                throw new RuntimeException(ex);
-            }
-        });
-        in.getContent().stream()
-                .filter(m -> !m.getType().equals(ModuleDataType.CLASS_OR_RESOURCE))
-                .forEach((m) -> {
-                    try {
-                        out.add(m);
-                    } catch (Exception ex) {
-                        throw new RuntimeException(ex);
-                    }
-                });
-    }
-
-    @Override
-    public Set<PluginType> getType() {
-        Set<PluginType> set = new HashSet<>();
-        set.add(CATEGORY.SORTER);
-        return Collections.unmodifiableSet(set);
-    }
-
-    @Override
-    public String getDescription() {
-        return PluginsResourceBundle.getDescription(NAME);
-    }
-
-    @Override
-    public boolean hasArguments() {
-        return true;
-    }
-
-    @Override
-    public String getArgumentsDescription() {
-       return PluginsResourceBundle.getArgument(NAME);
-    }
-
-    @Override
-    public void configure(Map<String, String> config) {
-        String val = config.get(NAME);
-        try {
-            String[] patterns = Utils.listParser.apply(val);
-            boolean isf = false;
-            List<String> paths = null;
-            if (patterns != null) {
-                if (patterns.length == 1) {
-                    String filePath = patterns[0];
-                    File f = new File(filePath);
-                    if (f.exists()) {
-                        isf = true;
-                        try (FileInputStream fis = new FileInputStream(f);
-                                InputStreamReader ins
-                                = new InputStreamReader(fis, StandardCharsets.UTF_8);
-                                BufferedReader reader = new BufferedReader(ins)) {
-                            paths = reader.lines().collect(Collectors.toList());
-                        }
-                    }
-                }
-                if (!isf) {
-                    for (String p : patterns) {
-                        p = p.replaceAll(" ", "");
-                        Pattern pattern = Pattern.compile(ResourceFilter.escape(p));
-                        filters.add(pattern);
-                    }
-                }
-            }
-            orderedPaths = paths;
-            isFile = isf;
-        } catch (IOException ex) {
-            throw new PluginException(ex);
-        }
-    }
-}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties	Wed Jul 05 21:42:16 2017 +0200
@@ -53,10 +53,10 @@
 
 onoff.argument=<on|off>
 
-sort-resources.argument=<paths in priority order | file with resource paths>
+order-resources.argument=<paths in priority order | file with resource paths>
 
-sort-resources.description=\
-Sort resources. e.g.: */modules-info.class,/java-base/java/lang/*
+order-resources.description=\
+Order resources. e.g.: */module-info.class,/java.base/java/lang/*
 
 strip-debug.description=\
 Strip debug information from the output image
@@ -68,7 +68,7 @@
 
 vm.description=\
 Select the HotSpot VM in the output image.  Default is all
- 
+
 zip.argument=[comma separated list of resource paths]
 
 zip.description=ZIP Compression
@@ -160,7 +160,7 @@
 
 err.no.plugins.path=No plugins path argument.
 
-err.dir.already.exits=directory already exists: {0} 
+err.dir.already.exits=directory already exists: {0}
 
 err.invalid.index=invalid index for option {0}
 
--- a/jdk/src/jdk.jlink/share/classes/module-info.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/src/jdk.jlink/share/classes/module-info.java	Wed Jul 05 21:42:16 2017 +0200
@@ -40,7 +40,7 @@
     provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
     provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin;
     provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.StripNativeCommandsPlugin;
-    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.SortResourcesPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.OrderResourcesPlugin;
     provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
     provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.OptimizationPlugin;
     provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
--- a/jdk/test/Makefile	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/Makefile	Wed Jul 05 21:42:16 2017 +0200
@@ -76,14 +76,20 @@
 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
--- a/jdk/test/ProblemList.txt	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 21:42:16 2017 +0200
@@ -210,6 +210,10 @@
 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 +228,8 @@
 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
--- a/jdk/test/com/oracle/security/ucrypto/TestDigest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/com/oracle/security/ucrypto/TestDigest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
     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;
-                }
+                md = MessageDigest.getInstance(a, p);
+            } catch (NoSuchAlgorithmException nsae) {
+                System.out.println("=> Skip, unsupported");
+                continue;
+            }
+            try {
                 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;
-                    }
-                }
+            } catch (NoSuchAlgorithmException nsae) {
+                System.out.println("=> Skip, no interop provider found");
+                continue;
+            }
 
-                // Test Interoperability for digest calls
-                md = MessageDigest.getInstance(a, p);
-                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 at iter " + i);
+                    testPassed = false;
+                } else {
+                    System.out.println("...diff1 test passed");
+                }
+            }
 
-                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 digest calls
+            md = MessageDigest.getInstance(a, p);
+            md2 = MessageDigest.getInstance(a, interopProvName);
 
-                // Test Cloning functionality
-                md = MessageDigest.getInstance(a, p);
-                md2 = (MessageDigest) md.clone(); // clone right after construction
+            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;
-                }
-                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;
+                } else {
+                    System.out.println("...diff2 test 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 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) {
--- a/jdk/test/java/lang/Integer/BitTwiddle.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/Integer/BitTwiddle.java	Wed Jul 05 21:42:16 2017 +0200
@@ -58,6 +58,21 @@
 
         for (int i = 0; i < N; i++) {
             int x = rnd.nextInt();
+
+            String expected = new StringBuilder()
+                .append(leftpad(toBinaryString(x), 32))
+                .reverse().toString();
+
+            String actual = leftpad(toBinaryString(reverse(x)), 32);
+
+            if (!expected.equals(actual)) {
+                throw new RuntimeException("reverse: \n" +
+                        expected + " \n" + actual);
+            }
+        }
+
+        for (int i = 0; i < N; i++) {
+            int x = rnd.nextInt();
             if (highestOneBit(x) != reverse(lowestOneBit(reverse(x))))
                 throw new RuntimeException("g: " + toHexString(x));
         }
@@ -136,4 +151,12 @@
                 throw new RuntimeException("z: " + toHexString(x));
         }
     }
+
+    private static String leftpad(String s, int width) {
+        String r = s;
+        for (int c = 0; c < width - s.length(); c++) {
+            r = "0" + r;
+        }
+        return r;
+    }
 }
--- a/jdk/test/java/lang/Long/BitTwiddle.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/Long/BitTwiddle.java	Wed Jul 05 21:42:16 2017 +0200
@@ -58,6 +58,21 @@
 
         for (int i = 0; i < N; i++) {
             long x = rnd.nextLong();
+
+            String expected = new StringBuilder()
+                .append(leftpad(toBinaryString(x), 64))
+                .reverse().toString();
+
+            String actual = leftpad(toBinaryString(reverse(x)), 64);
+
+            if (!expected.equals(actual)) {
+                throw new RuntimeException("reverse: \n" +
+                        expected + " \n" + actual);
+            }
+        }
+
+        for (int i = 0; i < N; i++) {
+            long x = rnd.nextLong();
             if (highestOneBit(x) != reverse(lowestOneBit(reverse(x))))
                 throw new RuntimeException("g: " + toHexString(x));
         }
@@ -136,4 +151,12 @@
                 throw new RuntimeException("z: " + toHexString(x));
         }
     }
+
+    private static String leftpad(String s, int width) {
+        String r = s;
+        for (int c = 0; c < width - s.length(); c++) {
+            r = "0" + r;
+        }
+        return r;
+    }
 }
--- a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -59,7 +59,9 @@
  * @modules java.base/sun.util.logging
  *          java.base/jdk.internal.logger
  *          java.logging/sun.util.logging.internal
- * @run  main/othervm DefaultLoggerBridgeTest
+ * @run  main/othervm DefaultLoggerBridgeTest NOSECURITY
+ * @run  main/othervm DefaultLoggerBridgeTest NOPERMISSIONS
+ * @run  main/othervm DefaultLoggerBridgeTest WITHPERMISSIONS
  * @author danielfuchs
  */
 public class DefaultLoggerBridgeTest {
@@ -275,7 +277,6 @@
             };
 
         Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> {
-            LoggerFinder provider;
             switch (testCase) {
                 case NOSECURITY:
                     System.out.println("\n*** Without Security Manager\n");
@@ -396,10 +397,10 @@
         final boolean old = allowAll.get().get();
         allowAll.get().set(true);
         try {
+            appSink = LoggingProviderImpl.getLogManagerAccess().demandLoggerFor(
+                    LogManager.getLogManager(), "foo", DefaultLoggerBridgeTest.class.getModule());
             sysSink = LoggingProviderImpl.getLogManagerAccess().demandLoggerFor(
                     LogManager.getLogManager(), "foo", Thread.class.getModule());
-            appSink = LoggingProviderImpl.getLogManagerAccess().demandLoggerFor(
-                    LogManager.getLogManager(), "foo", DefaultLoggerBridgeTest.class.getModule());
             if (appSink == sysSink) {
                 throw new RuntimeException("identical backend loggers");
             }
--- a/jdk/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -28,7 +28,7 @@
  * @summary Test verifies that lambda forms are cached when run with multiple threads
  * @author kshefov
  * @library /lib/testlibrary/jsr292 /lib/testlibrary
- * @modules java.management
+ * @modules jdk.management
  * @build TestMethods
  * @build LambdaFormTestCase
  * @build LFCachingTestCase
--- a/jdk/test/java/lang/management/BufferPoolMXBean/Basic.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/BufferPoolMXBean/Basic.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, 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
@@ -24,7 +24,7 @@
 /* @test
  * @bug 6606598 7024172
  * @summary Unit test for java.lang.management.BufferPoolMXBean
- * @modules java.management
+ * @modules jdk.management
  * @run main/othervm Basic
  * @key randomness
  */
--- a/jdk/test/java/lang/management/GarbageCollectorMXBean/GcInfoCompositeType.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/GarbageCollectorMXBean/GcInfoCompositeType.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -26,8 +26,7 @@
  * @bug     6396794
  * @summary Check that LastGcInfo contents are reasonable
  * @author  Eamonn McManus
- * @modules java.management
- *          jdk.management
+ * @modules jdk.management
  * @run     main/othervm -XX:-ExplicitGCInvokesConcurrent GcInfoCompositeType
  */
 // Passing "-XX:-ExplicitGCInvokesConcurrent" to force System.gc()
--- a/jdk/test/java/lang/management/MXBean/MXBeanBehavior.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/MXBean/MXBeanBehavior.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -27,8 +27,7 @@
  * @summary Check that java.lang.management MXBeans have the same behavior
  *          as user MXBeans
  * @author  Eamonn McManus
- * @modules java.management
- *          jdk.management
+ * @modules jdk.management
  * @run     main/othervm MXBeanBehavior
  */
 
--- a/jdk/test/java/lang/management/ManagementFactory/GetPlatformMXBeans.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ManagementFactory/GetPlatformMXBeans.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -28,7 +28,7 @@
  *          methods and PlatformManagedObject.getObjectName()
  * @author  Mandy Chung
  *
- * @modules java.management
+ * @modules jdk.management
  * @run main GetPlatformMXBeans
  */
 
--- a/jdk/test/java/lang/management/ManagementFactory/GetPlatformManagementInterfaces.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ManagementFactory/GetPlatformManagementInterfaces.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -28,7 +28,7 @@
  *          ManagementFactory.getPlatformManagementInterfaces() method
  * @author  Frederic Parain
  *
- * @modules java.management
+ * @modules jdk.management
  * @run main GetPlatformManagementInterfaces
  */
 
--- a/jdk/test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -27,8 +27,7 @@
  * @summary Test that all the platform MXBeans are wrapped in StandardMBean so
  *          an MBeanServer which does not have support for MXBeans can be used.
  * @author Luis-Miguel Alventosa
- * @modules java.management
- *          jdk.management
+ * @modules jdk.management
  * @run clean MBeanServerMXBeanUnsupportedTest
  * @run build MBeanServerMXBeanUnsupportedTest
  * @run main/othervm MBeanServerMXBeanUnsupportedTest
--- a/jdk/test/java/lang/management/ManagementFactory/MXBeanException.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ManagementFactory/MXBeanException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, 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
@@ -29,7 +29,7 @@
  *
  * @author  Mandy Chung
  *
- * @modules java.management
+ * @modules jdk.management
  * @build MXBeanException
  * @run main MXBeanException
  */
--- a/jdk/test/java/lang/management/ManagementFactory/MXBeanProxyTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ManagementFactory/MXBeanProxyTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, 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
@@ -25,7 +25,7 @@
  * @test
  * @bug     5024531
  * @summary Basic Test for ManagementFactory.newPlatformMXBean().
- * @modules java.management
+ * @modules jdk.management
  * @run main/othervm MXBeanProxyTest
  * @author  Mandy Chung
  */
--- a/jdk/test/java/lang/management/ManagementFactory/PlatformMBeanServerTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ManagementFactory/PlatformMBeanServerTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
  * @bug     4947536
  * @summary Basic unit test of ManagementFactory.getPlatformMBeanServer()
  * @author  Mandy Chung
- * @modules java.management
+ * @modules jdk.management
  */
 
 import java.lang.management.*;
--- a/jdk/test/java/lang/management/ManagementFactory/ProxyExceptions.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ManagementFactory/ProxyExceptions.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, 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
@@ -27,8 +27,7 @@
  * @summary Test type mapping of the platform MXBean proxy
  *          returned from Management.newPlatformMXBeanProxy().
  * @author  Mandy Chung
- * @modules java.management
- *          jdk.management
+ * @modules jdk.management
  */
 import java.lang.management.*;
 import javax.management.*;
--- a/jdk/test/java/lang/management/ManagementFactory/ProxyTypeMapping.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ManagementFactory/ProxyTypeMapping.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, 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
@@ -28,8 +28,7 @@
  *          returned from Management.newPlatformMXBeanProxy().
  * @author  Mandy Chung
  *
- * @modules java.management
- *          jdk.management
+ * @modules jdk.management
  * @compile ProxyTypeMapping.java
  * @run main/othervm -verbose:gc ProxyTypeMapping
  */
--- a/jdk/test/java/lang/management/ManagementFactory/ThreadMXBeanProxy.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ManagementFactory/ThreadMXBeanProxy.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -29,7 +29,7 @@
  *
  * @author  Mandy Chung
  *
- * @modules java.management
+ * @modules jdk.management
  * @run main ThreadMXBeanProxy
  */
 
--- a/jdk/test/java/lang/management/ManagementFactory/ValidateOpenTypes.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ManagementFactory/ValidateOpenTypes.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, 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
@@ -28,8 +28,7 @@
  *          MBeanServer.
  * @author  Mandy Chung
  *
- * @modules java.management
- *          jdk.management
+ * @modules jdk.management
  * @compile ValidateOpenTypes.java
  * @run main/othervm -verbose:gc ValidateOpenTypes
  */
--- a/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
  * @author  Mandy Chung
  *
  * @library /lib/testlibrary/
- * @modules java.management
+ * @modules jdk.management
  * @build jdk.testlibrary.* CollectionUsageThreshold MemoryUtil RunUtil
  * @requires vm.opt.ExplicitGCInvokesConcurrent == "false" | vm.opt.ExplicitGCInvokesConcurrent == "null"
  * @run main/timeout=300 CollectionUsageThreshold
--- a/jdk/test/java/lang/management/MemoryMXBean/GetMBeanInfo.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/MemoryMXBean/GetMBeanInfo.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @summary Make sure MemoryMXBean has two notification types.
  * @author  Mandy Chung
  *
- * @modules java.management
+ * @modules jdk.management
  * @run main GetMBeanInfo
  */
 
--- a/jdk/test/java/lang/management/MemoryMXBean/MemoryManagement.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/MemoryMXBean/MemoryManagement.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
  *
  * @author  Mandy Chung
  *
- * @modules java.management
+ * @modules jdk.management
  * @build MemoryManagement MemoryUtil
  * @run main/othervm/timeout=600 -Xmn8m -XX:+IgnoreUnrecognizedVMOptions -XX:G1HeapRegionSize=1 -XX:-UseLargePages MemoryManagement
  */
--- a/jdk/test/java/lang/management/MemoryMXBean/MemoryTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/MemoryMXBean/MemoryTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
  *          MemoryMXBean.getMemoryManager().
  * @author  Mandy Chung
  *
- * @modules java.management
+ * @modules jdk.management
  * @run main MemoryTest 2
  */
 
--- a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
  * @author  Mandy Chung
  *
  * @library /lib/testlibrary/
- * @modules java.management
+ * @modules jdk.management
  * @build jdk.testlibrary.* ResetPeakMemoryUsage MemoryUtil RunUtil
  * @run main ResetPeakMemoryUsage
  */
--- a/jdk/test/java/lang/management/PlatformLoggingMXBean/LoggingMXBeanTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/PlatformLoggingMXBean/LoggingMXBeanTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -27,8 +27,7 @@
  * @summary Test if proxy for PlatformLoggingMXBean is equivalent
  *          to proxy for LoggingMXBean
  *
- * @modules java.management
- *          jdk.management
+ * @modules jdk.management
  * @build LoggingMXBeanTest
  * @run main LoggingMXBeanTest
  */
--- a/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,8 +29,7 @@
  *          This test performs similar testing as
  *          java/util/logging/LoggingMXBeanTest.
  *
- * @modules java.management
- *          jdk.management
+ * @modules jdk.management
  * @build PlatformLoggingMXBeanTest
  * @run main PlatformLoggingMXBeanTest
  */
--- a/jdk/test/java/lang/management/ThreadMXBean/ThreadInfoArray.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/lang/management/ThreadMXBean/ThreadInfoArray.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, 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
@@ -30,7 +30,7 @@
  * @author  Mandy Chung
  * @author  Jaroslav Bachorik
  *
- * @modules java.management
+ * @modules jdk.management
  * @build ThreadInfoArray
  * @run main ThreadInfoArray
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/BasicWebSocketAPITest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,332 @@
+/*
+ * 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 org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.WebSocket;
+import java.net.http.WebSocket.CloseCode;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+/*
+ * @test
+ * @bug 8087113
+ * @build TestKit
+ * @run testng/othervm BasicWebSocketAPITest
+ */
+public class BasicWebSocketAPITest {
+
+    @Test
+    public void webSocket() throws Exception {
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(IllegalArgumentException.class,
+                                "(?i).*\\bnegative\\b.*",
+                                () -> ws.request(-1))
+        );
+        checkAndClose((ws) ->
+                TestKit.assertNotThrows(() -> ws.request(0))
+        );
+        checkAndClose((ws) ->
+                TestKit.assertNotThrows(() -> ws.request(1))
+        );
+        checkAndClose((ws) ->
+                TestKit.assertNotThrows(() -> ws.request(Long.MAX_VALUE))
+        );
+        checkAndClose((ws) ->
+                TestKit.assertNotThrows(ws::isClosed)
+        );
+        checkAndClose((ws) ->
+                TestKit.assertNotThrows(ws::getSubprotocol)
+        );
+        checkAndClose(
+                (ws) -> {
+                    try {
+                        ws.abort();
+                    } catch (IOException ignored) { }
+                    // No matter what happens during the first abort invocation,
+                    // other invocations must return normally
+                    TestKit.assertNotThrows(ws::abort);
+                    TestKit.assertNotThrows(ws::abort);
+                }
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(NullPointerException.class,
+                                "message",
+                                () -> ws.sendBinary((byte[]) null, true))
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(NullPointerException.class,
+                                "message",
+                                () -> ws.sendBinary((ByteBuffer) null, true))
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(NullPointerException.class,
+                                "message",
+                                () -> ws.sendPing(null))
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(NullPointerException.class,
+                                "message",
+                                () -> ws.sendPong(null))
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(NullPointerException.class,
+                                "message",
+                                () -> ws.sendText((CharSequence) null, true))
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(NullPointerException.class,
+                                "message",
+                                () -> ws.sendText((CharSequence) null))
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(NullPointerException.class,
+                                "message",
+                                () -> ws.sendText((Stream<? extends CharSequence>) null))
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(NullPointerException.class,
+                                "code",
+                                () -> ws.sendClose(null, ""))
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertNotThrows(
+                                () -> ws.sendClose(CloseCode.NORMAL_CLOSURE, ""))
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(NullPointerException.class,
+                                "reason",
+                                () -> ws.sendClose(CloseCode.NORMAL_CLOSURE, null))
+        );
+        checkAndClose(
+                (ws) ->
+                        TestKit.assertThrows(NullPointerException.class,
+                                "code|reason",
+                                () -> ws.sendClose(null, null))
+        );
+    }
+
+    @Test
+    public void builder() {
+        URI ws = URI.create("ws://localhost:9001");
+        // FIXME: check all 24 cases:
+        // {null, ws, wss, incorrect} x {null, HttpClient.getDefault(), custom} x {null, listener}
+        //
+        // if (any null) or (any incorrect)
+        //     NPE or IAE is thrown
+        // else
+        //     builder is created
+        TestKit.assertThrows(NullPointerException.class,
+                "uri",
+                () -> WebSocket.newBuilder(null, defaultListener())
+        );
+        TestKit.assertThrows(NullPointerException.class,
+                "listener",
+                () -> WebSocket.newBuilder(ws, null)
+        );
+        URI uri = URI.create("ftp://localhost:9001");
+        TestKit.assertThrows(IllegalArgumentException.class,
+                "(?i).*\\buri\\b\\s+\\bscheme\\b.*",
+                () -> WebSocket.newBuilder(uri, defaultListener())
+        );
+        TestKit.assertNotThrows(
+                () -> WebSocket.newBuilder(ws, defaultListener())
+        );
+        URI uri1 = URI.create("wss://localhost:9001");
+        TestKit.assertNotThrows(
+                () -> WebSocket.newBuilder(uri1, defaultListener())
+        );
+        URI uri2 = URI.create("wss://localhost:9001#a");
+        TestKit.assertThrows(IllegalArgumentException.class,
+                "(?i).*\\bfragment\\b.*",
+                () -> WebSocket.newBuilder(uri2, HttpClient.getDefault(), defaultListener())
+        );
+        TestKit.assertThrows(NullPointerException.class,
+                "uri",
+                () -> WebSocket.newBuilder(null, HttpClient.getDefault(), defaultListener())
+        );
+        TestKit.assertThrows(NullPointerException.class,
+                "client",
+                () -> WebSocket.newBuilder(ws, null, defaultListener())
+        );
+        TestKit.assertThrows(NullPointerException.class,
+                "listener",
+                () -> WebSocket.newBuilder(ws, HttpClient.getDefault(), null)
+        );
+        // FIXME: check timeout works
+        // (i.e. it directly influences the time WebSocket waits for connection + opening handshake)
+        TestKit.assertNotThrows(
+                () -> WebSocket.newBuilder(ws, defaultListener()).connectTimeout(1, TimeUnit.SECONDS)
+        );
+        WebSocket.Builder builder = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                "(?i).*\\bnegative\\b.*",
+                () -> builder.connectTimeout(-1, TimeUnit.SECONDS)
+        );
+        WebSocket.Builder builder1 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(NullPointerException.class,
+                "unit",
+                () -> builder1.connectTimeout(1, null)
+        );
+        // FIXME: check these headers are actually received by the server
+        TestKit.assertNotThrows(
+                () -> WebSocket.newBuilder(ws, defaultListener()).header("a", "b")
+        );
+        TestKit.assertNotThrows(
+                () -> WebSocket.newBuilder(ws, defaultListener()).header("a", "b").header("a", "b")
+        );
+        // FIXME: check all 18 cases:
+        // {null, websocket(7), custom} x {null, custom}
+        WebSocket.Builder builder2 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(NullPointerException.class,
+                "name",
+                () -> builder2.header(null, "b")
+        );
+        WebSocket.Builder builder3 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(NullPointerException.class,
+                "value",
+                () -> builder3.header("a", null)
+        );
+        WebSocket.Builder builder4 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                () -> builder4.header("Sec-WebSocket-Accept", "")
+        );
+        WebSocket.Builder builder5 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                () -> builder5.header("Sec-WebSocket-Extensions", "")
+        );
+        WebSocket.Builder builder6 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                () -> builder6.header("Sec-WebSocket-Key", "")
+        );
+        WebSocket.Builder builder7 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                () -> builder7.header("Sec-WebSocket-Protocol", "")
+        );
+        WebSocket.Builder builder8 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                () -> builder8.header("Sec-WebSocket-Version", "")
+        );
+        WebSocket.Builder builder9 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                () -> builder9.header("Connection", "")
+        );
+        WebSocket.Builder builder10 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                () -> builder10.header("Upgrade", "")
+        );
+        // FIXME: check 3 cases (1 arg):
+        // {null, incorrect, custom}
+        // FIXME: check 12 cases (2 args):
+        // {null, incorrect, custom} x {(String) null, (String[]) null, incorrect, custom}
+        // FIXME: check 27 cases (3 args) (the interesting part in null inside var-arg):
+        // {null, incorrect, custom}^3
+        // FIXME: check the server receives them in the order listed
+        TestKit.assertThrows(NullPointerException.class,
+                "mostPreferred",
+                () -> WebSocket.newBuilder(ws, defaultListener()).subprotocols(null)
+        );
+        TestKit.assertThrows(NullPointerException.class,
+                "lesserPreferred",
+                () -> WebSocket.newBuilder(ws, defaultListener()).subprotocols("a", null)
+        );
+        TestKit.assertThrows(NullPointerException.class,
+                "lesserPreferred\\[0\\]",
+                () -> WebSocket.newBuilder(ws, defaultListener()).subprotocols("a", null, "b")
+        );
+        TestKit.assertThrows(NullPointerException.class,
+                "lesserPreferred\\[1\\]",
+                () -> WebSocket.newBuilder(ws, defaultListener()).subprotocols("a", "b", null)
+        );
+        TestKit.assertNotThrows(
+                () -> WebSocket.newBuilder(ws, defaultListener()).subprotocols("a")
+        );
+        TestKit.assertNotThrows(
+                () -> WebSocket.newBuilder(ws, defaultListener()).subprotocols("a", "b", "c")
+        );
+        WebSocket.Builder builder11 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                () -> builder11.subprotocols("")
+        );
+        WebSocket.Builder builder12 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                () -> builder12.subprotocols("a", "a")
+        );
+        WebSocket.Builder builder13 = WebSocket.newBuilder(ws, defaultListener());
+        TestKit.assertThrows(IllegalArgumentException.class,
+                () -> builder13.subprotocols("a" + ((char) 0x7f))
+        );
+    }
+
+    private static WebSocket.Listener defaultListener() {
+        return new WebSocket.Listener() { };
+    }
+
+    //
+    // Automatically closes everything after the check has been performed
+    //
+    private static void checkAndClose(Consumer<? super WebSocket> c) {
+        HandshakePhase HandshakePhase
+                = new HandshakePhase(new InetSocketAddress("127.0.0.1", 0));
+        URI serverURI = HandshakePhase.getURI();
+        CompletableFuture<SocketChannel> cfc = HandshakePhase.afterHandshake();
+        WebSocket.Builder b = WebSocket.newBuilder(serverURI, defaultListener());
+        CompletableFuture<WebSocket> cfw = b.buildAsync();
+
+        try {
+            WebSocket ws;
+            try {
+                ws = cfw.get();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            c.accept(ws);
+        } finally {
+            try {
+                SocketChannel now = cfc.getNow(null);
+                if (now != null) {
+                    now.close();
+                }
+            } catch (Throwable ignored) { }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/HandshakePhase.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,265 @@
+/*
+ * 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.IOException;
+import java.io.UncheckedIOException;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Function;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+
+//
+// Performs a simple opening handshake and yields the channel.
+//
+// Client Request:
+//
+//    GET /chat HTTP/1.1
+//    Host: server.example.com
+//    Upgrade: websocket
+//    Connection: Upgrade
+//    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+//    Origin: http://example.com
+//    Sec-WebSocket-Protocol: chat, superchat
+//    Sec-WebSocket-Version: 13
+//
+//
+// Server Response:
+//
+//    HTTP/1.1 101 Switching Protocols
+//    Upgrade: websocket
+//    Connection: Upgrade
+//    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+//    Sec-WebSocket-Protocol: chat
+//
+final class HandshakePhase {
+
+    private final ServerSocketChannel ssc;
+
+    HandshakePhase(InetSocketAddress address) {
+        requireNonNull(address);
+        try {
+            ssc = ServerSocketChannel.open();
+            ssc.bind(address);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    //
+    // Returned CF completes normally after the handshake has been performed
+    //
+    CompletableFuture<SocketChannel> afterHandshake(
+            Function<List<String>, List<String>> mapping) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    SocketChannel socketChannel = accept();
+                    try {
+                        StringBuilder request = new StringBuilder();
+                        if (!readRequest(socketChannel, request)) {
+                            throw new IllegalStateException();
+                        }
+                        List<String> strings = Arrays.asList(
+                                request.toString().split("\r\n")
+                        );
+                        List<String> response = mapping.apply(strings);
+                        writeResponse(socketChannel, response);
+                        return socketChannel;
+                    } catch (Throwable t) {
+                        try {
+                            socketChannel.close();
+                        } catch (IOException ignored) { }
+                        throw t;
+                    }
+                });
+    }
+
+    CompletableFuture<SocketChannel> afterHandshake() {
+        return afterHandshake((request) -> {
+            List<String> response = new LinkedList<>();
+            Iterator<String> iterator = request.iterator();
+            if (!iterator.hasNext()) {
+                throw new IllegalStateException("The request is empty");
+            }
+            if (!"GET / HTTP/1.1".equals(iterator.next())) {
+                throw new IllegalStateException
+                        ("Unexpected status line: " + request.get(0));
+            }
+            response.add("HTTP/1.1 101 Switching Protocols");
+            Map<String, String> requestHeaders = new HashMap<>();
+            while (iterator.hasNext()) {
+                String header = iterator.next();
+                String[] split = header.split(": ");
+                if (split.length != 2) {
+                    throw new IllegalStateException
+                            ("Unexpected header: " + header
+                                    + ", split=" + Arrays.toString(split));
+                }
+                if (requestHeaders.put(split[0], split[1]) != null) {
+                    throw new IllegalStateException
+                            ("Duplicating headers: " + Arrays.toString(split));
+                }
+            }
+            if (requestHeaders.containsKey("Sec-WebSocket-Protocol")) {
+                throw new IllegalStateException("Subprotocols are not expected");
+            }
+            if (requestHeaders.containsKey("Sec-WebSocket-Extensions")) {
+                throw new IllegalStateException("Extensions are not expected");
+            }
+            expectHeader(requestHeaders, "Connection", "Upgrade");
+            response.add("Connection: Upgrade");
+            expectHeader(requestHeaders, "Upgrade", "websocket");
+            response.add("Upgrade: websocket");
+            expectHeader(requestHeaders, "Sec-WebSocket-Version", "13");
+            String key = requestHeaders.get("Sec-WebSocket-Key");
+            if (key == null) {
+                throw new IllegalStateException("Sec-WebSocket-Key is missing");
+            }
+            MessageDigest sha1 = null;
+            try {
+                sha1 = MessageDigest.getInstance("SHA-1");
+            } catch (NoSuchAlgorithmException e) {
+                throw new InternalError(e);
+            }
+            String x = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+            sha1.update(x.getBytes(StandardCharsets.ISO_8859_1));
+            String v = Base64.getEncoder().encodeToString(sha1.digest());
+            response.add("Sec-WebSocket-Accept: " + v);
+            return response;
+        });
+    }
+
+    private String expectHeader(Map<String, String> headers,
+                                String name,
+                                String value) {
+        String v = headers.get(name);
+        if (!value.equals(v)) {
+            throw new IllegalStateException(
+                    format("Expected '%s: %s', actual: '%s: %s'",
+                            name, value, name, v)
+            );
+        }
+        return v;
+    }
+
+    URI getURI() {
+        InetSocketAddress a;
+        try {
+            a = (InetSocketAddress) ssc.getLocalAddress();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+        return URI.create("ws://" + a.getHostName() + ":" + a.getPort());
+    }
+
+    private int read(SocketChannel socketChannel, ByteBuffer buffer) {
+        try {
+            int num = socketChannel.read(buffer);
+            if (num == -1) {
+                throw new IllegalStateException("Unexpected EOF");
+            }
+            assert socketChannel.isBlocking() && num > 0;
+            return num;
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    private SocketChannel accept() {
+        SocketChannel socketChannel = null;
+        try {
+            socketChannel = ssc.accept();
+            socketChannel.configureBlocking(true);
+        } catch (IOException e) {
+            if (socketChannel != null) {
+                try {
+                    socketChannel.close();
+                } catch (IOException ignored) { }
+            }
+            throw new UncheckedIOException(e);
+        }
+        return socketChannel;
+    }
+
+    private boolean readRequest(SocketChannel socketChannel,
+                                StringBuilder request) {
+        ByteBuffer buffer = ByteBuffer.allocateDirect(512);
+        read(socketChannel, buffer);
+        CharBuffer decoded;
+        buffer.flip();
+        try {
+            decoded =
+                    StandardCharsets.ISO_8859_1.newDecoder().decode(buffer);
+        } catch (CharacterCodingException e) {
+            throw new UncheckedIOException(e);
+        }
+        request.append(decoded);
+        return Pattern.compile("\r\n\r\n").matcher(request).find();
+    }
+
+    private void writeResponse(SocketChannel socketChannel,
+                               List<String> response) {
+        String s = response.stream().collect(Collectors.joining("\r\n"))
+                + "\r\n\r\n";
+        ByteBuffer encoded;
+        try {
+            encoded =
+                    StandardCharsets.ISO_8859_1.newEncoder().encode(CharBuffer.wrap(s));
+        } catch (CharacterCodingException e) {
+            throw new UncheckedIOException(e);
+        }
+        write(socketChannel, encoded);
+    }
+
+    private void write(SocketChannel socketChannel, ByteBuffer buffer) {
+        try {
+            while (buffer.hasRemaining()) {
+                socketChannel.write(buffer);
+            }
+        } catch (IOException e) {
+            try {
+                socketChannel.close();
+            } catch (IOException ignored) { }
+            throw new UncheckedIOException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/Timeout.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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);
+        }
+    }
+
+}
Binary file jdk/test/java/net/httpclient/http2/keystore.p12 has changed
--- a/jdk/test/java/net/httpclient/security/Security.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/net/httpclient/security/Security.java	Wed Jul 05 21:42:16 2017 +0200
@@ -68,6 +68,8 @@
 import java.util.logging.ConsoleHandler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.lang.reflect.InvocationTargetException;
+import java.net.BindException;
 
 /**
  * Security checks test
@@ -142,8 +144,12 @@
         }
     }
 
-    static Object getProxy(int port, boolean b) throws Exception {
-        return proxyConstructor.newInstance(port, b);
+    static Object getProxy(int port, boolean b) throws Throwable {
+        try {
+            return proxyConstructor.newInstance(port, b);
+        } catch (InvocationTargetException e) {
+            throw e.getTargetException();
+        }
     }
 
     static Class<?> proxyClass;
@@ -319,10 +325,10 @@
         Object proxy = null;
         try {
             proxy = getProxy(proxyPort, true);
-        } catch (IOException e) {
-            System.out.println("Cannot bind. Not running test");
-            throw new SecurityException("test not run");
-        } catch (Exception ee) {
+        } catch (BindException e) {
+            System.out.println("Bind failed");
+            throw e;
+        } catch (Throwable ee) {
             throw new RuntimeException(ee);
         }
         System.out.println("Proxy port = " + proxyPort);
--- a/jdk/test/java/nio/Buffer/Basic-X.java.template	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/Basic-X.java.template	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
     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 @@
 
     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 @@
 
     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 @@
         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 @@
     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 @@
     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 @@
     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 @@
     }
 
     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 @@
 
     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 @@
                 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 @@
         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 @@
                 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 @@
         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 @@
                 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 @@
         // 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 @@
         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 @@
         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 @@
         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 @@
 #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 @@
             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 @@
 
         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 @@
             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 @@
         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 @@
 
         // 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 @@
         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 @@
             }
         }
 #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) {
--- a/jdk/test/java/nio/Buffer/BasicByte.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/BasicByte.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
     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 @@
 
     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 @@
 
     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 @@
         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 @@
     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 @@
     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 @@
     }
 
     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 @@
 
     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 @@
                 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 @@
         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 @@
                 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 @@
         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 @@
                 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);
     }
 
@@ -521,8 +549,6 @@
 
 
 
-
-
         // Compact
 
         relPut(b);
@@ -537,38 +563,14 @@
         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 @@
 
 
 
-        byte v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (byte)-1);
@@ -665,6 +666,10 @@
 
 
 
+
+
+
+
         // Comparison
         b.rewind();
         ByteBuffer b2 = ByteBuffer.allocate(b.capacity());
@@ -683,14 +688,15 @@
 
 
 
-                    )
+                    ) {
                     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 @@
             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 @@
 
         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 @@
             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();
-                }});
+        catchReadOnlyBuffer(b, () -> 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.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 @@
 
 
         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
@@ -1001,47 +928,6 @@
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
     public static void test(final byte [] ba) {
         int offset = 47;
         int length = 900;
@@ -1052,40 +938,21 @@
         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 @@
             }
         }
 
-        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) {
--- a/jdk/test/java/nio/Buffer/BasicChar.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/BasicChar.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
     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 @@
 
     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 @@
 
     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 @@
         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 @@
     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));
@@ -435,12 +432,42 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              CharBuffer xb, CharBuffer yb,
                              char x, char y) {
         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 @@
                 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 @@
         // 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 @@
         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 @@
 
 
 
-        char v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (char)-1);
@@ -665,6 +666,10 @@
 
 
 
+
+
+
+
         // Comparison
         b.rewind();
         CharBuffer b2 = CharBuffer.allocate(b.capacity());
@@ -683,14 +688,15 @@
 
 
 
-                    )
+                    ) {
                     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 @@
             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 @@
 
         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 @@
             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 @@
 
 
         // 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 @@
         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 @@
 
         // 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 @@
         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 static void test() {
--- a/jdk/test/java/nio/Buffer/BasicDouble.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/BasicDouble.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
     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 @@
 
     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 @@
 
     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 @@
         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) {
@@ -435,12 +432,42 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              DoubleBuffer xb, DoubleBuffer yb,
                              double x, double y) {
         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 @@
                 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);
     }
 
@@ -521,8 +549,6 @@
 
 
 
-
-
         // Compact
 
         relPut(b);
@@ -537,38 +563,14 @@
         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 @@
         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 @@
 
 
 
+
+
+        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 @@
 
 
 
-                    )
+                    ) {
                     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 @@
             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 @@
 
         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 @@
             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 @@
 
 
         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
@@ -1001,47 +928,6 @@
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
     public static void test(final double [] ba) {
         int offset = 47;
         int length = 900;
@@ -1052,40 +938,21 @@
         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 static void test() {
--- a/jdk/test/java/nio/Buffer/BasicFloat.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/BasicFloat.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
     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 @@
 
     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 @@
 
     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 @@
         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) {
@@ -435,12 +432,42 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              FloatBuffer xb, FloatBuffer yb,
                              float x, float y) {
         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 @@
                 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);
     }
 
@@ -521,8 +549,6 @@
 
 
 
-
-
         // Compact
 
         relPut(b);
@@ -537,38 +563,14 @@
         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 @@
 
 
 
-        float v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (float)-1);
@@ -644,13 +645,15 @@
         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 @@
 
 
 
+
+
         // Comparison
         b.rewind();
         FloatBuffer b2 = FloatBuffer.allocate(b.capacity());
@@ -683,14 +688,15 @@
 
                     || 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 @@
             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 @@
 
         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 @@
             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 @@
 
 
         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
@@ -1001,47 +928,6 @@
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
     public static void test(final float [] ba) {
         int offset = 47;
         int length = 900;
@@ -1052,40 +938,21 @@
         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 static void test() {
--- a/jdk/test/java/nio/Buffer/BasicInt.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/BasicInt.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
     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 @@
 
     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 @@
 
     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 @@
         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) {
@@ -435,12 +432,42 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              IntBuffer xb, IntBuffer yb,
                              int x, int y) {
         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 @@
                 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);
     }
 
@@ -521,8 +549,6 @@
 
 
 
-
-
         // Compact
 
         relPut(b);
@@ -537,38 +563,14 @@
         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 @@
 
 
 
-        int v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (int)-1);
@@ -665,6 +666,10 @@
 
 
 
+
+
+
+
         // Comparison
         b.rewind();
         IntBuffer b2 = IntBuffer.allocate(b.capacity());
@@ -683,14 +688,15 @@
 
 
 
-                    )
+                    ) {
                     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 @@
             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 @@
 
         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 @@
             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 @@
 
 
         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
@@ -1001,47 +928,6 @@
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
     public static void test(final int [] ba) {
         int offset = 47;
         int length = 900;
@@ -1052,40 +938,21 @@
         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 static void test() {
--- a/jdk/test/java/nio/Buffer/BasicLong.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/BasicLong.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
     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 @@
 
     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 @@
 
     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 @@
         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) {
@@ -435,12 +432,42 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              LongBuffer xb, LongBuffer yb,
                              long x, long y) {
         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 @@
                 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);
     }
 
@@ -521,8 +549,6 @@
 
 
 
-
-
         // Compact
 
         relPut(b);
@@ -537,38 +563,14 @@
         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 @@
 
 
 
-        long v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (long)-1);
@@ -665,6 +666,10 @@
 
 
 
+
+
+
+
         // Comparison
         b.rewind();
         LongBuffer b2 = LongBuffer.allocate(b.capacity());
@@ -683,14 +688,15 @@
 
 
 
-                    )
+                    ) {
                     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 @@
             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 @@
 
         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 @@
             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 @@
 
 
         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
@@ -1001,47 +928,6 @@
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
     public static void test(final long [] ba) {
         int offset = 47;
         int length = 900;
@@ -1052,40 +938,21 @@
         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 static void test() {
--- a/jdk/test/java/nio/Buffer/BasicShort.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/BasicShort.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
     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 @@
 
     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 @@
 
     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 @@
         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) {
@@ -435,12 +432,42 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              ShortBuffer xb, ShortBuffer yb,
                              short x, short y) {
         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 @@
                 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);
     }
 
@@ -521,8 +549,6 @@
 
 
 
-
-
         // Compact
 
         relPut(b);
@@ -537,38 +563,14 @@
         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 @@
 
 
 
-        short v;
         b.flip();
         ck(b, b.get(), 0);
         ck(b, b.get(), (short)-1);
@@ -665,6 +666,10 @@
 
 
 
+
+
+
+
         // Comparison
         b.rewind();
         ShortBuffer b2 = ShortBuffer.allocate(b.capacity());
@@ -683,14 +688,15 @@
 
 
 
-                    )
+                    ) {
                     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 @@
             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 @@
 
         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 @@
             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 @@
 
 
         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
@@ -1001,47 +928,6 @@
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
     public static void test(final short [] ba) {
         int offset = 47;
         int length = 900;
@@ -1052,40 +938,21 @@
         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 static void test() {
--- a/jdk/test/java/nio/Buffer/LimitDirectMemory.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/LimitDirectMemory.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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.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 @@
 
         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 @@
         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++) {
--- a/jdk/test/java/nio/Buffer/Order.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/Order.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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,24 +39,24 @@
 
     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());
+    private static void ckByteBuffer(ByteBuffer bb) {
+        ckViews(bb);
         bb.order(be);
-        ckViews(bb, be);
+        ckViews(bb);
         bb.order(le);
-        ckViews(bb, le);
+        ckViews(bb);
 
         if (bb.hasArray()) {
             byte[] array = bb.array();
@@ -74,6 +74,8 @@
         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 +87,4 @@
         OrderFloat.ckFloatBuffer();
         OrderDouble.ckDoubleBuffer();
     }
-
 }
--- a/jdk/test/java/nio/Buffer/SwapMicroBenchmark.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/Buffer/SwapMicroBenchmark.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 {
--- a/jdk/test/java/nio/channels/SocketChannel/AdaptSocket.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/channels/SocketChannel/AdaptSocket.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, 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
@@ -22,6 +22,7 @@
  */
 
 /* @test
+ * @bug 8156002
  * @summary Unit test for socket-channel adaptors
  * @library ..
  */
@@ -29,6 +30,7 @@
 import java.io.*;
 import java.net.*;
 import java.nio.channels.*;
+import java.util.Arrays;
 
 
 public class AdaptSocket {
@@ -100,10 +102,15 @@
         try {
             byte[] b = new byte[100];
             int n = is.read(b);
-            if (n != 5)
+            if (shouldTimeout) {
+                throw new Exception("Should time out, but not, data: " + Arrays.toString(b));
+            }
+            if (n != 5) {
                 throw new Exception("Incorrect number of bytes read: " + n);
-            if (!dataString.equals(new String(b, 0, n, "US-ASCII")))
+            }
+            if (!dataString.equals(new String(b, 0, n, "US-ASCII"))) {
                 throw new Exception("Incorrect data read: " + n);
+            }
         } catch (SocketTimeoutException x) {
             if (shouldTimeout) {
                 out.println("Read timed out, as expected");
@@ -135,6 +142,7 @@
 
         testRead(so, shouldTimeout);
         for (int i = 0; i < 4; i++) {
+            out.println("loop: " + i);
             testRead(so, shouldTimeout);
         }
 
@@ -163,9 +171,9 @@
             testRead(echoServer, 8000, false);
         }
 
-        try (TestServers.EchoServer lingerEchoServer
-                = TestServers.EchoServer.startNewServer(100)) {
-            testRead(lingerEchoServer, 10, true);
+        try (TestServers.NoResponseServer noResponseServer
+                = TestServers.NoResponseServer.startNewServer()) {
+            testRead(noResponseServer, 10, true);
         }
     }
 }
--- a/jdk/test/java/nio/channels/TestServers.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/nio/channels/TestServers.java	Wed Jul 05 21:42:16 2017 +0200
@@ -340,7 +340,7 @@
      * exactly matches the RFC - the only purpose of this server is to have
      * something that responds to nio tests...
      */
-    static final class EchoServer extends AbstractTcpServer {
+    static class EchoServer extends AbstractTcpServer {
 
         public EchoServer() {
             this(0L);
@@ -400,6 +400,21 @@
     }
 
     /**
+     * A small TCP Server that accept connections but does not response to any input.
+     */
+    static final class NoResponseServer extends EchoServer {
+        public NoResponseServer() {
+            super(Long.MAX_VALUE);
+        }
+
+        public static NoResponseServer startNewServer() throws IOException {
+            final NoResponseServer noResponseServer = new NoResponseServer();
+            noResponseServer.start();
+            return noResponseServer;
+        }
+    }
+
+    /**
      * A small TCP server that emulates the Day & Time service for tests
      * purposes. See http://en.wikipedia.org/wiki/Daytime_Protocol This server
      * uses an anonymous port - NOT the standard port 13. We don't guarantee
--- a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 1999, 2012, 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
- *
- * @summary HttpSocket functionality test
- * @author Dana Burns
- *
- * @library ../../testlibrary
- * @modules java.rmi/sun.rmi.registry
- *          java.rmi/sun.rmi.server
- *          java.rmi/sun.rmi.transport
- *          java.rmi/sun.rmi.transport.proxy
- *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary HttpSocketTest HttpSocketTest_Stub
- * @run main/othervm/policy=security.policy HttpSocketTest
- */
-
-/*
- *  This test assures remote methods can be carried out over RMI.
- *  After setting the RMI runtime socket factory to the http proxy version,
- *  a registry is created, a remote object (an instance of this class) is
- *  registered with it, and then it is exercised.
- */
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.Naming;
-import java.rmi.RMISecurityManager;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
-import java.rmi.server.RMISocketFactory;
-import java.rmi.server.UnicastRemoteObject;
-import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory;
-
-interface MyRemoteInterface extends Remote {
-    void setRemoteObject( Remote r ) throws RemoteException;
-    Remote getRemoteObject() throws RemoteException;
-}
-
-public class HttpSocketTest extends UnicastRemoteObject
-    implements MyRemoteInterface
-{
-    private static final String NAME = "HttpSocketTest";
-
-    public HttpSocketTest() throws RemoteException{}
-
-    private Remote ro;
-
-    public static void main(String[] args)
-        throws Exception
-    {
-
-        Registry registry = null;
-
-        TestLibrary.suggestSecurityManager(null);
-
-        // Set the socket factory.
-        System.err.println("installing socket factory");
-        RMISocketFactory.setSocketFactory(new RMIHttpToPortSocketFactory());
-        int registryPort = -1;
-
-        try {
-            System.err.println("Starting registry");
-            registry = TestLibrary.createRegistryOnUnusedPort();
-            registryPort = TestLibrary.getRegistryPort(registry);
-        } catch (Exception e) {
-            TestLibrary.bomb(e);
-        }
-
-        try {
-            registry.rebind( NAME, new HttpSocketTest() );
-            MyRemoteInterface httpTest =
-                (MyRemoteInterface)Naming.lookup("//:" + registryPort + "/" + NAME);
-            httpTest.setRemoteObject( new HttpSocketTest() );
-            Remote r = httpTest.getRemoteObject();
-
-        } catch (Exception e) {
-            TestLibrary.bomb(e);
-        }
-
-
-    }
-
-    public void setRemoteObject( Remote ro ) throws RemoteException {
-        this.ro = ro;
-    }
-
-    public Remote getRemoteObject() throws RemoteException {
-        return( this.ro );
-    }
-
-}
--- a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 1999, 2008, 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.
- */
-
-// Stub class generated by rmic, do not edit.
-// Contents subject to change without notice.
-
-public final class HttpSocketTest_Stub
-    extends java.rmi.server.RemoteStub
-    implements MyRemoteInterface, java.rmi.Remote
-{
-    private static final java.rmi.server.Operation[] operations = {
-        new java.rmi.server.Operation("java.rmi.Remote getRemoteObject()"),
-        new java.rmi.server.Operation("void setRemoteObject(java.rmi.Remote)")
-    };
-
-    private static final long interfaceHash = 3775375480010579665L;
-
-    private static final long serialVersionUID = 2;
-
-    private static boolean useNewInvoke;
-    private static java.lang.reflect.Method $method_getRemoteObject_0;
-    private static java.lang.reflect.Method $method_setRemoteObject_1;
-
-    static {
-        try {
-            java.rmi.server.RemoteRef.class.getMethod("invoke",
-                new java.lang.Class[] {
-                    java.rmi.Remote.class,
-                    java.lang.reflect.Method.class,
-                    java.lang.Object[].class,
-                    long.class
-                });
-            useNewInvoke = true;
-            $method_getRemoteObject_0 = MyRemoteInterface.class.getMethod("getRemoteObject", new java.lang.Class[] {});
-            $method_setRemoteObject_1 = MyRemoteInterface.class.getMethod("setRemoteObject", new java.lang.Class[] {java.rmi.Remote.class});
-        } catch (java.lang.NoSuchMethodException e) {
-            useNewInvoke = false;
-        }
-    }
-
-    // constructors
-    public HttpSocketTest_Stub() {
-        super();
-    }
-    public HttpSocketTest_Stub(java.rmi.server.RemoteRef ref) {
-        super(ref);
-    }
-
-    // methods from remote interfaces
-
-    // implementation of getRemoteObject()
-    public java.rmi.Remote getRemoteObject()
-        throws java.rmi.RemoteException
-    {
-        try {
-            if (useNewInvoke) {
-                Object $result = ref.invoke(this, $method_getRemoteObject_0, null, -2578437860804964265L);
-                return ((java.rmi.Remote) $result);
-            } else {
-                java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash);
-                ref.invoke(call);
-                java.rmi.Remote $result;
-                try {
-                    java.io.ObjectInput in = call.getInputStream();
-                    $result = (java.rmi.Remote) in.readObject();
-                } catch (java.io.IOException e) {
-                    throw new java.rmi.UnmarshalException("error unmarshalling return", e);
-                } catch (java.lang.ClassNotFoundException e) {
-                    throw new java.rmi.UnmarshalException("error unmarshalling return", e);
-                } finally {
-                    ref.done(call);
-                }
-                return $result;
-            }
-        } catch (java.lang.RuntimeException e) {
-            throw e;
-        } catch (java.rmi.RemoteException e) {
-            throw e;
-        } catch (java.lang.Exception e) {
-            throw new java.rmi.UnexpectedException("undeclared checked exception", e);
-        }
-    }
-
-    // implementation of setRemoteObject(Remote)
-    public void setRemoteObject(java.rmi.Remote $param_Remote_1)
-        throws java.rmi.RemoteException
-    {
-        try {
-            if (useNewInvoke) {
-                ref.invoke(this, $method_setRemoteObject_1, new java.lang.Object[] {$param_Remote_1}, -7518632118115022871L);
-            } else {
-                java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash);
-                try {
-                    java.io.ObjectOutput out = call.getOutputStream();
-                    out.writeObject($param_Remote_1);
-                } catch (java.io.IOException e) {
-                    throw new java.rmi.MarshalException("error marshalling arguments", e);
-                }
-                ref.invoke(call);
-                ref.done(call);
-            }
-        } catch (java.lang.RuntimeException e) {
-            throw e;
-        } catch (java.rmi.RemoteException e) {
-            throw e;
-        } catch (java.lang.Exception e) {
-            throw new java.rmi.UnexpectedException("undeclared checked exception", e);
-        }
-    }
-}
--- a/jdk/test/java/rmi/transport/httpSocket/security.policy	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-
-grant {
-    permission java.net.SocketPermission "*:1024-", "accept,connect,listen";
-    permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry";
-    permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.server";
-    permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport";
-    permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.proxy";
-    permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.tcp";
-    permission java.lang.RuntimePermission "setFactory";
-};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/SecureRandom/MacNativePRNGSetSeed.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.security.SecureRandom;
+
+/* @test
+ * @bug 8156709
+ * @summary Cannot call setSeed on NativePRNG on Mac if EGD is /dev/urandom
+ * @requires os.name == "Mac OS X"
+ * @run main/othervm -Djava.security.egd=file:/dev/urandom MacNativePRNGSetSeed
+ */
+public class MacNativePRNGSetSeed {
+    public static void main(String[] args) throws Exception {
+        SecureRandom sr = SecureRandom.getInstance("NativePRNG");
+        sr.setSeed(1);
+    }
+}
--- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java	Wed Jul 05 21:42:16 2017 +0200
@@ -73,7 +73,10 @@
 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 @@
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
+    @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 @@
 
             {"www"},
             {"WW"},
+
+            {"vv"},
+            {"vvv"},
         };
     }
 
--- a/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java	Wed Jul 05 21:42:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, 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
@@ -71,12 +71,15 @@
 import java.time.DayOfWeek;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.chrono.ThaiBuddhistDate;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.DateTimeParseException;
 import java.time.format.ResolverStyle;
 import java.time.temporal.IsoFields;
 import java.time.temporal.Temporal;
+import java.time.temporal.TemporalField;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 
 import org.testng.annotations.DataProvider;
@@ -439,6 +442,29 @@
     }
 
     //-----------------------------------------------------------------------
+    // range refinedby
+    //-----------------------------------------------------------------------
+    @DataProvider(name="isofields")
+    Object[][] data_isofields() {
+        return new Object[][] {
+               {IsoFields.DAY_OF_QUARTER},
+               {IsoFields.QUARTER_OF_YEAR},
+               {IsoFields.WEEK_OF_WEEK_BASED_YEAR},
+               {IsoFields.WEEK_BASED_YEAR},
+        };
+    }
+
+    @Test(dataProvider = "isofields")
+    public void test_isofields_rangerefinedby(TemporalField field) {
+        field.rangeRefinedBy(LocalDate.now());
+    }
+
+    @Test(dataProvider = "isofields", expectedExceptions = UnsupportedTemporalTypeException.class)
+    public void test_nonisofields_rangerefinedby(TemporalField field) {
+        field.rangeRefinedBy(ThaiBuddhistDate.now());
+    }
+
+    //-----------------------------------------------------------------------
     public void test_loop() {
         // loop round at least one 400 year cycle, including before 1970
         LocalDate date = LocalDate.of(1960, 1, 5);  // Tuseday of week 1 1960
--- a/jdk/test/java/util/Arrays/SortingNearlySortedPrimitive.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/util/Arrays/SortingNearlySortedPrimitive.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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;
+
+    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);
+    }
 
-    @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},
-        };
+    // 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(dataProvider = "arrays")
-    public void runTests(String testName, Supplier<int[]> dataMethod) throws Exception {
-        int[] intSourceArray = dataMethod.get();
+    @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 @@
 
     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 @@
         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 @@
         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 @@
         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;
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +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.
- *
- * 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 8132734
- * @summary Test the extended API and the aliasing additions in JarFile that
- *          support multi-release jar files
- * @library /lib/testlibrary/java/util/jar
- * @build Compiler JarBuilder CreateMultiReleaseTestJars
- * @run testng MultiReleaseJarAPI
- */
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.util.Arrays;
-import java.util.jar.JarFile;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import jdk.Version;
-
-import static java.util.jar.JarFile.Release;
-
-import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-
-public class MultiReleaseJarAPI {
-
-    static final int MAJOR_VERSION = Version.current().major();
-
-    String userdir = System.getProperty("user.dir",".");
-    CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
-    File unversioned = new File(userdir, "unversioned.jar");
-    File multirelease = new File(userdir, "multi-release.jar");
-    File signedmultirelease = new File(userdir, "signed-multi-release.jar");
-    Release[] values = JarFile.Release.values();
-
-
-    @BeforeClass
-    public void initialize() throws Exception {
-        creator.compileEntries();
-        creator.buildUnversionedJar();
-        creator.buildMultiReleaseJar();
-        creator.buildSignedMultiReleaseJar();
-    }
-
-    @AfterClass
-    public void close() throws IOException {
-        Files.delete(unversioned.toPath());
-        Files.delete(multirelease.toPath());
-        Files.delete(signedmultirelease.toPath());
-    }
-
-    @Test
-    public void isMultiReleaseJar() throws Exception {
-        try (JarFile jf = new JarFile(unversioned)) {
-            Assert.assertFalse(jf.isMultiRelease());
-        }
-
-        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
-            Assert.assertFalse(jf.isMultiRelease());
-        }
-
-        try (JarFile jf = new JarFile(multirelease)) {
-            Assert.assertFalse(jf.isMultiRelease());
-        }
-
-        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
-            Assert.assertTrue(jf.isMultiRelease());
-        }
-
-        testCustomMultiReleaseValue("true", true);
-        testCustomMultiReleaseValue("true\r\nOther: value", true);
-        testCustomMultiReleaseValue("true\nOther: value", true);
-        testCustomMultiReleaseValue("true\rOther: value", true);
-
-        testCustomMultiReleaseValue("false", false);
-        testCustomMultiReleaseValue(" true", false);
-        testCustomMultiReleaseValue("true ", false);
-        testCustomMultiReleaseValue("true\n ", false);
-        testCustomMultiReleaseValue("true\r ", false);
-        testCustomMultiReleaseValue("true\n true", false);
-        testCustomMultiReleaseValue("true\r\n true", false);
-    }
-
-    private void testCustomMultiReleaseValue(String value, boolean expected) throws Exception {
-        creator.buildCustomMultiReleaseJar("custom-mr.jar", value);
-        File custom = new File(userdir, "custom-mr.jar");
-        try (JarFile jf = new JarFile(custom, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
-            Assert.assertEquals(jf.isMultiRelease(), expected);
-        }
-        Files.delete(custom.toPath());
-    }
-
-    @Test
-    public void testVersioning() throws Exception {
-        // multi-release jar
-        JarFile jar = new JarFile(multirelease);
-        Assert.assertEquals(Release.BASE, jar.getVersion());
-        jar.close();
-
-        for (Release value : values) {
-            System.err.println("test versioning for Release " + value);
-            try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, value)) {
-                Assert.assertEquals(value, jf.getVersion());
-            }
-        }
-
-        // regular, unversioned, jar
-        for (Release value : values) {
-            try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, value)) {
-                Assert.assertEquals(Release.BASE, jf.getVersion());
-            }
-        }
-
-        // assure that we have a Release object corresponding to the actual runtime version
-        String version = "VERSION_" + MAJOR_VERSION;
-        boolean runtimeVersionExists = false;
-        for (Release value : values) {
-            if (version.equals(value.name())) runtimeVersionExists = true;
-        }
-        Assert.assertTrue(runtimeVersionExists);
-    }
-
-    @Test
-    public void testAliasing() throws Exception {
-        for (Release value : values) {
-            System.err.println("test aliasing for Release " + value);
-            String name = value.name();
-            String prefix;
-            if (name.equals("BASE")) {
-                prefix = "";
-            } else if (name.equals("RUNTIME")) {
-                prefix = "META-INF/versions/" + MAJOR_VERSION + "/";
-            } else {
-                prefix = "META-INF/versions/" + name.substring(8) + "/";
-            }
-            // test both multi-release jars
-            readAndCompare(multirelease, value, "README", prefix + "README");
-            readAndCompare(multirelease, value, "version/Version.class", prefix + "version/Version.class");
-            // and signed multi-release jars
-            readAndCompare(signedmultirelease, value, "README", prefix + "README");
-            readAndCompare(signedmultirelease, value, "version/Version.class", prefix + "version/Version.class");
-        }
-    }
-
-    private void readAndCompare(File jar, Release version, String name, String realName) throws Exception {
-        byte[] baseBytes;
-        byte[] versionedBytes;
-        try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, Release.BASE)) {
-            ZipEntry ze = jf.getEntry(realName);
-            try (InputStream is = jf.getInputStream(ze)) {
-                baseBytes = is.readAllBytes();
-            }
-        }
-        assert baseBytes.length > 0;
-
-        try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, version)) {
-            ZipEntry ze = jf.getEntry(name);
-            try (InputStream is = jf.getInputStream(ze)) {
-                versionedBytes = is.readAllBytes();
-            }
-        }
-        assert versionedBytes.length > 0;
-
-        Assert.assertTrue(Arrays.equals(baseBytes, versionedBytes));
-    }
-
-    @Test
-    public void testNames() throws Exception {
-        String rname = "version/Version.class";
-        String vname = "META-INF/versions/9/version/Version.class";
-        ZipEntry ze1;
-        ZipEntry ze2;
-        try (JarFile jf = new JarFile(multirelease)) {
-            ze1 = jf.getEntry(vname);
-        }
-        Assert.assertEquals(ze1.getName(), vname);
-        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
-            ze2 = jf.getEntry(rname);
-        }
-        Assert.assertEquals(ze2.getName(), rname);
-        Assert.assertNotEquals(ze1.getName(), ze2.getName());
-    }
-}
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +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.
- *
- * 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 8132734
- * @summary Test the System properties for JarFile that support multi-release jar files
- * @library /lib/testlibrary/java/util/jar
- * @build Compiler JarBuilder CreateMultiReleaseTestJars SimpleHttpServer
- * @run testng MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
- * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
- */
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties {
-    private SimpleHttpServer server;
-
-    @BeforeClass
-    public void initialize() throws Exception {
-        server = new SimpleHttpServer();
-        server.start();
-        super.initialize();
-    }
-
-    @Override
-    protected void initializeClassLoader() throws Exception {
-        URL[] urls = new URL[]{
-                new URL("http://localhost:" + server.getPort() + "/multi-release.jar")
-        };
-        cldr = new URLClassLoader(urls);
-        // load any class, Main is convenient and in the root entries
-        rootClass = cldr.loadClass("version.Main");
-    }
-
-    @AfterClass
-    public void close() throws IOException {
-        // Windows requires server to stop before file is deleted
-        if (server != null)
-            server.stop();
-        super.close();
-    }
-
-    /*
-     * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader
-     */
-
-    @Test
-    public void testURLClassLoader() throws Throwable {
-        Class<?> vcls = cldr.loadClass("version.Version");
-        invokeMethod(vcls, rtVersion);
-    }
-
-    @Test
-    public void testGetResourceAsStream() throws Exception {
-        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
-        // use rootClass as a base for getting resources
-        getResourceAsStream(rootClass, resource);
-    }
-
-    @Test
-    public void testGetResource() throws Exception {
-        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
-        // use rootClass as a base for getting resources
-        getResource(rootClass, resource);
-    }
-}
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +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.
- *
- * 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 8132734
- * @summary Test the extended API and the aliasing additions in JarFile that
- *          support multi-release jar files
- * @library /lib/testlibrary/java/util/jar
- * @build Compiler JarBuilder CreateMultiReleaseTestJars
- * @run testng MultiReleaseJarIterators
- */
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.stream.Collectors;
-import java.util.zip.ZipFile;
-import jdk.Version;
-
-import static java.util.jar.JarFile.Release;
-
-import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-
-public class MultiReleaseJarIterators {
-
-    static final int MAJOR_VERSION = Version.current().major();
-
-    String userdir = System.getProperty("user.dir", ".");
-    File unversioned = new File(userdir, "unversioned.jar");
-    File multirelease = new File(userdir, "multi-release.jar");
-    Map<String,JarEntry> uvEntries = new HashMap<>();
-    Map<String,JarEntry> mrEntries = new HashMap<>();
-    Map<String,JarEntry> baseEntries = new HashMap<>();
-    Map<String,JarEntry> v9Entries = new HashMap<>();
-    Map<String, JarEntry> v10Entries = new HashMap<>();
-
-    @BeforeClass
-    public void initialize() throws Exception {
-        CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
-        creator.compileEntries();
-        creator.buildUnversionedJar();
-        creator.buildMultiReleaseJar();
-
-        try (JarFile jf = new JarFile(multirelease)) {
-            for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements(); ) {
-                JarEntry je = e.nextElement();
-                String name = je.getName();
-                mrEntries.put(name, je);
-                if (name.startsWith("META-INF/versions/")) {
-                    if (name.startsWith("META-INF/versions/9/")) {
-                        v9Entries.put(name.substring(20), je);
-                    } else if (name.startsWith("META-INF/versions/10/")) {
-                        v10Entries.put(name.substring(21), je);
-                    }
-                } else {
-                    baseEntries.put(name, je);
-                }
-            }
-        }
-        Assert.assertEquals(mrEntries.size(), 14);
-        Assert.assertEquals(baseEntries.size(), 6);
-        Assert.assertEquals(v9Entries.size(), 5);
-        Assert.assertEquals(v10Entries.size(), 3);
-
-        try (JarFile jf = new JarFile(unversioned)) {
-            jf.entries().asIterator().forEachRemaining(je -> uvEntries.put(je.getName(), je));
-        }
-        Assert.assertEquals(uvEntries.size(), 6);
-    }
-
-    @AfterClass
-    public void close() throws IOException {
-        Files.delete(unversioned.toPath());
-        Files.delete(multirelease.toPath());
-    }
-
-    @Test
-    public void testMultiReleaseJar() throws IOException {
-        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ)) {
-            testEnumeration(jf, mrEntries);
-            testStream(jf, mrEntries);
-        }
-
-        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.BASE)) {
-            testEnumeration(jf, baseEntries);
-            testStream(jf, baseEntries);
-        }
-
-        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
-            testEnumeration(jf, v9Entries);
-            testStream(jf, v9Entries);
-        }
-
-        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
-            Map<String,JarEntry> expectedEntries;
-            switch (MAJOR_VERSION) {
-                case 9:
-                    expectedEntries = v9Entries;
-                    break;
-                case 10:  // won't get here until JDK 10
-                    expectedEntries = v10Entries;
-                    break;
-                default:
-                    expectedEntries = baseEntries;
-                    break;
-            }
-
-            testEnumeration(jf, expectedEntries);
-            testStream(jf, expectedEntries);
-        }
-    }
-
-    @Test
-    public void testUnversionedJar() throws IOException {
-        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ)) {
-            testEnumeration(jf, uvEntries);
-            testStream(jf, uvEntries);
-        }
-
-        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.BASE)) {
-            testEnumeration(jf, uvEntries);
-            testStream(jf, uvEntries);
-        }
-
-        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
-            testEnumeration(jf, uvEntries);
-            testStream(jf, uvEntries);
-        }
-
-        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
-            testEnumeration(jf, uvEntries);
-            testStream(jf, uvEntries);
-        }
-    }
-
-    private void testEnumeration(JarFile jf, Map<String,JarEntry> expectedEntries) {
-        Map<String, JarEntry> actualEntries = new HashMap<>();
-        for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements(); ) {
-            JarEntry je = e.nextElement();
-            actualEntries.put(je.getName(), je);
-        }
-
-        testEntries(jf, actualEntries, expectedEntries);
-    }
-
-
-    private void testStream(JarFile jf, Map<String,JarEntry> expectedEntries) {
-        Map<String,JarEntry> actualEntries = jf.stream().collect(Collectors.toMap(je -> je.getName(), je -> je));
-
-        testEntries(jf, actualEntries, expectedEntries);
-    }
-
-    private void testEntries(JarFile jf, Map<String,JarEntry> actualEntries, Map<String,JarEntry> expectedEntries) {
-        /* For multi-release jar files constructed with a Release object,
-         * actualEntries contain versionedEntries that are considered part of the
-         * public API.  They have a 1-1 correspondence with baseEntries,
-         * so entries that are not part of the public API won't be present,
-         * i.e. those entries with a name that starts with version/PackagePrivate
-         * in this particular jar file (multi-release.jar)
-         */
-
-        Map<String,JarEntry> entries;
-        if (expectedEntries == mrEntries) {
-            Assert.assertEquals(actualEntries.size(), mrEntries.size());
-            entries = mrEntries;
-        } else if (expectedEntries == uvEntries) {
-            Assert.assertEquals(actualEntries.size(), uvEntries.size());
-            entries = uvEntries;
-        } else {
-            Assert.assertEquals(actualEntries.size(), baseEntries.size());  // this is correct
-            entries = baseEntries;
-        }
-
-        entries.keySet().forEach(name -> {
-            JarEntry ee = expectedEntries.get(name);
-            if (ee == null) ee = entries.get(name);
-            JarEntry ae = actualEntries.get(name);
-            try {
-                compare(jf, ae, ee);
-            } catch (IOException x) {
-                throw new RuntimeException(x);
-            }
-        });
-    }
-
-    private void compare(JarFile jf, JarEntry actual, JarEntry expected) throws IOException {
-        byte[] abytes;
-        byte[] ebytes;
-
-        try (InputStream is = jf.getInputStream(actual)) {
-            abytes = is.readAllBytes();
-        }
-
-        try (InputStream is = jf.getInputStream(expected)) {
-            ebytes = is.readAllBytes();
-        }
-
-        Assert.assertEquals(abytes, ebytes);
-    }
-}
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +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.
- *
- * 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 8132734
- * @summary Test the System properties for JarFile that support multi-release jar files
- * @library /lib/testlibrary/java/util/jar
- * @build Compiler JarBuilder CreateMultiReleaseTestJars
- * @run testng MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
- * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
- */
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.file.Files;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import jdk.Version;
-
-import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-public class MultiReleaseJarProperties {
-
-    static final int MAJOR_VERSION = Version.current().major();
-
-    final static int ROOTVERSION = 8; // magic number from knowledge of internals
-    final static String userdir = System.getProperty("user.dir", ".");
-    final static File multirelease = new File(userdir, "multi-release.jar");
-    protected int rtVersion;
-    boolean force;
-    protected ClassLoader cldr;
-    protected Class<?> rootClass;
-
-    @BeforeClass
-    public void initialize() throws Exception {
-        CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
-        creator.compileEntries();
-        creator.buildMultiReleaseJar();
-
-        rtVersion = Integer.getInteger("jdk.util.jar.version", MAJOR_VERSION);
-        String mrprop = System.getProperty("jdk.util.jar.enableMultiRelease", "");
-        if (mrprop.equals("false")) {
-            rtVersion = ROOTVERSION;
-        } else if (rtVersion < ROOTVERSION) {
-            rtVersion = ROOTVERSION;
-        } else if (rtVersion > MAJOR_VERSION) {
-            rtVersion = MAJOR_VERSION;
-        }
-        force = mrprop.equals("force");
-
-        initializeClassLoader();
-    }
-
-    protected void initializeClassLoader() throws Exception {
-        URL[] urls = new URL[]{multirelease.toURI().toURL()};
-        cldr = new URLClassLoader(urls);
-        // load any class, Main is convenient and in the root entries
-        rootClass = cldr.loadClass("version.Main");
-    }
-
-    @AfterClass
-    public void close() throws IOException {
-        ((URLClassLoader)cldr).close();
-        Files.delete(multirelease.toPath());
-    }
-
-    /*
-     * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader
-     */
-    @Test
-    public void testURLClassLoader() throws Throwable {
-        Class<?> vcls = cldr.loadClass("version.Version");
-        invokeMethod(vcls, rtVersion);
-    }
-
-    protected void invokeMethod(Class<?> vcls, int expected) throws Throwable {
-        MethodType mt = MethodType.methodType(int.class);
-        MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt);
-        Assert.assertEquals(expected, (int) mh.invoke(vcls.newInstance()));
-    }
-
-    /*
-     * jdk.util.jar.enableMultiRelease=force should affect a custom class loader
-     */
-    @Test
-    public void testClassLoader() throws Throwable {
-        try (JarFile jf = new JarFile(multirelease)) {  // do not set runtime versioning
-            ClassLoader cldr = new CustomClassLoader(jf);
-            Class<?> vcls = cldr.loadClass("version.Version");
-            if (rtVersion == 9) {
-                try {
-                    cldr.loadClass("version.PackagePrivate");
-                } catch (ClassNotFoundException x) {
-                    if (force) throw x;
-                }
-            }
-            invokeMethod(vcls, force ? rtVersion : ROOTVERSION);
-        }
-    }
-
-    private static class CustomClassLoader extends ClassLoader {
-        private final JarFile jf;
-
-        CustomClassLoader(JarFile jf) throws Exception {
-            super(null);
-            this.jf = jf;
-        }
-
-        protected Class<?> findClass(String name) throws ClassNotFoundException {
-            try {
-                byte[] b;
-                String entryName = name.replace(".", "/") + ".class";
-                JarEntry je = jf.getJarEntry(entryName);
-                if (je != null) {
-                    try (InputStream is = jf.getInputStream(je)) {
-                        b = new byte[(int) je.getSize()];
-                        is.read(b);
-                    }
-                    return defineClass(name, b, 0, b.length);
-                }
-                throw new ClassNotFoundException(name);
-            } catch (IOException x) {
-                throw new ClassNotFoundException(x.getMessage());
-            }
-        }
-    }
-
-    @Test
-    public void testGetResourceAsStream() throws Exception {
-        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
-        // use fileRootClass as a base for getting resources
-        getResourceAsStream(rootClass, resource);
-    }
-
-    protected void getResourceAsStream(Class<?> rootClass, String resource) throws Exception {
-        try (InputStream is = rootClass.getResourceAsStream(resource)) {
-            byte[] bytes = is.readAllBytes();
-            resource = new String(bytes);
-        }
-        String match = "return " + rtVersion + ";";
-        Assert.assertTrue(resource.contains(match));
-    }
-
-    @Test
-    public void testGetResource() throws Exception {
-        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
-        // use rootClass as a base for getting resources
-        getResource(rootClass, resource);
-    }
-
-    protected void getResource(Class<?> rootClass, String resource) throws Exception {
-        URL url = rootClass.getResource(resource);
-        try (InputStream is = url.openStream()) {
-            byte[] bytes = is.readAllBytes();
-            resource = new String(bytes);
-        }
-        String match = "return " + rtVersion + ";";
-        Assert.assertTrue(resource.contains(match));
-    }
-}
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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 8132734
- * @summary Test potential security related issues
- * @library /lib/testlibrary/java/util/jar
- * @build Compiler JarBuilder CreateMultiReleaseTestJars
- * @run testng MultiReleaseJarSecurity
- */
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.security.CodeSigner;
-import java.security.cert.Certificate;
-import java.util.Arrays;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.zip.ZipFile;
-import jdk.Version;
-
-import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-public class MultiReleaseJarSecurity {
-
-    static final int MAJOR_VERSION = Version.current().major();
-
-    String userdir = System.getProperty("user.dir",".");
-    File multirelease = new File(userdir, "multi-release.jar");
-    File signedmultirelease = new File(userdir, "signed-multi-release.jar");
-
-    @BeforeClass
-    public void initialize() throws Exception {
-        CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
-        creator.compileEntries();
-        creator.buildMultiReleaseJar();
-        creator.buildSignedMultiReleaseJar();
-    }
-
-    @AfterClass
-    public void close() throws IOException {
-        Files.delete(multirelease.toPath());
-        Files.delete(signedmultirelease.toPath());
-    }
-
-    @Test
-    public void testCertsAndSigners() throws IOException {
-        try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, JarFile.Release.RUNTIME)) {
-            CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class"));
-            CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + MAJOR_VERSION + "/version/Version.class"));
-            Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates()));
-            Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners()));
-        }
-    }
-
-    private static class CertsAndSigners {
-        final private JarFile jf;
-        final private JarEntry je;
-        private boolean readComplete;
-
-        CertsAndSigners(JarFile jf, JarEntry je) {
-            this.jf = jf;
-            this.je = je;
-        }
-
-        Certificate[] getCertificates() throws IOException {
-            readEntry();
-            return je.getCertificates();
-        }
-
-        CodeSigner[] getCodeSigners() throws IOException {
-            readEntry();
-            return je.getCodeSigners();
-        }
-
-        private void readEntry() throws IOException {
-            if (!readComplete) {
-                try (InputStream is = jf.getInputStream(je)) {
-                    is.readAllBytes();
-                }
-                readComplete = true;
-            }
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ *
+ * 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 8132734
+ * @summary Test the extended API and the aliasing additions in JarFile that
+ *          support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarAPI
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import jdk.Version;
+
+import static java.util.jar.JarFile.Release;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+public class MultiReleaseJarAPI {
+
+    static final int MAJOR_VERSION = Version.current().major();
+
+    String userdir = System.getProperty("user.dir",".");
+    CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
+    File unversioned = new File(userdir, "unversioned.jar");
+    File multirelease = new File(userdir, "multi-release.jar");
+    File signedmultirelease = new File(userdir, "signed-multi-release.jar");
+    Release[] values = JarFile.Release.values();
+
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        creator.compileEntries();
+        creator.buildUnversionedJar();
+        creator.buildMultiReleaseJar();
+        creator.buildSignedMultiReleaseJar();
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        Files.delete(unversioned.toPath());
+        Files.delete(multirelease.toPath());
+        Files.delete(signedmultirelease.toPath());
+    }
+
+    @Test
+    public void isMultiReleaseJar() throws Exception {
+        try (JarFile jf = new JarFile(unversioned)) {
+            Assert.assertFalse(jf.isMultiRelease());
+        }
+
+        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
+            Assert.assertFalse(jf.isMultiRelease());
+        }
+
+        try (JarFile jf = new JarFile(multirelease)) {
+            Assert.assertFalse(jf.isMultiRelease());
+        }
+
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
+            Assert.assertTrue(jf.isMultiRelease());
+        }
+
+        testCustomMultiReleaseValue("true", true);
+        testCustomMultiReleaseValue("true\r\nOther: value", true);
+        testCustomMultiReleaseValue("true\nOther: value", true);
+        testCustomMultiReleaseValue("true\rOther: value", true);
+
+        testCustomMultiReleaseValue("false", false);
+        testCustomMultiReleaseValue(" true", false);
+        testCustomMultiReleaseValue("true ", false);
+        testCustomMultiReleaseValue("true\n ", false);
+        testCustomMultiReleaseValue("true\r ", false);
+        testCustomMultiReleaseValue("true\n true", false);
+        testCustomMultiReleaseValue("true\r\n true", false);
+    }
+
+    private void testCustomMultiReleaseValue(String value, boolean expected) throws Exception {
+        creator.buildCustomMultiReleaseJar("custom-mr.jar", value);
+        File custom = new File(userdir, "custom-mr.jar");
+        try (JarFile jf = new JarFile(custom, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
+            Assert.assertEquals(jf.isMultiRelease(), expected);
+        }
+        Files.delete(custom.toPath());
+    }
+
+    @Test
+    public void testVersioning() throws Exception {
+        // multi-release jar
+        JarFile jar = new JarFile(multirelease);
+        Assert.assertEquals(Release.BASE, jar.getVersion());
+        jar.close();
+
+        for (Release value : values) {
+            System.err.println("test versioning for Release " + value);
+            try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, value)) {
+                Assert.assertEquals(value, jf.getVersion());
+            }
+        }
+
+        // regular, unversioned, jar
+        for (Release value : values) {
+            try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, value)) {
+                Assert.assertEquals(Release.BASE, jf.getVersion());
+            }
+        }
+
+        // assure that we have a Release object corresponding to the actual runtime version
+        String version = "VERSION_" + MAJOR_VERSION;
+        boolean runtimeVersionExists = false;
+        for (Release value : values) {
+            if (version.equals(value.name())) runtimeVersionExists = true;
+        }
+        Assert.assertTrue(runtimeVersionExists);
+    }
+
+    @Test
+    public void testAliasing() throws Exception {
+        for (Release value : values) {
+            System.err.println("test aliasing for Release " + value);
+            String name = value.name();
+            String prefix;
+            if (name.equals("BASE")) {
+                prefix = "";
+            } else if (name.equals("RUNTIME")) {
+                prefix = "META-INF/versions/" + MAJOR_VERSION + "/";
+            } else {
+                prefix = "META-INF/versions/" + name.substring(8) + "/";
+            }
+            // test both multi-release jars
+            readAndCompare(multirelease, value, "README", prefix + "README");
+            readAndCompare(multirelease, value, "version/Version.class", prefix + "version/Version.class");
+            // and signed multi-release jars
+            readAndCompare(signedmultirelease, value, "README", prefix + "README");
+            readAndCompare(signedmultirelease, value, "version/Version.class", prefix + "version/Version.class");
+        }
+    }
+
+    private void readAndCompare(File jar, Release version, String name, String realName) throws Exception {
+        byte[] baseBytes;
+        byte[] versionedBytes;
+        try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, Release.BASE)) {
+            ZipEntry ze = jf.getEntry(realName);
+            try (InputStream is = jf.getInputStream(ze)) {
+                baseBytes = is.readAllBytes();
+            }
+        }
+        assert baseBytes.length > 0;
+
+        try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, version)) {
+            ZipEntry ze = jf.getEntry(name);
+            try (InputStream is = jf.getInputStream(ze)) {
+                versionedBytes = is.readAllBytes();
+            }
+        }
+        assert versionedBytes.length > 0;
+
+        Assert.assertTrue(Arrays.equals(baseBytes, versionedBytes));
+    }
+
+    @Test
+    public void testNames() throws Exception {
+        String rname = "version/Version.class";
+        String vname = "META-INF/versions/9/version/Version.class";
+        ZipEntry ze1;
+        ZipEntry ze2;
+        try (JarFile jf = new JarFile(multirelease)) {
+            ze1 = jf.getEntry(vname);
+        }
+        Assert.assertEquals(ze1.getName(), vname);
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
+            ze2 = jf.getEntry(rname);
+        }
+        Assert.assertEquals(ze2.getName(), rname);
+        Assert.assertNotEquals(ze1.getName(), ze2.getName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarHttpProperties.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8132734
+ * @summary Test the System properties for JarFile that support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @modules jdk.jartool
+ *          jdk.compiler
+ *          jdk.httpserver
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars SimpleHttpServer
+ * @run testng MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties {
+    private SimpleHttpServer server;
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        server = new SimpleHttpServer();
+        server.start();
+        super.initialize();
+    }
+
+    @Override
+    protected void initializeClassLoader() throws Exception {
+        URL[] urls = new URL[]{
+                new URL("http://localhost:" + server.getPort() + "/multi-release.jar")
+        };
+        cldr = new URLClassLoader(urls);
+        // load any class, Main is convenient and in the root entries
+        rootClass = cldr.loadClass("version.Main");
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        // Windows requires server to stop before file is deleted
+        if (server != null)
+            server.stop();
+        super.close();
+    }
+
+    /*
+     * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader
+     */
+
+    @Test
+    public void testURLClassLoader() throws Throwable {
+        Class<?> vcls = cldr.loadClass("version.Version");
+        invokeMethod(vcls, rtVersion);
+    }
+
+    @Test
+    public void testGetResourceAsStream() throws Exception {
+        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+        // use rootClass as a base for getting resources
+        getResourceAsStream(rootClass, resource);
+    }
+
+    @Test
+    public void testGetResource() throws Exception {
+        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+        // use rootClass as a base for getting resources
+        getResource(rootClass, resource);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarIterators.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ *
+ * 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 8132734
+ * @summary Test the extended API and the aliasing additions in JarFile that
+ *          support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarIterators
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.zip.ZipFile;
+import jdk.Version;
+
+import static java.util.jar.JarFile.Release;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+public class MultiReleaseJarIterators {
+
+    static final int MAJOR_VERSION = Version.current().major();
+
+    String userdir = System.getProperty("user.dir", ".");
+    File unversioned = new File(userdir, "unversioned.jar");
+    File multirelease = new File(userdir, "multi-release.jar");
+    Map<String,JarEntry> uvEntries = new HashMap<>();
+    Map<String,JarEntry> mrEntries = new HashMap<>();
+    Map<String,JarEntry> baseEntries = new HashMap<>();
+    Map<String,JarEntry> v9Entries = new HashMap<>();
+    Map<String, JarEntry> v10Entries = new HashMap<>();
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
+        creator.compileEntries();
+        creator.buildUnversionedJar();
+        creator.buildMultiReleaseJar();
+
+        try (JarFile jf = new JarFile(multirelease)) {
+            for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements(); ) {
+                JarEntry je = e.nextElement();
+                String name = je.getName();
+                mrEntries.put(name, je);
+                if (name.startsWith("META-INF/versions/")) {
+                    if (name.startsWith("META-INF/versions/9/")) {
+                        v9Entries.put(name.substring(20), je);
+                    } else if (name.startsWith("META-INF/versions/10/")) {
+                        v10Entries.put(name.substring(21), je);
+                    }
+                } else {
+                    baseEntries.put(name, je);
+                }
+            }
+        }
+        Assert.assertEquals(mrEntries.size(), 14);
+        Assert.assertEquals(baseEntries.size(), 6);
+        Assert.assertEquals(v9Entries.size(), 5);
+        Assert.assertEquals(v10Entries.size(), 3);
+
+        try (JarFile jf = new JarFile(unversioned)) {
+            jf.entries().asIterator().forEachRemaining(je -> uvEntries.put(je.getName(), je));
+        }
+        Assert.assertEquals(uvEntries.size(), 6);
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        Files.delete(unversioned.toPath());
+        Files.delete(multirelease.toPath());
+    }
+
+    @Test
+    public void testMultiReleaseJar() throws IOException {
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ)) {
+            testEnumeration(jf, mrEntries);
+            testStream(jf, mrEntries);
+        }
+
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.BASE)) {
+            testEnumeration(jf, baseEntries);
+            testStream(jf, baseEntries);
+        }
+
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
+            testEnumeration(jf, v9Entries);
+            testStream(jf, v9Entries);
+        }
+
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
+            Map<String,JarEntry> expectedEntries;
+            switch (MAJOR_VERSION) {
+                case 9:
+                    expectedEntries = v9Entries;
+                    break;
+                case 10:  // won't get here until JDK 10
+                    expectedEntries = v10Entries;
+                    break;
+                default:
+                    expectedEntries = baseEntries;
+                    break;
+            }
+
+            testEnumeration(jf, expectedEntries);
+            testStream(jf, expectedEntries);
+        }
+    }
+
+    @Test
+    public void testUnversionedJar() throws IOException {
+        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ)) {
+            testEnumeration(jf, uvEntries);
+            testStream(jf, uvEntries);
+        }
+
+        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.BASE)) {
+            testEnumeration(jf, uvEntries);
+            testStream(jf, uvEntries);
+        }
+
+        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
+            testEnumeration(jf, uvEntries);
+            testStream(jf, uvEntries);
+        }
+
+        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
+            testEnumeration(jf, uvEntries);
+            testStream(jf, uvEntries);
+        }
+    }
+
+    private void testEnumeration(JarFile jf, Map<String,JarEntry> expectedEntries) {
+        Map<String, JarEntry> actualEntries = new HashMap<>();
+        for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements(); ) {
+            JarEntry je = e.nextElement();
+            actualEntries.put(je.getName(), je);
+        }
+
+        testEntries(jf, actualEntries, expectedEntries);
+    }
+
+
+    private void testStream(JarFile jf, Map<String,JarEntry> expectedEntries) {
+        Map<String,JarEntry> actualEntries = jf.stream().collect(Collectors.toMap(je -> je.getName(), je -> je));
+
+        testEntries(jf, actualEntries, expectedEntries);
+    }
+
+    private void testEntries(JarFile jf, Map<String,JarEntry> actualEntries, Map<String,JarEntry> expectedEntries) {
+        /* For multi-release jar files constructed with a Release object,
+         * actualEntries contain versionedEntries that are considered part of the
+         * public API.  They have a 1-1 correspondence with baseEntries,
+         * so entries that are not part of the public API won't be present,
+         * i.e. those entries with a name that starts with version/PackagePrivate
+         * in this particular jar file (multi-release.jar)
+         */
+
+        Map<String,JarEntry> entries;
+        if (expectedEntries == mrEntries) {
+            Assert.assertEquals(actualEntries.size(), mrEntries.size());
+            entries = mrEntries;
+        } else if (expectedEntries == uvEntries) {
+            Assert.assertEquals(actualEntries.size(), uvEntries.size());
+            entries = uvEntries;
+        } else {
+            Assert.assertEquals(actualEntries.size(), baseEntries.size());  // this is correct
+            entries = baseEntries;
+        }
+
+        entries.keySet().forEach(name -> {
+            JarEntry ee = expectedEntries.get(name);
+            if (ee == null) ee = entries.get(name);
+            JarEntry ae = actualEntries.get(name);
+            try {
+                compare(jf, ae, ee);
+            } catch (IOException x) {
+                throw new RuntimeException(x);
+            }
+        });
+    }
+
+    private void compare(JarFile jf, JarEntry actual, JarEntry expected) throws IOException {
+        byte[] abytes;
+        byte[] ebytes;
+
+        try (InputStream is = jf.getInputStream(actual)) {
+            abytes = is.readAllBytes();
+        }
+
+        try (InputStream is = jf.getInputStream(expected)) {
+            ebytes = is.readAllBytes();
+        }
+
+        Assert.assertEquals(abytes, ebytes);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarProperties.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ *
+ * 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 8132734
+ * @summary Test the System properties for JarFile that support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import jdk.Version;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarProperties {
+
+    static final int MAJOR_VERSION = Version.current().major();
+
+    final static int ROOTVERSION = 8; // magic number from knowledge of internals
+    final static String userdir = System.getProperty("user.dir", ".");
+    final static File multirelease = new File(userdir, "multi-release.jar");
+    protected int rtVersion;
+    boolean force;
+    protected ClassLoader cldr;
+    protected Class<?> rootClass;
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
+        creator.compileEntries();
+        creator.buildMultiReleaseJar();
+
+        rtVersion = Integer.getInteger("jdk.util.jar.version", MAJOR_VERSION);
+        String mrprop = System.getProperty("jdk.util.jar.enableMultiRelease", "");
+        if (mrprop.equals("false")) {
+            rtVersion = ROOTVERSION;
+        } else if (rtVersion < ROOTVERSION) {
+            rtVersion = ROOTVERSION;
+        } else if (rtVersion > MAJOR_VERSION) {
+            rtVersion = MAJOR_VERSION;
+        }
+        force = mrprop.equals("force");
+
+        initializeClassLoader();
+    }
+
+    protected void initializeClassLoader() throws Exception {
+        URL[] urls = new URL[]{multirelease.toURI().toURL()};
+        cldr = new URLClassLoader(urls);
+        // load any class, Main is convenient and in the root entries
+        rootClass = cldr.loadClass("version.Main");
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        ((URLClassLoader)cldr).close();
+        Files.delete(multirelease.toPath());
+    }
+
+    /*
+     * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader
+     */
+    @Test
+    public void testURLClassLoader() throws Throwable {
+        Class<?> vcls = cldr.loadClass("version.Version");
+        invokeMethod(vcls, rtVersion);
+    }
+
+    protected void invokeMethod(Class<?> vcls, int expected) throws Throwable {
+        MethodType mt = MethodType.methodType(int.class);
+        MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt);
+        Assert.assertEquals(expected, (int) mh.invoke(vcls.newInstance()));
+    }
+
+    /*
+     * jdk.util.jar.enableMultiRelease=force should affect a custom class loader
+     */
+    @Test
+    public void testClassLoader() throws Throwable {
+        try (JarFile jf = new JarFile(multirelease)) {  // do not set runtime versioning
+            ClassLoader cldr = new CustomClassLoader(jf);
+            Class<?> vcls = cldr.loadClass("version.Version");
+            if (rtVersion == 9) {
+                try {
+                    cldr.loadClass("version.PackagePrivate");
+                } catch (ClassNotFoundException x) {
+                    if (force) throw x;
+                }
+            }
+            invokeMethod(vcls, force ? rtVersion : ROOTVERSION);
+        }
+    }
+
+    private static class CustomClassLoader extends ClassLoader {
+        private final JarFile jf;
+
+        CustomClassLoader(JarFile jf) throws Exception {
+            super(null);
+            this.jf = jf;
+        }
+
+        protected Class<?> findClass(String name) throws ClassNotFoundException {
+            try {
+                byte[] b;
+                String entryName = name.replace(".", "/") + ".class";
+                JarEntry je = jf.getJarEntry(entryName);
+                if (je != null) {
+                    try (InputStream is = jf.getInputStream(je)) {
+                        b = new byte[(int) je.getSize()];
+                        is.read(b);
+                    }
+                    return defineClass(name, b, 0, b.length);
+                }
+                throw new ClassNotFoundException(name);
+            } catch (IOException x) {
+                throw new ClassNotFoundException(x.getMessage());
+            }
+        }
+    }
+
+    @Test
+    public void testGetResourceAsStream() throws Exception {
+        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+        // use fileRootClass as a base for getting resources
+        getResourceAsStream(rootClass, resource);
+    }
+
+    protected void getResourceAsStream(Class<?> rootClass, String resource) throws Exception {
+        try (InputStream is = rootClass.getResourceAsStream(resource)) {
+            byte[] bytes = is.readAllBytes();
+            resource = new String(bytes);
+        }
+        String match = "return " + rtVersion + ";";
+        Assert.assertTrue(resource.contains(match));
+    }
+
+    @Test
+    public void testGetResource() throws Exception {
+        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+        // use rootClass as a base for getting resources
+        getResource(rootClass, resource);
+    }
+
+    protected void getResource(Class<?> rootClass, String resource) throws Exception {
+        URL url = rootClass.getResource(resource);
+        try (InputStream is = url.openStream()) {
+            byte[] bytes = is.readAllBytes();
+            resource = new String(bytes);
+        }
+        String match = "return " + rtVersion + ";";
+        Assert.assertTrue(resource.contains(match));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarSecurity.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ *
+ * 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 8132734
+ * @summary Test potential security related issues
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarSecurity
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.security.CodeSigner;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.zip.ZipFile;
+import jdk.Version;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarSecurity {
+
+    static final int MAJOR_VERSION = Version.current().major();
+
+    String userdir = System.getProperty("user.dir",".");
+    File multirelease = new File(userdir, "multi-release.jar");
+    File signedmultirelease = new File(userdir, "signed-multi-release.jar");
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
+        creator.compileEntries();
+        creator.buildMultiReleaseJar();
+        creator.buildSignedMultiReleaseJar();
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        Files.delete(multirelease.toPath());
+        Files.delete(signedmultirelease.toPath());
+    }
+
+    @Test
+    public void testCertsAndSigners() throws IOException {
+        try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, JarFile.Release.RUNTIME)) {
+            CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class"));
+            CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + MAJOR_VERSION + "/version/Version.class"));
+            Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates()));
+            Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners()));
+        }
+    }
+
+    private static class CertsAndSigners {
+        final private JarFile jf;
+        final private JarEntry je;
+        private boolean readComplete;
+
+        CertsAndSigners(JarFile jf, JarEntry je) {
+            this.jf = jf;
+            this.je = je;
+        }
+
+        Certificate[] getCertificates() throws IOException {
+            readEntry();
+            return je.getCertificates();
+        }
+
+        CodeSigner[] getCodeSigners() throws IOException {
+            readEntry();
+            return je.getCodeSigners();
+        }
+
+        private void readEntry() throws IOException {
+            if (!readComplete) {
+                try (InputStream is = jf.getInputStream(je)) {
+                    is.readAllBytes();
+                }
+                readComplete = true;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/jar/JarFile/mrjar/TEST.properties	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,3 @@
+modules = \
+    jdk.compiler \
+    jdk.jartool
--- a/jdk/test/java/util/regex/RegExTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/util/regex/RegExTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -33,6 +33,9 @@
  * 6350801 6676425 6878475 6919132 6931676 6948903 6990617 7014645 7039066
  * 7067045 7014640 7189363 8007395 8013252 8013254 8012646 8023647 6559590
  * 8027645 8035076 8039124 8035975 8074678 6854417 8143854 8147531 7071819
+ * 8151481 4867170 7080302 6728861 6995635 6736245 4916384
+ * 6328855 6192895 6345469 6988218 6693451 7006761 8140212
+ *
  * @library /lib/testlibrary
  * @build jdk.testlibrary.*
  * @run main RegExTest
@@ -162,6 +165,7 @@
         patternAsPredicate();
         invalidFlags();
         grapheme();
+        expoBacktracking();
 
         if (failure) {
             throw new
@@ -2659,51 +2663,101 @@
         check(p, "test\u00e4\u0323\u0300", true);
         check(p, "test\u00e4\u0300\u0323", true);
 
-        /*
-         * The following canonical equivalence tests don't work. Bug id: 4916384.
-         *
+        Object[][] data = new Object[][] {
+
+        // JDK-4867170
+        { "[\u1f80-\u1f82]", "ab\u1f80cd",             "f", true },
+        { "[\u1f80-\u1f82]", "ab\u1f81cd",             "f", true },
+        { "[\u1f80-\u1f82]", "ab\u1f82cd",             "f", true },
+        { "[\u1f80-\u1f82]", "ab\u03b1\u0314\u0345cd", "f", true },
+        { "[\u1f80-\u1f82]", "ab\u03b1\u0345\u0314cd", "f", true },
+        { "[\u1f80-\u1f82]", "ab\u1f01\u0345cd",       "f", true },
+        { "[\u1f80-\u1f82]", "ab\u1f00\u0345cd",       "f", true },
+
+        { "\\p{IsGreek}",    "ab\u1f80cd",             "f", true },
+        { "\\p{IsGreek}",    "ab\u1f81cd",             "f", true },
+        { "\\p{IsGreek}",    "ab\u1f82cd",             "f", true },
+        { "\\p{IsGreek}",    "ab\u03b1\u0314\u0345cd", "f", true },
+        { "\\p{IsGreek}",    "ab\u1f01\u0345cd",       "f", true },
+
+        // backtracking, force to match "\u1f80", instead of \u1f82"
+        { "ab\\p{IsGreek}\u0300cd", "ab\u03b1\u0313\u0345\u0300cd", "m", true },
+
+        { "[\\p{IsGreek}]",  "\u03b1\u0314\u0345",     "m", true },
+        { "\\p{IsGreek}",    "\u03b1\u0314\u0345",     "m", true },
+
+        { "[^\u1f80-\u1f82]","\u1f81",                 "m", false },
+        { "[^\u1f80-\u1f82]","\u03b1\u0314\u0345",     "m", false },
+        { "[^\u1f01\u0345]", "\u1f81",                 "f", false },
+
+        { "[^\u1f81]+",      "\u1f80\u1f82",           "f", true },
+        { "[\u1f80]",        "ab\u1f80cd",             "f", true },
+        { "\u1f80",          "ab\u1f80cd",             "f", true },
+        { "\u1f00\u0345\u0300",  "\u1f82", "m", true },
+        { "\u1f80",          "-\u1f00\u0345\u0300-",   "f", true },
+        { "\u1f82",          "\u1f00\u0345\u0300",     "m", true },
+        { "\u1f82",          "\u1f80\u0300",           "m", true },
+
+        // JDK-7080302       # compile failed
+        { "a(\u0041\u0301\u0328)", "a\u0041\u0301\u0328", "m", true},
+
+        // JDK-6728861, same cause as above one
+        { "\u00e9\u00e9n", "e\u0301e\u0301n", "m", true},
+
+        // JDK-6995635
+        { "(\u00e9)", "e\u0301", "m", true },
+
+        // JDK-6736245
+        // intereting special case, nfc(u2add+u0338) -> u2add+u0338) NOT u2adc
+        { "\u2ADC", "\u2ADC", "m", true},          // NFC
+        { "\u2ADC", "\u2ADD\u0338", "m", true},    // NFD
+
+        //  4916384.
+        // Decomposed hangul (jamos) works inside clazz
+        { "[\u1100\u1161]", "\u1100\u1161", "m", true},
+        { "[\u1100\u1161]", "\uac00", "m", true},
+
+        { "[\uac00]", "\u1100\u1161", "m", true},
+        { "[\uac00]", "\uac00", "m", true},
+
         // Decomposed hangul (jamos)
-        p = Pattern.compile("\u1100\u1161", Pattern.CANON_EQ);
-        m = p.matcher("\u1100\u1161");
-        if (!m.matches())
-            failCount++;
-
-        m.reset("\uac00");
-        if (!m.matches())
-            failCount++;
+        { "\u1100\u1161", "\u1100\u1161", "m", true},
+        { "\u1100\u1161", "\uac00", "m", true},
 
         // Composed hangul
-        p = Pattern.compile("\uac00", Pattern.CANON_EQ);
-        m = p.matcher("\u1100\u1161");
-        if (!m.matches())
-            failCount++;
-
-        m.reset("\uac00");
-        if (!m.matches())
-            failCount++;
+        { "\uac00",  "\u1100\u1161", "m", true },
+        { "\uac00",  "\uac00", "m", true },
+
+        /* Need a NFDSlice to nfd the source to solve this issue
+           u+1d1c0 -> nfd: <u+1d1ba><u+1d165><u+1d16f>  -> nfc: <u+1d1ba><u+1d165><u+1d16f>
+           u+1d1bc -> nfd: <u+1d1ba><u+1d165>           -> nfc: <u+1d1ba><u+1d165>
+           <u+1d1bc><u+1d16f> -> nfd: <u+1d1ba><u+1d165><u+1d16f> -> nfc: <u+1d1ba><u+1d165><u+1d16f>
 
         // Decomposed supplementary outside char classes
-        p = Pattern.compile("test\ud834\uddbc\ud834\udd6f", Pattern.CANON_EQ);
-        m = p.matcher("test\ud834\uddc0");
-        if (!m.matches())
-            failCount++;
-
-        m.reset("test\ud834\uddbc\ud834\udd6f");
-        if (!m.matches())
-            failCount++;
-
+        // { "test\ud834\uddbc\ud834\udd6f", "test\ud834\uddc0", "m", true },
         // Composed supplementary outside char classes
-        p = Pattern.compile("test\ud834\uddc0", Pattern.CANON_EQ);
-        m.reset("test\ud834\uddbc\ud834\udd6f");
-        if (!m.matches())
-            failCount++;
-
-        m = p.matcher("test\ud834\uddc0");
-        if (!m.matches())
-            failCount++;
-
+        // { "test\ud834\uddc0", "test\ud834\uddbc\ud834\udd6f", "m", true },
         */
-
+        { "test\ud834\uddbc\ud834\udd6f", "test\ud834\uddbc\ud834\udd6f", "m", true },
+        { "test\ud834\uddc0",             "test\ud834\uddbc\ud834\udd6f", "m", true },
+
+        { "test\ud834\uddc0",             "test\ud834\uddc0",             "m", true },
+        { "test\ud834\uddbc\ud834\udd6f", "test\ud834\uddc0",             "m", true },
+        };
+
+        int failCount = 0;
+        for (Object[] d : data) {
+            String pn = (String)d[0];
+            String tt = (String)d[1];
+            boolean isFind = "f".equals(((String)d[2]));
+            boolean expected = (boolean)d[3];
+            boolean ret = isFind ? Pattern.compile(pn, Pattern.CANON_EQ).matcher(tt).find()
+                                 : Pattern.compile(pn, Pattern.CANON_EQ).matcher(tt).matches();
+            if (ret != expected) {
+                failCount++;
+                continue;
+            }
+        }
         report("Canonical Equivalence");
     }
 
@@ -3846,7 +3900,6 @@
         if (!patternString.startsWith("'")) {
             return Pattern.compile(patternString);
         }
-
         int break1 = patternString.lastIndexOf("'");
         String flagString = patternString.substring(
                                           break1+1, patternString.length());
@@ -4092,10 +4145,11 @@
         report("NamedGroupCapture");
     }
 
-    // This is for bug 6969132
+    // This is for bug 6919132
     private static void nonBmpClassComplementTest() throws Exception {
         Pattern p = Pattern.compile("\\P{Lu}");
         Matcher m = p.matcher(new String(new int[] {0x1d400}, 0, 1));
+
         if (m.find() && m.start() == 1)
             failCount++;
 
@@ -4113,6 +4167,11 @@
         if (m.find() && m.start() == 1)
             failCount++;
 
+        p = Pattern.compile("\\P{sc=GRANTHA}");
+        m = p.matcher(new String(new int[] {0x11350}, 0, 1));
+        if (m.find() && m.start() == 1)
+            failCount++;
+
         report("NonBmpClassComplement");
     }
 
@@ -4662,4 +4721,92 @@
             failCount++;
         report("Unicode extended grapheme cluster");
     }
+
+    // hangup/timeout if go into exponential backtracking
+    private static void expoBacktracking() throws Exception {
+
+        Object[][] patternMatchers = {
+            // 6328855
+            { "(.*\n*)*",
+              "this little fine string lets\r\njava.lang.String.matches\r\ncrash\r\n(We don't know why but adding \r* to the regex makes it work again)",
+              false },
+            // 6192895
+            { " *([a-zA-Z0-9/\\-\\?:\\(\\)\\.,'\\+\\{\\}]+ *)+",
+              "Hello World this is a test this is a test this is a test A",
+              true },
+            { " *([a-zA-Z0-9/\\-\\?:\\(\\)\\.,'\\+\\{\\}]+ *)+",
+              "Hello World this is a test this is a test this is a test \u4e00 ",
+              false },
+            { " *([a-z0-9]+ *)+",
+              "hello world this is a test this is a test this is a test A",
+              false },
+            // 4771934 [FIXED] #5013651?
+            { "^(\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,4})+[,;]?)+$",
+              "abc@efg.abc,efg@abc.abc,abc@xyz.mno;abc@sdfsd.com",
+              true },
+            // 4866249 [FIXED]
+            { "<\\s*" + "(meta|META)" + "(\\s|[^>])+" + "(CHARSET|charset)=" + "(\\s|[^>])+>",
+              "<META http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-5\">",
+              true },
+            { "^(\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,4})+[,;]?)+$",
+              "abc@efg.abc,efg@abc.abc,abc@xyz.mno;sdfsd.com",
+              false },
+            // 6345469
+            { "((<[^>]+>)?(((\\s)?)*(\\&nbsp;)?)*((\\s)?)*)+",
+              "&nbsp;&nbsp; < br/> &nbsp; < / p> <p> <html> <adfasfdasdf>&nbsp; </p>",
+              true }, // --> matched
+            { "((<[^>]+>)?(((\\s)?)*(\\&nbsp;)?)*((\\s)?)*)+",
+              "&nbsp;&nbsp; < br/> &nbsp; < / p> <p> <html> <adfasfdasdf>&nbsp; p </p>",
+              false },
+            // 5026912
+            { "^\\s*" + "(\\w|\\d|[\\xC0-\\xFF]|/)+" + "\\s+|$",
+              "156580451111112225588087755221111111566969655555555",
+              false},
+            // 6988218
+            { "^([+-]?((0[xX](\\p{XDigit}+))|(((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)))|[n|N]?'([^']*(?:'')*[^']*)*')",
+              "'%)) order by ANGEBOT.ID",
+              false},    // find
+            // 6693451
+            { "^(\\s*foo\\s*)*$",
+              "foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo",
+              true },
+            { "^(\\s*foo\\s*)*$",
+              "foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo fo",
+              false
+            },
+            // 7006761
+            { "(([0-9A-Z]+)([_]?+)*)*", "FOOOOO_BAAAR_FOOOOOOOOO_BA_", true},
+            { "(([0-9A-Z]+)([_]?+)*)*", "FOOOOO_BAAAR_FOOOOOOOOO_BA_ ", false},
+            // 8140212
+            { "(?<before>.*)\\{(?<reflection>\\w+):(?<innerMethod>\\w+(\\.?\\w+(\\(((?<args>(('[^']*')|((/|\\w)+))(,(('[^']*')|((/|\\w)+)))*))?\\))?)*)\\}(?<after>.*)",
+              "{CeGlobal:getSodCutoff.getGui.getAmqp.getSimpleModeEnabled()",
+              false
+            },
+            { "^(a+)+$", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", true},
+            { "^(a+)+$", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!", false},
+
+            { "(x+)*y",  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy", true },
+            { "(x+)*y",  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz", false},
+
+            { "(x+x+)+y", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy", true},
+            { "(x+x+)+y", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz", false},
+
+            { "(([0-9A-Z]+)([_]?+)*)*", "--------------------------------------", false},
+
+            /* not fixed
+            //8132141   --->    second level exponential backtracking
+            { "(h|h|ih(((i|a|c|c|a|i|i|j|b|a|i|b|a|a|j))+h)ahbfhba|c|i)*",
+              "hchcchicihcchciiicichhcichcihcchiihichiciiiihhcchicchhcihchcihiihciichhccciccichcichiihcchcihhicchcciicchcccihiiihhihihihichicihhcciccchihhhcchichchciihiicihciihcccciciccicciiiiiiiiicihhhiiiihchccchchhhhiiihchihcccchhhiiiiiiiicicichicihcciciihichhhhchihciiihhiccccccciciihhichiccchhicchicihihccichicciihcichccihhiciccccccccichhhhihihhcchchihihiihhihihihicichihiiiihhhhihhhchhichiicihhiiiiihchccccchichci" },
+            */
+        };
+
+        for (Object[] pm : patternMatchers) {
+            String p = (String)pm[0];
+            String s = (String)pm[1];
+            boolean r = (Boolean)pm[2];
+            if (r != Pattern.compile(p).matcher(s).matches()) {
+                failCount++;
+            }
+        }
+    }
 }
--- a/jdk/test/java/util/regex/TestCases.txt	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/java/util/regex/TestCases.txt	Wed Jul 05 21:42:16 2017 +0200
@@ -139,6 +139,71 @@
 aaabbbcccdefg
 true defg 0
 
+// Negation with nested char class and intersection
+[^[c]]
+c
+false 0
+
+[^[a-z]]
+e
+false 0
+
+[^[a-z][A-Z]]
+E
+false 0
+
+[^a-d[0-9][m-p]]
+e
+true e 0
+
+[^a-d[0-9][m-p]]
+8
+false 0
+
+[^[a-c]&&[d-f]]
+z
+true z 0
+
+[^a-c&&d-f]
+a
+true a 0
+
+[^a-m&&m-z]
+m
+false 0
+
+[^a-m&&m-z&&a-c]
+m
+true m 0
+
+[^a-cd-f&&[d-f]]
+c
+true c 0
+
+[^[a-c][d-f]&&abc]
+a
+false 0
+
+[^[a-c][d-f]&&abc]
+d
+true d 0
+
+[^[a-c][d-f]&&abc[def]]
+a
+false 0
+
+[^[a-c][d-f]&&abc[def]]
+e
+false 0
+
+[^[a-c]&&[b-d]&&[c-e]]
+a
+true a 0
+
+[^[a-c]&&[b-d]&&[c-e]]
+c
+false 0
+
 // Making sure a ^ not in first position matches literal ^
 [abc^b]
 b
--- a/jdk/test/lib/testlibrary/java/util/jar/Compiler.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/lib/testlibrary/java/util/jar/Compiler.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
@@ -44,7 +44,7 @@
         // so do it the old fashioned way
         // options = Arrays.asList("-release", String.valueOf(release));
         String target = String.valueOf(release);
-        options = Arrays.asList("-source", target, "-target", target);
+        options = Arrays.asList("-source", target, "-target", target, "-classpath", "");
         return this;
     }
 
@@ -53,7 +53,9 @@
         Map<String,ClassFileObject> cfos = createClassFileObjects();
         JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
         JavaFileManager jfm = new CustomFileManager(jc.getStandardFileManager(null, null, null), cfos);
-        jc.getTask(null, jfm, null, options, null, cunits).call();
+        if(!jc.getTask(null, jfm, null, options, null, cunits).call()) {
+            throw new RuntimeException("Compilation failed");
+        }
         return createOutput(cfos);
     }
 
--- a/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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 8023862
- * @summary Verify that the default value of the java.rmi.server.disableHttp
- *          has been changed from false to true.
- * @modules java.rmi/sun.rmi.transport.proxy
- * @compile -XDignore.symbol.file DisableHttpDefaultValue.java
- *
- * @run main/othervm                                     DisableHttpDefaultValue true
- * @run main/othervm -Djava.rmi.server.disableHttp       DisableHttpDefaultValue false
- * @run main/othervm -Djava.rmi.server.disableHttp=false DisableHttpDefaultValue false
- * @run main/othervm -Djava.rmi.server.disableHttp=xyzzy DisableHttpDefaultValue false
- * @run main/othervm -Djava.rmi.server.disableHttp=true  DisableHttpDefaultValue true
- */
-
-import sun.rmi.transport.proxy.RMIMasterSocketFactory;
-
-public class DisableHttpDefaultValue {
-    /**
-     * Subclass RMIMasterSocketFactory to get access to
-     * protected field altFactoryList. This list has a
-     * zero size if proxying is disabled.
-     */
-    static class SocketFactory extends RMIMasterSocketFactory {
-        boolean proxyDisabled() {
-            return altFactoryList.size() == 0;
-        }
-    }
-
-    /**
-     * Takes a single arg, which is the expected boolean value of
-     * java.rmi.server.disableHttp.
-     */
-    public static void main(String[] args) throws Exception {
-        // Force there to be a proxy host, so that we are able to
-        // tell whether proxying is enabled or disabled.
-        System.setProperty("http.proxyHost", "proxy.example.com");
-
-        String propval = System.getProperty("java.rmi.server.disableHttp");
-        String propdisp = (propval == null) ? "null" : ("\"" + propval + "\"");
-        boolean expected = Boolean.parseBoolean(args[0]);
-        boolean actual = new SocketFactory().proxyDisabled();
-        System.out.printf("### prop=%s exp=%s act=%s%n", propdisp, expected, actual);
-        if (expected != actual)
-            throw new AssertionError();
-    }
-}
--- a/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2002, 2012, 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 4290727
- * @summary Verify that ConnectException will trigger HTTP fallback if
- *          sun.rmi.transport.proxy.eagerHttpFallback system property is set.
- *
- * @library ../../../../java/rmi/testlibrary
- * @modules java.rmi/sun.rmi.registry
- *          java.rmi/sun.rmi.server
- *          java.rmi/sun.rmi.transport
- *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary
- * @run main/othervm EagerHttpFallback
- */
-
-import java.rmi.*;
-import java.rmi.registry.*;
-
-public class EagerHttpFallback {
-
-    static final int INITIAL_PORT = TestLibrary.getUnusedRandomPort();
-    static final int FALLBACK_PORT = TestLibrary.getUnusedRandomPort();
-
-    public static void main(String[] args) throws Exception {
-        System.setProperty("http.proxyHost", "127.0.0.1");
-        System.setProperty("http.proxyPort", Integer.toString(FALLBACK_PORT));
-        System.setProperty("sun.rmi.transport.proxy.eagerHttpFallback",
-                           "true");
-        LocateRegistry.createRegistry(FALLBACK_PORT);
-
-        /*
-         * The call below should trigger a ConnectException in the
-         * RMIMasterSocketFactory when it attempts a direct connection to
-         * INITIAL_PORT, which no one is listening on.  Since
-         * eagerHttpFallback is set, this ConnectException should trigger HTTP
-         * fallback, which will send a call through the HTTP proxy, which is
-         * configured to be localhost with a port behind which a registry is
-         * listening--so if fallback works properly, the list() call should
-         * succeed.
-         */
-        try {
-            LocateRegistry.getRegistry(INITIAL_PORT).list();
-        } catch (Exception e) {
-            System.err.println(
-                "call on registry stub with port " + INITIAL_PORT +
-                "did not successfully perform HTTP fallback to " +
-                FALLBACK_PORT);
-            throw e;
-        }
-    }
-}
--- a/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 1999, 2012, 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 4203167
- *
- * @summary RMI blocks in HttpAwareServerSocket.accept() if you telnet to it
- * @author Adrian Colley
- *
- * @library ../../../../../java/rmi/testlibrary
- * @modules java.rmi/sun.rmi.transport.proxy
- * @build TestIface TestImpl TestImpl_Stub
- * @run main/othervm/policy=security.policy/timeout=60 BlockAcceptTest
- */
-
-/* This test attempts to stymie the RMI accept loop.  The accept loop in
- * RMI endlessly accepts a connection, spawns a thread for it, and repeats.
- * The accept() call can be replaced by a user-supplied library which
- * might foolishly block indefinitely in its accept() method, which would
- * prevent RMI from accepting other connections on that socket.
- *
- * Unfortunately, HttpAwareServerSocket (default server socket) is/was such
- * a foolish thing.  It reads 4 bytes to see if they're "POST" before
- * returning.  The bug fix is to move the HTTP stuff into the mainloop,
- * which has the side effect of enabling it for non-default socketfactories.
- *
- * This test:
- * 1. Creates an object and exports it.
- * 2. Connects to the listening RMI port and sends nothing, to hold it up.
- * 3. Makes a regular call, using HTTP tunnelling.
- * 4. Fails to deadlock, thereby passing the test.
- *
- * Some runtime dependencies I'm trying to eliminate:
- * 1. We don't know the port number until after exporting the object, but
- *    have to set it in http.proxyPort somehow.  Hopefully http.proxyPort
- *    isn't read too soon or this test will fail with a ConnectException.
- */
-
-import java.rmi.*;
-import java.rmi.server.RMISocketFactory;
-import java.io.*;
-import java.net.*;
-
-import sun.rmi.transport.proxy.RMIMasterSocketFactory;
-import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory;
-
-public class BlockAcceptTest
-{
-    public static void main(String[] args)
-        throws Exception
-    {
-        // Make trouble for ourselves
-        if (System.getSecurityManager() == null)
-            System.setSecurityManager(new RMISecurityManager());
-
-        // HTTP direct to the server port
-        System.setProperty("http.proxyHost", "127.0.0.1");
-
-        // Set the socket factory.
-        System.err.println("(installing HTTP-out socket factory)");
-        HttpOutFactory fac = new HttpOutFactory();
-        RMISocketFactory.setSocketFactory(fac);
-
-        // Create remote object
-        TestImpl impl = new TestImpl();
-
-        // Export and get which port.
-        System.err.println("(exporting remote object)");
-        TestIface stub = impl.export();
-        try {
-            int port = fac.whichPort();
-
-            // Sanity
-            if (port == 0)
-                throw new Error("TEST FAILED: export didn't reserve a port(?)");
-
-            // Set the HTTP port, at last.
-            System.setProperty("http.proxyPort", port+"");
-
-            // Now, connect to that port
-            //Thread.sleep(2000);
-            System.err.println("(connecting to listening port on 127.0.0.1:" +
-                               port + ")");
-            Socket DoS = new Socket("127.0.0.1", port);
-            // we hold the connection open until done with the test.
-
-            // The test itself: make a remote call and see if it's blocked or
-            // if it works
-            //Thread.sleep(2000);
-            System.err.println("(making RMI-through-HTTP call)");
-            System.err.println("(typical test failure deadlocks here)");
-            String result = stub.testCall("dummy load");
-
-            System.err.println(" => " + result);
-            if (!("OK".equals(result)))
-                throw new Error("TEST FAILED: result not OK");
-            System.err.println("Test passed.");
-
-            // Clean up, including writing a byte to that connection just in
-            // case an optimizer thought of optimizing it out of existence
-            try {
-                DoS.getOutputStream().write(0);
-                DoS.getOutputStream().close();
-            } catch (Throwable apathy) {
-            }
-
-        } finally {
-            try {
-                impl.unexport();
-            } catch (Throwable unmatter) {
-            }
-        }
-
-        // Should exit here
-    }
-
-    private static class HttpOutFactory
-        extends RMISocketFactory
-    {
-        private int servport = 0;
-
-        public Socket createSocket(String h, int p)
-            throws IOException
-        {
-            return ((new RMIHttpToPortSocketFactory()).createSocket(h, p));
-        }
-
-        /** Create a server socket and remember which port it's on.
-         * Aborts if createServerSocket(0) is called twice, because then
-         * it doesn't know whether to remember the first or second port.
-         */
-        public ServerSocket createServerSocket(int p)
-            throws IOException
-        {
-            ServerSocket ss;
-            ss = (new RMIMasterSocketFactory()).createServerSocket(p);
-            if (p == 0) {
-                if (servport != 0) {
-                    System.err.println("TEST FAILED: " +
-                                       "Duplicate createServerSocket(0)");
-                    throw new Error("Test aborted (createServerSocket)");
-                }
-                servport = ss.getLocalPort();
-            }
-            return (ss);
-        }
-
-        /** Return which port was reserved by createServerSocket(0).
-         * If the return value was 0, createServerSocket(0) wasn't called.
-         */
-        public int whichPort() {
-            return (servport);
-        }
-    } // end class HttpOutFactory
-}
--- a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 1999, 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.rmi.*;
-
-public interface TestIface
-    extends Remote
-{
-    public String testCall(String ign)
-        throws RemoteException;
-}
--- a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 1999, 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.rmi.*;
-import java.rmi.server.*;
-
-public class TestImpl
-    extends Object
-    implements TestIface
-{
-    public TestImpl() {
-    }
-
-    public TestIface export()
-        throws RemoteException
-    {
-        return (TestIface)UnicastRemoteObject.exportObject(this);
-    }
-
-    public void unexport()
-        throws NoSuchObjectException
-    {
-        UnicastRemoteObject.unexportObject(this, true);
-    }
-
-    public String testCall(String ign) {
-        return ("OK");
-    }
-}
--- a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 1999, 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.
- */
-
-// Stub class generated by rmic, do not edit.
-// Contents subject to change without notice.
-
-public final class TestImpl_Stub
-    extends java.rmi.server.RemoteStub
-    implements TestIface
-{
-    private static final long serialVersionUID = 2;
-
-    private static java.lang.reflect.Method $method_testCall_0;
-
-    static {
-        try {
-            $method_testCall_0 = TestIface.class.getMethod("testCall", new java.lang.Class[] {java.lang.String.class});
-        } catch (java.lang.NoSuchMethodException e) {
-            throw new java.lang.NoSuchMethodError(
-                "stub class initialization failed");
-        }
-    }
-
-    // constructors
-    public TestImpl_Stub(java.rmi.server.RemoteRef ref) {
-        super(ref);
-    }
-
-    // methods from remote interfaces
-
-    // implementation of testCall(String)
-    public java.lang.String testCall(java.lang.String $param_String_1)
-        throws java.rmi.RemoteException
-    {
-        try {
-            Object $result = ref.invoke(this, $method_testCall_0, new java.lang.Object[] {$param_String_1}, -4495720265115653109L);
-            return ((java.lang.String) $result);
-        } catch (java.lang.RuntimeException e) {
-            throw e;
-        } catch (java.rmi.RemoteException e) {
-            throw e;
-        } catch (java.lang.Exception e) {
-            throw new java.rmi.UnexpectedException("undeclared checked exception", e);
-        }
-    }
-}
--- a/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-grant {
-    // Take this out once we can specify -Djava.security.debug on
-    // the run line and figure out what else is needed
-    permission java.security.AllPermission;
-
-    permission java.net.SocketPermission "*:1024-65535", "connect,listen";
-    permission java.util.PropertyPermission "http.proxyHost", "write";
-    permission java.util.PropertyPermission "http.proxyPort", "write";
-    permission java.lang.RuntimePermission "setFactory";
-};
--- a/jdk/test/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java	Wed Jul 05 21:42:16 2017 +0200
@@ -71,18 +71,19 @@
                     KeyPairGenerator.getInstance("DiffieHellman", provider);
             kpg.initialize(keySize.primeSize);
             KeyPair kp = kpg.generateKeyPair();
-            checkKeyPair(kp, keySize.primeSize);
+            checkKeyPair(kp, keySize.primeSize, provider);
 
             DHPublicKey publicKey = (DHPublicKey)kp.getPublic();
             BigInteger p = publicKey.getParams().getP();
             BigInteger g = publicKey.getParams().getG();
             kpg.initialize(new DHParameterSpec(p, g));
             kp = kpg.generateKeyPair();
-            checkKeyPair(kp, keySize.primeSize);
+            checkKeyPair(kp, keySize.primeSize, provider);
         }
     }
 
-    private static void checkKeyPair(KeyPair kp, int pSize) throws Exception {
+    private static void checkKeyPair(KeyPair kp, int pSize,
+                Provider provider) throws Exception {
 
         DHPrivateKey privateKey = (DHPrivateKey)kp.getPrivate();
         BigInteger p = privateKey.getParams().getP();
@@ -106,18 +107,21 @@
         BigInteger leftOpen = BigInteger.ONE;
         BigInteger rightOpen = p.subtract(BigInteger.ONE);
 
-        BigInteger x = privateKey.getX();
-        if ((x.compareTo(leftOpen) <= 0) ||
-                (x.compareTo(rightOpen) >= 0)) {
-            throw new Exception(
-                "X outside range [2, p - 2]:  x: " + x + " p: " + p);
+        // ignore the private key range checking on Solaris at present
+        if (!provider.getName().equals("SunPKCS11-Solaris")) {
+            BigInteger x = privateKey.getX();
+            if ((x.compareTo(leftOpen) <= 0) ||
+                    (x.compareTo(rightOpen) >= 0)) {
+                throw new Exception(
+                    "X outside range [2, p - 2]:  x: " + x + " p: " + p);
+            }
         }
 
         BigInteger y = publicKey.getY();
         if ((y.compareTo(leftOpen) <= 0) ||
                 (y.compareTo(rightOpen) >= 0)) {
             throw new Exception(
-                "Y outside range [2, p - 2]:  x: " + x + " p: " + p);
+                "Y outside range [2, p - 2]:  y: " + y + " p: " + p);
         }
     }
 
--- a/jdk/test/sun/security/provider/MessageDigest/Offsets.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/sun/security/provider/MessageDigest/Offsets.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
         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);
     }
 
 }
--- a/jdk/test/sun/security/provider/MessageDigest/TestSHAClone.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/sun/security/provider/MessageDigest/TestSHAClone.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
 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 @@
 
     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())) {
--- a/jdk/test/sun/security/provider/SecureRandom/DRBGAlg.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/sun/security/provider/SecureRandom/DRBGAlg.java	Wed Jul 05 21:42:16 2017 +0200
@@ -47,7 +47,6 @@
 
         check(null, "Hash_DRBG", "SHA-256", "reseed_only", ",128");
         check("", "Hash_DRBG", "SHA-256", "reseed_only", ",128");
-        check("sha-1", "Hash_DRBG", "SHA-1", "reseed_only", ",128");
         check("sha-256", "Hash_DRBG", "SHA-256", "reseed_only", ",128");
         check("SHA-3");
         check("hash_drbg", "Hash_DRBG", "SHA-256", "reseed_only", ",128");
@@ -61,20 +60,20 @@
                 "Hash_DRBG", "SHA-512", "pr_and_reseed", ",192");
 
         check("Hash_DRBG,Hmac_DRBG");
-        check("SHA-1,SHA-256");
+        check("SHA-224,SHA-256");
         check("128,256");
         check("none,reseed_only");
         check("use_df,no_df");
-        check("Hash_DRBG,,SHA-1");
+        check("Hash_DRBG,,SHA-256");
 
         check(null, DrbgParameters.instantiation(112, PR_AND_RESEED, null),
                 "Hash_DRBG", "SHA-256", "pr_and_reseed", ",112");
         check(null, DrbgParameters.instantiation(256, PR_AND_RESEED, null),
                 "Hash_DRBG", "SHA-256", "pr_and_reseed", ",256");
         check(null, DrbgParameters.instantiation(384, PR_AND_RESEED, null));
-        check("sha-1", DrbgParameters.instantiation(112, PR_AND_RESEED, null),
-                "Hash_DRBG", "SHA-1", "pr_and_reseed", ",112");
-        check("sha-1", DrbgParameters.instantiation(192, PR_AND_RESEED, null));
+        check("sha-224", DrbgParameters.instantiation(112, PR_AND_RESEED, null),
+                "Hash_DRBG", "SHA-224", "pr_and_reseed", ",112");
+        check("sha-224", DrbgParameters.instantiation(256, PR_AND_RESEED, null));
         check("hash_drbg,sha-512,Pr_and_Reseed,192",
                 DrbgParameters.instantiation(112, NONE, null),
                 "Hash_DRBG", "SHA-512", "reseed_only", ",112");
@@ -86,23 +85,23 @@
                 DrbgParameters.instantiation(192, PR_AND_RESEED, null),
                 "Hash_DRBG", "SHA-256", "pr_and_reseed", ",192");
 
-        check("hash_drbg,sha-1", new MoreDrbgParameters(
+        check("hash_drbg,sha-224", new MoreDrbgParameters(
                     null, null, "sha-512", null, false,
                     DrbgParameters.instantiation(-1, NONE, null)),
                 "Hash_DRBG", "SHA-512");
-        check("hash_drbg,sha-1", new MoreDrbgParameters(
+        check("hash_drbg,sha-224", new MoreDrbgParameters(
                     null, null, null, null, false,
                     DrbgParameters.instantiation(-1, NONE, null)),
-                "Hash_DRBG", "SHA-1");
+                "Hash_DRBG", "SHA-224");
         check("hash_drbg", new MoreDrbgParameters(
                     null, "hmac_drbg", null, null, false,
                     DrbgParameters.instantiation(-1, NONE, null)),
                 "HMAC_DRBG", "SHA-256");
 
-        check("hash_drbg,sha-1", new MoreDrbgParameters(
+        check("hash_drbg,sha-224", new MoreDrbgParameters(
                     null, null, "sha-3", null, false,
                     DrbgParameters.instantiation(-1, NONE, null)));
-        check("hash_drbg,sha-1", new MoreDrbgParameters(
+        check("hash_drbg,sha-224", new MoreDrbgParameters(
                     null, "Unknown_DRBG", null, null, false,
                     DrbgParameters.instantiation(-1, NONE, null)));
     }
--- a/jdk/test/sun/security/provider/SecureRandom/DrbgCavp.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/sun/security/provider/SecureRandom/DrbgCavp.java	Wed Jul 05 21:42:16 2017 +0200
@@ -278,10 +278,13 @@
                                                     ps)),
                                     "SUN");
                         } catch (NoSuchAlgorithmException iae) {
+                            // We don't support SHA-1 and 3KeyTDEA. AES-192 or
                             // AES-256 might not be available. This is OK.
-                            if ((algorithm.equals("AES-192")
+                            if (algorithm.equals("SHA-1") ||
+                                    algorithm.equals("3KeyTDEA") ||
+                                    ((algorithm.equals("AES-192")
                                     || algorithm.equals("AES-256"))
-                                    && AES_LIMIT == 128) {
+                                    && AES_LIMIT == 128)) {
                                 hd = null;
                             } else {
                                 throw iae;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/provider/SecureRandom/SHA1PRNGReseed.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.SecureRandom;
+
+/**
+ * @test
+ * @bug 8154523
+ * @summary SHA1PRNG output should change after setSeed
+ */
+public class SHA1PRNGReseed {
+
+    public static void main(String[] args) throws Exception {
+        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
+        sr.setSeed(0);
+        sr.nextInt();
+
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        new ObjectOutputStream(bout).writeObject(sr);
+
+        SecureRandom sr2 = (SecureRandom) new ObjectInputStream(
+                new ByteArrayInputStream(bout.toByteArray())).readObject();
+
+        int i1 = sr.nextInt();
+        sr2.setSeed(1);
+        int i2 = sr2.nextInt();
+
+        if (i1 == i2) {
+            throw new Exception("output should not be the same");
+        }
+    }
+}
--- a/jdk/test/sun/security/rsa/SignatureTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/sun/security/rsa/SignatureTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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.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 @@
  * @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 @@
      */
     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 @@
         // 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);
+            }
+        }
+        )));
 
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/x509/AlgorithmId/OidTableInit.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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();
+    }
+}
--- a/jdk/test/tools/jlink/JLinkTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/jdk/test/tools/jlink/JLinkTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -162,7 +162,7 @@
         {
             String[] userOptions2 = {"--compress=2:compress-filter=^/java.base/*",
                 "--strip-debug", "--exclude-resources",
-                "*.jcov, */META-INF/*", "--sort-resources",
+                "*.jcov, */META-INF/*", "--order-resources",
                 "*/module-info.class,/sortcomposite2/*,*/javax/management/*"};
             String moduleName = "excludezipfilterskipdebugcomposite2";
             helper.generateDefaultJModule(moduleName, "composite2");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ *
+ * 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
+ * @summary Test sorter plugin
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ * @run main OrderResourcesPluginTest
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.tools.jlink.internal.PoolImpl;
+
+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.TransformerPlugin;
+
+public class OrderResourcesPluginTest {
+
+    public static void main(String[] args) throws Exception {
+        new OrderResourcesPluginTest().test();
+    }
+
+    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])
+        };
+
+        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])
+        };
+
+        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])
+        };
+
+        Pool resources = new PoolImpl();
+        for (ModuleData r : array) {
+            resources.add(r);
+        }
+
+        {
+            Pool out = new PoolImpl();
+            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);
+        }
+
+        {
+            // Order of resources in the file, then un-ordered resources.
+            File order = new File("resources.order");
+            order.createNewFile();
+            StringBuilder builder = new StringBuilder();
+            // 5 first resources come from file
+            for (int i = 0; i < 5; i++) {
+                String path = sorted2[i].getPath();
+                int index = path.indexOf('/', 1);
+                path = path.substring(index + 1, path.length() - ".class".length());
+                builder.append(path).append("\n");
+            }
+            Files.write(order.toPath(), builder.toString().getBytes());
+
+            Pool out = new PoolImpl();
+            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);
+
+        }
+    }
+
+    private void check(Collection<ModuleData> outResources,
+            ModuleData[] 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) {
+            System.err.println("Resource: " + r);
+            if (!sorted[i].getPath().equals(r.getPath())) {
+                throw new AssertionError("Resource not properly sorted, difference at: " + i + "\n"
+                        + "expected: " + Arrays.toString(sorted) + ",\n"
+                        + "     got: " + outResources);
+            }
+            i++;
+        }
+    }
+}
--- a/jdk/test/tools/jlink/plugins/SorterPluginTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +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.
- *
- * 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
- * @summary Test sorter plugin
- * @author Jean-Francois Denise
- * @modules jdk.jlink/jdk.tools.jlink.internal
- *          jdk.jlink/jdk.tools.jlink.internal.plugins
- * @run main SorterPluginTest
- */
-
-import java.io.File;
-import java.nio.file.Files;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import jdk.tools.jlink.internal.PoolImpl;
-
-import jdk.tools.jlink.internal.plugins.SortResourcesPlugin;
-import jdk.tools.jlink.plugin.Pool;
-import jdk.tools.jlink.plugin.Pool.ModuleData;
-import jdk.tools.jlink.plugin.TransformerPlugin;
-
-public class SorterPluginTest {
-
-    public static void main(String[] args) throws Exception {
-        new SorterPluginTest().test();
-    }
-
-    public void test() throws Exception {
-        ModuleData[] array = {
-                Pool.newResource("/module1/toto1", new byte[0]),
-                Pool.newResource("/module2/toto1", new byte[0]),
-                Pool.newResource("/module3/toto1", new byte[0]),
-                Pool.newResource("/module3/toto1/module-info.class", new byte[0]),
-                Pool.newResource("/zazou/toto1", new byte[0]),
-                Pool.newResource("/module4/zazou", new byte[0]),
-                Pool.newResource("/module5/toto1", new byte[0]),
-                Pool.newResource("/module6/toto1/module-info.class", new byte[0])
-        };
-
-        ModuleData[] sorted = {
-                Pool.newResource("/zazou/toto1", new byte[0]),
-                Pool.newResource("/module3/toto1/module-info.class", new byte[0]),
-                Pool.newResource("/module6/toto1/module-info.class", new byte[0]),
-                Pool.newResource("/module1/toto1", new byte[0]),
-                Pool.newResource("/module2/toto1", new byte[0]),
-                Pool.newResource("/module3/toto1", new byte[0]),
-                Pool.newResource("/module4/zazou", new byte[0]),
-                Pool.newResource("/module5/toto1", new byte[0]),
-};
-
-        ModuleData[] sorted2 = {
-            Pool.newResource("/module5/toto1", new byte[0]),
-            Pool.newResource("/module6/toto1/module-info.class", new byte[0]),
-            Pool.newResource("/module4/zazou", new byte[0]),
-            Pool.newResource("/module3/toto1", new byte[0]),
-            Pool.newResource("/module3/toto1/module-info.class", new byte[0]),
-            Pool.newResource("/module1/toto1", new byte[0]),
-            Pool.newResource("/module2/toto1", new byte[0]),
-            Pool.newResource("/zazou/toto1", new byte[0]),};
-
-        Pool resources = new PoolImpl();
-        for (ModuleData r : array) {
-            resources.add(r);
-        }
-
-        {
-            Pool out = new PoolImpl();
-            Map<String, String> config = new HashMap<>();
-            config.put(SortResourcesPlugin.NAME, "/zazou/*,*/module-info.class");
-            TransformerPlugin p = new SortResourcesPlugin();
-            p.configure(config);
-            p.visit(resources, out);
-            check(out.getContent(), sorted);
-        }
-
-        {
-            // Order of resources in the file, then un-ordered resources.
-            File order = new File("resources.order");
-            order.createNewFile();
-            StringBuilder builder = new StringBuilder();
-            // 5 first resources come from file
-            for (int i = 0; i < 5; i++) {
-                builder.append(sorted2[i].getPath()).append("\n");
-            }
-            Files.write(order.toPath(), builder.toString().getBytes());
-
-            Pool out = new PoolImpl();
-            Map<String, String> config = new HashMap<>();
-            config.put(SortResourcesPlugin.NAME, order.getAbsolutePath());
-            TransformerPlugin p = new SortResourcesPlugin();
-            p.configure(config);
-            p.visit(resources, out);
-            check(out.getContent(), sorted2);
-
-        }
-    }
-
-    private void check(Collection<ModuleData> outResources,
-            ModuleData[] 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) {
-            System.err.println("Resource: " + r);
-            if (!sorted[i].getPath().equals(r.getPath())) {
-                throw new AssertionError("Resource not properly sorted, difference at: " + i + "\n"
-                        + "expected: " + Arrays.toString(sorted) + ",\n"
-                        + "     got: " + outResources);
-            }
-            i++;
-        }
-    }
-}
--- a/langtools/.hgtags	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/.hgtags	Wed Jul 05 21:42:16 2017 +0200
@@ -360,3 +360,4 @@
 31c8b18fdc5b94a2ddd5ea0694f350a2c907e9f7 jdk-9+115
 3e3553ee39d9e081573bc7c88a252214a3152763 jdk-9+116
 59adcdd0cd3b6724b4fc0083c258bf4682689f2f jdk-9+117
+59a16fa5dedea9ff5bea0a501e4d0d40193426f3 jdk-9+118
--- a/langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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.IOException;
 import java.nio.file.Path;
 import java.util.Arrays;
+import java.util.Collection;
 
 import static javax.tools.FileManagerUtils.*;
 
@@ -176,7 +177,8 @@
     /**
      * 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 @@
      * 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 @@
      *
      * @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 @@
     /**
      * 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 @@
      * {@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 @@
         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) { }
 }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
         }
 
         @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 @@
                 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 {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
         public java.util.List<? extends ModuleElement> getTargetModules() {
-            return Collections.unmodifiableList(modules);
+            return modules == null
+                    ? null
+                    : Collections.unmodifiableList(modules);
         }
 
         @Override
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -841,6 +841,28 @@
             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;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
             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);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Wed Jul 05 21:42:16 2017 +0200
@@ -109,6 +109,8 @@
 
     protected boolean symbolFileEnabled;
 
+    private PathFactory pathFactory = Paths::get;
+
     protected enum SortFiles implements Comparator<Path> {
         FORWARD {
             @Override
@@ -166,6 +168,16 @@
         }
     }
 
+    @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 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 @@
                 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 @@
 
         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 @@
 
     @Override @DefinedBy(Api.COMPILER)
     public void setLocationFromPaths(Location location,
-                            Iterable<? extends Path> searchpath)
+                            Collection<? extends Path> searchpath)
         throws IOException
     {
         nullCheck(location);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Wed Jul 05 21:42:16 2017 +0200
@@ -68,6 +68,7 @@
 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 @@
 
     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 @@
         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 @@
         this.fsInfo = fsInfo;
     }
 
+    void setPathFactory(PathFactory f) {
+        pathFactory = f;
+    }
+
     boolean isDefaultBootClassPath() {
         BootClassPathLocationHandler h
                 = (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
@@ -167,7 +178,7 @@
      * @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 @@
      * 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 @@
                     entries.add(emptyPathDefault);
                 }
             } else {
-                entries.add(Paths.get(s));
+                entries.add(getPath(s));
             }
         }
         return entries;
@@ -465,7 +476,7 @@
             // 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 @@
         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 @@
             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 @@
             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 @@
                             || 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 @@
     }
 
     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 @@
             }
 
             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 @@
 
         @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 @@
         }
 
         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 @@
                 return;
             }
 
-            if (javaHome == null) {
+            if (systemJavaHome == null) {
                 systemModules = Collections.emptyMap();
                 return;
             }
@@ -1431,15 +1441,15 @@
                     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 @@
 
                     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);
                 }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java	Wed Jul 05 21:42:16 2017 +0200
@@ -109,7 +109,7 @@
         private DirectoryFileObject(BaseFileManager fileManager, Path path,
                 Path userPackageRootDir, RelativePath relativePath) {
             super(fileManager, path);
-            this.userPackageRootDir = userPackageRootDir;
+            this.userPackageRootDir = Objects.requireNonNull(userPackageRootDir);
             this.relativePath = relativePath;
         }
 
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 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 {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
         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;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java	Wed Jul 05 21:42:16 2017 +0200
@@ -60,8 +60,8 @@
     /** 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<>();
 
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -28,7 +28,7 @@
 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.*;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -40,7 +40,7 @@
 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.
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -149,8 +149,8 @@
                 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);
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.tools.javac.code.Type;
-
-
-/**
- * Abstract implementation of <code>Type</code>, with useful
- * defaults for the methods in <code>Type</code> (and a couple from
- * <code>ProgramElementDoc</code>).
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Scott Seligman
- * @since 1.5
- */
-abstract class AbstractTypeImpl implements com.sun.javadoc.Type {
-
-    protected final DocEnv env;
-    protected final Type type;
-
-    protected AbstractTypeImpl(DocEnv env, Type type) {
-        this.env = env;
-        this.type = type;
-    }
-
-    public String typeName() {
-        return type.tsym.name.toString();
-    }
-
-    public String qualifiedTypeName() {
-        return type.tsym.getQualifiedName().toString();
-    }
-
-    public com.sun.javadoc.Type getElementType() {
-        return null;
-    }
-
-    public String simpleTypeName() {
-        return type.tsym.name.toString();
-    }
-
-    public String name() {
-        return typeName();
-    }
-
-    public String qualifiedName() {
-        return qualifiedTypeName();
-    }
-
-    public String toString() {
-        return qualifiedTypeName();
-    }
-
-    public String dimension() {
-        return "";
-    }
-
-    public boolean isPrimitive() {
-        return false;
-    }
-
-    public ClassDoc asClassDoc() {
-        return null;
-    }
-
-    public TypeVariable asTypeVariable() {
-        return null;
-    }
-
-    public WildcardType asWildcardType() {
-        return null;
-    }
-
-    public ParameterizedType asParameterizedType() {
-        return null;
-    }
-
-    public AnnotationTypeDoc asAnnotationTypeDoc() {
-        return null;
-    }
-
-    public AnnotatedType asAnnotatedType() {
-        return null;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.code.Attribute;
-import com.sun.tools.javac.code.Attribute.TypeCompound;
-import com.sun.tools.javac.util.List;
-
-/**
- * Implementation of <code>AnnotatedType</code>, which
- * represents an annotated type.
- *
- * @author Mahmood Ali
- * @since 1.8
- */
-public class AnnotatedTypeImpl
-        extends AbstractTypeImpl implements AnnotatedType {
-
-    AnnotatedTypeImpl(DocEnv env, com.sun.tools.javac.code.Type type) {
-        super(env, type);
-    }
-
-    /**
-     * Get the annotations of this program element.
-     * Return an empty array if there are none.
-     */
-    @Override
-    public AnnotationDesc[] annotations() {
-        List<? extends TypeCompound> tas = type.getAnnotationMirrors();
-        if (tas == null ||
-                tas.isEmpty()) {
-            return new AnnotationDesc[0];
-        }
-        AnnotationDesc res[] = new AnnotationDesc[tas.length()];
-        int i = 0;
-        for (Attribute.Compound a : tas) {
-            res[i++] = new AnnotationDescImpl(env, a);
-        }
-        return res;
-    }
-
-    @Override
-    public com.sun.javadoc.Type underlyingType() {
-        return TypeMaker.getType(env, type, true, false);
-    }
-
-    @Override
-    public AnnotatedType asAnnotatedType() {
-        return this;
-    }
-
-    @Override
-    public String toString() {
-        return typeName();
-    }
-
-    @Override
-    public String typeName() {
-        return this.underlyingType().typeName();
-    }
-
-    @Override
-    public String qualifiedTypeName() {
-        return this.underlyingType().qualifiedTypeName();
-    }
-
-    @Override
-    public String simpleTypeName() {
-        return this.underlyingType().simpleTypeName();
-    }
-
-    @Override
-    public String dimension() {
-        return this.underlyingType().dimension();
-    }
-
-    @Override
-    public boolean isPrimitive() {
-        return this.underlyingType().isPrimitive();
-    }
-
-    @Override
-    public ClassDoc asClassDoc() {
-        return this.underlyingType().asClassDoc();
-    }
-
-    @Override
-    public TypeVariable asTypeVariable() {
-        return this.underlyingType().asTypeVariable();
-    }
-
-    @Override
-    public WildcardType asWildcardType() {
-        return this.underlyingType().asWildcardType();
-    }
-
-    @Override
-    public ParameterizedType asParameterizedType() {
-        return this.underlyingType().asParameterizedType();
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.tools.javac.code.Attribute;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Pair;
-
-
-/**
- * Represents an annotation.
- * An annotation associates a value with each element of an annotation type.
- * Sure it ought to be called "Annotation", but that clashes with
- * java.lang.annotation.Annotation.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Scott Seligman
- * @since 1.5
- */
-
-public class AnnotationDescImpl implements AnnotationDesc {
-
-    private final DocEnv env;
-    private final Attribute.Compound annotation;
-
-
-    AnnotationDescImpl(DocEnv env, Attribute.Compound annotation) {
-        this.env = env;
-        this.annotation = annotation;
-    }
-
-    /**
-     * Returns the annotation type of this annotation.
-     */
-    public AnnotationTypeDoc annotationType() {
-        ClassSymbol atsym = (ClassSymbol)annotation.type.tsym;
-        if (annotation.type.isErroneous()) {
-            env.warning(null, "javadoc.class_not_found", annotation.type.toString());
-            return new AnnotationTypeDocImpl(env, atsym);
-        } else {
-            return (AnnotationTypeDoc)env.getClassDoc(atsym);
-        }
-    }
-
-    /**
-     * Returns this annotation's elements and their values.
-     * Only those explicitly present in the annotation are
-     * included, not those assuming their default values.
-     * Returns an empty array if there are none.
-     */
-    public ElementValuePair[] elementValues() {
-        List<Pair<MethodSymbol,Attribute>> vals = annotation.values;
-        ElementValuePair res[] = new ElementValuePair[vals.length()];
-        int i = 0;
-        for (Pair<MethodSymbol,Attribute> val : vals) {
-            res[i++] = new ElementValuePairImpl(env, val.fst, val.snd);
-        }
-        return res;
-    }
-
-    /**
-     * Check for the synthesized bit on the annotation.
-     *
-     * @return true if the annotation is synthesized.
-     */
-    public boolean isSynthesized() {
-        return annotation.isSynthesized();
-    }
-
-    /**
-     * Returns a string representation of this annotation.
-     * String is of one of the forms:
-     * <pre>
-     *     {@code @com.example.foo(name1=val1, name2=val2)}
-     *     {@code @com.example.foo(val)}
-     *     {@code @com.example.foo}
-     * </pre>
-     * Omit parens for marker annotations, and omit "value=" when allowed.
-     */
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("@");
-        sb.append(annotation.type.tsym);
-
-        ElementValuePair vals[] = elementValues();
-        if (vals.length > 0) {          // omit parens for marker annotation
-            sb.append('(');
-            boolean first = true;
-            for (ElementValuePair val : vals) {
-                if (!first) {
-                    sb.append(", ");
-                }
-                first = false;
-
-                String name = val.element().name();
-                if (vals.length == 1 && name.equals("value")) {
-                    sb.append(val.value());
-                } else {
-                    sb.append(val);
-                }
-            }
-            sb.append(')');
-        }
-        return sb.toString();
-    }
-
-
-    /**
-     * Represents an association between an annotation type element
-     * and one of its values.
-     */
-    public static class ElementValuePairImpl implements ElementValuePair {
-
-        private final DocEnv env;
-        private final MethodSymbol meth;
-        private final Attribute value;
-
-        ElementValuePairImpl(DocEnv env, MethodSymbol meth, Attribute value) {
-            this.env = env;
-            this.meth = meth;
-            this.value = value;
-        }
-
-        /**
-         * Returns the annotation type element.
-         */
-        public AnnotationTypeElementDoc element() {
-            return env.getAnnotationTypeElementDoc(meth);
-        }
-
-        /**
-         * Returns the value associated with the annotation type element.
-         */
-        public AnnotationValue value() {
-            return new AnnotationValueImpl(env, value);
-        }
-
-        /**
-         * Returns a string representation of this pair
-         * of the form "name=value".
-         */
-        @Override
-        public String toString() {
-            return meth.name + "=" + value();
-        }
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationTypeDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2003, 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 com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.util.List;
-
-import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
-
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-
-/**
- * Represents an annotation type.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Scott Seligman
- * @since 1.5
- */
-
-public class AnnotationTypeDocImpl
-        extends ClassDocImpl implements AnnotationTypeDoc {
-
-    public AnnotationTypeDocImpl(DocEnv env, ClassSymbol sym) {
-        this(env, sym, null);
-    }
-
-    public AnnotationTypeDocImpl(DocEnv env, ClassSymbol sym, TreePath treePath) {
-        super(env, sym, treePath);
-    }
-
-    /**
-     * Returns true, as this is an annotation type.
-     * (For legacy doclets, return false.)
-     */
-    public boolean isAnnotationType() {
-        return !isInterface();
-    }
-
-    /**
-     * Returns false.  Though technically an interface, an annotation
-     * type is not considered an interface for this purpose.
-     * (For legacy doclets, returns true.)
-     */
-    public boolean isInterface() {
-        return env.legacyDoclet;
-    }
-
-    /**
-     * Returns an empty array, as all methods are annotation type elements.
-     * (For legacy doclets, returns the elements.)
-     * @see #elements()
-     */
-    public MethodDoc[] methods(boolean filter) {
-        return env.legacyDoclet
-                ? (MethodDoc[])elements()
-                : new MethodDoc[0];
-    }
-
-    /**
-     * Returns the elements of this annotation type.
-     * Returns an empty array if there are none.
-     * Elements are always public, so no need to filter them.
-     */
-    public AnnotationTypeElementDoc[] elements() {
-        List<AnnotationTypeElementDoc> elements = List.nil();
-        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
-            if (sym != null && sym.kind == MTH) {
-                MethodSymbol s = (MethodSymbol)sym;
-                elements = elements.prepend(env.getAnnotationTypeElementDoc(s));
-            }
-        }
-        return
-            elements.toArray(new AnnotationTypeElementDoc[elements.length()]);
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationTypeElementDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Symbol.*;
-
-/**
- * Represents an element of an annotation type.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Scott Seligman
- * @since 1.5
- */
-
-public class AnnotationTypeElementDocImpl
-        extends MethodDocImpl implements AnnotationTypeElementDoc {
-
-    public AnnotationTypeElementDocImpl(DocEnv env, MethodSymbol sym) {
-        super(env, sym);
-    }
-
-    public AnnotationTypeElementDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) {
-        super(env, sym, treePath);
-    }
-
-    /**
-     * Returns true, as this is an annotation type element.
-     * (For legacy doclets, return false.)
-     */
-    public boolean isAnnotationTypeElement() {
-        return !isMethod();
-    }
-
-    /**
-     * Returns false.  Although this is technically a method, we don't
-     * consider it one for this purpose.
-     * (For legacy doclets, return true.)
-     */
-    public boolean isMethod() {
-        return env.legacyDoclet;
-    }
-
-    /**
-     * Returns false, even though this is indeed abstract.  See
-     * MethodDocImpl.isAbstract() for the (il)logic behind this.
-     */
-    public boolean isAbstract() {
-        return false;
-    }
-
-    /**
-     * Returns the default value of this element.
-     * Returns null if this element has no default.
-     */
-    public AnnotationValue defaultValue() {
-        return (sym.defaultValue == null)
-               ? null
-               : new AnnotationValueImpl(env, sym.defaultValue);
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.tools.javac.code.Attribute;
-
-import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
-
-/**
- * Represents a value of an annotation type element.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Scott Seligman
- * @since 1.5
- */
-
-public class AnnotationValueImpl implements AnnotationValue {
-
-    private final DocEnv env;
-    private final Attribute attr;
-
-
-    AnnotationValueImpl(DocEnv env, Attribute attr) {
-        this.env = env;
-        this.attr = attr;
-    }
-
-    /**
-     * Returns the value.
-     * The type of the returned object is one of the following:
-     * <ul><li> a wrapper class for a primitive type
-     *     <li> <code>String</code>
-     *     <li> <code>Type</code> (representing a class literal)
-     *     <li> <code>FieldDoc</code> (representing an enum constant)
-     *     <li> <code>AnnotationDesc</code>
-     *     <li> <code>AnnotationValue[]</code>
-     * </ul>
-     */
-    public Object value() {
-        ValueVisitor vv = new ValueVisitor();
-        attr.accept(vv);
-        return vv.value;
-    }
-
-    private class ValueVisitor implements Attribute.Visitor {
-        public Object value;
-
-        public void visitConstant(Attribute.Constant c) {
-            if (c.type.hasTag(BOOLEAN)) {
-                // javac represents false and true as integers 0 and 1
-                value = Boolean.valueOf(
-                                ((Integer)c.value).intValue() != 0);
-            } else {
-                value = c.value;
-            }
-        }
-
-        public void visitClass(Attribute.Class c) {
-            value = TypeMaker.getType(env,
-                                      env.types.erasure(c.classType));
-        }
-
-        public void visitEnum(Attribute.Enum e) {
-            value = env.getFieldDoc(e.value);
-        }
-
-        public void visitCompound(Attribute.Compound c) {
-            value = new AnnotationDescImpl(env, c);
-        }
-
-        public void visitArray(Attribute.Array a) {
-            AnnotationValue vals[] = new AnnotationValue[a.values.length];
-            for (int i = 0; i < vals.length; i++) {
-                vals[i] = new AnnotationValueImpl(env, a.values[i]);
-            }
-            value = vals;
-        }
-
-        public void visitError(Attribute.Error e) {
-            value = "<error>";
-        }
-    }
-
-    /**
-     * Returns a string representation of the value.
-     *
-     * @return the text of a Java language annotation value expression
-     *          whose value is the value of this annotation type element.
-     */
-    @Override
-    public String toString() {
-        ToStringVisitor tv = new ToStringVisitor();
-        attr.accept(tv);
-        return tv.toString();
-    }
-
-    private class ToStringVisitor implements Attribute.Visitor {
-        private final StringBuilder sb = new StringBuilder();
-
-        @Override
-        public String toString() {
-            return sb.toString();
-        }
-
-        public void visitConstant(Attribute.Constant c) {
-            if (c.type.hasTag(BOOLEAN)) {
-                // javac represents false and true as integers 0 and 1
-                sb.append(((Integer)c.value).intValue() != 0);
-            } else {
-                sb.append(FieldDocImpl.constantValueExpression(c.value));
-            }
-        }
-
-        public void visitClass(Attribute.Class c) {
-            sb.append(c);
-        }
-
-        public void visitEnum(Attribute.Enum e) {
-            sb.append(e);
-        }
-
-        public void visitCompound(Attribute.Compound c) {
-            sb.append(new AnnotationDescImpl(env, c));
-        }
-
-        public void visitArray(Attribute.Array a) {
-            // Omit braces from singleton.
-            if (a.values.length != 1) sb.append('{');
-
-            boolean first = true;
-            for (Attribute elem : a.values) {
-                if (first) {
-                    first = false;
-                } else {
-                    sb.append(", ");
-                }
-                elem.accept(this);
-            }
-            // Omit braces from singleton.
-            if (a.values.length != 1) sb.append('}');
-        }
-
-        public void visitError(Attribute.Error e) {
-            sb.append("<error>");
-        }
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1329 +0,0 @@
-/*
- * Copyright (c) 1997, 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 com.sun.tools.javadoc;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Modifier;
-import java.net.URI;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.tools.FileObject;
-import javax.tools.JavaFileManager.Location;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.StandardLocation;
-
-import com.sun.javadoc.*;
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Kinds;
-import com.sun.tools.javac.code.Kinds.KindSelector;
-import com.sun.tools.javac.code.Scope;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.ClassType;
-import com.sun.tools.javac.code.TypeTag;
-import com.sun.tools.javac.comp.AttrContext;
-import com.sun.tools.javac.comp.Env;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
-import com.sun.tools.javac.tree.JCTree.JCImport;
-import com.sun.tools.javac.tree.TreeInfo;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Names;
-import com.sun.tools.javac.util.Position;
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
-import static com.sun.tools.javac.code.TypeTag.CLASS;
-import static com.sun.tools.javac.tree.JCTree.Tag.*;
-
-/**
- * Represents a java class and provides access to information
- * about the class, the class' comment and tags, and the
- * members of the class.  A ClassDocImpl only exists if it was
- * processed in this run of javadoc.  References to classes
- * which may or may not have been processed in this run are
- * referred to using Type (which can be converted to ClassDocImpl,
- * if possible).
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @see Type
- *
- * @since 1.2
- * @author Robert Field
- * @author Neal Gafter (rewrite)
- * @author Scott Seligman (generics, enums, annotations)
- */
-
-public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
-
-    public final ClassType type;        // protected->public for debugging
-    public final ClassSymbol tsym;
-
-    boolean isIncluded = false;         // Set in RootDocImpl
-
-    private SerializedForm serializedForm;
-
-    /**
-     * Constructor
-     */
-    public ClassDocImpl(DocEnv env, ClassSymbol sym) {
-        this(env, sym, null);
-    }
-
-    /**
-     * Constructor
-     */
-    public ClassDocImpl(DocEnv env, ClassSymbol sym, TreePath treePath) {
-        super(env, sym, treePath);
-        this.type = (ClassType)sym.type;
-        this.tsym = sym;
-    }
-
-    public com.sun.javadoc.Type getElementType() {
-        return null;
-    }
-
-    /**
-     * Returns the flags in terms of javac's flags
-     */
-    protected long getFlags() {
-        return getFlags(tsym);
-    }
-
-    /**
-     * Returns the flags of a ClassSymbol in terms of javac's flags
-     */
-    static long getFlags(ClassSymbol clazz) {
-        try {
-            return clazz.flags();
-        } catch (CompletionFailure ex) {
-            /* Quietly ignore completion failures and try again - the type
-             * for which the CompletionFailure was thrown shouldn't be completed
-             * again by the completer that threw the CompletionFailure.
-             */
-            return getFlags(clazz);
-        }
-    }
-
-    /**
-     * Is a ClassSymbol an annotation type?
-     */
-    static boolean isAnnotationType(ClassSymbol clazz) {
-        return (getFlags(clazz) & Flags.ANNOTATION) != 0;
-    }
-
-    /**
-     * Identify the containing class
-     */
-    protected ClassSymbol getContainingClass() {
-        return tsym.owner.enclClass();
-    }
-
-    /**
-     * Return true if this is a class, not an interface.
-     */
-    @Override
-    public boolean isClass() {
-        return !Modifier.isInterface(getModifiers());
-    }
-
-    /**
-     * Return true if this is a ordinary class,
-     * not an enumeration, exception, an error, or an interface.
-     */
-    @Override
-    public boolean isOrdinaryClass() {
-        if (isEnum() || isInterface() || isAnnotationType()) {
-            return false;
-        }
-        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
-            if (t.tsym == env.syms.errorType.tsym ||
-                t.tsym == env.syms.exceptionType.tsym) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Return true if this is an enumeration.
-     * (For legacy doclets, return false.)
-     */
-    @Override
-    public boolean isEnum() {
-        return (getFlags() & Flags.ENUM) != 0
-               &&
-               !env.legacyDoclet;
-    }
-
-    /**
-     * Return true if this is an interface, but not an annotation type.
-     * Overridden by AnnotationTypeDocImpl.
-     */
-    @Override
-    public boolean isInterface() {
-        return Modifier.isInterface(getModifiers());
-    }
-
-    /**
-     * Return true if this is an exception class
-     */
-    @Override
-    public boolean isException() {
-        if (isEnum() || isInterface() || isAnnotationType()) {
-            return false;
-        }
-        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
-            if (t.tsym == env.syms.exceptionType.tsym) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Return true if this is an error class
-     */
-    @Override
-    public boolean isError() {
-        if (isEnum() || isInterface() || isAnnotationType()) {
-            return false;
-        }
-        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
-            if (t.tsym == env.syms.errorType.tsym) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Return true if this is a throwable class
-     */
-    public boolean isThrowable() {
-        if (isEnum() || isInterface() || isAnnotationType()) {
-            return false;
-        }
-        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
-            if (t.tsym == env.syms.throwableType.tsym) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Return true if this class is abstract
-     */
-    public boolean isAbstract() {
-        return Modifier.isAbstract(getModifiers());
-    }
-
-    /**
-     * Returns true if this class was synthesized by the compiler.
-     */
-    public boolean isSynthetic() {
-        return (getFlags() & Flags.SYNTHETIC) != 0;
-    }
-
-    /**
-     * Return true if this class is included in the active set.
-     * A ClassDoc is included iff either it is specified on the
-     * commandline, or if it's containing package is specified
-     * on the command line, or if it is a member class of an
-     * included class.
-     */
-
-    public boolean isIncluded() {
-        if (isIncluded) {
-            return true;
-        }
-        if (env.shouldDocument(tsym)) {
-            // Class is nameable from top-level and
-            // the class and all enclosing classes
-            // pass the modifier filter.
-            if (containingPackage().isIncluded()) {
-                return isIncluded=true;
-            }
-            ClassDoc outer = containingClass();
-            if (outer != null && outer.isIncluded()) {
-                return isIncluded=true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Return the package that this class is contained in.
-     */
-    @Override
-    public PackageDoc containingPackage() {
-        PackageDocImpl p = env.getPackageDoc(tsym.packge());
-        if (p.setDocPath == false) {
-            FileObject docPath;
-            try {
-                Location location = env.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
-                    ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
-
-                docPath = env.fileManager.getFileForInput(
-                        location, p.qualifiedName(), "package.html");
-            } catch (IOException e) {
-                docPath = null;
-            }
-
-            if (docPath == null) {
-                // fall back on older semantics of looking in same directory as
-                // source file for this class
-                SourcePosition po = position();
-                if (env.fileManager instanceof StandardJavaFileManager &&
-                        po instanceof SourcePositionImpl) {
-                    URI uri = ((SourcePositionImpl) po).filename.toUri();
-                    if ("file".equals(uri.getScheme())) {
-                        File f = new File(uri);
-                        File dir = f.getParentFile();
-                        if (dir != null) {
-                            File pf = new File(dir, "package.html");
-                            if (pf.exists()) {
-                                StandardJavaFileManager sfm = (StandardJavaFileManager) env.fileManager;
-                                docPath = sfm.getJavaFileObjects(pf).iterator().next();
-                            }
-                        }
-
-                    }
-                }
-            }
-
-            p.setDocPath(docPath);
-        }
-        return p;
-    }
-
-    /**
-     * Return the class name without package qualifier - but with
-     * enclosing class qualifier - as a String.
-     * <pre>
-     * Examples:
-     *  for java.util.Hashtable
-     *  return Hashtable
-     *  for java.util.Map.Entry
-     *  return Map.Entry
-     * </pre>
-     */
-    public String name() {
-        if (name == null) {
-            name = getClassName(tsym, false);
-        }
-        return name;
-    }
-
-    private String name;
-
-    /**
-     * Return the qualified class name as a String.
-     * <pre>
-     * Example:
-     *  for java.util.Hashtable
-     *  return java.util.Hashtable
-     *  if no qualifier, just return flat name
-     * </pre>
-     */
-    public String qualifiedName() {
-        if (qualifiedName == null) {
-            qualifiedName = getClassName(tsym, true);
-        }
-        return qualifiedName;
-    }
-
-    private String qualifiedName;
-
-    /**
-     * Return unqualified name of type excluding any dimension information.
-     * <p>
-     * For example, a two dimensional array of String returns 'String'.
-     */
-    public String typeName() {
-        return name();
-    }
-
-    /**
-     * Return qualified name of type excluding any dimension information.
-     *<p>
-     * For example, a two dimensional array of String
-     * returns 'java.lang.String'.
-     */
-    public String qualifiedTypeName() {
-        return qualifiedName();
-    }
-
-    /**
-     * Return the simple name of this type.
-     */
-    public String simpleTypeName() {
-        if (simpleTypeName == null) {
-            simpleTypeName = tsym.name.toString();
-        }
-        return simpleTypeName;
-    }
-
-    private String simpleTypeName;
-
-    /**
-     * Return the qualified name and any type parameters.
-     * Each parameter is a type variable with optional bounds.
-     */
-    @Override
-    public String toString() {
-        return classToString(env, tsym, true);
-    }
-
-    /**
-     * Return the class name as a string.  If "full" is true the name is
-     * qualified, otherwise it is qualified by its enclosing class(es) only.
-     */
-    static String getClassName(ClassSymbol c, boolean full) {
-        if (full) {
-            return c.getQualifiedName().toString();
-        } else {
-            String n = "";
-            for ( ; c != null; c = c.owner.enclClass()) {
-                n = c.name + (n.equals("") ? "" : ".") + n;
-            }
-            return n;
-        }
-    }
-
-    /**
-     * Return the class name with any type parameters as a string.
-     * Each parameter is a type variable with optional bounds.
-     * If "full" is true all names are qualified, otherwise they are
-     * qualified by their enclosing class(es) only.
-     */
-    static String classToString(DocEnv env, ClassSymbol c, boolean full) {
-        StringBuilder s = new StringBuilder();
-        if (!c.isInner()) {             // if c is not an inner class
-            s.append(getClassName(c, full));
-        } else {
-            // c is an inner class, so include type params of outer.
-            ClassSymbol encl = c.owner.enclClass();
-            s.append(classToString(env, encl, full))
-             .append('.')
-             .append(c.name);
-        }
-        s.append(TypeMaker.typeParametersString(env, c, full));
-        return s.toString();
-    }
-
-    /**
-     * Is this class (or any enclosing class) generic?  That is, does
-     * it have type parameters?
-     */
-    static boolean isGeneric(ClassSymbol c) {
-        return c.type.allparams().nonEmpty();
-    }
-
-    /**
-     * Return the formal type parameters of this class or interface.
-     * Return an empty array if there are none.
-     */
-    public TypeVariable[] typeParameters() {
-        if (env.legacyDoclet) {
-            return new TypeVariable[0];
-        }
-        TypeVariable res[] = new TypeVariable[type.getTypeArguments().length()];
-        TypeMaker.getTypes(env, type.getTypeArguments(), res);
-        return res;
-    }
-
-    /**
-     * Return the type parameter tags of this class or interface.
-     */
-    public ParamTag[] typeParamTags() {
-        return (env.legacyDoclet)
-            ? new ParamTag[0]
-            : comment().typeParamTags();
-    }
-
-    /**
-     * Return the modifier string for this class. If it's an interface
-     * exclude 'abstract' keyword from the modifier string
-     */
-    @Override
-    public String modifiers() {
-        return Modifier.toString(modifierSpecifier());
-    }
-
-    @Override
-    public int modifierSpecifier() {
-        int modifiers = getModifiers();
-        return (isInterface() || isAnnotationType())
-                ? modifiers & ~Modifier.ABSTRACT
-                : modifiers;
-    }
-
-    /**
-     * Return the superclass of this class
-     *
-     * @return the ClassDocImpl for the superclass of this class, null
-     * if there is no superclass.
-     */
-    public ClassDoc superclass() {
-        if (isInterface() || isAnnotationType()) return null;
-        if (tsym == env.syms.objectType.tsym) return null;
-        ClassSymbol c = (ClassSymbol)env.types.supertype(type).tsym;
-        if (c == null || c == tsym) c = (ClassSymbol)env.syms.objectType.tsym;
-        return env.getClassDoc(c);
-    }
-
-    /**
-     * Return the superclass of this class.  Return null if this is an
-     * interface.  A superclass is represented by either a
-     * <code>ClassDoc</code> or a <code>ParameterizedType</code>.
-     */
-    public com.sun.javadoc.Type superclassType() {
-        if (isInterface() || isAnnotationType() ||
-                (tsym == env.syms.objectType.tsym))
-            return null;
-        Type sup = env.types.supertype(type);
-        return TypeMaker.getType(env,
-                                 (sup.hasTag(TypeTag.NONE)) ? env.syms.objectType : sup);
-    }
-
-    /**
-     * Test whether this class is a subclass of the specified class.
-     *
-     * @param cd the candidate superclass.
-     * @return true if cd is a superclass of this class.
-     */
-    public boolean subclassOf(ClassDoc cd) {
-        return tsym.isSubClass(((ClassDocImpl)cd).tsym, env.types);
-    }
-
-    /**
-     * Return interfaces implemented by this class or interfaces
-     * extended by this interface.
-     *
-     * @return An array of ClassDocImpl representing the interfaces.
-     * Return an empty array if there are no interfaces.
-     */
-    public ClassDoc[] interfaces() {
-        ListBuffer<ClassDocImpl> ta = new ListBuffer<>();
-        for (Type t : env.types.interfaces(type)) {
-            ta.append(env.getClassDoc((ClassSymbol)t.tsym));
-        }
-        //### Cache ta here?
-        return ta.toArray(new ClassDocImpl[ta.length()]);
-    }
-
-    /**
-     * Return interfaces implemented by this class or interfaces extended
-     * by this interface. Includes only directly-declared interfaces, not
-     * inherited interfaces.
-     * Return an empty array if there are no interfaces.
-     */
-    public com.sun.javadoc.Type[] interfaceTypes() {
-        //### Cache result here?
-        return TypeMaker.getTypes(env, env.types.interfaces(type));
-    }
-
-    /**
-     * Return fields in class.
-     * @param filter include only the included fields if filter==true
-     */
-    public FieldDoc[] fields(boolean filter) {
-        return fields(filter, false);
-    }
-
-    /**
-     * Return included fields in class.
-     */
-    public FieldDoc[] fields() {
-        return fields(true, false);
-    }
-
-    /**
-     * Return the enum constants if this is an enum type.
-     */
-    public FieldDoc[] enumConstants() {
-        return fields(false, true);
-    }
-
-    /**
-     * Return fields in class.
-     * @param filter  if true, return only the included fields
-     * @param enumConstants  if true, return the enum constants instead
-     */
-    private FieldDoc[] fields(boolean filter, boolean enumConstants) {
-        List<FieldDocImpl> fields = List.nil();
-        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
-            if (sym != null && sym.kind == VAR) {
-                VarSymbol s = (VarSymbol)sym;
-                boolean isEnum = ((s.flags() & Flags.ENUM) != 0) &&
-                                 !env.legacyDoclet;
-                if (isEnum == enumConstants &&
-                        (!filter || env.shouldDocument(s))) {
-                    fields = fields.prepend(env.getFieldDoc(s));
-                }
-            }
-        }
-        return fields.toArray(new FieldDocImpl[fields.length()]);
-    }
-
-    /**
-     * Return methods in class.
-     * This method is overridden by AnnotationTypeDocImpl.
-     *
-     * @param filter include only the included methods if filter==true
-     * @return an array of MethodDocImpl for representing the visible
-     * methods in this class.  Does not include constructors.
-     */
-    public MethodDoc[] methods(boolean filter) {
-        Names names = tsym.name.table.names;
-        List<MethodDocImpl> methods = List.nil();
-        for (Symbol sym :tsym.members().getSymbols(NON_RECURSIVE)) {
-            if (sym != null
-                && sym.kind == MTH
-                && sym.name != names.init
-                && sym.name != names.clinit) {
-                MethodSymbol s = (MethodSymbol)sym;
-                if (!filter || env.shouldDocument(s)) {
-                    methods = methods.prepend(env.getMethodDoc(s));
-                }
-            }
-        }
-        //### Cache methods here?
-        return methods.toArray(new MethodDocImpl[methods.length()]);
-    }
-
-    /**
-     * Return included methods in class.
-     *
-     * @return an array of MethodDocImpl for representing the visible
-     * methods in this class.  Does not include constructors.
-     */
-    public MethodDoc[] methods() {
-        return methods(true);
-    }
-
-    /**
-     * Return constructors in class.
-     *
-     * @param filter include only the included constructors if filter==true
-     * @return an array of ConstructorDocImpl for representing the visible
-     * constructors in this class.
-     */
-    public ConstructorDoc[] constructors(boolean filter) {
-        Names names = tsym.name.table.names;
-        List<ConstructorDocImpl> constructors = List.nil();
-        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
-            if (sym != null &&
-                sym.kind == MTH && sym.name == names.init) {
-                MethodSymbol s = (MethodSymbol)sym;
-                if (!filter || env.shouldDocument(s)) {
-                    constructors = constructors.prepend(env.getConstructorDoc(s));
-                }
-            }
-        }
-        //### Cache constructors here?
-        return constructors.toArray(new ConstructorDocImpl[constructors.length()]);
-    }
-
-    /**
-     * Return included constructors in class.
-     *
-     * @return an array of ConstructorDocImpl for representing the visible
-     * constructors in this class.
-     */
-    public ConstructorDoc[] constructors() {
-        return constructors(true);
-    }
-
-    /**
-     * Adds all inner classes of this class, and their
-     * inner classes recursively, to the list l.
-     */
-    void addAllClasses(ListBuffer<ClassDocImpl> l, boolean filtered) {
-        try {
-            if (isSynthetic()) return;
-            // sometimes synthetic classes are not marked synthetic
-            if (!JavadocTool.isValidClassName(tsym.name.toString())) return;
-            if (filtered && !env.shouldDocument(tsym)) return;
-            if (l.contains(this)) return;
-            l.append(this);
-            List<ClassDocImpl> more = List.nil();
-            for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
-                if (sym != null && sym.kind == TYP) {
-                    ClassSymbol s = (ClassSymbol)sym;
-                    ClassDocImpl c = env.getClassDoc(s);
-                    if (c.isSynthetic()) continue;
-                    if (c != null) more = more.prepend(c);
-                }
-            }
-            // this extra step preserves the ordering from oldjavadoc
-            for (; more.nonEmpty(); more=more.tail) {
-                more.head.addAllClasses(l, filtered);
-            }
-        } catch (CompletionFailure e) {
-            // quietly ignore completion failures
-        }
-    }
-
-    /**
-     * Return inner classes within this class.
-     *
-     * @param filter include only the included inner classes if filter==true.
-     * @return an array of ClassDocImpl for representing the visible
-     * classes defined in this class. Anonymous and local classes
-     * are not included.
-     */
-    public ClassDoc[] innerClasses(boolean filter) {
-        ListBuffer<ClassDocImpl> innerClasses = new ListBuffer<>();
-        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
-            if (sym != null && sym.kind == TYP) {
-                ClassSymbol s = (ClassSymbol)sym;
-                if ((s.flags_field & Flags.SYNTHETIC) != 0) continue;
-                if (!filter || env.isVisible(s)) {
-                    innerClasses.prepend(env.getClassDoc(s));
-                }
-            }
-        }
-        //### Cache classes here?
-        return innerClasses.toArray(new ClassDocImpl[innerClasses.length()]);
-    }
-
-    /**
-     * Return included inner classes within this class.
-     *
-     * @return an array of ClassDocImpl for representing the visible
-     * classes defined in this class. Anonymous and local classes
-     * are not included.
-     */
-    public ClassDoc[] innerClasses() {
-        return innerClasses(true);
-    }
-
-    /**
-     * Find a class within the context of this class.
-     * Search order: qualified name, in this class (inner),
-     * in this package, in the class imports, in the package
-     * imports.
-     * Return the ClassDocImpl if found, null if not found.
-     */
-    //### The specified search order is not the normal rule the
-    //### compiler would use.  Leave as specified or change it?
-    public ClassDoc findClass(String className) {
-        ClassDoc searchResult = searchClass(className);
-        if (searchResult == null) {
-            ClassDocImpl enclosingClass = (ClassDocImpl)containingClass();
-            //Expand search space to include enclosing class.
-            while (enclosingClass != null && enclosingClass.containingClass() != null) {
-                enclosingClass = (ClassDocImpl)enclosingClass.containingClass();
-            }
-            searchResult = enclosingClass == null ?
-                null : enclosingClass.searchClass(className);
-        }
-        return searchResult;
-    }
-
-    private ClassDoc searchClass(String className) {
-        Names names = tsym.name.table.names;
-
-        // search by qualified name first
-        ClassDoc cd = env.lookupClass(className);
-        if (cd != null) {
-            return cd;
-        }
-
-        // search inner classes
-        //### Add private entry point to avoid creating array?
-        //### Replicate code in innerClasses here to avoid consing?
-        for (ClassDoc icd : innerClasses()) {
-            if (icd.name().equals(className) ||
-                    //### This is from original javadoc but it looks suspicious to me...
-                    //### I believe it is attempting to compensate for the confused
-                    //### convention of including the nested class qualifiers in the
-                    //### 'name' of the inner class, rather than the true simple name.
-                    icd.name().endsWith("." + className)) {
-                return icd;
-            } else {
-                ClassDoc innercd = ((ClassDocImpl) icd).searchClass(className);
-                if (innercd != null) {
-                    return innercd;
-                }
-            }
-        }
-
-        // check in this package
-        cd = containingPackage().findClass(className);
-        if (cd != null) {
-            return cd;
-        }
-
-        // make sure that this symbol has been completed
-        tsym.complete();
-
-        // search imports
-
-        if (tsym.sourcefile != null) {
-
-            //### This information is available only for source classes.
-
-            Env<AttrContext> compenv = env.enter.getEnv(tsym);
-            if (compenv == null) return null;
-
-            Scope s = compenv.toplevel.namedImportScope;
-            for (Symbol sym : s.getSymbolsByName(names.fromString(className))) {
-                if (sym.kind == TYP) {
-                    ClassDoc c = env.getClassDoc((ClassSymbol)sym);
-                    return c;
-                }
-            }
-
-            s = compenv.toplevel.starImportScope;
-            for (Symbol sym : s.getSymbolsByName(names.fromString(className))) {
-                if (sym.kind == TYP) {
-                    ClassDoc c = env.getClassDoc((ClassSymbol)sym);
-                    return c;
-                }
-            }
-        }
-
-        return null; // not found
-    }
-
-
-    private boolean hasParameterTypes(MethodSymbol method, String[] argTypes) {
-
-        if (argTypes == null) {
-            // wildcard
-            return true;
-        }
-
-        int i = 0;
-        List<Type> types = method.type.getParameterTypes();
-
-        if (argTypes.length != types.length()) {
-            return false;
-        }
-
-        for (Type t : types) {
-            String argType = argTypes[i++];
-            // For vararg method, "T..." matches type T[].
-            if (i == argTypes.length) {
-                argType = argType.replace("...", "[]");
-            }
-            if (!hasTypeName(env.types.erasure(t), argType)) {  //###(gj)
-                return false;
-            }
-        }
-        return true;
-    }
-    // where
-    private boolean hasTypeName(Type t, String name) {
-        return
-            name.equals(TypeMaker.getTypeName(t, true))
-            ||
-            name.equals(TypeMaker.getTypeName(t, false))
-            ||
-            (qualifiedName() + "." + name).equals(TypeMaker.getTypeName(t, true));
-    }
-
-
-
-    /**
-     * Find a method in this class scope.
-     * Search order: this class, interfaces, superclasses, outerclasses.
-     * Note that this is not necessarily what the compiler would do!
-     *
-     * @param methodName the unqualified name to search for.
-     * @param paramTypes the array of Strings for method parameter types.
-     * @return the first MethodDocImpl which matches, null if not found.
-     */
-    public MethodDocImpl findMethod(String methodName, String[] paramTypes) {
-        // Use hash table 'searched' to avoid searching same class twice.
-        //### It is not clear how this could happen.
-        return searchMethod(methodName, paramTypes, new HashSet<ClassDocImpl>());
-    }
-
-    private MethodDocImpl searchMethod(String methodName,
-                                       String[] paramTypes, Set<ClassDocImpl> searched) {
-        //### Note that this search is not necessarily what the compiler would do!
-
-        Names names = tsym.name.table.names;
-        // do not match constructors
-        if (names.init.contentEquals(methodName)) {
-            return null;
-        }
-
-        ClassDocImpl cdi;
-        MethodDocImpl mdi;
-
-        if (searched.contains(this)) {
-            return null;
-        }
-        searched.add(this);
-
-        //DEBUG
-        /*---------------------------------*
-         System.out.print("searching " + this + " for " + methodName);
-         if (paramTypes == null) {
-         System.out.println("()");
-         } else {
-         System.out.print("(");
-         for (int k=0; k < paramTypes.length; k++) {
-         System.out.print(paramTypes[k]);
-         if ((k + 1) < paramTypes.length) {
-         System.out.print(", ");
-         }
-         }
-         System.out.println(")");
-         }
-         *---------------------------------*/
-
-        // search current class
-
-        //### Using modifier filter here isn't really correct,
-        //### but emulates the old behavior.  Instead, we should
-        //### apply the normal rules of visibility and inheritance.
-
-        if (paramTypes == null) {
-            // If no parameters specified, we are allowed to return
-            // any method with a matching name.  In practice, the old
-            // code returned the first method, which is now the last!
-            // In order to provide textually identical results, we
-            // attempt to emulate the old behavior.
-            MethodSymbol lastFound = null;
-            for (Symbol sym : tsym.members().getSymbolsByName(names.fromString(methodName))) {
-                if (sym.kind == MTH) {
-                    //### Should intern methodName as Name.
-                    if (sym.name.toString().equals(methodName)) {
-                        lastFound = (MethodSymbol)sym;
-                    }
-                }
-            }
-            if (lastFound != null) {
-                return env.getMethodDoc(lastFound);
-            }
-        } else {
-            for (Symbol sym : tsym.members().getSymbolsByName(names.fromString(methodName))) {
-                if (sym != null &&
-                    sym.kind == MTH) {
-                    //### Should intern methodName as Name.
-                    if (hasParameterTypes((MethodSymbol)sym, paramTypes)) {
-                        return env.getMethodDoc((MethodSymbol)sym);
-                    }
-                }
-            }
-        }
-
-        //### If we found a MethodDoc above, but which did not pass
-        //### the modifier filter, we should return failure here!
-
-        // search superclass
-        cdi = (ClassDocImpl)superclass();
-        if (cdi != null) {
-            mdi = cdi.searchMethod(methodName, paramTypes, searched);
-            if (mdi != null) {
-                return mdi;
-            }
-        }
-
-        // search interfaces
-        for (ClassDoc intf : interfaces()) {
-            cdi = (ClassDocImpl) intf;
-            mdi = cdi.searchMethod(methodName, paramTypes, searched);
-            if (mdi != null) {
-                return mdi;
-            }
-        }
-
-        // search enclosing class
-        cdi = (ClassDocImpl)containingClass();
-        if (cdi != null) {
-            mdi = cdi.searchMethod(methodName, paramTypes, searched);
-            if (mdi != null) {
-                return mdi;
-            }
-        }
-
-        //###(gj) As a temporary measure until type variables are better
-        //### handled, try again without the parameter types.
-        //### This should most often find the right method, and occassionally
-        //### find the wrong one.
-        //if (paramTypes != null) {
-        //    return findMethod(methodName, null);
-        //}
-
-        return null;
-    }
-
-    /**
-     * Find constructor in this class.
-     *
-     * @param constrName the unqualified name to search for.
-     * @param paramTypes the array of Strings for constructor parameters.
-     * @return the first ConstructorDocImpl which matches, null if not found.
-     */
-    public ConstructorDoc findConstructor(String constrName,
-                                          String[] paramTypes) {
-        Names names = tsym.name.table.names;
-        for (Symbol sym : tsym.members().getSymbolsByName(names.fromString("<init>"))) {
-            if (sym.kind == MTH) {
-                if (hasParameterTypes((MethodSymbol)sym, paramTypes)) {
-                    return env.getConstructorDoc((MethodSymbol)sym);
-                }
-            }
-        }
-
-        //###(gj) As a temporary measure until type variables are better
-        //### handled, try again without the parameter types.
-        //### This will often find the right constructor, and occassionally
-        //### find the wrong one.
-        //if (paramTypes != null) {
-        //    return findConstructor(constrName, null);
-        //}
-
-        return null;
-    }
-
-    /**
-     * Find a field in this class scope.
-     * Search order: this class, outerclasses, interfaces,
-     * superclasses. IMP: If see tag is defined in an inner class,
-     * which extends a super class and if outerclass and the super
-     * class have a visible field in common then Java compiler cribs
-     * about the ambiguity, but the following code will search in the
-     * above given search order.
-     *
-     * @param fieldName the unqualified name to search for.
-     * @return the first FieldDocImpl which matches, null if not found.
-     */
-    public FieldDoc findField(String fieldName) {
-        return searchField(fieldName, new HashSet<ClassDocImpl>());
-    }
-
-    private FieldDocImpl searchField(String fieldName, Set<ClassDocImpl> searched) {
-        Names names = tsym.name.table.names;
-        if (searched.contains(this)) {
-            return null;
-        }
-        searched.add(this);
-
-        for (Symbol sym : tsym.members().getSymbolsByName(names.fromString(fieldName))) {
-            if (sym.kind == VAR) {
-                //### Should intern fieldName as Name.
-                return env.getFieldDoc((VarSymbol)sym);
-            }
-        }
-
-        //### If we found a FieldDoc above, but which did not pass
-        //### the modifier filter, we should return failure here!
-
-        ClassDocImpl cdi = (ClassDocImpl)containingClass();
-        if (cdi != null) {
-            FieldDocImpl fdi = cdi.searchField(fieldName, searched);
-            if (fdi != null) {
-                return fdi;
-            }
-        }
-
-        // search superclass
-        cdi = (ClassDocImpl)superclass();
-        if (cdi != null) {
-            FieldDocImpl fdi = cdi.searchField(fieldName, searched);
-            if (fdi != null) {
-                return fdi;
-            }
-        }
-
-        // search interfaces
-        for (ClassDoc intf : interfaces()) {
-            cdi = (ClassDocImpl) intf;
-            FieldDocImpl fdi = cdi.searchField(fieldName, searched);
-            if (fdi != null) {
-                return fdi;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Get the list of classes declared as imported.
-     * These are called "single-type-import declarations" in the JLS.
-     * This method is deprecated in the ClassDoc interface.
-     *
-     * @return an array of ClassDocImpl representing the imported classes.
-     *
-     * @deprecated  Import declarations are implementation details that
-     *          should not be exposed here.  In addition, not all imported
-     *          classes are imported through single-type-import declarations.
-     */
-    @Deprecated
-    public ClassDoc[] importedClasses() {
-        // information is not available for binary classfiles
-        if (tsym.sourcefile == null) return new ClassDoc[0];
-
-        ListBuffer<ClassDocImpl> importedClasses = new ListBuffer<>();
-
-        Env<AttrContext> compenv = env.enter.getEnv(tsym);
-        if (compenv == null) return new ClassDocImpl[0];
-
-        Name asterisk = tsym.name.table.names.asterisk;
-        for (JCTree t : compenv.toplevel.defs) {
-            if (t.hasTag(IMPORT)) {
-                JCTree imp = ((JCImport) t).qualid;
-                if ((TreeInfo.name(imp) != asterisk) &&
-                    imp.type.tsym.kind.matches(KindSelector.TYP)) {
-                    importedClasses.append(
-                            env.getClassDoc((ClassSymbol)imp.type.tsym));
-                }
-            }
-        }
-
-        return importedClasses.toArray(new ClassDocImpl[importedClasses.length()]);
-    }
-
-    /**
-     * Get the list of packages declared as imported.
-     * These are called "type-import-on-demand declarations" in the JLS.
-     * This method is deprecated in the ClassDoc interface.
-     *
-     * @return an array of PackageDocImpl representing the imported packages.
-     *
-     * ###NOTE: the syntax supports importing all inner classes from a class as well.
-     * @deprecated  Import declarations are implementation details that
-     *          should not be exposed here.  In addition, this method's
-     *          return type does not allow for all type-import-on-demand
-     *          declarations to be returned.
-     */
-    @Deprecated
-    public PackageDoc[] importedPackages() {
-        // information is not available for binary classfiles
-        if (tsym.sourcefile == null) return new PackageDoc[0];
-
-        ListBuffer<PackageDocImpl> importedPackages = new ListBuffer<>();
-
-        //### Add the implicit "import java.lang.*" to the result
-        Names names = tsym.name.table.names;
-        importedPackages.append(env.getPackageDoc(env.syms.enterPackage(env.syms.java_base, names.java_lang)));
-
-        Env<AttrContext> compenv = env.enter.getEnv(tsym);
-        if (compenv == null) return new PackageDocImpl[0];
-
-        for (JCTree t : compenv.toplevel.defs) {
-            if (t.hasTag(IMPORT)) {
-                JCTree imp = ((JCImport) t).qualid;
-                if (TreeInfo.name(imp) == names.asterisk) {
-                    JCFieldAccess sel = (JCFieldAccess)imp;
-                    Symbol s = sel.selected.type.tsym;
-                    PackageDocImpl pdoc = env.getPackageDoc(s.packge());
-                    if (!importedPackages.contains(pdoc))
-                        importedPackages.append(pdoc);
-                }
-            }
-        }
-
-        return importedPackages.toArray(new PackageDocImpl[importedPackages.length()]);
-    }
-
-    /**
-     * Return the type's dimension information.
-     * Always return "", as this is not an array type.
-     */
-    public String dimension() {
-        return "";
-    }
-
-    /**
-     * Return this type as a class, which it already is.
-     */
-    public ClassDoc asClassDoc() {
-        return this;
-    }
-
-    /**
-     * Return null (unless overridden), as this is not an annotation type.
-     */
-    public AnnotationTypeDoc asAnnotationTypeDoc() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not a class instantiation.
-     */
-    public ParameterizedType asParameterizedType() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not a type variable.
-     */
-    public TypeVariable asTypeVariable() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not a wildcard type.
-     */
-    public WildcardType asWildcardType() {
-        return null;
-    }
-
-    /**
-     * Returns null, as this is not an annotated type.
-     */
-    public AnnotatedType asAnnotatedType() {
-        return null;
-    }
-
-    /**
-     * Return false, as this is not a primitive type.
-     */
-    public boolean isPrimitive() {
-        return false;
-    }
-
-    //--- Serialization ---
-
-    //### These methods ignore modifier filter.
-
-    /**
-     * Return true if this class implements <code>java.io.Serializable</code>.
-     *
-     * Since <code>java.io.Externalizable</code> extends
-     * <code>java.io.Serializable</code>,
-     * Externalizable objects are also Serializable.
-     */
-    public boolean isSerializable() {
-        try {
-            return env.types.isSubtype(type, env.syms.serializableType);
-        } catch (CompletionFailure ex) {
-            // quietly ignore completion failures
-            return false;
-        }
-    }
-
-    /**
-     * Return true if this class implements
-     * <code>java.io.Externalizable</code>.
-     */
-    public boolean isExternalizable() {
-        try {
-            return env.types.isSubtype(type, env.externalizableSym.type);
-        } catch (CompletionFailure ex) {
-            // quietly ignore completion failures
-            return false;
-        }
-    }
-
-    /**
-     * Return the serialization methods for this class.
-     *
-     * @return an array of <code>MethodDocImpl</code> that represents
-     * the serialization methods for this class.
-     */
-    public MethodDoc[] serializationMethods() {
-        if (serializedForm == null) {
-            serializedForm = new SerializedForm(env, tsym, this);
-        }
-        //### Clone this?
-        return serializedForm.methods();
-    }
-
-    /**
-     * Return the Serializable fields of class.<p>
-     *
-     * Return either a list of default fields documented by
-     * <code>serial</code> tag<br>
-     * or return a single <code>FieldDoc</code> for
-     * <code>serialPersistentField</code> member.
-     * There should be a <code>serialField</code> tag for
-     * each Serializable field defined by an <code>ObjectStreamField</code>
-     * array component of <code>serialPersistentField</code>.
-     *
-     * @return an array of {@code FieldDoc} for the Serializable fields
-     *         of this class.
-     *
-     * @see #definesSerializableFields()
-     * @see SerialFieldTagImpl
-     */
-    public FieldDoc[] serializableFields() {
-        if (serializedForm == null) {
-            serializedForm = new SerializedForm(env, tsym, this);
-        }
-        //### Clone this?
-        return serializedForm.fields();
-    }
-
-    /**
-     * Return true if Serializable fields are explicitly defined with
-     * the special class member <code>serialPersistentFields</code>.
-     *
-     * @see #serializableFields()
-     * @see SerialFieldTagImpl
-     */
-    public boolean definesSerializableFields() {
-        if (!isSerializable() || isExternalizable()) {
-            return false;
-        } else {
-            if (serializedForm == null) {
-                serializedForm = new SerializedForm(env, tsym, this);
-            }
-            //### Clone this?
-            return serializedForm.definesSerializableFields();
-        }
-    }
-
-    /**
-     * Determine if a class is a RuntimeException.
-     * <p>
-     * Used only by ThrowsTagImpl.
-     */
-    boolean isRuntimeException() {
-        return tsym.isSubClass(env.syms.runtimeExceptionType.tsym, env.types);
-    }
-
-    /**
-     * Return the source position of the entity, or null if
-     * no position is available.
-     */
-    @Override
-    public SourcePosition position() {
-        if (tsym.sourcefile == null) return null;
-        return SourcePositionImpl.make(tsym.sourcefile,
-                                       (tree==null) ? Position.NOPOS : tree.pos,
-                                       lineMap);
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Comment.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,460 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import com.sun.javadoc.*;
-import com.sun.tools.javac.util.ListBuffer;
-
-/**
- * Comment contains all information in comment part.
- *      It allows users to get first sentence of this comment, get
- *      comment for different tags...
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Kaiyang Liu (original)
- * @author Robert Field (rewrite)
- * @author Atul M Dambalkar
- * @author Neal Gafter (rewrite)
- */
-class Comment {
-
-    /**
-     * sorted comments with different tags.
-     */
-    private final ListBuffer<Tag> tagList = new ListBuffer<>();
-
-    /**
-     * text minus any tags.
-     */
-    private String text;
-
-    /**
-     * Doc environment
-     */
-    private final DocEnv docenv;
-
-    /**
-     * constructor of Comment.
-     */
-    Comment(final DocImpl holder, final String commentString) {
-        this.docenv = holder.env;
-
-        /**
-         * Separate the comment into the text part and zero to N tags.
-         * Simple state machine is in one of three states:
-         * <pre>
-         * IN_TEXT: parsing the comment text or tag text.
-         * TAG_NAME: parsing the name of a tag.
-         * TAG_GAP: skipping through the gap between the tag name and
-         * the tag text.
-         * </pre>
-         */
-        @SuppressWarnings("fallthrough")
-        class CommentStringParser {
-            /**
-             * The entry point to the comment string parser
-             */
-            void parseCommentStateMachine() {
-                final int IN_TEXT = 1;
-                final int TAG_GAP = 2;
-                final int TAG_NAME = 3;
-                int state = TAG_GAP;
-                boolean newLine = true;
-                String tagName = null;
-                int tagStart = 0;
-                int textStart = 0;
-                int lastNonWhite = -1;
-                int len = commentString.length();
-                for (int inx = 0; inx < len; ++inx) {
-                    char ch = commentString.charAt(inx);
-                    boolean isWhite = Character.isWhitespace(ch);
-                    switch (state)  {
-                        case TAG_NAME:
-                            if (isWhite) {
-                                tagName = commentString.substring(tagStart, inx);
-                                state = TAG_GAP;
-                            }
-                            break;
-                        case TAG_GAP:
-                            if (isWhite) {
-                                break;
-                            }
-                            textStart = inx;
-                            state = IN_TEXT;
-                            /* fall thru */
-                        case IN_TEXT:
-                            if (newLine && ch == '@') {
-                                parseCommentComponent(tagName, textStart,
-                                                      lastNonWhite+1);
-                                tagStart = inx;
-                                state = TAG_NAME;
-                            }
-                            break;
-                    }
-                    if (ch == '\n') {
-                        newLine = true;
-                    } else if (!isWhite) {
-                        lastNonWhite = inx;
-                        newLine = false;
-                    }
-                }
-                // Finish what's currently being processed
-                switch (state)  {
-                    case TAG_NAME:
-                        tagName = commentString.substring(tagStart, len);
-                        /* fall thru */
-                    case TAG_GAP:
-                        textStart = len;
-                        /* fall thru */
-                    case IN_TEXT:
-                        parseCommentComponent(tagName, textStart, lastNonWhite+1);
-                        break;
-                }
-            }
-
-            /**
-             * Save away the last parsed item.
-             */
-            void parseCommentComponent(String tagName,
-                                       int from, int upto) {
-                String tx = upto <= from ? "" : commentString.substring(from, upto);
-                if (tagName == null) {
-                    text = tx;
-                } else {
-                    TagImpl tag;
-                    switch (tagName) {
-                        case "@exception":
-                        case "@throws":
-                            warnIfEmpty(tagName, tx);
-                            tag = new ThrowsTagImpl(holder, tagName, tx);
-                            break;
-                        case "@param":
-                            warnIfEmpty(tagName, tx);
-                            tag = new ParamTagImpl(holder, tagName, tx);
-                            break;
-                        case "@see":
-                            warnIfEmpty(tagName, tx);
-                            tag = new SeeTagImpl(holder, tagName, tx);
-                            break;
-                        case "@serialField":
-                            warnIfEmpty(tagName, tx);
-                            tag = new SerialFieldTagImpl(holder, tagName, tx);
-                            break;
-                        case "@return":
-                            warnIfEmpty(tagName, tx);
-                            tag = new TagImpl(holder, tagName, tx);
-                            break;
-                        case "@author":
-                            warnIfEmpty(tagName, tx);
-                            tag = new TagImpl(holder, tagName, tx);
-                            break;
-                        case "@version":
-                            warnIfEmpty(tagName, tx);
-                            tag = new TagImpl(holder, tagName, tx);
-                            break;
-                        default:
-                            tag = new TagImpl(holder, tagName, tx);
-                            break;
-                    }
-                    tagList.append(tag);
-                }
-            }
-
-            void warnIfEmpty(String tagName, String tx) {
-                if (tx.length() == 0) {
-                    docenv.warning(holder, "tag.tag_has_no_arguments", tagName);
-                }
-            }
-
-        }
-
-        new CommentStringParser().parseCommentStateMachine();
-    }
-
-    /**
-     * Return the text of the comment.
-     */
-    String commentText() {
-        return text;
-    }
-
-    /**
-     * Return all tags in this comment.
-     */
-    Tag[] tags() {
-        return tagList.toArray(new Tag[tagList.length()]);
-    }
-
-    /**
-     * Return tags of the specified kind in this comment.
-     */
-    Tag[] tags(String tagname) {
-        ListBuffer<Tag> found = new ListBuffer<>();
-        String target = tagname;
-        if (target.charAt(0) != '@') {
-            target = "@" + target;
-        }
-        for (Tag tag : tagList) {
-            if (tag.kind().equals(target)) {
-                found.append(tag);
-            }
-        }
-        return found.toArray(new Tag[found.length()]);
-    }
-
-    /**
-     * Return throws tags in this comment.
-     */
-    ThrowsTag[] throwsTags() {
-        ListBuffer<ThrowsTag> found = new ListBuffer<>();
-        for (Tag next : tagList) {
-            if (next instanceof ThrowsTag) {
-                found.append((ThrowsTag)next);
-            }
-        }
-        return found.toArray(new ThrowsTag[found.length()]);
-    }
-
-    /**
-     * Return param tags (excluding type param tags) in this comment.
-     */
-    ParamTag[] paramTags() {
-        return paramTags(false);
-    }
-
-    /**
-     * Return type param tags in this comment.
-     */
-    ParamTag[] typeParamTags() {
-        return paramTags(true);
-    }
-
-    /**
-     * Return param tags in this comment.  If typeParams is true
-     * include only type param tags, otherwise include only ordinary
-     * param tags.
-     */
-    private ParamTag[] paramTags(boolean typeParams) {
-        ListBuffer<ParamTag> found = new ListBuffer<>();
-        for (Tag next : tagList) {
-            if (next instanceof ParamTag) {
-                ParamTag p = (ParamTag)next;
-                if (typeParams == p.isTypeParameter()) {
-                    found.append(p);
-                }
-            }
-        }
-        return found.toArray(new ParamTag[found.length()]);
-    }
-
-    /**
-     * Return see also tags in this comment.
-     */
-    SeeTag[] seeTags() {
-        ListBuffer<SeeTag> found = new ListBuffer<>();
-        for (Tag next : tagList) {
-            if (next instanceof SeeTag) {
-                found.append((SeeTag)next);
-            }
-        }
-        return found.toArray(new SeeTag[found.length()]);
-    }
-
-    /**
-     * Return serialField tags in this comment.
-     */
-    SerialFieldTag[] serialFieldTags() {
-        ListBuffer<SerialFieldTag> found = new ListBuffer<>();
-        for (Tag next : tagList) {
-            if (next instanceof SerialFieldTag) {
-                found.append((SerialFieldTag)next);
-            }
-        }
-        return found.toArray(new SerialFieldTag[found.length()]);
-    }
-
-    /**
-     * Return array of tags with text and inline See Tags for a Doc comment.
-     */
-    static Tag[] getInlineTags(DocImpl holder, String inlinetext) {
-        ListBuffer<Tag> taglist = new ListBuffer<>();
-        int delimend = 0, textstart = 0, len = inlinetext.length();
-        boolean inPre = false;
-        DocEnv docenv = holder.env;
-
-        if (len == 0) {
-            return taglist.toArray(new Tag[taglist.length()]);
-        }
-        while (true) {
-            int linkstart;
-            if ((linkstart = inlineTagFound(holder, inlinetext,
-                                            textstart)) == -1) {
-                taglist.append(new TagImpl(holder, "Text",
-                                           inlinetext.substring(textstart)));
-                break;
-            } else {
-                inPre = scanForPre(inlinetext, textstart, linkstart, inPre);
-                int seetextstart = linkstart;
-                for (int i = linkstart; i < inlinetext.length(); i++) {
-                    char c = inlinetext.charAt(i);
-                    if (Character.isWhitespace(c) ||
-                        c == '}') {
-                        seetextstart = i;
-                        break;
-                     }
-                }
-                String linkName = inlinetext.substring(linkstart+2, seetextstart);
-                if (!(inPre && (linkName.equals("code") || linkName.equals("literal")))) {
-                    //Move past the white space after the inline tag name.
-                    while (Character.isWhitespace(inlinetext.
-                                                      charAt(seetextstart))) {
-                        if (inlinetext.length() <= seetextstart) {
-                            taglist.append(new TagImpl(holder, "Text",
-                                                       inlinetext.substring(textstart, seetextstart)));
-                            docenv.warning(holder,
-                                           "tag.Improper_Use_Of_Link_Tag",
-                                           inlinetext);
-                            return taglist.toArray(new Tag[taglist.length()]);
-                        } else {
-                            seetextstart++;
-                        }
-                    }
-                }
-                taglist.append(new TagImpl(holder, "Text",
-                                           inlinetext.substring(textstart, linkstart)));
-                textstart = seetextstart;   // this text is actually seetag
-                if ((delimend = findInlineTagDelim(inlinetext, textstart)) == -1) {
-                    //Missing closing '}' character.
-                    // store the text as it is with the {@link.
-                    taglist.append(new TagImpl(holder, "Text",
-                                               inlinetext.substring(textstart)));
-                    docenv.warning(holder,
-                                   "tag.End_delimiter_missing_for_possible_SeeTag",
-                                   inlinetext);
-                    return taglist.toArray(new Tag[taglist.length()]);
-                } else {
-                    //Found closing '}' character.
-                    if (linkName.equals("see")
-                           || linkName.equals("link")
-                           || linkName.equals("linkplain")) {
-                        taglist.append( new SeeTagImpl(holder, "@" + linkName,
-                              inlinetext.substring(textstart, delimend)));
-                    } else {
-                        taglist.append( new TagImpl(holder, "@" + linkName,
-                              inlinetext.substring(textstart, delimend)));
-                    }
-                    textstart = delimend + 1;
-                }
-            }
-            if (textstart == inlinetext.length()) {
-                break;
-            }
-        }
-        return taglist.toArray(new Tag[taglist.length()]);
-    }
-
-    /** regex for case-insensitive match for {@literal <pre> } and  {@literal </pre> }. */
-    private static final Pattern prePat = Pattern.compile("(?i)<(/?)pre>");
-
-    private static boolean scanForPre(String inlinetext, int start, int end, boolean inPre) {
-        Matcher m = prePat.matcher(inlinetext).region(start, end);
-        while (m.find()) {
-            inPre = m.group(1).isEmpty();
-        }
-        return inPre;
-    }
-
-    /**
-     * Recursively find the index of the closing '}' character for an inline tag
-     * and return it.  If it can't be found, return -1.
-     * @param inlineText the text to search in.
-     * @param searchStart the index of the place to start searching at.
-     * @return the index of the closing '}' character for an inline tag.
-     * If it can't be found, return -1.
-     */
-    private static int findInlineTagDelim(String inlineText, int searchStart) {
-        int delimEnd, nestedOpenBrace;
-        if ((delimEnd = inlineText.indexOf("}", searchStart)) == -1) {
-            return -1;
-        } else if (((nestedOpenBrace = inlineText.indexOf("{", searchStart)) != -1) &&
-            nestedOpenBrace < delimEnd){
-            //Found a nested open brace.
-            int nestedCloseBrace = findInlineTagDelim(inlineText, nestedOpenBrace + 1);
-            return (nestedCloseBrace != -1) ?
-                findInlineTagDelim(inlineText, nestedCloseBrace + 1) :
-                -1;
-        } else {
-            return delimEnd;
-        }
-    }
-
-    /**
-     * Recursively search for the characters '{', '@', followed by
-     * name of inline tag and white space,
-     * if found
-     *    return the index of the text following the white space.
-     * else
-     *    return -1.
-     */
-    private static int inlineTagFound(DocImpl holder, String inlinetext, int start) {
-        DocEnv docenv = holder.env;
-        int linkstart = inlinetext.indexOf("{@", start);
-        if (start == inlinetext.length() || linkstart == -1) {
-            return -1;
-        } else if (inlinetext.indexOf('}', linkstart) == -1) {
-            //Missing '}'.
-            docenv.warning(holder, "tag.Improper_Use_Of_Link_Tag",
-                    inlinetext.substring(linkstart, inlinetext.length()));
-            return -1;
-        } else {
-            return linkstart;
-        }
-    }
-
-
-    /**
-     * Return array of tags for the locale specific first sentence in the text.
-     */
-    static Tag[] firstSentenceTags(DocImpl holder, String text) {
-        DocLocale doclocale = holder.env.doclocale;
-        return getInlineTags(holder,
-                             doclocale.localeSpecificFirstSentence(holder, text));
-    }
-
-    /**
-     * Return text for this Doc comment.
-     */
-    @Override
-    public String toString() {
-        return text;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ConstructorDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.MethodSymbol;
-
-/**
- * Represents a constructor of a java class.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since 1.2
- * @author Robert Field
- * @author Neal Gafter (rewrite)
- */
-
-public class ConstructorDocImpl
-        extends ExecutableMemberDocImpl implements ConstructorDoc {
-
-    /**
-     * constructor.
-     */
-    public ConstructorDocImpl(DocEnv env, MethodSymbol sym) {
-        super(env, sym);
-    }
-
-    /**
-     * constructor.
-     */
-    public ConstructorDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) {
-        super(env, sym, treePath);
-    }
-
-    /**
-     * Return true if it is a constructor, which it is.
-     *
-     * @return true
-     */
-    public boolean isConstructor() {
-        return true;
-    }
-
-    /**
-     * Get the name.
-     *
-     * @return the name of the member.
-     */
-    public String name() {
-        ClassSymbol c = sym.enclClass();
-        return c.name.toString();
-    }
-
-    /**
-     * Get the name.
-     *
-     * @return the qualified name of the member.
-     */
-    public String qualifiedName() {
-        return sym.enclClass().getQualifiedName().toString();
-    }
-
-    /**
-     * Returns a string representation of this constructor.  Includes the
-     * qualified signature and any type parameters.
-     * Type parameters precede the class name, as they do in the syntax
-     * for invoking constructors with explicit type parameters using "new".
-     * (This is unlike the syntax for invoking methods with explicit type
-     * parameters.)
-     */
-    public String toString() {
-        return typeParametersString() + qualifiedName() + signature();
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,869 +0,0 @@
-/*
- * Copyright (c) 2000, 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 com.sun.tools.javadoc;
-
-import java.lang.reflect.Modifier;
-import java.util.*;
-
-import javax.tools.JavaFileManager;
-
-import com.sun.javadoc.*;
-import com.sun.source.tree.CompilationUnitTree;
-import com.sun.source.util.JavacTask;
-import com.sun.source.util.TreePath;
-import com.sun.tools.doclint.DocLint;
-import com.sun.tools.javac.api.BasicJavacTask;
-import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.CompletionFailure;
-import com.sun.tools.javac.code.Symbol.MethodSymbol;
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
-import com.sun.tools.javac.code.Symbol.VarSymbol;
-import com.sun.tools.javac.code.Type.ClassType;
-import com.sun.tools.javac.comp.Check;
-import com.sun.tools.javac.comp.Enter;
-import com.sun.tools.javac.file.JavacFileManager;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCClassDecl;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.Convert;
-import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Names;
-
-/**
- * Holds the environment for a run of javadoc.
- * Holds only the information needed throughout the
- * run and not the compiler info that could be GC'ed
- * or ported.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since 1.4
- * @author Robert Field
- * @author Neal Gafter (rewrite)
- * @author Scott Seligman (generics)
- */
-public class DocEnv {
-    protected static final Context.Key<DocEnv> docEnvKey = new Context.Key<>();
-
-    public static DocEnv instance(Context context) {
-        DocEnv instance = context.get(docEnvKey);
-        if (instance == null)
-            instance = new DocEnv(context);
-        return instance;
-    }
-
-    DocLocale doclocale;
-
-    private final Messager messager;
-
-    /** Predefined symbols known to the compiler. */
-    final Symtab syms;
-
-    /** Referenced directly in RootDocImpl. */
-    private final ClassFinder finder;
-
-    /** Javadoc's own version of the compiler's enter phase. */
-    final Enter enter;
-
-    /** The name table. */
-    private Names names;
-
-    /** The encoding name. */
-    private String encoding;
-
-    final Symbol externalizableSym;
-
-    /** Access filter (public, protected, ...).  */
-    protected ModifierFilter showAccess;
-
-    /** True if we are using a sentence BreakIterator. */
-    boolean breakiterator;
-
-    /**
-     * True if we do not want to print any notifications at all.
-     */
-    boolean quiet = false;
-
-    Check chk;
-    Types types;
-    JavaFileManager fileManager;
-    Context context;
-    DocLint doclint;
-
-    WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<>();
-
-    /** Allow documenting from class files? */
-    boolean docClasses = false;
-
-    /** Does the doclet only expect pre-1.5 doclet API? */
-    protected boolean legacyDoclet = true;
-
-    /**
-     * Set this to true if you would like to not emit any errors, warnings and
-     * notices.
-     */
-    private boolean silent = false;
-
-    /**
-     * The source language version.
-     */
-    protected Source source;
-
-    /**
-     * Constructor
-     *
-     * @param context      Context for this javadoc instance.
-     */
-    protected DocEnv(Context context) {
-        context.put(docEnvKey, this);
-        this.context = context;
-
-        messager = Messager.instance0(context);
-        syms = Symtab.instance(context);
-        finder = JavadocClassFinder.instance(context);
-        enter = JavadocEnter.instance(context);
-        names = Names.instance(context);
-        externalizableSym = syms.enterClass(syms.java_base, names.fromString("java.io.Externalizable"));
-        chk = Check.instance(context);
-        types = Types.instance(context);
-        fileManager = context.get(JavaFileManager.class);
-        if (fileManager instanceof JavacFileManager) {
-            ((JavacFileManager)fileManager).setSymbolFileEnabled(false);
-        }
-
-        // Default.  Should normally be reset with setLocale.
-        this.doclocale = new DocLocale(this, "", breakiterator);
-        source = Source.instance(context);
-    }
-
-    public void setSilent(boolean silent) {
-        this.silent = silent;
-    }
-
-    /**
-     * Look up ClassDoc by qualified name.
-     */
-    public ClassDocImpl lookupClass(String name) {
-        ClassSymbol c = getClassSymbol(name);
-        if (c != null) {
-            return getClassDoc(c);
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Load ClassDoc by qualified name.
-     */
-    public ClassDocImpl loadClass(String name) {
-        try {
-            Name nameImpl = names.fromString(name);
-            ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
-            ClassSymbol c = finder.loadClass(mod != null ? mod : syms.errModule, nameImpl);
-            return getClassDoc(c);
-        } catch (CompletionFailure ex) {
-            chk.completionError(null, ex);
-            return null;
-        }
-    }
-
-    /**
-     * Look up PackageDoc by qualified name.
-     */
-    public PackageDocImpl lookupPackage(String name) {
-        //### Jing alleges that class check is needed
-        //### to avoid a compiler bug.  Most likely
-        //### instead a dummy created for error recovery.
-        //### Should investigate this.
-        Name nameImpl = names.fromString(name);
-        ModuleSymbol mod = syms.inferModule(nameImpl);
-        PackageSymbol p = mod != null ? syms.getPackage(mod, nameImpl) : null;
-        ClassSymbol c = getClassSymbol(name);
-        if (p != null && c == null) {
-            return getPackageDoc(p);
-        } else {
-            return null;
-        }
-    }
-        // where
-        /** Retrieve class symbol by fully-qualified name.
-         */
-        ClassSymbol getClassSymbol(String name) {
-            // Name may contain nested class qualification.
-            // Generate candidate flatnames with successively shorter
-            // package qualifiers and longer nested class qualifiers.
-            int nameLen = name.length();
-            char[] nameChars = name.toCharArray();
-            int idx = name.length();
-            for (;;) {
-                Name nameImpl = names.fromChars(nameChars, 0, nameLen);
-                ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
-                ClassSymbol s = mod != null ? syms.getClass(mod, nameImpl) : null;
-                if (s != null)
-                    return s; // found it!
-                idx = name.substring(0, idx).lastIndexOf('.');
-                if (idx < 0) break;
-                nameChars[idx] = '$';
-            }
-            return null;
-        }
-
-    /**
-     * Set the locale.
-     */
-    public void setLocale(String localeName) {
-        // create locale specifics
-        doclocale = new DocLocale(this, localeName, breakiterator);
-        // update Messager if locale has changed.
-        messager.setLocale(doclocale.locale);
-    }
-
-    /** Check whether this member should be documented. */
-    public boolean shouldDocument(VarSymbol sym) {
-        long mod = sym.flags();
-
-        if ((mod & Flags.SYNTHETIC) != 0) {
-            return false;
-        }
-
-        return showAccess.checkModifier(translateModifiers(mod));
-    }
-
-    /** Check whether this member should be documented. */
-    public boolean shouldDocument(MethodSymbol sym) {
-        long mod = sym.flags();
-
-        if ((mod & Flags.SYNTHETIC) != 0) {
-            return false;
-        }
-
-        return showAccess.checkModifier(translateModifiers(mod));
-    }
-
-    /** check whether this class should be documented. */
-    public boolean shouldDocument(ClassSymbol sym) {
-        return
-            (sym.flags_field&Flags.SYNTHETIC) == 0 && // no synthetics
-            (docClasses || getClassDoc(sym).tree != null) &&
-            isVisible(sym);
-    }
-
-    //### Comment below is inaccurate wrt modifier filter testing
-    /**
-     * Check the visibility if this is an nested class.
-     * if this is not a nested class, return true.
-     * if this is an static visible nested class,
-     *    return true.
-     * if this is an visible nested class
-     *    if the outer class is visible return true.
-     *    else return false.
-     * IMPORTANT: This also allows, static nested classes
-     * to be defined inside an nested class, which is not
-     * allowed by the compiler. So such an test case will
-     * not reach upto this method itself, but if compiler
-     * allows it, then that will go through.
-     */
-    protected boolean isVisible(ClassSymbol sym) {
-        long mod = sym.flags_field;
-        if (!showAccess.checkModifier(translateModifiers(mod))) {
-            return false;
-        }
-        ClassSymbol encl = sym.owner.enclClass();
-        return (encl == null || (mod & Flags.STATIC) != 0 || isVisible(encl));
-    }
-
-    //---------------- print forwarders ----------------//
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param msg message to print.
-     */
-    public void printError(String msg) {
-        if (silent)
-            return;
-        messager.printError(msg);
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param key selects message from resource
-     */
-    public void error(DocImpl doc, String key) {
-        if (silent)
-            return;
-        messager.error(doc==null ? null : doc.position(), key);
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param key selects message from resource
-     */
-    public void error(SourcePosition pos, String key) {
-        if (silent)
-            return;
-        messager.error(pos, key);
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param msg message to print.
-     */
-    public void printError(SourcePosition pos, String msg) {
-        if (silent)
-            return;
-        messager.printError(pos, msg);
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument
-     */
-    public void error(DocImpl doc, String key, String a1) {
-        if (silent)
-            return;
-        messager.error(doc==null ? null : doc.position(), key, a1);
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument
-     * @param a2 second argument
-     */
-    public void error(DocImpl doc, String key, String a1, String a2) {
-        if (silent)
-            return;
-        messager.error(doc==null ? null : doc.position(), key, a1, a2);
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument
-     * @param a2 second argument
-     * @param a3 third argument
-     */
-    public void error(DocImpl doc, String key, String a1, String a2, String a3) {
-        if (silent)
-            return;
-        messager.error(doc==null ? null : doc.position(), key, a1, a2, a3);
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param msg message to print.
-     */
-    public void printWarning(String msg) {
-        if (silent)
-            return;
-        messager.printWarning(msg);
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param key selects message from resource
-     */
-    public void warning(DocImpl doc, String key) {
-        if (silent)
-            return;
-        messager.warning(doc==null ? null : doc.position(), key);
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param msg message to print.
-     */
-    public void printWarning(SourcePosition pos, String msg) {
-        if (silent)
-            return;
-        messager.printWarning(pos, msg);
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument
-     */
-    public void warning(DocImpl doc, String key, String a1) {
-        if (silent)
-            return;
-        // suppress messages that have (probably) been covered by doclint
-        if (doclint != null && doc != null && key.startsWith("tag"))
-            return;
-        messager.warning(doc==null ? null : doc.position(), key, a1);
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument
-     * @param a2 second argument
-     */
-    public void warning(DocImpl doc, String key, String a1, String a2) {
-        if (silent)
-            return;
-        messager.warning(doc==null ? null : doc.position(), key, a1, a2);
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument
-     * @param a2 second argument
-     * @param a3 third argument
-     */
-    public void warning(DocImpl doc, String key, String a1, String a2, String a3) {
-        if (silent)
-            return;
-        messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3);
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument
-     * @param a2 second argument
-     * @param a3 third argument
-     */
-    public void warning(DocImpl doc, String key, String a1, String a2, String a3,
-                        String a4) {
-        if (silent)
-            return;
-        messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3, a4);
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param msg message to print.
-     */
-    public void printNotice(String msg) {
-        if (silent || quiet)
-            return;
-        messager.printNotice(msg);
-    }
-
-
-    /**
-     * Print a message.
-     *
-     * @param key selects message from resource
-     */
-    public void notice(String key) {
-        if (silent || quiet)
-            return;
-        messager.notice(key);
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param msg message to print.
-     */
-    public void printNotice(SourcePosition pos, String msg) {
-        if (silent || quiet)
-            return;
-        messager.printNotice(pos, msg);
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument
-     */
-    public void notice(String key, String a1) {
-        if (silent || quiet)
-            return;
-        messager.notice(key, a1);
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument
-     * @param a2 second argument
-     */
-    public void notice(String key, String a1, String a2) {
-        if (silent || quiet)
-            return;
-        messager.notice(key, a1, a2);
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument
-     * @param a2 second argument
-     * @param a3 third argument
-     */
-    public void notice(String key, String a1, String a2, String a3) {
-        if (silent || quiet)
-            return;
-        messager.notice(key, a1, a2, a3);
-    }
-
-    /**
-     * Exit, reporting errors and warnings.
-     */
-    public void exit() {
-        // Messager should be replaced by a more general
-        // compilation environment.  This can probably
-        // subsume DocEnv as well.
-        messager.exit();
-    }
-
-    protected Map<PackageSymbol, PackageDocImpl> packageMap = new HashMap<>();
-    /**
-     * Return the PackageDoc of this package symbol.
-     */
-    public PackageDocImpl getPackageDoc(PackageSymbol pack) {
-        PackageDocImpl result = packageMap.get(pack);
-        if (result != null) return result;
-        result = new PackageDocImpl(this, pack);
-        packageMap.put(pack, result);
-        return result;
-    }
-
-    /**
-     * Create the PackageDoc (or a subtype) for a package symbol.
-     */
-    void makePackageDoc(PackageSymbol pack, TreePath treePath) {
-        PackageDocImpl result = packageMap.get(pack);
-        if (result != null) {
-            if (treePath != null) result.setTreePath(treePath);
-        } else {
-            result = new PackageDocImpl(this, pack, treePath);
-            packageMap.put(pack, result);
-        }
-    }
-
-
-    protected Map<ClassSymbol, ClassDocImpl> classMap = new HashMap<>();
-    /**
-     * Return the ClassDoc (or a subtype) of this class symbol.
-     */
-    public ClassDocImpl getClassDoc(ClassSymbol clazz) {
-        ClassDocImpl result = classMap.get(clazz);
-        if (result != null) return result;
-        if (isAnnotationType(clazz)) {
-            result = new AnnotationTypeDocImpl(this, clazz);
-        } else {
-            result = new ClassDocImpl(this, clazz);
-        }
-        classMap.put(clazz, result);
-        return result;
-    }
-
-    /**
-     * Create the ClassDoc (or a subtype) for a class symbol.
-     */
-    protected void makeClassDoc(ClassSymbol clazz, TreePath treePath) {
-        ClassDocImpl result = classMap.get(clazz);
-        if (result != null) {
-            if (treePath != null) result.setTreePath(treePath);
-            return;
-        }
-        if (isAnnotationType((JCClassDecl) treePath.getLeaf())) {   // flags of clazz may not yet be set
-            result = new AnnotationTypeDocImpl(this, clazz, treePath);
-        } else {
-            result = new ClassDocImpl(this, clazz, treePath);
-        }
-        classMap.put(clazz, result);
-    }
-
-    protected static boolean isAnnotationType(ClassSymbol clazz) {
-        return ClassDocImpl.isAnnotationType(clazz);
-    }
-
-    protected static boolean isAnnotationType(JCClassDecl tree) {
-        return (tree.mods.flags & Flags.ANNOTATION) != 0;
-    }
-
-    protected Map<VarSymbol, FieldDocImpl> fieldMap = new HashMap<>();
-    /**
-     * Return the FieldDoc of this var symbol.
-     */
-    public FieldDocImpl getFieldDoc(VarSymbol var) {
-        FieldDocImpl result = fieldMap.get(var);
-        if (result != null) return result;
-        result = new FieldDocImpl(this, var);
-        fieldMap.put(var, result);
-        return result;
-    }
-    /**
-     * Create a FieldDoc for a var symbol.
-     */
-    protected void makeFieldDoc(VarSymbol var, TreePath treePath) {
-        FieldDocImpl result = fieldMap.get(var);
-        if (result != null) {
-            if (treePath != null) result.setTreePath(treePath);
-        } else {
-            result = new FieldDocImpl(this, var, treePath);
-            fieldMap.put(var, result);
-        }
-    }
-
-    protected Map<MethodSymbol, ExecutableMemberDocImpl> methodMap = new HashMap<>();
-    /**
-     * Create a MethodDoc for this MethodSymbol.
-     * Should be called only on symbols representing methods.
-     */
-    protected void makeMethodDoc(MethodSymbol meth, TreePath treePath) {
-        MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);
-        if (result != null) {
-            if (treePath != null) result.setTreePath(treePath);
-        } else {
-            result = new MethodDocImpl(this, meth, treePath);
-            methodMap.put(meth, result);
-        }
-    }
-
-    /**
-     * Return the MethodDoc for a MethodSymbol.
-     * Should be called only on symbols representing methods.
-     */
-    public MethodDocImpl getMethodDoc(MethodSymbol meth) {
-        assert !meth.isConstructor() : "not expecting a constructor symbol";
-        MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);
-        if (result != null) return result;
-        result = new MethodDocImpl(this, meth);
-        methodMap.put(meth, result);
-        return result;
-    }
-
-    /**
-     * Create the ConstructorDoc for a MethodSymbol.
-     * Should be called only on symbols representing constructors.
-     */
-    protected void makeConstructorDoc(MethodSymbol meth, TreePath treePath) {
-        ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);
-        if (result != null) {
-            if (treePath != null) result.setTreePath(treePath);
-        } else {
-            result = new ConstructorDocImpl(this, meth, treePath);
-            methodMap.put(meth, result);
-        }
-    }
-
-    /**
-     * Return the ConstructorDoc for a MethodSymbol.
-     * Should be called only on symbols representing constructors.
-     */
-    public ConstructorDocImpl getConstructorDoc(MethodSymbol meth) {
-        assert meth.isConstructor() : "expecting a constructor symbol";
-        ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);
-        if (result != null) return result;
-        result = new ConstructorDocImpl(this, meth);
-        methodMap.put(meth, result);
-        return result;
-    }
-
-    /**
-     * Create the AnnotationTypeElementDoc for a MethodSymbol.
-     * Should be called only on symbols representing annotation type elements.
-     */
-    protected void makeAnnotationTypeElementDoc(MethodSymbol meth, TreePath treePath) {
-        AnnotationTypeElementDocImpl result =
-            (AnnotationTypeElementDocImpl)methodMap.get(meth);
-        if (result != null) {
-            if (treePath != null) result.setTreePath(treePath);
-        } else {
-            result =
-                new AnnotationTypeElementDocImpl(this, meth, treePath);
-            methodMap.put(meth, result);
-        }
-    }
-
-    /**
-     * Return the AnnotationTypeElementDoc for a MethodSymbol.
-     * Should be called only on symbols representing annotation type elements.
-     */
-    public AnnotationTypeElementDocImpl getAnnotationTypeElementDoc(
-            MethodSymbol meth) {
-
-        AnnotationTypeElementDocImpl result =
-            (AnnotationTypeElementDocImpl)methodMap.get(meth);
-        if (result != null) return result;
-        result = new AnnotationTypeElementDocImpl(this, meth);
-        methodMap.put(meth, result);
-        return result;
-    }
-
-//  private Map<ClassType, ParameterizedTypeImpl> parameterizedTypeMap =
-//          new HashMap<ClassType, ParameterizedTypeImpl>();
-    /**
-     * Return the ParameterizedType of this instantiation.
-//   * ### Could use Type.sameTypeAs() instead of equality matching in hashmap
-//   * ### to avoid some duplication.
-     */
-    ParameterizedTypeImpl getParameterizedType(ClassType t) {
-        return new ParameterizedTypeImpl(this, t);
-//      ParameterizedTypeImpl result = parameterizedTypeMap.get(t);
-//      if (result != null) return result;
-//      result = new ParameterizedTypeImpl(this, t);
-//      parameterizedTypeMap.put(t, result);
-//      return result;
-    }
-
-    TreePath getTreePath(JCCompilationUnit tree) {
-        TreePath p = treePaths.get(tree);
-        if (p == null)
-            treePaths.put(tree, p = new TreePath(tree));
-        return p;
-    }
-
-    TreePath getTreePath(JCCompilationUnit toplevel, JCPackageDecl tree) {
-        TreePath p = treePaths.get(tree);
-        if (p == null)
-            treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree));
-        return p;
-    }
-
-    TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) {
-        TreePath p = treePaths.get(tree);
-        if (p == null)
-            treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree));
-        return p;
-    }
-
-    TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) {
-        return new TreePath(getTreePath(toplevel, cdecl), tree);
-    }
-
-    /**
-     * Set the encoding.
-     */
-    public void setEncoding(String encoding) {
-        this.encoding = encoding;
-    }
-
-    /**
-     * Get the encoding.
-     */
-    public String getEncoding() {
-        return encoding;
-    }
-
-    /**
-     * Convert modifier bits from private coding used by
-     * the compiler to that of java.lang.reflect.Modifier.
-     */
-    static int translateModifiers(long flags) {
-        int result = 0;
-        if ((flags & Flags.ABSTRACT) != 0)
-            result |= Modifier.ABSTRACT;
-        if ((flags & Flags.FINAL) != 0)
-            result |= Modifier.FINAL;
-        if ((flags & Flags.INTERFACE) != 0)
-            result |= Modifier.INTERFACE;
-        if ((flags & Flags.NATIVE) != 0)
-            result |= Modifier.NATIVE;
-        if ((flags & Flags.PRIVATE) != 0)
-            result |= Modifier.PRIVATE;
-        if ((flags & Flags.PROTECTED) != 0)
-            result |= Modifier.PROTECTED;
-        if ((flags & Flags.PUBLIC) != 0)
-            result |= Modifier.PUBLIC;
-        if ((flags & Flags.STATIC) != 0)
-            result |= Modifier.STATIC;
-        if ((flags & Flags.SYNCHRONIZED) != 0)
-            result |= Modifier.SYNCHRONIZED;
-        if ((flags & Flags.TRANSIENT) != 0)
-            result |= Modifier.TRANSIENT;
-        if ((flags & Flags.VOLATILE) != 0)
-            result |= Modifier.VOLATILE;
-        return result;
-    }
-
-    void initDoclint(Collection<String> opts, Collection<String> customTagNames, String htmlVersion) {
-        ArrayList<String> doclintOpts = new ArrayList<>();
-        boolean msgOptionSeen = false;
-
-        for (String opt : opts) {
-            if (opt.startsWith(DocLint.XMSGS_OPTION)) {
-                if (opt.equals(DocLint.XMSGS_CUSTOM_PREFIX + "none"))
-                    return;
-                msgOptionSeen = true;
-            }
-            doclintOpts.add(opt);
-        }
-
-        if (!msgOptionSeen) {
-            doclintOpts.add(DocLint.XMSGS_OPTION);
-        }
-
-        String sep = "";
-        StringBuilder customTags = new StringBuilder();
-        for (String customTag : customTagNames) {
-            customTags.append(sep);
-            customTags.append(customTag);
-            sep = DocLint.SEPARATOR;
-        }
-        doclintOpts.add(DocLint.XCUSTOM_TAGS_PREFIX + customTags.toString());
-        doclintOpts.add(DocLint.XHTML_VERSION_PREFIX + htmlVersion);
-
-        JavacTask t = BasicJavacTask.instance(context);
-        doclint = new DocLint();
-        // standard doclet normally generates H1, H2
-        doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2");
-        doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false);
-    }
-
-    boolean showTagMessages() {
-        return (doclint == null);
-    }
-
-    Map<CompilationUnitTree, Boolean> shouldCheck = new HashMap<>();
-
-    boolean shouldCheck(CompilationUnitTree unit) {
-        return shouldCheck.computeIfAbsent(unit, doclint :: shouldCheck);
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,444 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.CollationKey;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.tools.FileObject;
-
-import com.sun.javadoc.*;
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.util.Position;
-
-/**
- * abstract base class of all Doc classes.  Doc item's are representations
- * of java language constructs (class, package, method,...) which have
- * comments and have been processed by this run of javadoc.  All Doc items
- * are unique, that is, they are == comparable.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since 1.2
- * @author Robert Field
- * @author Atul M Dambalkar
- * @author Neal Gafter (rewrite)
- */
-public abstract class DocImpl implements Doc, Comparable<Object> {
-
-    /**
-     * Doc environment
-     */
-    protected final DocEnv env;   //### Rename this everywhere to 'docenv' ?
-
-    /**
-     * Back pointer to the tree node for this doc item.
-     * May be null if there is no associated tree.
-     */
-    protected TreePath treePath;
-
-    /**
-     *  The complex comment object, lazily initialized.
-     */
-    private Comment comment;
-
-    /**
-     * The cached sort key, to take care of Natural Language Text sorting.
-     */
-    private CollationKey collationkey = null;
-
-    /**
-     *  Raw documentation string.
-     */
-    protected String documentation;  // Accessed in PackageDocImpl, RootDocImpl
-
-    /**
-     * Cached first sentence.
-     */
-    private Tag[] firstSentence;
-
-    /**
-     * Cached inline tags.
-     */
-    private Tag[] inlineTags;
-
-    /**
-     * Constructor.
-     */
-    DocImpl(DocEnv env, TreePath treePath) {
-        this.treePath = treePath;
-        this.documentation = getCommentText(treePath);
-        this.env = env;
-    }
-
-    private static String getCommentText(TreePath p) {
-        if (p == null)
-            return null;
-
-        JCCompilationUnit topLevel = (JCCompilationUnit) p.getCompilationUnit();
-        JCTree tree = (JCTree) p.getLeaf();
-        return topLevel.docComments.getCommentText(tree);
-    }
-
-    /**
-     * So subclasses have the option to do lazy initialization of
-     * "documentation" string.
-     */
-    protected String documentation() {
-        if (documentation == null) documentation = "";
-        return documentation;
-    }
-
-    /**
-     * For lazy initialization of comment.
-     */
-    Comment comment() {
-        if (comment == null) {
-            String d = documentation();
-            if (env.doclint != null
-                    && treePath != null
-                    && env.shouldCheck(treePath.getCompilationUnit())
-                    && d.equals(getCommentText(treePath))) {
-                env.doclint.scan(treePath);
-            }
-            comment = new Comment(this, d);
-        }
-        return comment;
-    }
-
-    /**
-     * Return the text of the comment for this doc item.
-     * TagImpls have been removed.
-     */
-    public String commentText() {
-        return comment().commentText();
-    }
-
-    /**
-     * Return all tags in this Doc item.
-     *
-     * @return an array of TagImpl containing all tags on this Doc item.
-     */
-    public Tag[] tags() {
-        return comment().tags();
-    }
-
-    /**
-     * Return tags of the specified kind in this Doc item.
-     *
-     * @param tagname name of the tag kind to search for.
-     * @return an array of TagImpl containing all tags whose 'kind()'
-     * matches 'tagname'.
-     */
-    public Tag[] tags(String tagname) {
-        return comment().tags(tagname);
-    }
-
-    /**
-     * Return the see also tags in this Doc item.
-     *
-     * @return an array of SeeTag containing all &#64;see tags.
-     */
-    public SeeTag[] seeTags() {
-        return comment().seeTags();
-    }
-
-    public Tag[] inlineTags() {
-        if (inlineTags == null) {
-            inlineTags = Comment.getInlineTags(this, commentText());
-        }
-        return inlineTags;
-    }
-
-    public Tag[] firstSentenceTags() {
-        if (firstSentence == null) {
-            //Parse all sentences first to avoid duplicate warnings.
-            inlineTags();
-            try {
-                env.setSilent(true);
-                firstSentence = Comment.firstSentenceTags(this, commentText());
-            } finally {
-                env.setSilent(false);
-            }
-        }
-        return firstSentence;
-    }
-
-    /**
-     * Utility for subclasses which read HTML documentation files.
-     */
-    String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException {
-        byte[] filecontents = new byte[input.available()];
-        try {
-            DataInputStream dataIn = new DataInputStream(input);
-            dataIn.readFully(filecontents);
-        } finally {
-            input.close();
-        }
-        String encoding = env.getEncoding();
-        String rawDoc = (encoding!=null)
-            ? new String(filecontents, encoding)
-            : new String(filecontents);
-        Pattern bodyPat = Pattern.compile("(?is).*<body\\b[^>]*>(.*)</body\\b.*");
-        Matcher m = bodyPat.matcher(rawDoc);
-        if (m.matches()) {
-            return m.group(1);
-        } else {
-            String key = rawDoc.matches("(?is).*<body\\b.*")
-                    ? "javadoc.End_body_missing_from_html_file"
-                    : "javadoc.Body_missing_from_html_file";
-            env.error(SourcePositionImpl.make(filename, Position.NOPOS, null), key);
-            return "";
-        }
-    }
-
-    /**
-     * Return the full unprocessed text of the comment.  Tags
-     * are included as text.  Used mainly for store and retrieve
-     * operations like internalization.
-     */
-    public String getRawCommentText() {
-        return documentation();
-    }
-
-    /**
-     * Set the full unprocessed text of the comment.  Tags
-     * are included as text.  Used mainly for store and retrieve
-     * operations like internalization.
-     */
-    public void setRawCommentText(String rawDocumentation) {
-        treePath = null;
-        documentation = rawDocumentation;
-        comment = null;
-    }
-
-    /**
-     * Set the full unprocessed text of the comment and tree path.
-     */
-    void setTreePath(TreePath treePath) {
-        this.treePath = treePath;
-        documentation = getCommentText(treePath);
-        comment = null;
-    }
-
-    /**
-     * return a key for sorting.
-     */
-    CollationKey key() {
-        if (collationkey == null) {
-            collationkey = generateKey();
-        }
-        return collationkey;
-    }
-
-    /**
-     * Generate a key for sorting.
-     * <p>
-     * Default is name().
-     */
-    CollationKey generateKey() {
-        String k = name();
-        // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
-        return env.doclocale.collator.getCollationKey(k);
-    }
-
-    /**
-     * Returns a string representation of this Doc item.
-     */
-    @Override
-    public String toString() {
-        return qualifiedName();
-    }
-
-    /**
-     * Returns the name of this Doc item.
-     *
-     * @return  the name
-     */
-    public abstract String name();
-
-    /**
-     * Returns the qualified name of this Doc item.
-     *
-     * @return  the name
-     */
-    public abstract String qualifiedName();
-
-    /**
-     * Compares this Object with the specified Object for order.  Returns a
-     * negative integer, zero, or a positive integer as this Object is less
-     * than, equal to, or greater than the given Object.
-     * <p>
-     * Included so that Doc item are java.lang.Comparable.
-     *
-     * @param   obj the {@code Object} to be compared.
-     * @return  a negative integer, zero, or a positive integer as this Object
-     *          is less than, equal to, or greater than the given Object.
-     * @exception ClassCastException the specified Object's type prevents it
-     *            from being compared to this Object.
-     */
-    public int compareTo(Object obj) {
-        // System.out.println("COMPARE \"" + this + "\" to \"" + obj + "\" = " + key().compareTo(((DocImpl)obj).key()));
-        return key().compareTo(((DocImpl)obj).key());
-    }
-
-    /**
-     * Is this Doc item a field?  False until overridden.
-     *
-     * @return true if it represents a field
-     */
-    public boolean isField() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item an enum constant?  False until overridden.
-     *
-     * @return true if it represents an enum constant
-     */
-    public boolean isEnumConstant() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item a constructor?  False until overridden.
-     *
-     * @return true if it represents a constructor
-     */
-    public boolean isConstructor() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item a method (but not a constructor or annotation
-     * type element)?
-     * False until overridden.
-     *
-     * @return true if it represents a method
-     */
-    public boolean isMethod() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item an annotation type element?
-     * False until overridden.
-     *
-     * @return true if it represents an annotation type element
-     */
-    public boolean isAnnotationTypeElement() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item a interface (but not an annotation type)?
-     * False until overridden.
-     *
-     * @return true if it represents a interface
-     */
-    public boolean isInterface() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item a exception class?  False until overridden.
-     *
-     * @return true if it represents a exception
-     */
-    public boolean isException() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item a error class?  False until overridden.
-     *
-     * @return true if it represents a error
-     */
-    public boolean isError() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item an enum type?  False until overridden.
-     *
-     * @return true if it represents an enum type
-     */
-    public boolean isEnum() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item an annotation type?  False until overridden.
-     *
-     * @return true if it represents an annotation type
-     */
-    public boolean isAnnotationType() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item an ordinary class (i.e. not an interface,
-     * annotation type, enumeration, exception, or error)?
-     * False until overridden.
-     *
-     * @return true if it represents an ordinary class
-     */
-    public boolean isOrdinaryClass() {
-        return false;
-    }
-
-    /**
-     * Is this Doc item a class
-     * (and not an interface or annotation type)?
-     * This includes ordinary classes, enums, errors and exceptions.
-     * False until overridden.
-     *
-     * @return true if it represents a class
-     */
-    public boolean isClass() {
-        return false;
-    }
-
-    /**
-     * return true if this Doc is include in the active set.
-     */
-    public abstract boolean isIncluded();
-
-    /**
-     * Return the source position of the entity, or null if
-     * no position is available.
-     */
-    public SourcePosition position() { return null; }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocLocale.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 2000, 2012, 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.sun.tools.javadoc;
-
-import java.text.BreakIterator;
-import java.text.Collator;
-import java.util.Locale;
-
-/**
- * This class holds the information about locales.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since 1.4
- * @author Robert Field
- */
-class DocLocale {
-
-    /**
-     * The locale name will be set by Main, if option is provided on the
-     * command line.
-     */
-    final String localeName;
-
-    /**
-     * The locale to be used. If user doesn't provide this,
-     * then set it to default locale value.
-     */
-    final Locale locale;
-
-    /**
-     * The collator for this application. This is to take care of Locale
-     * Specific or Natural Language Text sorting.
-     */
-    final Collator collator;
-
-    /**
-     * Enclosing DocEnv
-     */
-    private final DocEnv docenv;
-
-    /**
-     * Sentence instance from the BreakIterator.
-     */
-    private final BreakIterator sentenceBreaker;
-
-    /**
-     * True is we should use <code>BreakIterator</code>
-     * to compute first sentence.
-     */
-    private boolean useBreakIterator = false;
-
-    /**
-     * The HTML sentence terminators.
-     */
-    static final String[] sentenceTerminators =
-                    {
-                        "<p>", "</p>", "<h1>", "<h2>",
-                        "<h3>", "<h4>", "<h5>", "<h6>",
-                        "</h1>", "</h2>", "</h3>", "</h4>", "</h5>",
-                        "</h6>", "<hr>", "<pre>", "</pre>"
-                    };
-
-    /**
-     * Constructor
-     */
-    DocLocale(DocEnv docenv, String localeName, boolean useBreakIterator) {
-        this.docenv = docenv;
-        this.localeName = localeName;
-        this.useBreakIterator = useBreakIterator;
-        locale = getLocale();
-        if (locale == null) {
-            docenv.exit();
-        } else {
-            Locale.setDefault(locale); // NOTE: updating global state
-        }
-        collator = Collator.getInstance(locale);
-        sentenceBreaker = BreakIterator.getSentenceInstance(locale);
-    }
-
-    /**
-     * Get the locale if specified on the command line
-     * else return null and if locale option is not used
-     * then return default locale.
-     */
-    private Locale getLocale() {
-        Locale userlocale = null;
-        if (localeName.length() > 0) {
-            int firstuscore = localeName.indexOf('_');
-            int seconduscore = -1;
-            String language = null;
-            String country = null;
-            String variant = null;
-            if (firstuscore == 2) {
-                language = localeName.substring(0, firstuscore);
-                seconduscore = localeName.indexOf('_', firstuscore + 1);
-                if (seconduscore > 0) {
-                    if (seconduscore != firstuscore + 3 ||
-                           localeName.length() <= seconduscore + 1) {
-                        docenv.error(null, "main.malformed_locale_name", localeName);
-                        return null;
-                    }
-                    country = localeName.substring(firstuscore + 1,
-                                                   seconduscore);
-                    variant = localeName.substring(seconduscore + 1);
-                } else if (localeName.length() == firstuscore + 3) {
-                    country = localeName.substring(firstuscore + 1);
-                } else {
-                    docenv.error(null, "main.malformed_locale_name", localeName);
-                    return null;
-                }
-            } else if (firstuscore == -1 && localeName.length() == 2) {
-                language = localeName;
-            } else {
-                docenv.error(null, "main.malformed_locale_name", localeName);
-                return null;
-            }
-            userlocale = searchLocale(language, country, variant);
-            if (userlocale == null) {
-                docenv.error(null, "main.illegal_locale_name", localeName);
-                return null;
-            } else {
-                return userlocale;
-            }
-        } else {
-            return Locale.getDefault();
-        }
-    }
-
-    /**
-     * Search the locale for specified language, specified country and
-     * specified variant.
-     */
-    private Locale searchLocale(String language, String country,
-                                String variant) {
-        for (Locale loc : Locale.getAvailableLocales()) {
-            if (loc.getLanguage().equals(language) &&
-                (country == null || loc.getCountry().equals(country)) &&
-                (variant == null || loc.getVariant().equals(variant))) {
-                return loc;
-            }
-        }
-        return null;
-    }
-
-    String localeSpecificFirstSentence(DocImpl doc, String s) {
-        if (s == null || s.length() == 0) {
-            return "";
-        }
-        int index = s.indexOf("-->");
-        if(s.trim().startsWith("<!--") && index != -1) {
-            return localeSpecificFirstSentence(doc, s.substring(index + 3, s.length()));
-        }
-        if (useBreakIterator || !locale.getLanguage().equals("en")) {
-            sentenceBreaker.setText(s.replace('\n', ' '));
-            int start = sentenceBreaker.first();
-            int end = sentenceBreaker.next();
-            return s.substring(start, end).trim();
-        } else {
-            return englishLanguageFirstSentence(s).trim();
-        }
-    }
-
-    /**
-     * Return the first sentence of a string, where a sentence ends
-     * with a period followed be white space.
-     */
-    private String englishLanguageFirstSentence(String s) {
-        if (s == null) {
-            return null;
-        }
-        int len = s.length();
-        boolean period = false;
-        for (int i = 0 ; i < len ; i++) {
-            switch (s.charAt(i)) {
-                case '.':
-                    period = true;
-                    break;
-                case ' ':
-                case '\t':
-                case '\n':
-            case '\r':
-            case '\f':
-                    if (period) {
-                        return s.substring(0, i);
-                    }
-                    break;
-            case '<':
-                    if (i > 0) {
-                        if (htmlSentenceTerminatorFound(s, i)) {
-                            return s.substring(0, i);
-                        }
-                    }
-                    break;
-                default:
-                    period = false;
-            }
-        }
-        return s;
-    }
-
-    /**
-     * Find out if there is any HTML tag in the given string. If found
-     * return true else return false.
-     */
-    private boolean htmlSentenceTerminatorFound(String str, int index) {
-        for (String terminator : sentenceTerminators) {
-            if (str.regionMatches(true, index, terminator,
-                                  0, terminator.length())) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,439 +0,0 @@
-/*
- * 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
- * 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.sun.tools.javadoc;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.regex.Pattern;
-
-import javax.tools.DocumentationTool;
-import javax.tools.JavaFileManager;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.util.ClientCodeException;
-import com.sun.tools.javac.util.List;
-
-import static com.sun.javadoc.LanguageVersion.*;
-
-
-/**
- * Class creates, controls and invokes doclets.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Neal Gafter (rewrite)
- */
-public class DocletInvoker {
-
-    private final Class<?> docletClass;
-
-    private final String docletClassName;
-
-    private final ClassLoader appClassLoader;
-
-    private final Messager messager;
-
-    /**
-     * In API mode, exceptions thrown while calling the doclet are
-     * propagated using ClientCodeException.
-     */
-    private final boolean apiMode;
-
-    /**
-     * Whether javadoc internal API should be exported to doclets
-     * and (indirectly) to taglets
-     */
-    private final boolean exportInternalAPI;
-
-    private static class DocletInvokeException extends Exception {
-        private static final long serialVersionUID = 0;
-    }
-
-    private String appendPath(String path1, String path2) {
-        if (path1 == null || path1.length() == 0) {
-            return path2 == null ? "." : path2;
-        } else if (path2 == null || path2.length() == 0) {
-            return path1;
-        } else {
-            return path1  + File.pathSeparator + path2;
-        }
-    }
-
-    public DocletInvoker(Messager messager, Class<?> docletClass, boolean apiMode, boolean exportInternalAPI) {
-        this.messager = messager;
-        this.docletClass = docletClass;
-        docletClassName = docletClass.getName();
-        appClassLoader = null;
-        this.apiMode = apiMode;
-        this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets
-
-        // this may not be soon enough if the class has already been loaded
-        if (exportInternalAPI) {
-            exportInternalAPI(docletClass.getClassLoader());
-        }
-    }
-
-    public DocletInvoker(Messager messager, JavaFileManager fileManager,
-                         String docletClassName, String docletPath,
-                         ClassLoader docletParentClassLoader,
-                         boolean apiMode,
-                         boolean exportInternalAPI) {
-        this.messager = messager;
-        this.docletClassName = docletClassName;
-        this.apiMode = apiMode;
-        this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets
-
-        if (fileManager != null && fileManager.hasLocation(DocumentationTool.Location.DOCLET_PATH)) {
-            appClassLoader = fileManager.getClassLoader(DocumentationTool.Location.DOCLET_PATH);
-        } else {
-            // construct class loader
-            String cpString = null;   // make sure env.class.path defaults to dot
-
-            // do prepends to get correct ordering
-            cpString = appendPath(System.getProperty("env.class.path"), cpString);
-            cpString = appendPath(System.getProperty("java.class.path"), cpString);
-            cpString = appendPath(docletPath, cpString);
-            URL[] urls = pathToURLs(cpString);
-            if (docletParentClassLoader == null)
-                appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName));
-            else
-                appClassLoader = new URLClassLoader(urls, docletParentClassLoader);
-        }
-
-        if (exportInternalAPI) {
-            exportInternalAPI(appClassLoader);
-        }
-
-        // attempt to find doclet
-        Class<?> dc = null;
-        try {
-            dc = appClassLoader.loadClass(docletClassName);
-        } catch (ClassNotFoundException exc) {
-            messager.error(Messager.NOPOS, "main.doclet_class_not_found", docletClassName);
-            messager.exit();
-        }
-        docletClass = dc;
-    }
-
-    /*
-     * Returns the delegation class loader to use when creating
-     * appClassLoader (used to load the doclet).  The context class
-     * loader is the best choice, but legacy behavior was to use the
-     * default delegation class loader (aka system class loader).
-     *
-     * Here we favor using the context class loader.  To ensure
-     * compatibility with existing apps, we revert to legacy
-     * behavior if either or both of the following conditions hold:
-     *
-     * 1) the doclet is loadable from the system class loader but not
-     *    from the context class loader,
-     *
-     * 2) this.getClass() is loadable from the system class loader but not
-     *    from the context class loader.
-     */
-    private ClassLoader getDelegationClassLoader(String docletClassName) {
-        ClassLoader ctxCL = Thread.currentThread().getContextClassLoader();
-        ClassLoader sysCL = ClassLoader.getSystemClassLoader();
-        if (sysCL == null)
-            return ctxCL;
-        if (ctxCL == null)
-            return sysCL;
-
-        // Condition 1.
-        try {
-            sysCL.loadClass(docletClassName);
-            try {
-                ctxCL.loadClass(docletClassName);
-            } catch (ClassNotFoundException e) {
-                return sysCL;
-            }
-        } catch (ClassNotFoundException e) {
-        }
-
-        // Condition 2.
-        try {
-            if (getClass() == sysCL.loadClass(getClass().getName())) {
-                try {
-                    if (getClass() != ctxCL.loadClass(getClass().getName()))
-                        return sysCL;
-                } catch (ClassNotFoundException e) {
-                    return sysCL;
-                }
-            }
-        } catch (ClassNotFoundException e) {
-        }
-
-        return ctxCL;
-    }
-
-    /**
-     * Generate documentation here.  Return true on success.
-     */
-    public boolean start(RootDoc root) {
-        Object retVal;
-        String methodName = "start";
-        Class<?>[] paramTypes = { RootDoc.class };
-        Object[] params = { root };
-        try {
-            retVal = invoke(methodName, null, paramTypes, params);
-        } catch (DocletInvokeException exc) {
-            return false;
-        }
-        if (retVal instanceof Boolean) {
-            return ((Boolean)retVal);
-        } else {
-            messager.error(Messager.NOPOS, "main.must_return_boolean",
-                           docletClassName, methodName);
-            return false;
-        }
-    }
-
-    /**
-     * Check for doclet added options here. Zero return means
-     * option not known.  Positive value indicates number of
-     * arguments to option.  Negative value means error occurred.
-     */
-    public int optionLength(String option) {
-        Object retVal;
-        String methodName = "optionLength";
-        Class<?>[] paramTypes = { String.class };
-        Object[] params = { option };
-        try {
-            retVal = invoke(methodName, 0, paramTypes, params);
-        } catch (DocletInvokeException exc) {
-            return -1;
-        }
-        if (retVal instanceof Integer) {
-            return ((Integer)retVal);
-        } else {
-            messager.error(Messager.NOPOS, "main.must_return_int",
-                           docletClassName, methodName);
-            return -1;
-        }
-    }
-
-    /**
-     * Let doclet check that all options are OK. Returning true means
-     * options are OK.  If method does not exist, assume true.
-     */
-    public boolean validOptions(List<String[]> optlist) {
-        Object retVal;
-        String options[][] = optlist.toArray(new String[optlist.length()][]);
-        String methodName = "validOptions";
-        DocErrorReporter reporter = messager;
-        Class<?>[] paramTypes = { String[][].class, DocErrorReporter.class };
-        Object[] params = { options, reporter };
-        try {
-            retVal = invoke(methodName, Boolean.TRUE, paramTypes, params);
-        } catch (DocletInvokeException exc) {
-            return false;
-        }
-        if (retVal instanceof Boolean) {
-            return ((Boolean)retVal);
-        } else {
-            messager.error(Messager.NOPOS, "main.must_return_boolean",
-                           docletClassName, methodName);
-            return false;
-        }
-    }
-
-    /**
-     * Return the language version supported by this doclet.
-     * If the method does not exist in the doclet, assume version 1.1.
-     */
-    public LanguageVersion languageVersion() {
-        try {
-            Object retVal;
-            String methodName = "languageVersion";
-            Class<?>[] paramTypes = new Class<?>[0];
-            Object[] params = new Object[0];
-            try {
-                retVal = invoke(methodName, JAVA_1_1, paramTypes, params);
-            } catch (DocletInvokeException exc) {
-                return JAVA_1_1;
-            }
-            if (retVal instanceof LanguageVersion) {
-                return (LanguageVersion)retVal;
-            } else {
-                messager.error(Messager.NOPOS, "main.must_return_languageversion",
-                               docletClassName, methodName);
-                return JAVA_1_1;
-            }
-        } catch (NoClassDefFoundError ex) { // for boostrapping, no Enum class.
-            return null;
-        }
-    }
-
-    /**
-     * Utility method for calling doclet functionality
-     */
-    private Object invoke(String methodName, Object returnValueIfNonExistent,
-                          Class<?>[] paramTypes, Object[] params)
-        throws DocletInvokeException {
-            Method meth;
-            try {
-                meth = docletClass.getMethod(methodName, paramTypes);
-            } catch (NoSuchMethodException exc) {
-                if (returnValueIfNonExistent == null) {
-                    messager.error(Messager.NOPOS, "main.doclet_method_not_found",
-                                   docletClassName, methodName);
-                    throw new DocletInvokeException();
-                } else {
-                    return returnValueIfNonExistent;
-                }
-            } catch (SecurityException exc) {
-                messager.error(Messager.NOPOS, "main.doclet_method_not_accessible",
-                               docletClassName, methodName);
-                throw new DocletInvokeException();
-            }
-            if (!Modifier.isStatic(meth.getModifiers())) {
-                messager.error(Messager.NOPOS, "main.doclet_method_must_be_static",
-                               docletClassName, methodName);
-                throw new DocletInvokeException();
-            }
-            ClassLoader savedCCL =
-                Thread.currentThread().getContextClassLoader();
-            try {
-                if (appClassLoader != null) // will be null if doclet class provided via API
-                    Thread.currentThread().setContextClassLoader(appClassLoader);
-                return meth.invoke(null , params);
-            } catch (IllegalArgumentException | NullPointerException exc) {
-                messager.error(Messager.NOPOS, "main.internal_error_exception_thrown",
-                               docletClassName, methodName, exc.toString());
-                throw new DocletInvokeException();
-            } catch (IllegalAccessException exc) {
-                messager.error(Messager.NOPOS, "main.doclet_method_not_accessible",
-                               docletClassName, methodName);
-                throw new DocletInvokeException();
-            }
-            catch (InvocationTargetException exc) {
-                Throwable err = exc.getTargetException();
-                if (apiMode)
-                    throw new ClientCodeException(err);
-                if (err instanceof java.lang.OutOfMemoryError) {
-                    messager.error(Messager.NOPOS, "main.out.of.memory");
-                } else {
-                    messager.error(Messager.NOPOS, "main.exception_thrown",
-                               docletClassName, methodName, exc.toString());
-                    exc.getTargetException().printStackTrace(System.err);
-                }
-                throw new DocletInvokeException();
-            } finally {
-                Thread.currentThread().setContextClassLoader(savedCCL);
-            }
-    }
-
-    /**
-     * Export javadoc internal API to the unnamed module for a classloader.
-     * This is to support continued use of existing non-standard doclets that
-     * use the internal toolkit API and related classes.
-     * @param cl the classloader
-     */
-    private void exportInternalAPI(ClassLoader cl) {
-        String[] packages = {
-            "com.sun.tools.doclets",
-            "com.sun.tools.doclets.standard",
-            "com.sun.tools.doclets.internal.toolkit",
-            "com.sun.tools.doclets.internal.toolkit.taglets",
-            "com.sun.tools.doclets.internal.toolkit.builders",
-            "com.sun.tools.doclets.internal.toolkit.util",
-            "com.sun.tools.doclets.internal.toolkit.util.links",
-            "com.sun.tools.doclets.formats.html",
-            "com.sun.tools.doclets.formats.html.markup"
-        };
-
-        try {
-            Method getModuleMethod = Class.class.getDeclaredMethod("getModule");
-            Object thisModule = getModuleMethod.invoke(getClass());
-
-            Class<?> moduleClass = Class.forName("java.lang.reflect.Module");
-            Method addExportsMethod = moduleClass.getDeclaredMethod("addExports", String.class, moduleClass);
-
-            Method getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule");
-            Object target = getUnnamedModuleMethod.invoke(cl);
-
-            for (String pack : packages) {
-                addExportsMethod.invoke(thisModule, pack, target);
-            }
-        } catch (Exception e) {
-            // do nothing
-        }
-    }
-
-    /**
-     * Utility method for converting a search path string to an array of directory and JAR file
-     * URLs.
-     *
-     * Note that this method is called by the DocletInvoker.
-     *
-     * @param path the search path string
-     * @return the resulting array of directory and JAR file URLs
-     */
-    private static URL[] pathToURLs(String path) {
-        java.util.List<URL> urls = new ArrayList<>();
-        for (String s: path.split(Pattern.quote(File.pathSeparator))) {
-            if (!s.isEmpty()) {
-                URL url = fileToURL(Paths.get(s));
-                if (url != null) {
-                    urls.add(url);
-                }
-            }
-        }
-        return urls.toArray(new URL[urls.size()]);
-    }
-
-    /**
-     * Returns the directory or JAR file URL corresponding to the specified local file name.
-     *
-     * @param file the Path object
-     * @return the resulting directory or JAR file URL, or null if unknown
-     */
-    private static URL fileToURL(Path file) {
-        Path p;
-        try {
-            p = file.toRealPath();
-        } catch (IOException e) {
-            p = file.toAbsolutePath();
-        }
-        try {
-            return p.normalize().toUri().toURL();
-        } catch (MalformedURLException e) {
-            return null;
-        }
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import java.lang.reflect.Modifier;
-import java.text.CollationKey;
-
-import com.sun.javadoc.*;
-
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
-
-/**
- * Represents a method or constructor of a java class.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since 1.2
- * @author Robert Field
- * @author Neal Gafter (rewrite)
- * @author Scott Seligman (generics, annotations)
- */
-
-public abstract class ExecutableMemberDocImpl
-        extends MemberDocImpl implements ExecutableMemberDoc {
-
-    protected final MethodSymbol sym;
-
-    /**
-     * Constructor.
-     */
-    public ExecutableMemberDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) {
-        super(env, sym, treePath);
-        this.sym = sym;
-    }
-
-    /**
-     * Constructor.
-     */
-    public ExecutableMemberDocImpl(DocEnv env, MethodSymbol sym) {
-        this(env, sym, null);
-    }
-
-    /**
-     * Returns the flags in terms of javac's flags
-     */
-    protected long getFlags() {
-        return sym.flags();
-    }
-
-    /**
-     * Identify the containing class
-     */
-    protected ClassSymbol getContainingClass() {
-        return sym.enclClass();
-    }
-
-    /**
-     * Return true if this method is native
-     */
-    public boolean isNative() {
-        return Modifier.isNative(getModifiers());
-    }
-
-    /**
-     * Return true if this method is synchronized
-     */
-    public boolean isSynchronized() {
-        return Modifier.isSynchronized(getModifiers());
-    }
-
-    /**
-     * Return true if this method was declared to take a variable number
-     * of arguments.
-     */
-    public boolean isVarArgs() {
-        return ((sym.flags() & Flags.VARARGS) != 0
-                && !env.legacyDoclet);
-    }
-
-    /**
-     * Returns true if this field was synthesized by the compiler.
-     */
-    public boolean isSynthetic() {
-        return ((sym.flags() & Flags.SYNTHETIC) != 0);
-    }
-
-    public boolean isIncluded() {
-        return containingClass().isIncluded() && env.shouldDocument(sym);
-    }
-
-    /**
-     * Return the throws tags in this method.
-     *
-     * @return an array of ThrowTagImpl containing all {@code @exception}
-     * and {@code @throws} tags.
-     */
-    public ThrowsTag[] throwsTags() {
-        return comment().throwsTags();
-    }
-
-    /**
-     * Return the param tags in this method, excluding the type
-     * parameter tags.
-     *
-     * @return an array of ParamTagImpl containing all {@code @param} tags.
-     */
-    public ParamTag[] paramTags() {
-        return comment().paramTags();
-    }
-
-    /**
-     * Return the type parameter tags in this method.
-     */
-    public ParamTag[] typeParamTags() {
-        return env.legacyDoclet
-            ? new ParamTag[0]
-            : comment().typeParamTags();
-    }
-
-    /**
-     * Return exceptions this method or constructor throws.
-     *
-     * @return an array of ClassDoc[] representing the exceptions
-     * thrown by this method.
-     */
-    public ClassDoc[] thrownExceptions() {
-        ListBuffer<ClassDocImpl> l = new ListBuffer<>();
-        for (Type ex : sym.type.getThrownTypes()) {
-            ex = env.types.erasure(ex);
-            //### Will these casts succeed in the face of static semantic
-            //### errors in the documented code?
-            ClassDocImpl cdi = env.getClassDoc((ClassSymbol)ex.tsym);
-            if (cdi != null) l.append(cdi);
-        }
-        return l.toArray(new ClassDocImpl[l.length()]);
-    }
-
-    /**
-     * Return exceptions this method or constructor throws.
-     * Each array element is either a <code>ClassDoc</code> or a
-     * <code>TypeVariable</code>.
-     */
-    public com.sun.javadoc.Type[] thrownExceptionTypes() {
-        return TypeMaker.getTypes(env, sym.type.getThrownTypes());
-    }
-
-    /**
-     * Get argument information.
-     *
-     * @see ParameterImpl
-     *
-     * @return an array of ParameterImpl, one element per argument
-     * in the order the arguments are present.
-     */
-    public Parameter[] parameters() {
-        // generate the parameters on the fly:  they're not cached
-        List<VarSymbol> params = sym.params();
-        Parameter result[] = new Parameter[params.length()];
-
-        int i = 0;
-        for (VarSymbol param : params) {
-            result[i++] = new ParameterImpl(env, param);
-        }
-        return result;
-    }
-
-    /**
-     * Get the receiver type of this executable element.
-     *
-     * @return the receiver type of this executable element.
-     * @since 1.8
-     */
-    public com.sun.javadoc.Type receiverType() {
-        Type recvtype = sym.type.asMethodType().recvtype;
-        return (recvtype != null) ? TypeMaker.getType(env, recvtype, false, true) : null;
-    }
-
-    /**
-     * Return the formal type parameters of this method or constructor.
-     * Return an empty array if there are none.
-     */
-    public TypeVariable[] typeParameters() {
-        if (env.legacyDoclet) {
-            return new TypeVariable[0];
-        }
-        TypeVariable res[] = new TypeVariable[sym.type.getTypeArguments().length()];
-        TypeMaker.getTypes(env, sym.type.getTypeArguments(), res);
-        return res;
-    }
-
-    /**
-     * Get the signature. It is the parameter list, type is qualified.
-     * For instance, for a method <code>mymethod(String x, int y)</code>,
-     * it will return <code>(java.lang.String,int)</code>.
-     */
-    public String signature() {
-        return makeSignature(true);
-    }
-
-    /**
-     * Get flat signature.  All types are not qualified.
-     * Return a String, which is the flat signiture of this member.
-     * It is the parameter list, type is not qualified.
-     * For instance, for a method <code>mymethod(String x, int y)</code>,
-     * it will return <code>(String, int)</code>.
-     */
-    public String flatSignature() {
-        return makeSignature(false);
-    }
-
-    private String makeSignature(boolean full) {
-        StringBuilder result = new StringBuilder();
-        result.append("(");
-        for (List<Type> types = sym.type.getParameterTypes(); types.nonEmpty(); ) {
-            Type t = types.head;
-            result.append(TypeMaker.getTypeString(env, t, full));
-            types = types.tail;
-            if (types.nonEmpty()) {
-                result.append(", ");
-            }
-        }
-        if (isVarArgs()) {
-            int len = result.length();
-            result.replace(len - 2, len, "...");
-        }
-        result.append(")");
-        return result.toString();
-    }
-
-    protected String typeParametersString() {
-        return TypeMaker.typeParametersString(env, sym, true);
-    }
-
-    /**
-     * Generate a key for sorting.
-     */
-    @Override
-    CollationKey generateKey() {
-        String k = name() + flatSignature() + typeParametersString();
-        // ',' and '&' are between '$' and 'a':  normalize to spaces.
-        k = k.replace(',', ' ').replace('&', ' ');
-        // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
-        return env.doclocale.collator.getCollationKey(k);
-    }
-
-    /**
-     * Return the source position of the entity, or null if
-     * no position is available.
-     */
-    @Override
-    public SourcePosition position() {
-        if (sym.enclClass().sourcefile == null) return null;
-        return SourcePositionImpl.make(sym.enclClass().sourcefile,
-                                       (tree==null) ? 0 : tree.pos,
-                                       lineMap);
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/FieldDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.source.util.TreePath;
-import java.lang.reflect.Modifier;
-
-import com.sun.javadoc.*;
-
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.VarSymbol;
-
-import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
-
-/**
- * Represents a field in a java class.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @see MemberDocImpl
- *
- * @since 1.2
- * @author Robert Field
- * @author Neal Gafter (rewrite)
- * @author Scott Seligman (generics, enums, annotations)
- */
-public class FieldDocImpl extends MemberDocImpl implements FieldDoc {
-
-    protected final VarSymbol sym;
-
-    /**
-     * Constructor.
-     */
-    public FieldDocImpl(DocEnv env, VarSymbol sym, TreePath treePath) {
-        super(env, sym, treePath);
-        this.sym = sym;
-    }
-
-    /**
-     * Constructor.
-     */
-    public FieldDocImpl(DocEnv env, VarSymbol sym) {
-        this(env, sym, null);
-    }
-
-    /**
-     * Returns the flags in terms of javac's flags
-     */
-    protected long getFlags() {
-        return sym.flags();
-    }
-
-    /**
-     * Identify the containing class
-     */
-    protected ClassSymbol getContainingClass() {
-        return sym.enclClass();
-    }
-
-    /**
-     * Get type of this field.
-     */
-    public com.sun.javadoc.Type type() {
-        return TypeMaker.getType(env, sym.type, false);
-    }
-
-    /**
-     * Get the value of a constant field.
-     *
-     * @return the value of a constant field. The value is
-     * automatically wrapped in an object if it has a primitive type.
-     * If the field is not constant, returns null.
-     */
-    public Object constantValue() {
-        Object result = sym.getConstValue();
-        if (result != null && sym.type.hasTag(BOOLEAN))
-            // javac represents false and true as Integers 0 and 1
-            result = Boolean.valueOf(((Integer)result).intValue() != 0);
-        return result;
-    }
-
-    /**
-     * Get the value of a constant field.
-     *
-     * @return the text of a Java language expression whose value
-     * is the value of the constant. The expression uses no identifiers
-     * other than primitive literals. If the field is
-     * not constant, returns null.
-     */
-    public String constantValueExpression() {
-        return constantValueExpression(constantValue());
-    }
-
-    /**
-     * A static version of the above.
-     */
-    static String constantValueExpression(Object cb) {
-        if (cb == null) return null;
-        if (cb instanceof Character) return sourceForm(((Character)cb).charValue());
-        if (cb instanceof Byte) return sourceForm(((Byte)cb).byteValue());
-        if (cb instanceof String) return sourceForm((String)cb);
-        if (cb instanceof Double) return sourceForm(((Double)cb).doubleValue(), 'd');
-        if (cb instanceof Float) return sourceForm(((Float)cb).doubleValue(), 'f');
-        if (cb instanceof Long) return cb + "L";
-        return cb.toString(); // covers int, short
-    }
-        // where
-        private static String sourceForm(double v, char suffix) {
-            if (Double.isNaN(v))
-                return "0" + suffix + "/0" + suffix;
-            if (v == Double.POSITIVE_INFINITY)
-                return "1" + suffix + "/0" + suffix;
-            if (v == Double.NEGATIVE_INFINITY)
-                return "-1" + suffix + "/0" + suffix;
-            return v + (suffix == 'f' || suffix == 'F' ? "" + suffix : "");
-        }
-        private static String sourceForm(char c) {
-            StringBuilder buf = new StringBuilder(8);
-            buf.append('\'');
-            sourceChar(c, buf);
-            buf.append('\'');
-            return buf.toString();
-        }
-        private static String sourceForm(byte c) {
-            return "0x" + Integer.toString(c & 0xff, 16);
-        }
-        private static String sourceForm(String s) {
-            StringBuilder buf = new StringBuilder(s.length() + 5);
-            buf.append('\"');
-            for (int i=0; i<s.length(); i++) {
-                char c = s.charAt(i);
-                sourceChar(c, buf);
-            }
-            buf.append('\"');
-            return buf.toString();
-        }
-        private static void sourceChar(char c, StringBuilder buf) {
-            switch (c) {
-            case '\b': buf.append("\\b"); return;
-            case '\t': buf.append("\\t"); return;
-            case '\n': buf.append("\\n"); return;
-            case '\f': buf.append("\\f"); return;
-            case '\r': buf.append("\\r"); return;
-            case '\"': buf.append("\\\""); return;
-            case '\'': buf.append("\\\'"); return;
-            case '\\': buf.append("\\\\"); return;
-            default:
-                if (isPrintableAscii(c)) {
-                    buf.append(c); return;
-                }
-                unicodeEscape(c, buf);
-                return;
-            }
-        }
-        private static void unicodeEscape(char c, StringBuilder buf) {
-            final String chars = "0123456789abcdef";
-            buf.append("\\u");
-            buf.append(chars.charAt(15 & (c>>12)));
-            buf.append(chars.charAt(15 & (c>>8)));
-            buf.append(chars.charAt(15 & (c>>4)));
-            buf.append(chars.charAt(15 & (c>>0)));
-        }
-        private static boolean isPrintableAscii(char c) {
-            return c >= ' ' && c <= '~';
-        }
-
-    /**
-     * Return true if this field is included in the active set.
-     */
-    public boolean isIncluded() {
-        return containingClass().isIncluded() && env.shouldDocument(sym);
-    }
-
-    /**
-     * Is this Doc item a field (but not an enum constant?
-     */
-    @Override
-    public boolean isField() {
-        return !isEnumConstant();
-    }
-
-    /**
-     * Is this Doc item an enum constant?
-     * (For legacy doclets, return false.)
-     */
-    @Override
-    public boolean isEnumConstant() {
-        return (getFlags() & Flags.ENUM) != 0 &&
-               !env.legacyDoclet;
-    }
-
-    /**
-     * Return true if this field is transient
-     */
-    public boolean isTransient() {
-        return Modifier.isTransient(getModifiers());
-    }
-
-    /**
-     * Return true if this field is volatile
-     */
-    public boolean isVolatile() {
-        return Modifier.isVolatile(getModifiers());
-    }
-
-    /**
-     * Returns true if this field was synthesized by the compiler.
-     */
-    public boolean isSynthetic() {
-        return (getFlags() & Flags.SYNTHETIC) != 0;
-    }
-
-    /**
-     * Return the serialField tags in this FieldDocImpl item.
-     *
-     * @return an array of <tt>SerialFieldTagImpl</tt> containing all
-     *         <code>&#64;serialField</code> tags.
-     */
-    public SerialFieldTag[] serialFieldTags() {
-        return comment().serialFieldTags();
-    }
-
-    public String name() {
-        if (name == null) {
-            name = sym.name.toString();
-        }
-        return name;
-    }
-
-    private String name;
-
-    public String qualifiedName() {
-        if (qualifiedName == null) {
-            qualifiedName = sym.enclClass().getQualifiedName() + "." + name();
-        }
-        return qualifiedName;
-    }
-
-    private String qualifiedName;
-
-    /**
-     * Return the source position of the entity, or null if
-     * no position is available.
-     */
-    @Override
-    public SourcePosition position() {
-        if (sym.enclClass().sourcefile == null) return null;
-        return SourcePositionImpl.make(sym.enclClass().sourcefile,
-                                       (tree==null) ? 0 : tree.pos,
-                                       lineMap);
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocClassFinder.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2001, 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 com.sun.tools.javadoc;
-
-import java.util.EnumSet;
-import javax.tools.JavaFileObject;
-
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
-import com.sun.tools.javac.code.ClassFinder;
-import com.sun.tools.javac.util.Context;
-
-/** Javadoc uses an extended class finder that records package.html entries
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- *  @author Neal Gafter
- */
-public class JavadocClassFinder extends ClassFinder {
-
-    public static JavadocClassFinder instance(Context context) {
-        ClassFinder instance = context.get(classFinderKey);
-        if (instance == null)
-            instance = new JavadocClassFinder(context);
-        return (JavadocClassFinder)instance;
-    }
-
-    public static void preRegister(Context context) {
-        context.put(classFinderKey, new Context.Factory<ClassFinder>() {
-            public ClassFinder make(Context c) {
-                return new JavadocClassFinder(c);
-            }
-        });
-    }
-
-    private DocEnv docenv;
-    private EnumSet<JavaFileObject.Kind> all = EnumSet.of(JavaFileObject.Kind.CLASS,
-                                                          JavaFileObject.Kind.SOURCE,
-                                                          JavaFileObject.Kind.HTML);
-    private EnumSet<JavaFileObject.Kind> noSource = EnumSet.of(JavaFileObject.Kind.CLASS,
-                                                               JavaFileObject.Kind.HTML);
-
-    public JavadocClassFinder(Context context) {
-        super(context);
-        docenv = DocEnv.instance(context);
-        preferSource = true;
-    }
-
-    /**
-     * Override getPackageFileKinds to include search for package.html
-     */
-    @Override
-    protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
-        return docenv.docClasses ? noSource : all;
-    }
-
-    /**
-     * Override extraFileActions to check for package documentation
-     */
-    @Override
-    protected void extraFileActions(PackageSymbol pack, JavaFileObject fo) {
-        if (fo.isNameCompatible("package", JavaFileObject.Kind.HTML))
-            docenv.getPackageDoc(pack).setDocPath(fo);
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocEnter.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2001, 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 com.sun.tools.javadoc;
-
-import javax.tools.JavaFileObject;
-
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.comp.Enter;
-import com.sun.tools.javac.tree.JCTree.*;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
-import com.sun.tools.javac.util.List;
-
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-
-/**
- *  Javadoc's own enter phase does a few things above and beyond that
- *  done by javac.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- *  @author Neal Gafter
- */
-public class JavadocEnter extends Enter {
-    public static JavadocEnter instance(Context context) {
-        Enter instance = context.get(enterKey);
-        if (instance == null)
-            instance = new JavadocEnter(context);
-        return (JavadocEnter)instance;
-    }
-
-    public static void preRegister(Context context) {
-        context.put(enterKey, new Context.Factory<Enter>() {
-               public Enter make(Context c) {
-                   return new JavadocEnter(c);
-               }
-        });
-    }
-
-    protected JavadocEnter(Context context) {
-        super(context);
-        messager = Messager.instance0(context);
-        docenv = DocEnv.instance(context);
-    }
-
-    final Messager messager;
-    final DocEnv docenv;
-
-    @Override
-    public void main(List<JCCompilationUnit> trees) {
-        // count all Enter errors as warnings.
-        int nerrors = messager.nerrors;
-        super.main(trees);
-        messager.nwarnings += (messager.nerrors - nerrors);
-        messager.nerrors = nerrors;
-    }
-
-    @Override
-    public void visitTopLevel(JCCompilationUnit tree) {
-        super.visitTopLevel(tree);
-        if (tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE)) {
-            JCPackageDecl pd = tree.getPackage();
-            TreePath tp = pd == null ? docenv.getTreePath(tree) : docenv.getTreePath(tree, pd);
-            docenv.makePackageDoc(tree.packge, tp);
-        }
-    }
-
-    @Override
-    public void visitClassDef(JCClassDecl tree) {
-        super.visitClassDef(tree);
-        if (tree.sym == null) return;
-        if (tree.sym.kind == TYP || tree.sym.kind == ERR) {
-            ClassSymbol c = tree.sym;
-            docenv.makeClassDoc(c, docenv.getTreePath(env.toplevel, tree));
-        }
-    }
-
-    /** Don't complain about a duplicate class. */
-    @Override
-    protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) {}
-
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.comp.MemberEnter;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.*;
-import com.sun.tools.javac.util.Context;
-
-import static com.sun.tools.javac.code.Flags.*;
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-
-/**
- *  Javadoc's own memberEnter phase does a few things above and beyond that
- *  done by javac.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- *  @author Neal Gafter
- */
-public class JavadocMemberEnter extends MemberEnter {
-    public static JavadocMemberEnter instance0(Context context) {
-        MemberEnter instance = context.get(memberEnterKey);
-        if (instance == null)
-            instance = new JavadocMemberEnter(context);
-        return (JavadocMemberEnter)instance;
-    }
-
-    public static void preRegister(Context context) {
-        context.put(memberEnterKey, new Context.Factory<MemberEnter>() {
-               public MemberEnter make(Context c) {
-                   return new JavadocMemberEnter(c);
-               }
-        });
-    }
-
-    final DocEnv docenv;
-
-    protected JavadocMemberEnter(Context context) {
-        super(context);
-        docenv = DocEnv.instance(context);
-    }
-
-    @Override
-    public void visitMethodDef(JCMethodDecl tree) {
-        super.visitMethodDef(tree);
-        MethodSymbol meth = tree.sym;
-        if (meth == null || meth.kind != MTH) return;
-        TreePath treePath = docenv.getTreePath(env.toplevel, env.enclClass, tree);
-        if (meth.isConstructor())
-            docenv.makeConstructorDoc(meth, treePath);
-        else if (isAnnotationTypeElement(meth))
-            docenv.makeAnnotationTypeElementDoc(meth, treePath);
-        else
-            docenv.makeMethodDoc(meth, treePath);
-
-        // release resources
-        tree.body = null;
-    }
-
-    @Override
-    public void visitVarDef(JCVariableDecl tree) {
-        if (tree.init != null) {
-            boolean isFinal = (tree.mods.flags & FINAL) != 0
-                    || (env.enclClass.mods.flags & INTERFACE) != 0;
-            if (!isFinal || containsNonConstantExpression(tree.init)) {
-                // Avoid unnecessary analysis and release resources.
-                // In particular, remove non-constant expressions
-                // which may trigger Attr.attribClass, since
-                // method bodies are also removed, in visitMethodDef.
-                tree.init = null;
-            }
-        }
-        super.visitVarDef(tree);
-        if (tree.sym != null &&
-                tree.sym.kind == VAR &&
-                !isParameter(tree.sym)) {
-            docenv.makeFieldDoc(tree.sym, docenv.getTreePath(env.toplevel, env.enclClass, tree));
-        }
-    }
-
-    private static boolean isAnnotationTypeElement(MethodSymbol meth) {
-        return ClassDocImpl.isAnnotationType(meth.enclClass());
-    }
-
-    private static boolean isParameter(VarSymbol var) {
-        return (var.flags() & Flags.PARAMETER) != 0;
-    }
-
-    /**
-     * Simple analysis of an expression tree to see if it contains tree nodes
-     * for any non-constant expression. This does not include checking references
-     * to other fields which may or may not be constant.
-     */
-    private static boolean containsNonConstantExpression(JCExpression tree) {
-        return new MaybeConstantExpressionScanner().containsNonConstantExpression(tree);
-    }
-
-    /**
-     * See JLS 15.18, Constant Expression
-     */
-    private static class MaybeConstantExpressionScanner extends JCTree.Visitor {
-        boolean maybeConstantExpr = true;
-
-        public boolean containsNonConstantExpression(JCExpression tree) {
-            scan(tree);
-            return !maybeConstantExpr;
-        }
-
-        public void scan(JCTree tree) {
-            // short circuit scan when end result is definitely false
-            if (maybeConstantExpr && tree != null)
-                tree.accept(this);
-        }
-
-        @Override
-        /** default for any non-overridden visit method. */
-        public void visitTree(JCTree tree) {
-            maybeConstantExpr = false;
-        }
-
-        @Override
-        public void visitBinary(JCBinary tree) {
-            switch (tree.getTag()) {
-                case MUL: case DIV: case MOD:
-                case PLUS: case MINUS:
-                case SL: case SR: case USR:
-                case LT: case LE: case GT: case GE:
-                case EQ: case NE:
-                case BITAND: case BITXOR: case BITOR:
-                case AND: case OR:
-                    break;
-                default:
-                    maybeConstantExpr = false;
-            }
-        }
-
-        @Override
-        public void visitConditional(JCConditional tree) {
-            scan(tree.cond);
-            scan(tree.truepart);
-            scan(tree.falsepart);
-        }
-
-        @Override
-        public void visitIdent(JCIdent tree) { }
-
-        @Override
-        public void visitLiteral(JCLiteral tree) { }
-
-        @Override
-        public void visitParens(JCParens tree) {
-            scan(tree.expr);
-        }
-
-        @Override
-        public void visitSelect(JCTree.JCFieldAccess tree) {
-            scan(tree.selected);
-        }
-
-        @Override
-        public void visitTypeCast(JCTypeCast tree) {
-            scan(tree.clazz);
-            scan(tree.expr);
-        }
-
-        @Override
-        public void visitTypeIdent(JCPrimitiveTypeTree tree) { }
-
-        @Override
-        public void visitUnary(JCUnary tree) {
-            switch (tree.getTag()) {
-                case POS: case NEG: case COMPL: case NOT:
-                    break;
-                default:
-                    maybeConstantExpr = false;
-            }
-        }
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTodo.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, 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.sun.tools.javadoc;
-
-import com.sun.tools.javac.comp.*;
-import com.sun.tools.javac.util.*;
-
-/**
- *  Javadoc's own todo queue doesn't queue its inputs, as javadoc
- *  doesn't perform attribution of method bodies or semantic checking.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- *  @author Neal Gafter
- */
-public class JavadocTodo extends Todo {
-    public static void preRegister(Context context) {
-        context.put(todoKey, new Context.Factory<Todo>() {
-               public Todo make(Context c) {
-                   return new JavadocTodo(c);
-               }
-        });
-    }
-
-    protected JavadocTodo(Context context) {
-        super(context);
-    }
-
-    @Override
-    public void append(Env<AttrContext> e) {
-        // do nothing; Javadoc doesn't perform attribution.
-    }
-
-    @Override
-    public boolean offer(Env<AttrContext> e) {
-        return false;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,430 +0,0 @@
-/*
- * 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
- * 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.sun.tools.javadoc;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileManager.Location;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.StandardLocation;
-
-import com.sun.tools.javac.code.ClassFinder;
-import com.sun.tools.javac.code.Symbol.Completer;
-import com.sun.tools.javac.code.Symbol.ModuleSymbol;
-import com.sun.tools.javac.comp.Enter;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCClassDecl;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.util.Abort;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
-
-
-/**
- *  This class could be the main entry point for Javadoc when Javadoc is used as a
- *  component in a larger software system. It provides operations to
- *  construct a new javadoc processor, and to run it on a set of source
- *  files.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- *  @author Neal Gafter
- */
-public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
-    DocEnv docenv;
-
-    final Messager messager;
-    final ClassFinder javadocFinder;
-    final Enter javadocEnter;
-    final Set<JavaFileObject> uniquefiles;
-
-    /**
-     * Construct a new JavaCompiler processor, using appropriately
-     * extended phases of the underlying compiler.
-     */
-    protected JavadocTool(Context context) {
-        super(context);
-        messager = Messager.instance0(context);
-        javadocFinder = JavadocClassFinder.instance(context);
-        javadocEnter = JavadocEnter.instance(context);
-        uniquefiles = new HashSet<>();
-    }
-
-    /**
-     * For javadoc, the parser needs to keep comments. Overrides method from JavaCompiler.
-     */
-    @Override
-    protected boolean keepComments() {
-        return true;
-    }
-
-    /**
-     *  Construct a new javadoc tool.
-     */
-    public static JavadocTool make0(Context context) {
-        // force the use of Javadoc's class finder
-        JavadocClassFinder.preRegister(context);
-
-        // force the use of Javadoc's own enter phase
-        JavadocEnter.preRegister(context);
-
-        // force the use of Javadoc's own member enter phase
-        JavadocMemberEnter.preRegister(context);
-
-        // force the use of Javadoc's own todo phase
-        JavadocTodo.preRegister(context);
-
-        // force the use of Messager as a Log
-        Messager.instance0(context);
-
-        return new JavadocTool(context);
-    }
-
-    public RootDocImpl getRootDocImpl(String doclocale,
-                                      String encoding,
-                                      ModifierFilter filter,
-                                      List<String> args,
-                                      List<String[]> options,
-                                      Iterable<? extends JavaFileObject> fileObjects,
-                                      boolean breakiterator,
-                                      List<String> subPackages,
-                                      List<String> excludedPackages,
-                                      boolean docClasses,
-                                      boolean legacyDoclet,
-                      boolean quiet) throws IOException {
-        docenv = DocEnv.instance(context);
-        docenv.showAccess = filter;
-        docenv.quiet = quiet;
-        docenv.breakiterator = breakiterator;
-        docenv.setLocale(doclocale);
-        docenv.setEncoding(encoding);
-        docenv.docClasses = docClasses;
-        docenv.legacyDoclet = legacyDoclet;
-
-        javadocFinder.sourceCompleter = docClasses ? Completer.NULL_COMPLETER : sourceCompleter;
-
-        if (docClasses) {
-            // If -Xclasses is set, the args should be a series of class names
-            for (String arg: args) {
-                if (!isValidPackageName(arg)) // checks
-                    docenv.error(null, "main.illegal_class_name", arg);
-            }
-            if (messager.nerrors() != 0) {
-                return null;
-            }
-            return new RootDocImpl(docenv, args, options);
-        }
-
-        ListBuffer<JCCompilationUnit> classTrees = new ListBuffer<>();
-        Set<String> includedPackages = new LinkedHashSet<>();
-
-        try {
-            StandardJavaFileManager fm = docenv.fileManager instanceof StandardJavaFileManager
-                    ? (StandardJavaFileManager) docenv.fileManager : null;
-            Set<String> packageNames = new LinkedHashSet<>();
-            // Normally, the args should be a series of package names or file names.
-            // Parse the files and collect the package names.
-            for (String arg: args) {
-                if (fm != null && arg.endsWith(".java") && new File(arg).exists()) {
-                    if (new File(arg).getName().equals("module-info.java")) {
-                        docenv.warning(null, "main.file_ignored", arg);
-                    } else {
-                        parse(fm.getJavaFileObjects(arg), classTrees, true);
-                    }
-                } else if (isValidPackageName(arg)) {
-                    packageNames.add(arg);
-                } else if (arg.endsWith(".java")) {
-                    if (fm == null)
-                        throw new IllegalArgumentException();
-                    else
-                        docenv.error(null, "main.file_not_found", arg);
-                } else {
-                    docenv.error(null, "main.illegal_package_name", arg);
-                }
-            }
-
-            // Parse file objects provide via the DocumentationTool API
-            parse(fileObjects, classTrees, true);
-            modules.enter(classTrees.toList(), null);
-
-            syms.unnamedModule.complete(); // TEMP to force reading all named modules
-
-            // Build up the complete list of any packages to be documented
-            Location location =
-                    modules.multiModuleMode && !modules.noModules ? StandardLocation.MODULE_SOURCE_PATH
-                    : docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH
-                    : StandardLocation.CLASS_PATH;
-
-            PackageTable t = new PackageTable(docenv.fileManager, location)
-                    .packages(packageNames)
-                    .subpackages(subPackages, excludedPackages);
-
-            includedPackages = t.getIncludedPackages();
-
-            // Parse the files in the packages to be documented
-            ListBuffer<JCCompilationUnit> packageTrees = new ListBuffer<>();
-            for (String packageName: includedPackages) {
-                List<JavaFileObject> files = t.getFiles(packageName);
-                docenv.notice("main.Loading_source_files_for_package", packageName);
-
-                if (files.isEmpty())
-                    messager.warning(Messager.NOPOS, "main.no_source_files_for_package", packageName);
-                parse(files, packageTrees, false);
-            }
-            modules.enter(packageTrees.toList(), null);
-
-            if (messager.nerrors() != 0) {
-                return null;
-            }
-
-            // Enter symbols for all files
-            docenv.notice("main.Building_tree");
-            javadocEnter.main(classTrees.toList().appendList(packageTrees.toList()));
-            enterDone = true;
-        } catch (Abort ex) {}
-
-        if (messager.nerrors() != 0)
-            return null;
-
-        return new RootDocImpl(docenv, listClasses(classTrees.toList()), List.from(includedPackages), options);
-    }
-
-    /** Is the given string a valid package name? */
-    boolean isValidPackageName(String s) {
-        int index;
-        while ((index = s.indexOf('.')) != -1) {
-            if (!isValidClassName(s.substring(0, index))) return false;
-            s = s.substring(index+1);
-        }
-        return isValidClassName(s);
-    }
-
-    private void parse(Iterable<? extends JavaFileObject> files, ListBuffer<JCCompilationUnit> trees,
-                       boolean trace) {
-        for (JavaFileObject fo: files) {
-            if (uniquefiles.add(fo)) { // ignore duplicates
-                if (trace)
-                    docenv.notice("main.Loading_source_file", fo.getName());
-                trees.append(parse(fo));
-            }
-        }
-    }
-
-    /** Are surrogates supported?
-     */
-    final static boolean surrogatesSupported = surrogatesSupported();
-    private static boolean surrogatesSupported() {
-        try {
-            boolean b = Character.isHighSurrogate('a');
-            return true;
-        } catch (NoSuchMethodError ex) {
-            return false;
-        }
-    }
-
-    /**
-     * Return true if given file name is a valid class name
-     * (including "package-info").
-     * @param s the name of the class to check.
-     * @return true if given class name is a valid class name
-     * and false otherwise.
-     */
-    public static boolean isValidClassName(String s) {
-        if (s.length() < 1) return false;
-        if (s.equals("package-info")) return true;
-        if (surrogatesSupported) {
-            int cp = s.codePointAt(0);
-            if (!Character.isJavaIdentifierStart(cp))
-                return false;
-            for (int j=Character.charCount(cp); j<s.length(); j+=Character.charCount(cp)) {
-                cp = s.codePointAt(j);
-                if (!Character.isJavaIdentifierPart(cp))
-                    return false;
-            }
-        } else {
-            if (!Character.isJavaIdentifierStart(s.charAt(0)))
-                return false;
-            for (int j=1; j<s.length(); j++)
-                if (!Character.isJavaIdentifierPart(s.charAt(j)))
-                    return false;
-        }
-        return true;
-    }
-
-    /**
-     * From a list of top level trees, return the list of contained class definitions
-     */
-    List<JCClassDecl> listClasses(List<JCCompilationUnit> trees) {
-        ListBuffer<JCClassDecl> result = new ListBuffer<>();
-        for (JCCompilationUnit t : trees) {
-            for (JCTree def : t.defs) {
-                if (def.hasTag(JCTree.Tag.CLASSDEF))
-                    result.append((JCClassDecl)def);
-            }
-        }
-        return result.toList();
-    }
-
-    /**
-     * A table to manage included and excluded packages.
-     */
-    class PackageTable {
-        private final Map<String, Entry> entries = new LinkedHashMap<>();
-        private final Set<String> includedPackages = new LinkedHashSet<>();
-        private final JavaFileManager fm;
-        private final Location location;
-        private final Set<JavaFileObject.Kind> sourceKinds = EnumSet.of(JavaFileObject.Kind.SOURCE);
-
-        /**
-         * Creates a table to manage included and excluded packages.
-         * @param fm The file manager used to locate source files
-         * @param locn the location used to locate source files
-         */
-        PackageTable(JavaFileManager fm, Location locn) {
-            this.fm = fm;
-            this.location = locn;
-            getEntry("").excluded = false;
-        }
-
-        PackageTable packages(Collection<String> packageNames) {
-            includedPackages.addAll(packageNames);
-            return this;
-        }
-
-        PackageTable subpackages(Collection<String> packageNames, Collection<String> excludePackageNames)
-                throws IOException {
-            for (String p: excludePackageNames) {
-                getEntry(p).excluded = true;
-            }
-
-            for (String packageName: packageNames) {
-                Location packageLocn = getLocation(packageName);
-                for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, true)) {
-                    String binaryName = fm.inferBinaryName(packageLocn, fo);
-                    String pn = getPackageName(binaryName);
-                    String simpleName = getSimpleName(binaryName);
-                    Entry e = getEntry(pn);
-                    if (!e.isExcluded() && isValidClassName(simpleName)) {
-                        includedPackages.add(pn);
-                        e.files = (e.files == null ? List.of(fo) : e.files.prepend(fo));
-                    }
-                }
-            }
-            return this;
-        }
-
-        /**
-         * Returns the aggregate set of included packages.
-         * @return the aggregate set of included packages
-         */
-        Set<String> getIncludedPackages() {
-            return includedPackages;
-        }
-
-        /**
-         * Returns the set of source files for a package.
-         * @param packageName the specified package
-         * @return the set of file objects for the specified package
-         * @throws IOException if an error occurs while accessing the files
-         */
-        List<JavaFileObject> getFiles(String packageName) throws IOException {
-            Entry e = getEntry(packageName);
-            // The files may have been found as a side effect of searching for subpackages
-            if (e.files != null)
-                return e.files;
-
-            ListBuffer<JavaFileObject> lb = new ListBuffer<>();
-            Location packageLocn = getLocation(packageName);
-            for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, false)) {
-                String binaryName = fm.inferBinaryName(packageLocn, fo);
-                String simpleName = getSimpleName(binaryName);
-                if (isValidClassName(simpleName)) {
-                    lb.append(fo);
-                }
-            }
-
-            return lb.toList();
-        }
-
-        private Location getLocation(String packageName) throws IOException {
-            if (location == StandardLocation.MODULE_SOURCE_PATH) {
-                // TODO: handle invalid results
-                ModuleSymbol msym = syms.inferModule(names.fromString(packageName));
-                return fm.getModuleLocation(location, msym.name.toString());
-            } else {
-                return location;
-            }
-        }
-
-        private Entry getEntry(String name) {
-            Entry e = entries.get(name);
-            if (e == null)
-                entries.put(name, e = new Entry(name));
-            return e;
-        }
-
-        private String getPackageName(String name) {
-            int lastDot = name.lastIndexOf(".");
-            return (lastDot == -1 ? "" : name.substring(0, lastDot));
-        }
-
-        private String getSimpleName(String name) {
-            int lastDot = name.lastIndexOf(".");
-            return (lastDot == -1 ? name : name.substring(lastDot + 1));
-        }
-
-        class Entry {
-            final String name;
-            Boolean excluded;
-            List<JavaFileObject> files;
-
-            Entry(String name) {
-                this.name = name;
-            }
-
-            boolean isExcluded() {
-                if (excluded == null)
-                    excluded = getEntry(getPackageName(name)).isExcluded();
-                return excluded;
-            }
-        }
-    }
-
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Main.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Main.java	Wed Jul 05 21:42:16 2017 +0200
@@ -27,6 +27,8 @@
 
 import java.io.PrintWriter;
 
+import com.sun.tools.javadoc.main.Start;
+
 /**
  * Provides external entry points (tool and programmatic)
  * for the javadoc program.
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/MemberDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Symbol;
-
-/**
- * Represents a member of a java class: field, constructor, or method.
- * This is an abstract class dealing with information common to
- * method, constructor and field members. Class members of a class
- * (nested classes) are represented instead by ClassDocImpl.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @see MethodDocImpl
- * @see FieldDocImpl
- * @see ClassDocImpl
- *
- * @author Robert Field
- * @author Neal Gafter
- */
-
-public abstract class MemberDocImpl
-    extends ProgramElementDocImpl
-    implements MemberDoc {
-
-    /**
-     * constructor.
-     */
-    public MemberDocImpl(DocEnv env, Symbol sym, TreePath treePath) {
-        super(env, sym, treePath);
-    }
-
-    /**
-     * Returns true if this field was synthesized by the compiler.
-     */
-    public abstract boolean isSynthetic();
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Messager.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,323 +0,0 @@
-/*
- * Copyright (c) 1997, 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 com.sun.tools.javadoc;
-
-import java.io.PrintWriter;
-import java.util.Locale;
-import java.util.ResourceBundle;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JCDiagnostic;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
-import com.sun.tools.javac.util.JavacMessages;
-import com.sun.tools.javac.util.Log;
-
-/**
- * Utility for integrating with javadoc tools and for localization.
- * Handle Resources. Access to error and warning counts.
- * Message formatting.
- * <br>
- * Also provides implementation for DocErrorReporter.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @see java.util.ResourceBundle
- * @see java.text.MessageFormat
- * @author Neal Gafter (rewrite)
- */
-public class Messager extends Log implements DocErrorReporter {
-    public static final SourcePosition NOPOS = null;
-
-    /** Get the current messager, which is also the compiler log. */
-    public static Messager instance0(Context context) {
-        Log instance = context.get(logKey);
-        if (instance == null || !(instance instanceof Messager))
-            throw new InternalError("no messager instance!");
-        return (Messager)instance;
-    }
-
-    public static void preRegister(Context context,
-                                   final String programName) {
-        context.put(logKey, new Context.Factory<Log>() {
-            public Log make(Context c) {
-                return new Messager(c,
-                                    programName);
-            }
-        });
-    }
-    public static void preRegister(Context context,
-                                   final String programName,
-                                   final PrintWriter errWriter,
-                                   final PrintWriter warnWriter,
-                                   final PrintWriter noticeWriter) {
-        context.put(logKey, new Context.Factory<Log>() {
-            public Log make(Context c) {
-                return new Messager(c,
-                                    programName,
-                                    errWriter,
-                                    warnWriter,
-                                    noticeWriter);
-            }
-        });
-    }
-
-    public class ExitJavadoc extends Error {
-        private static final long serialVersionUID = 0;
-    }
-
-    final String programName;
-
-    private Locale locale;
-    private final JavacMessages messages;
-    private final JCDiagnostic.Factory javadocDiags;
-
-    /** The default writer for diagnostics
-     */
-    static final PrintWriter defaultErrWriter = new PrintWriter(System.err);
-    static final PrintWriter defaultWarnWriter = new PrintWriter(System.err);
-    static final PrintWriter defaultNoticeWriter = new PrintWriter(System.out);
-
-    /**
-     * Constructor
-     * @param programName  Name of the program (for error messages).
-     */
-    protected Messager(Context context, String programName) {
-        this(context, programName, defaultErrWriter, defaultWarnWriter, defaultNoticeWriter);
-    }
-
-    /**
-     * Constructor
-     * @param programName  Name of the program (for error messages).
-     * @param errWriter    Stream for error messages
-     * @param warnWriter   Stream for warnings
-     * @param noticeWriter Stream for other messages
-     */
-    @SuppressWarnings("deprecation")
-    protected Messager(Context context,
-                       String programName,
-                       PrintWriter errWriter,
-                       PrintWriter warnWriter,
-                       PrintWriter noticeWriter) {
-        super(context, errWriter, warnWriter, noticeWriter);
-        messages = JavacMessages.instance(context);
-        messages.add(locale -> ResourceBundle.getBundle("com.sun.tools.javadoc.resources.javadoc",
-                                                         locale));
-        javadocDiags = new JCDiagnostic.Factory(messages, "javadoc");
-        this.programName = programName;
-
-    }
-
-    public void setLocale(Locale locale) {
-        this.locale = locale;
-    }
-
-    /**
-     * get and format message string from resource
-     *
-     * @param key selects message from resource
-     * @param args arguments for the message
-     */
-    String getText(String key, Object... args) {
-        return messages.getLocalizedString(locale, key, args);
-    }
-
-    /**
-     * Print error message, increment error count.
-     * Part of DocErrorReporter.
-     *
-     * @param msg message to print
-     */
-    public void printError(String msg) {
-        printError(null, msg);
-    }
-
-    /**
-     * Print error message, increment error count.
-     * Part of DocErrorReporter.
-     *
-     * @param pos the position where the error occurs
-     * @param msg message to print
-     */
-    public void printError(SourcePosition pos, String msg) {
-        if (diagListener != null) {
-            report(DiagnosticType.ERROR, pos, msg);
-            return;
-        }
-
-        if (nerrors < MaxErrors) {
-            String prefix = (pos == null) ? programName : pos.toString();
-            errWriter.println(prefix + ": " + getText("javadoc.error") + " - " + msg);
-            errWriter.flush();
-            prompt();
-            nerrors++;
-        }
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     * Part of DocErrorReporter.
-     *
-     * @param msg message to print
-     */
-    public void printWarning(String msg) {
-        printWarning(null, msg);
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     * Part of DocErrorReporter.
-     *
-     * @param pos the position where the error occurs
-     * @param msg message to print
-     */
-    public void printWarning(SourcePosition pos, String msg) {
-        if (diagListener != null) {
-            report(DiagnosticType.WARNING, pos, msg);
-            return;
-        }
-
-        if (nwarnings < MaxWarnings) {
-            String prefix = (pos == null) ? programName : pos.toString();
-            warnWriter.println(prefix +  ": " + getText("javadoc.warning") +" - " + msg);
-            warnWriter.flush();
-            nwarnings++;
-        }
-    }
-
-    /**
-     * Print a message.
-     * Part of DocErrorReporter.
-     *
-     * @param msg message to print
-     */
-    public void printNotice(String msg) {
-        printNotice(null, msg);
-    }
-
-    /**
-     * Print a message.
-     * Part of DocErrorReporter.
-     *
-     * @param pos the position where the error occurs
-     * @param msg message to print
-     */
-    public void printNotice(SourcePosition pos, String msg) {
-        if (diagListener != null) {
-            report(DiagnosticType.NOTE, pos, msg);
-            return;
-        }
-
-        if (pos == null)
-            noticeWriter.println(msg);
-        else
-            noticeWriter.println(pos + ": " + msg);
-        noticeWriter.flush();
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param key selects message from resource
-     */
-    public void error(SourcePosition pos, String key, Object... args) {
-        printError(pos, getText(key, args));
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param key selects message from resource
-     */
-    public void warning(SourcePosition pos, String key, Object... args) {
-        printWarning(pos, getText(key, args));
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param key selects message from resource
-     */
-    public void notice(String key, Object... args) {
-        printNotice(getText(key, args));
-    }
-
-    /**
-     * Return total number of errors, including those recorded
-     * in the compilation log.
-     */
-    public int nerrors() { return nerrors; }
-
-    /**
-     * Return total number of warnings, including those recorded
-     * in the compilation log.
-     */
-    public int nwarnings() { return nwarnings; }
-
-    /**
-     * Print exit message.
-     */
-    public void exitNotice() {
-        if (nerrors > 0) {
-            notice((nerrors > 1) ? "main.errors" : "main.error",
-                   "" + nerrors);
-        }
-        if (nwarnings > 0) {
-            notice((nwarnings > 1) ?  "main.warnings" : "main.warning",
-                   "" + nwarnings);
-        }
-    }
-
-    /**
-     * Force program exit, e.g., from a fatal error.
-     * <p>
-     * TODO: This method does not really belong here.
-     */
-    public void exit() {
-        throw new ExitJavadoc();
-    }
-
-    private void report(DiagnosticType type, SourcePosition pos, String msg) {
-        switch (type) {
-            case ERROR:
-            case WARNING:
-                Object prefix = (pos == null) ? programName : pos;
-                report(javadocDiags.create(type, null, null, "msg", prefix, msg));
-                break;
-
-            case NOTE:
-                String key = (pos == null) ? "msg" : "pos.msg";
-                report(javadocDiags.create(type, null, null, key, pos, msg));
-                break;
-
-            default:
-                throw new IllegalArgumentException(type.toString());
-        }
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/MethodDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/*
- * Copyright (c) 1997, 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 com.sun.tools.javadoc;
-
-import java.lang.reflect.Modifier;
-
-import com.sun.javadoc.*;
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Type;
-import static com.sun.tools.javac.code.TypeTag.CLASS;
-
-/**
- * Represents a method of a java class.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since 1.2
- * @author Robert Field
- * @author Neal Gafter (rewrite)
- */
-
-public class MethodDocImpl
-        extends ExecutableMemberDocImpl implements MethodDoc {
-
-    /**
-     * constructor.
-     */
-    public MethodDocImpl(DocEnv env, MethodSymbol sym) {
-        super(env, sym);
-    }
-
-    /**
-     * constructor.
-     */
-    public MethodDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) {
-        super(env, sym, treePath);
-    }
-
-    /**
-     * Return true if it is a method, which it is.
-     * Note: constructors are not methods.
-     * This method is overridden by AnnotationTypeElementDocImpl.
-     *
-     * @return true
-     */
-    public boolean isMethod() {
-        return true;
-    }
-
-    /**
-     * Return true if this method is default
-     */
-    public boolean isDefault() {
-        return (sym.flags() & Flags.DEFAULT) != 0;
-    }
-
-    /**
-     * Return true if this method is abstract
-     */
-    public boolean isAbstract() {
-        return (Modifier.isAbstract(getModifiers()) && !isDefault());
-    }
-
-    /**
-     * Get return type.
-     *
-     * @return the return type of this method, null if it
-     * is a constructor.
-     */
-    public com.sun.javadoc.Type returnType() {
-        return TypeMaker.getType(env, sym.type.getReturnType(), false);
-    }
-
-    /**
-     * Return the class that originally defined the method that
-     * is overridden by the current definition, or null if no
-     * such class exists.
-     *
-     * @return a ClassDocImpl representing the superclass that
-     * originally defined this method, null if this method does
-     * not override a definition in a superclass.
-     */
-    public ClassDoc overriddenClass() {
-        com.sun.javadoc.Type t = overriddenType();
-        return (t != null) ? t.asClassDoc() : null;
-    }
-
-    /**
-     * Return the type containing the method that this method overrides.
-     * It may be a <code>ClassDoc</code> or a <code>ParameterizedType</code>.
-     */
-    public com.sun.javadoc.Type overriddenType() {
-
-        if ((sym.flags() & Flags.STATIC) != 0) {
-            return null;
-        }
-
-        ClassSymbol origin = (ClassSymbol)sym.owner;
-        for (Type t = env.types.supertype(origin.type);
-             t.hasTag(CLASS);
-             t = env.types.supertype(t)) {
-            ClassSymbol c = (ClassSymbol)t.tsym;
-            for (Symbol sym2 : membersOf(c).getSymbolsByName(sym.name)) {
-                if (sym.overrides(sym2, origin, env.types, true)) {
-                    return TypeMaker.getType(env, t);
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Return the method that this method overrides.
-     *
-     * @return a MethodDoc representing a method definition
-     * in a superclass this method overrides, null if
-     * this method does not override.
-     */
-    public MethodDoc overriddenMethod() {
-
-        // Real overriding only.  Static members are simply hidden.
-        // Likewise for constructors, but the MethodSymbol.overrides
-        // method takes this into account.
-        if ((sym.flags() & Flags.STATIC) != 0) {
-            return null;
-        }
-
-        // Derived from  com.sun.tools.javac.comp.Check.checkOverride .
-
-        ClassSymbol origin = (ClassSymbol)sym.owner;
-        for (Type t = env.types.supertype(origin.type);
-             t.hasTag(CLASS);
-             t = env.types.supertype(t)) {
-            ClassSymbol c = (ClassSymbol)t.tsym;
-            for (Symbol sym2 : membersOf(c).getSymbolsByName(sym.name)) {
-                if (sym.overrides(sym2, origin, env.types, true)) {
-                    return env.getMethodDoc((MethodSymbol)sym2);
-                }
-            }
-        }
-        return null;
-    }
-
-    /**Retrieve members of c, ignoring any CompletionFailures that occur. */
-    private Scope membersOf(ClassSymbol c) {
-        try {
-            return c.members();
-        } catch (CompletionFailure cf) {
-            /* Quietly ignore completion failures and try again - the type
-             * for which the CompletionFailure was thrown shouldn't be completed
-             * again by the completer that threw the CompletionFailure.
-             */
-            return membersOf(c);
-        }
-    }
-
-    /**
-     * Tests whether this method overrides another.
-     * The overridden method may be one declared in a superclass or
-     * a superinterface (unlike {@link #overriddenMethod()}).
-     *
-     * <p> When a non-abstract method overrides an abstract one, it is
-     * also said to <i>implement</i> the other.
-     *
-     * @param meth  the other method to examine
-     * @return <tt>true</tt> if this method overrides the other
-     */
-    public boolean overrides(MethodDoc meth) {
-        MethodSymbol overridee = ((MethodDocImpl) meth).sym;
-        ClassSymbol origin = (ClassSymbol) sym.owner;
-
-        return sym.name == overridee.name &&
-
-               // not reflexive as per JLS
-               sym != overridee &&
-
-               // we don't care if overridee is static, though that wouldn't
-               // compile
-               !sym.isStatic() &&
-
-               // sym, whose declaring type is the origin, must be
-               // in a subtype of overridee's type
-               env.types.asSuper(origin.type, overridee.owner) != null &&
-
-               // check access and signatures; don't check return types
-               sym.overrides(overridee, origin, env.types, false);
-    }
-
-
-    public String name() {
-        if (name == null) {
-            name = sym.name.toString();
-        }
-        return name;
-    }
-
-    private String name;
-
-    public String qualifiedName() {
-        if (qualifiedName == null) {
-            qualifiedName =  sym.enclClass().getQualifiedName() + "." + sym.name;
-        }
-        return qualifiedName;
-    }
-
-    private String qualifiedName;
-
-    /**
-     * Returns a string representation of this method.  Includes the
-     * qualified signature, the qualified method name, and any type
-     * parameters.  Type parameters follow the class name, as they do
-     * in the syntax for invoking methods with explicit type parameters.
-     */
-    public String toString() {
-        return sym.enclClass().getQualifiedName() +
-                "." + typeParametersString() + name() + signature();
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ModifierFilter.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2000, 2012, 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.sun.tools.javadoc;
-
-import static com.sun.tools.javac.code.Flags.*;
-
-/**
- *   A class whose instances are filters over Modifier bits.
- *   Filtering is done by returning boolean values.
- *   Classes, methods and fields can be filtered, or filtering
- *   can be done directly on modifier bits.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- *   @see com.sun.tools.javac.code.Flags
- *   @author Robert Field
- */
-
-public class ModifierFilter {
-
-    /**
-    * Package private access.
-    * A "pseudo-" modifier bit that can be used in the
-    * constructors of this class to specify package private
-    * access. This is needed since there is no Modifier.PACKAGE.
-    */
-    public static final long PACKAGE = 0x8000000000000000L;
-
-    /**
-    * All access modifiers.
-    * A short-hand set of modifier bits that can be used in the
-    * constructors of this class to specify all access modifiers,
-    * Same as PRIVATE | PROTECTED | PUBLIC | PACKAGE.
-    */
-    public static final long ALL_ACCESS =
-                PRIVATE | PROTECTED | PUBLIC | PACKAGE;
-
-    private long oneOf;
-    private long must;
-    private long cannot;
-
-    private static final int ACCESS_BITS = PRIVATE | PROTECTED | PUBLIC;
-
-    /**
-     * Constructor - Specify a filter.
-     *
-     * @param   oneOf   If zero, everything passes the filter.
-     *                  If non-zero, at least one of the specified
-     *                  bits must be on in the modifier bits to
-     *                  pass the filter.
-     */
-    public ModifierFilter(long oneOf) {
-        this(oneOf, 0, 0);
-    }
-
-    /**
-     * Constructor - Specify a filter.
-     * For example, the filter below  will only pass synchronized
-     * methods that are private or package private access and are
-     * not native or static.
-     * <pre>
-     * ModifierFilter(  Modifier.PRIVATE | ModifierFilter.PACKAGE,
-     *                  Modifier.SYNCHRONIZED,
-     *                  Modifier.NATIVE | Modifier.STATIC)
-     * </pre><p>
-     * Each of the three arguments must either be
-     * zero or the or'ed combination of the bits specified in the
-     * class Modifier or this class. During filtering, these values
-     * are compared against the modifier bits as follows:
-     *
-     * @param   oneOf   If zero, ignore this argument.
-     *                  If non-zero, at least one of the bits must be on.
-     * @param   must    All bits specified must be on.
-     * @param   cannot  None of the bits specified can be on.
-     */
-    public ModifierFilter(long oneOf, long must, long cannot) {
-        this.oneOf = oneOf;
-        this.must = must;
-        this.cannot = cannot;
-    }
-
-    /**
-     * Filter on modifier bits.
-     *
-     * @param   modifierBits    Bits as specified in the Modifier class
-     *
-     * @return                  Whether the modifierBits pass this filter.
-     */
-    public boolean checkModifier(int modifierBits) {
-        // Add in the "pseudo-" modifier bit PACKAGE, if needed
-        long fmod = ((modifierBits & ACCESS_BITS) == 0) ?
-                        modifierBits | PACKAGE :
-                        modifierBits;
-        return ((oneOf == 0) || ((oneOf & fmod) != 0)) &&
-                ((must & fmod) == must) &&
-                ((cannot & fmod) == 0);
-    }
-
-} // end ModifierFilter
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,389 +0,0 @@
-/*
- * Copyright (c) 1997, 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 com.sun.tools.javadoc;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.tools.FileObject;
-
-import com.sun.javadoc.*;
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Attribute;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Position;
-
-import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
-
-/**
- * Represents a java package.  Provides access to information
- * about the package, the package's comment and tags, and the
- * classes in the package.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since 1.2
- * @author Kaiyang Liu (original)
- * @author Robert Field (rewrite)
- * @author Neal Gafter (rewrite)
- * @author Scott Seligman (package-info.java)
- */
-
-public class PackageDocImpl extends DocImpl implements PackageDoc {
-
-    public final PackageSymbol sym;
-    private JCCompilationUnit tree = null;    // for source position
-
-    public FileObject docPath = null;
-    private boolean foundDoc;   // found a doc comment in either
-                                // package.html or package-info.java
-
-    boolean isIncluded = false;  // Set in RootDocImpl.
-    public boolean setDocPath = false;  //Flag to avoid setting doc path multiple times.
-
-    /**
-     * Constructor
-     */
-    public PackageDocImpl(DocEnv env, PackageSymbol sym) {
-        this(env, sym, null);
-    }
-
-    /**
-     * Constructor
-     */
-    public PackageDocImpl(DocEnv env, PackageSymbol sym, TreePath treePath) {
-        super(env, treePath);
-        this.sym = sym;
-        this.tree = (treePath == null) ? null : (JCCompilationUnit) treePath.getCompilationUnit();
-        foundDoc = (documentation != null);
-    }
-
-    void setTree(JCTree tree) {
-        this.tree = (JCCompilationUnit) tree;
-    }
-
-    public void setTreePath(TreePath treePath) {
-        super.setTreePath(treePath);
-        checkDoc();
-    }
-
-    /**
-     * Do lazy initialization of "documentation" string.
-     */
-    protected String documentation() {
-        if (documentation != null)
-            return documentation;
-        if (docPath != null) {
-            // read from file
-            try {
-                InputStream s = docPath.openInputStream();
-                documentation = readHTMLDocumentation(s, docPath);
-            } catch (IOException exc) {
-                documentation = "";
-                env.error(null, "javadoc.File_Read_Error", docPath.getName());
-            }
-        } else {
-            // no doc file to be had
-            documentation = "";
-        }
-        return documentation;
-    }
-
-    /**
-     * Cache of all classes contained in this package, including
-     * member classes of those classes, and their member classes, etc.
-     * Includes only those classes at the specified protection level
-     * and weaker.
-     */
-    private List<ClassDocImpl> allClassesFiltered = null;
-
-    /**
-     * Cache of all classes contained in this package, including
-     * member classes of those classes, and their member classes, etc.
-     */
-    private List<ClassDocImpl> allClasses = null;
-
-    /**
-     * Return a list of all classes contained in this package, including
-     * member classes of those classes, and their member classes, etc.
-     */
-    private List<ClassDocImpl> getClasses(boolean filtered) {
-        if (allClasses != null && !filtered) {
-            return allClasses;
-        }
-        if (allClassesFiltered != null && filtered) {
-            return allClassesFiltered;
-        }
-        ListBuffer<ClassDocImpl> classes = new ListBuffer<>();
-        for (Symbol enumerated : sym.members().getSymbols(NON_RECURSIVE)) {
-            if (enumerated != null) {
-                ClassSymbol s = (ClassSymbol)enumerated;
-                ClassDocImpl c = env.getClassDoc(s);
-                if (c != null && !c.isSynthetic())
-                    c.addAllClasses(classes, filtered);
-            }
-        }
-        if (filtered)
-            return allClassesFiltered = classes.toList();
-        else
-            return allClasses = classes.toList();
-    }
-
-    /**
-     * Add all included classes (including Exceptions and Errors)
-     * and interfaces.
-     */
-    public void addAllClassesTo(ListBuffer<ClassDocImpl> list) {
-        list.appendList(getClasses(true));
-    }
-
-    /**
-     * Get all classes (including Exceptions and Errors)
-     * and interfaces.
-     * @since J2SE1.4.
-     *
-     * @return all classes and interfaces in this package, filtered to include
-     * only the included classes if filter==true.
-     */
-    public ClassDoc[] allClasses(boolean filter) {
-        List<ClassDocImpl> classes = getClasses(filter);
-        return classes.toArray(new ClassDocImpl[classes.length()]);
-    }
-
-    /**
-     * Get all included classes (including Exceptions and Errors)
-     * and interfaces.  Same as allClasses(true).
-     *
-     * @return all included classes and interfaces in this package.
-     */
-    public ClassDoc[] allClasses() {
-        return allClasses(true);
-    }
-
-    /**
-     * Get ordinary classes (that is, exclude exceptions, errors,
-     * enums, interfaces, and annotation types) in this package.
-     *
-     * @return included ordinary classes in this package.
-     */
-    public ClassDoc[] ordinaryClasses() {
-        ListBuffer<ClassDocImpl> ret = new ListBuffer<>();
-        for (ClassDocImpl c : getClasses(true)) {
-            if (c.isOrdinaryClass()) {
-                ret.append(c);
-            }
-        }
-        return ret.toArray(new ClassDocImpl[ret.length()]);
-    }
-
-    /**
-     * Get Exception classes in this package.
-     *
-     * @return included Exceptions in this package.
-     */
-    public ClassDoc[] exceptions() {
-        ListBuffer<ClassDocImpl> ret = new ListBuffer<>();
-        for (ClassDocImpl c : getClasses(true)) {
-            if (c.isException()) {
-                ret.append(c);
-            }
-        }
-        return ret.toArray(new ClassDocImpl[ret.length()]);
-    }
-
-    /**
-     * Get Error classes in this package.
-     *
-     * @return included Errors in this package.
-     */
-    public ClassDoc[] errors() {
-        ListBuffer<ClassDocImpl> ret = new ListBuffer<>();
-        for (ClassDocImpl c : getClasses(true)) {
-            if (c.isError()) {
-                ret.append(c);
-            }
-        }
-        return ret.toArray(new ClassDocImpl[ret.length()]);
-    }
-
-    /**
-     * Get included enum types in this package.
-     *
-     * @return included enum types in this package.
-     */
-    public ClassDoc[] enums() {
-        ListBuffer<ClassDocImpl> ret = new ListBuffer<>();
-        for (ClassDocImpl c : getClasses(true)) {
-            if (c.isEnum()) {
-                ret.append(c);
-            }
-        }
-        return ret.toArray(new ClassDocImpl[ret.length()]);
-    }
-
-    /**
-     * Get included interfaces in this package, omitting annotation types.
-     *
-     * @return included interfaces in this package.
-     */
-    public ClassDoc[] interfaces() {
-        ListBuffer<ClassDocImpl> ret = new ListBuffer<>();
-        for (ClassDocImpl c : getClasses(true)) {
-            if (c.isInterface()) {
-                ret.append(c);
-            }
-        }
-        return ret.toArray(new ClassDocImpl[ret.length()]);
-    }
-
-    /**
-     * Get included annotation types in this package.
-     *
-     * @return included annotation types in this package.
-     */
-    public AnnotationTypeDoc[] annotationTypes() {
-        ListBuffer<AnnotationTypeDocImpl> ret = new ListBuffer<>();
-        for (ClassDocImpl c : getClasses(true)) {
-            if (c.isAnnotationType()) {
-                ret.append((AnnotationTypeDocImpl)c);
-            }
-        }
-        return ret.toArray(new AnnotationTypeDocImpl[ret.length()]);
-    }
-
-    /**
-     * Get the annotations of this package.
-     * Return an empty array if there are none.
-     */
-    public AnnotationDesc[] annotations() {
-        AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()];
-        int i = 0;
-        for (Attribute.Compound a : sym.getRawAttributes()) {
-            res[i++] = new AnnotationDescImpl(env, a);
-        }
-        return res;
-    }
-
-
-    /**
-     * Lookup for a class within this package.
-     *
-     * @return ClassDocImpl of found class, or null if not found.
-     */
-    public ClassDoc findClass(String className) {
-        final boolean filtered = true;
-        for (ClassDocImpl c : getClasses(filtered)) {
-            if (c.name().equals(className)) {
-                return c;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Return true if this package is included in the active set.
-     */
-    public boolean isIncluded() {
-        return isIncluded;
-    }
-
-    /**
-     * Get package name.
-     *
-     * Note that we do not provide a means of obtaining the simple
-     * name of a package -- package names are always returned in their
-     * uniquely qualified form.
-     */
-    public String name() {
-        return qualifiedName();
-    }
-
-    /**
-     * Get package name.
-     */
-    public String qualifiedName() {
-        if (qualifiedName == null) {
-            Name fullname = sym.getQualifiedName();
-            // Some bogus tests depend on the interned "" being returned.
-            // See 6457276.
-            qualifiedName = fullname.isEmpty() ? "" : fullname.toString();
-        }
-        return qualifiedName;
-    }
-
-    private String qualifiedName;
-
-    /**
-     * set doc path for an unzipped directory
-     */
-    public void setDocPath(FileObject path) {
-        setDocPath = true;
-        if (path == null)
-            return;
-        if (!path.equals(docPath)) {
-            docPath = path;
-            checkDoc();
-        }
-    }
-
-    // Has checkDoc() sounded off yet?
-    private boolean checkDocWarningEmitted = false;
-
-    /**
-     * Invoked when a source of package doc comments is located.
-     * Emits a diagnostic if this is the second one.
-     */
-    private void checkDoc() {
-        if (foundDoc) {
-            if (!checkDocWarningEmitted) {
-                env.warning(null, "javadoc.Multiple_package_comments", name());
-                checkDocWarningEmitted = true;
-            }
-        } else {
-            foundDoc = true;
-        }
-    }
-
-    /**
-     * Return the source position of the entity, or null if
-     * no position is available.
-     */
-    public SourcePosition position() {
-        return (tree != null)
-                ? SourcePositionImpl.make(tree.sourcefile, tree.pos, tree.lineMap)
-                : SourcePositionImpl.make(docPath, Position.NOPOS, null);
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParamTagImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.sun.tools.javadoc;
-
-import java.util.regex.*;
-
-import com.sun.javadoc.*;
-
-/**
- * Represents an @param documentation tag.
- * Parses and stores the name and comment parts of the parameter tag.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Robert Field
- *
- */
-class ParamTagImpl extends TagImpl implements ParamTag {
-
-    private static final Pattern typeParamRE = Pattern.compile("<([^<>]+)>");
-
-    private final String parameterName;
-    private final String parameterComment;
-    private final boolean isTypeParameter;
-
-    /**
-     * Cached inline tags.
-     */
-    private Tag[] inlineTags;
-
-    ParamTagImpl(DocImpl holder, String name, String text) {
-        super(holder, name, text);
-        String[] sa = divideAtWhite();
-
-        Matcher m = typeParamRE.matcher(sa[0]);
-        isTypeParameter = m.matches();
-        parameterName = isTypeParameter ? m.group(1) : sa[0];
-        parameterComment = sa[1];
-    }
-
-    /**
-     * Return the parameter name.
-     */
-    public String parameterName() {
-        return parameterName;
-    }
-
-    /**
-     * Return the parameter comment.
-     */
-    public String parameterComment() {
-        return parameterComment;
-    }
-
-    /**
-     * Return the kind of this tag.
-     */
-    @Override
-    public String kind() {
-        return "@param";
-    }
-
-    /**
-     * Return true if this ParamTag corresponds to a type parameter.
-     */
-    public boolean isTypeParameter() {
-        return isTypeParameter;
-    }
-
-    /**
-     * convert this object to a string.
-     */
-    @Override
-    public String toString() {
-        return name + ":" + text;
-    }
-
-    /**
-     * For the parameter comment with embedded @link tags return the array of
-     * TagImpls consisting of SeeTagImpl(s) and text containing TagImpl(s).
-     *
-     * @return TagImpl[] Array of tags with inline SeeTagImpls.
-     * @see TagImpl#inlineTags()
-     * @see ThrowsTagImpl#inlineTags()
-     */
-    @Override
-    public Tag[] inlineTags() {
-        if (inlineTags == null) {
-            inlineTags = Comment.getInlineTags(holder, parameterComment);
-        }
-        return inlineTags;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParameterImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.tools.javac.code.Attribute;
-import com.sun.tools.javac.code.Symbol.VarSymbol;
-
-/**
- * ParameterImpl information.
- * This includes a parameter type and parameter name.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Kaiyang Liu (original)
- * @author Robert Field (rewrite)
- * @author Scott Seligman (generics, annotations)
- */
-class ParameterImpl implements Parameter {
-
-    private final DocEnv env;
-    private final VarSymbol sym;
-    private final com.sun.javadoc.Type type;
-
-    /**
-     * Constructor of parameter info class.
-     */
-    ParameterImpl(DocEnv env, VarSymbol sym) {
-        this.env = env;
-        this.sym = sym;
-        this.type = TypeMaker.getType(env, sym.type, false);
-    }
-
-    /**
-     * Get the type of this parameter.
-     */
-    public com.sun.javadoc.Type type() {
-        return type;
-    }
-
-    /**
-     * Get local name of this parameter.
-     * For example if parameter is the short 'index', returns "index".
-     */
-    public String name() {
-        return sym.toString();
-    }
-
-    /**
-     * Get type name of this parameter.
-     * For example if parameter is the short 'index', returns "short".
-     */
-    public String typeName() {
-        return (type instanceof ClassDoc || type instanceof TypeVariable)
-                ? type.typeName()       // omit formal type params or bounds
-                : type.toString();
-    }
-
-    /**
-     * Returns a string representation of the parameter.
-     * <p>
-     * For example if parameter is the short 'index', returns "short index".
-     *
-     * @return type name and parameter name of this parameter.
-     */
-    public String toString() {
-        return typeName() + " " + sym;
-    }
-
-    /**
-     * Get the annotations of this parameter.
-     * Return an empty array if there are none.
-     */
-    public AnnotationDesc[] annotations() {
-        AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()];
-        int i = 0;
-        for (Attribute.Compound a : sym.getRawAttributes()) {
-            res[i++] = new AnnotationDescImpl(env, a);
-        }
-        return res;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ParameterizedTypeImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, 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.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.ClassType;
-
-import static com.sun.tools.javac.code.TypeTag.CLASS;
-
-
-/**
- * Implementation of <code>ParameterizedType</code>, which
- * represents an invocation of a generic class or interface.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Scott Seligman
- * @since 1.5
- */
-public class ParameterizedTypeImpl
-        extends AbstractTypeImpl implements ParameterizedType {
-
-    ParameterizedTypeImpl(DocEnv env, Type type) {
-        super(env, type);
-    }
-
-    /**
-     * Return the generic class or interface that declared this type.
-     */
-    @Override
-    public ClassDoc asClassDoc() {
-        return env.getClassDoc((ClassSymbol)type.tsym);
-    }
-
-    /**
-     * Return the actual type arguments of this type.
-     */
-    public com.sun.javadoc.Type[] typeArguments() {
-        return TypeMaker.getTypes(env, type.getTypeArguments());
-    }
-
-    /**
-     * Return the class type that is a direct supertype of this one.
-     * Return null if this is an interface type.
-     */
-    public com.sun.javadoc.Type superclassType() {
-        if (asClassDoc().isInterface()) {
-            return null;
-        }
-        Type sup = env.types.supertype(type);
-        return TypeMaker.getType(env,
-                                 (sup != type) ? sup : env.syms.objectType);
-    }
-
-    /**
-     * Return the interface types directly implemented by or extended by this
-     * parameterized type.
-     * Return an empty array if there are no interfaces.
-     */
-    public com.sun.javadoc.Type[] interfaceTypes() {
-        return TypeMaker.getTypes(env, env.types.interfaces(type));
-    }
-
-    /**
-     * Return the type that contains this type as a member.
-     * Return null is this is a top-level type.
-     */
-    public com.sun.javadoc.Type containingType() {
-        if (type.getEnclosingType().hasTag(CLASS)) {
-            // This is the type of an inner class.
-            return TypeMaker.getType(env, type.getEnclosingType());
-        }
-        ClassSymbol enclosing = type.tsym.owner.enclClass();
-        if (enclosing != null) {
-            // Nested but not inner.  Return the ClassDoc of the enclosing
-            // class or interface.
-            // See java.lang.reflect.ParameterizedType.getOwnerType().
-            return env.getClassDoc(enclosing);
-        }
-        return null;
-    }
-
-
-    // Asking for the "name" of a parameterized type doesn't exactly make
-    // sense.  It's a type expression.  Return the name of its generic
-    // type.
-    @Override
-    public String typeName() {
-        return TypeMaker.getTypeName(type, false);
-    }
-
-    @Override
-    public ParameterizedType asParameterizedType() {
-        return this;
-    }
-
-    @Override
-    public String toString() {
-        return parameterizedTypeToString(env, (ClassType)type, true);
-    }
-
-    static String parameterizedTypeToString(DocEnv env, ClassType cl,
-                                            boolean full) {
-        if (env.legacyDoclet) {
-            return TypeMaker.getTypeName(cl, full);
-        }
-        StringBuilder s = new StringBuilder();
-        if (!(cl.getEnclosingType().hasTag(CLASS))) {               // if not an inner class...
-            s.append(TypeMaker.getTypeName(cl, full));
-        } else {
-            ClassType encl = (ClassType)cl.getEnclosingType();
-            s.append(parameterizedTypeToString(env, encl, full))
-             .append('.')
-             .append(cl.tsym.name.toString());
-        }
-        s.append(TypeMaker.typeArgumentsString(env, cl, full));
-        return s.toString();
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PrimitiveType.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-/**
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- */
-class PrimitiveType implements com.sun.javadoc.Type {
-
-    private final String name;
-
-    static final PrimitiveType voidType = new PrimitiveType("void");
-    static final PrimitiveType booleanType = new PrimitiveType("boolean");
-    static final PrimitiveType byteType = new PrimitiveType("byte");
-    static final PrimitiveType charType = new PrimitiveType("char");
-    static final PrimitiveType shortType = new PrimitiveType("short");
-    static final PrimitiveType intType = new PrimitiveType("int");
-    static final PrimitiveType longType = new PrimitiveType("long");
-    static final PrimitiveType floatType = new PrimitiveType("float");
-    static final PrimitiveType doubleType = new PrimitiveType("double");
-
-    // error type, should never actually be used
-    static final PrimitiveType errorType = new PrimitiveType("");
-
-    PrimitiveType(String name) {
-        this.name = name;
-    }
-
-    /**
-     * Return unqualified name of type excluding any dimension information.
-     * <p>
-     * For example, a two dimensional array of String returns 'String'.
-     */
-    public String typeName() {
-        return name;
-    }
-
-    public com.sun.javadoc.Type getElementType() {
-        return null;
-    }
-
-    /**
-     * Return qualified name of type excluding any dimension information.
-     *<p>
-     * For example, a two dimensional array of String
-     * returns 'java.lang.String'.
-     */
-    public String qualifiedTypeName() {
-        return name;
-    }
-
-    /**
-     * Return the simple name of this type.
-     */
-    public String simpleTypeName() {
-        return name;
-    }
-
-    /**
-     * Return the type's dimension information, as a string.
-     * <p>
-     * For example, a two dimensional array of String returns '[][]'.
-     */
-    public String dimension() {
-        return "";
-    }
-
-    /**
-     * Return this type as a class.  Array dimensions are ignored.
-     *
-     * @return a ClassDocImpl if the type is a Class.
-     * Return null if it is a primitive type..
-     */
-    public ClassDoc asClassDoc() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not an annotation type.
-     */
-    public AnnotationTypeDoc asAnnotationTypeDoc() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not an instantiation.
-     */
-    public ParameterizedType asParameterizedType() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not a type variable.
-     */
-    public TypeVariable asTypeVariable() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not a wildcard type.
-     */
-    public WildcardType asWildcardType() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not an annotated type.
-     */
-    public AnnotatedType asAnnotatedType() {
-        return null;
-    }
-
-    /**
-     * Returns a string representation of the type.
-     *
-     * Return name of type including any dimension information.
-     * <p>
-     * For example, a two dimensional array of String returns
-     * <code>String[][]</code>.
-     *
-     * @return name of type including any dimension information.
-     */
-    public String toString() {
-        return qualifiedTypeName();
-    }
-
-    /**
-     * Return true if this is a primitive type.
-     */
-    public boolean isPrimitive() {
-        return true;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ProgramElementDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.sun.tools.javadoc;
-
-import java.lang.reflect.Modifier;
-import java.text.CollationKey;
-
-import com.sun.javadoc.*;
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Attribute;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.util.Position;
-
-/**
- * Represents a java program element: class, interface, field,
- * constructor, or method.
- * This is an abstract class dealing with information common to
- * these elements.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @see MemberDocImpl
- * @see ClassDocImpl
- *
- * @author Robert Field
- * @author Neal Gafter (rewrite)
- * @author Scott Seligman (generics, enums, annotations)
- */
-public abstract class ProgramElementDocImpl
-        extends DocImpl implements ProgramElementDoc {
-
-    private final Symbol sym;
-
-    // For source position information.
-    JCTree tree = null;
-    Position.LineMap lineMap = null;
-
-
-    // Cache for getModifiers().
-    private int modifiers = -1;
-
-    protected ProgramElementDocImpl(DocEnv env, Symbol sym, TreePath treePath) {
-        super(env, treePath);
-        this.sym = sym;
-        if (treePath != null) {
-            tree = (JCTree) treePath.getLeaf();
-            lineMap = ((JCCompilationUnit) treePath.getCompilationUnit()).lineMap;
-        }
-    }
-
-    @Override
-    void setTreePath(TreePath treePath) {
-        super.setTreePath(treePath);
-        this.tree = (JCTree) treePath.getLeaf();
-        this.lineMap = ((JCCompilationUnit) treePath.getCompilationUnit()).lineMap;
-    }
-
-    /**
-     * Subclasses override to identify the containing class
-     */
-    protected abstract ClassSymbol getContainingClass();
-
-    /**
-     * Returns the flags in terms of javac's flags
-     */
-    abstract protected long getFlags();
-
-    /**
-     * Returns the modifier flags in terms of java.lang.reflect.Modifier.
-     */
-    protected int getModifiers() {
-        if (modifiers == -1) {
-            modifiers = DocEnv.translateModifiers(getFlags());
-        }
-        return modifiers;
-    }
-
-    /**
-     * Get the containing class of this program element.
-     *
-     * @return a ClassDocImpl for this element's containing class.
-     * If this is a class with no outer class, return null.
-     */
-    public ClassDoc containingClass() {
-        if (getContainingClass() == null) {
-            return null;
-        }
-        return env.getClassDoc(getContainingClass());
-    }
-
-    /**
-     * Return the package that this member is contained in.
-     * Return "" if in unnamed package.
-     */
-    public PackageDoc containingPackage() {
-        return env.getPackageDoc(getContainingClass().packge());
-    }
-
-    /**
-     * Get the modifier specifier integer.
-     *
-     * @see java.lang.reflect.Modifier
-     */
-    public int modifierSpecifier() {
-        int modifiers = getModifiers();
-        if (isMethod() && containingClass().isInterface())
-            // Remove the implicit abstract modifier.
-            return modifiers & ~Modifier.ABSTRACT;
-        return modifiers;
-    }
-
-    /**
-     * Get modifiers string.
-     * <pre>
-     * Example, for:
-     *   public abstract int foo() { ... }
-     * modifiers() would return:
-     *   'public abstract'
-     * </pre>
-     * Annotations are not included.
-     */
-    public String modifiers() {
-        int modifiers = getModifiers();
-        if (isAnnotationTypeElement() ||
-                (isMethod() && containingClass().isInterface())) {
-            // Remove the implicit abstract modifier.
-            return Modifier.toString(modifiers & ~Modifier.ABSTRACT);
-        } else {
-            return Modifier.toString(modifiers);
-        }
-    }
-
-    /**
-     * Get the annotations of this program element.
-     * Return an empty array if there are none.
-     */
-    public AnnotationDesc[] annotations() {
-        AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()];
-        int i = 0;
-        for (Attribute.Compound a : sym.getRawAttributes()) {
-            res[i++] = new AnnotationDescImpl(env, a);
-        }
-        return res;
-    }
-
-    /**
-     * Return true if this program element is public
-     */
-    public boolean isPublic() {
-        int modifiers = getModifiers();
-        return Modifier.isPublic(modifiers);
-    }
-
-    /**
-     * Return true if this program element is protected
-     */
-    public boolean isProtected() {
-        int modifiers = getModifiers();
-        return Modifier.isProtected(modifiers);
-    }
-
-    /**
-     * Return true if this program element is private
-     */
-    public boolean isPrivate() {
-        int modifiers = getModifiers();
-        return Modifier.isPrivate(modifiers);
-    }
-
-    /**
-     * Return true if this program element is package private
-     */
-    public boolean isPackagePrivate() {
-        return !(isPublic() || isPrivate() || isProtected());
-    }
-
-    /**
-     * Return true if this program element is static
-     */
-    public boolean isStatic() {
-        int modifiers = getModifiers();
-        return Modifier.isStatic(modifiers);
-    }
-
-    /**
-     * Return true if this program element is final
-     */
-    public boolean isFinal() {
-        int modifiers = getModifiers();
-        return Modifier.isFinal(modifiers);
-    }
-
-    /**
-     * Generate a key for sorting.
-     */
-    CollationKey generateKey() {
-        String k = name();
-        // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
-        return env.doclocale.collator.getCollationKey(k);
-    }
-
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/RootDocImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,394 +0,0 @@
-/*
- * Copyright (c) 1997, 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 com.sun.tools.javadoc;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Locale;
-
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.tree.JCTree.JCClassDecl;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Position;
-
-/**
- * This class holds the information from one run of javadoc.
- * Particularly the packages, classes and options specified
- * by the user.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since 1.2
- * @author Robert Field
- * @author Atul M Dambalkar
- * @author Neal Gafter (rewrite)
- */
-public class RootDocImpl extends DocImpl implements RootDoc {
-
-    /**
-     * list of classes specified on the command line.
-     */
-    private List<ClassDocImpl> cmdLineClasses;
-
-    /**
-     * list of packages specified on the command line.
-     */
-    private List<PackageDocImpl> cmdLinePackages;
-
-    /**
-     * a collection of all options.
-     */
-    private List<String[]> options;
-
-    /**
-     * Constructor used when reading source files.
-     *
-     * @param env the documentation environment, state for this javadoc run
-     * @param classes list of classes specified on the commandline
-     * @param packages list of package names specified on the commandline
-     * @param options list of options
-     */
-    public RootDocImpl(DocEnv env, List<JCClassDecl> classes, List<String> packages, List<String[]> options) {
-        super(env, null);
-        this.options = options;
-        setPackages(env, packages);
-        setClasses(env, classes);
-    }
-
-    /**
-     * Constructor used when reading class files.
-     *
-     * @param env the documentation environment, state for this javadoc run
-     * @param classes list of class names specified on the commandline
-     * @param options list of options
-     */
-    public RootDocImpl(DocEnv env, List<String> classes, List<String[]> options) {
-        super(env, null);
-        this.options = options;
-        cmdLinePackages = List.nil();
-        ListBuffer<ClassDocImpl> classList = new ListBuffer<>();
-        for (String className : classes) {
-            ClassDocImpl c = env.loadClass(className);
-            if (c == null)
-                env.error(null, "javadoc.class_not_found", className);
-            else
-                classList = classList.append(c);
-        }
-        cmdLineClasses = classList.toList();
-    }
-
-    /**
-     * Initialize classes information. Those classes are input from
-     * command line.
-     *
-     * @param env the compilation environment
-     * @param classes a list of ClassDeclaration
-     */
-    private void setClasses(DocEnv env, List<JCClassDecl> classes) {
-        ListBuffer<ClassDocImpl> result = new ListBuffer<>();
-        for (JCClassDecl def : classes) {
-            //### Do we want modifier check here?
-            if (env.shouldDocument(def.sym)) {
-                ClassDocImpl cd = env.getClassDoc(def.sym);
-                if (cd != null) {
-                    cd.isIncluded = true;
-                    result.append(cd);
-                } //else System.out.println(" (classdoc is null)");//DEBUG
-            } //else System.out.println(" (env.shouldDocument() returned false)");//DEBUG
-        }
-        cmdLineClasses = result.toList();
-    }
-
-    /**
-     * Initialize packages information.
-     *
-     * @param env the compilation environment
-     * @param packages a list of package names (String)
-     */
-    private void setPackages(DocEnv env, List<String> packages) {
-        ListBuffer<PackageDocImpl> packlist = new ListBuffer<>();
-        for (String name : packages) {
-            PackageDocImpl pkg = env.lookupPackage(name);
-            if (pkg != null) {
-                pkg.isIncluded = true;
-                packlist.append(pkg);
-            } else {
-                env.warning(null, "main.no_source_files_for_package", name);
-            }
-        }
-        cmdLinePackages = packlist.toList();
-    }
-
-    /**
-     * Command line options.
-     *
-     * <pre>
-     * For example, given:
-     *     javadoc -foo this that -bar other ...
-     *
-     * This method will return:
-     *      options()[0][0] = "-foo"
-     *      options()[0][1] = "this"
-     *      options()[0][2] = "that"
-     *      options()[1][0] = "-bar"
-     *      options()[1][1] = "other"
-     * </pre>
-     *
-     * @return an array of arrays of String.
-     */
-    public String[][] options() {
-        return options.toArray(new String[options.length()][]);
-    }
-
-    /**
-     * Packages specified on the command line.
-     */
-    public PackageDoc[] specifiedPackages() {
-        return (PackageDoc[])cmdLinePackages
-            .toArray(new PackageDocImpl[cmdLinePackages.length()]);
-    }
-
-    /**
-     * Classes and interfaces specified on the command line.
-     */
-    public ClassDoc[] specifiedClasses() {
-        ListBuffer<ClassDocImpl> classesToDocument = new ListBuffer<>();
-        for (ClassDocImpl cd : cmdLineClasses) {
-            cd.addAllClasses(classesToDocument, true);
-        }
-        return (ClassDoc[])classesToDocument.toArray(new ClassDocImpl[classesToDocument.length()]);
-    }
-
-    /**
-     * Return all classes and interfaces (including those inside
-     * packages) to be documented.
-     */
-    public ClassDoc[] classes() {
-        ListBuffer<ClassDocImpl> classesToDocument = new ListBuffer<>();
-        for (ClassDocImpl cd : cmdLineClasses) {
-            cd.addAllClasses(classesToDocument, true);
-        }
-        for (PackageDocImpl pd : cmdLinePackages) {
-            pd.addAllClassesTo(classesToDocument);
-        }
-        return classesToDocument.toArray(new ClassDocImpl[classesToDocument.length()]);
-    }
-
-    /**
-     * Return a ClassDoc for the specified class/interface name
-     *
-     * @param qualifiedName qualified class name
-     *                        (i.e. includes package name).
-     *
-     * @return a ClassDocImpl holding the specified class, null if
-     * this class is not referenced.
-     */
-    public ClassDoc classNamed(String qualifiedName) {
-        return env.lookupClass(qualifiedName);
-    }
-
-    /**
-     * Return a PackageDoc for the specified package name
-     *
-     * @param name package name
-     *
-     * @return a PackageDoc holding the specified package, null if
-     * this package is not referenced.
-     */
-    public PackageDoc packageNamed(String name) {
-        return env.lookupPackage(name);
-    }
-
-    /**
-     * Return the name of this Doc item.
-     *
-     * @return the string <code>"*RootDocImpl*"</code>.
-     */
-    public String name() {
-        return "*RootDocImpl*";
-    }
-
-    /**
-     * Return the name of this Doc item.
-     *
-     * @return the string <code>"*RootDocImpl*"</code>.
-     */
-    public String qualifiedName() {
-        return "*RootDocImpl*";
-    }
-
-    /**
-     * Return true if this Doc is include in the active set.
-     * RootDocImpl isn't even a program entity so it is always false.
-     */
-    public boolean isIncluded() {
-        return false;
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param msg message to print
-     */
-    public void printError(String msg) {
-        env.printError(msg);
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param msg message to print
-     */
-    public void printError(SourcePosition pos, String msg) {
-        env.printError(pos, msg);
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param msg message to print
-     */
-    public void printWarning(String msg) {
-        env.printWarning(msg);
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param msg message to print
-     */
-    public void printWarning(SourcePosition pos, String msg) {
-        env.printWarning(pos, msg);
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param msg message to print
-     */
-    public void printNotice(String msg) {
-        env.printNotice(msg);
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param msg message to print
-     */
-    public void printNotice(SourcePosition pos, String msg) {
-        env.printNotice(pos, msg);
-    }
-
-    /**
-     * Return the path of the overview file and null if it does not exist.
-     * @return the path of the overview file and null if it does not exist.
-     */
-    private JavaFileObject getOverviewPath() {
-        for (String[] opt : options) {
-            if (opt[0].equals("-overview")) {
-                if (env.fileManager instanceof StandardJavaFileManager) {
-                    StandardJavaFileManager fm = (StandardJavaFileManager) env.fileManager;
-                    return fm.getJavaFileObjects(opt[1]).iterator().next();
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Do lazy initialization of "documentation" string.
-     */
-    @Override
-    protected String documentation() {
-        if (documentation == null) {
-            JavaFileObject overviewPath = getOverviewPath();
-            if (overviewPath == null) {
-                // no doc file to be had
-                documentation = "";
-            } else {
-                // read from file
-                try {
-                    documentation = readHTMLDocumentation(
-                        overviewPath.openInputStream(),
-                        overviewPath);
-                } catch (IOException exc) {
-                    documentation = "";
-                    env.error(null, "javadoc.File_Read_Error", overviewPath.getName());
-                }
-            }
-        }
-        return documentation;
-    }
-
-    /**
-     * Return the source position of the entity, or null if
-     * no position is available.
-     */
-    @Override
-    public SourcePosition position() {
-        JavaFileObject path;
-        return ((path = getOverviewPath()) == null) ?
-            null :
-            SourcePositionImpl.make(path, Position.NOPOS, null);
-    }
-
-    /**
-     * Return the locale provided by the user or the default locale value.
-     */
-    public Locale getLocale() {
-        return env.doclocale.locale;
-    }
-
-    /**
-     * Return the current file manager.
-     */
-    public JavaFileManager getFileManager() {
-        return env.fileManager;
-    }
-
-    public void initDocLint(Collection<String> opts, Collection<String> customTagNames,
-            String htmlVersion) {
-        env.initDoclint(opts, customTagNames, htmlVersion);
-    }
-
-    public boolean isFunctionalInterface(AnnotationDesc annotationDesc) {
-        return env.source.allowLambda()
-            && annotationDesc.annotationType().qualifiedName().equals(
-                env.syms.functionalInterfaceType.toString());
-    }
-
-    public boolean showTagMessages() {
-        return env.showTagMessages();
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SeeTagImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,542 +0,0 @@
-/*
- * Copyright (c) 1997, 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 com.sun.tools.javadoc;
-
-import java.io.File;
-import java.util.Locale;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.code.Printer;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Type.CapturedType;
-import com.sun.tools.javac.util.*;
-
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-
-/**
- * Represents a see also documentation tag.
- * The @see tag can be plain text, or reference a class or member.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Kaiyang Liu (original)
- * @author Robert Field (rewrite)
- * @author Atul M Dambalkar
- *
- */
-class SeeTagImpl extends TagImpl implements SeeTag, LayoutCharacters {
-
-    //### TODO: Searching for classes, fields, and methods
-    //### should follow the normal rules applied by the compiler.
-
-    /**
-     * where of  where#what - i.e. the class name (may be empty)
-     */
-    private String where;
-
-    /**
-     * what of  where#what - i.e. the member (may be null)
-     */
-    private String what;
-
-    private PackageDoc referencedPackage;
-    private ClassDoc referencedClass;
-    private MemberDoc referencedMember;
-
-    String label = "";
-
-    SeeTagImpl(DocImpl holder, String name, String text) {
-        super(holder, name, text);
-        parseSeeString();
-        if (where != null) {
-            ClassDocImpl container = null;
-            if (holder instanceof MemberDoc) {
-                container =
-                  (ClassDocImpl)((ProgramElementDoc)holder).containingClass();
-            } else if (holder instanceof ClassDoc) {
-                container = (ClassDocImpl)holder;
-            }
-            findReferenced(container);
-            if (showRef) showRef();
-        }
-    }
-
-    private static final boolean showRef = false;
-
-    private void showRef() {
-        Symbol sym;
-        if (referencedMember != null) {
-            if (referencedMember instanceof MethodDocImpl)
-                sym = ((MethodDocImpl) referencedMember).sym;
-            else if (referencedMember instanceof FieldDocImpl)
-                sym = ((FieldDocImpl) referencedMember).sym;
-            else
-                sym = ((ConstructorDocImpl) referencedMember).sym;
-        } else if (referencedClass != null) {
-            sym = ((ClassDocImpl) referencedClass).tsym;
-        } else if (referencedPackage != null) {
-            sym = ((PackageDocImpl) referencedPackage).sym;
-        } else
-            return;
-
-        final JavacMessages messages = JavacMessages.instance(docenv().context);
-        Locale locale = Locale.getDefault();
-        Printer printer = new Printer() {
-            int count;
-            @Override
-            protected String localize(Locale locale, String key, Object... args) {
-                return messages.getLocalizedString(locale, key, args);
-            }
-            @Override
-            protected String capturedVarId(CapturedType t, Locale locale) {
-                return "CAP#" + (++count);
-            }
-        };
-
-        String s = text.replaceAll("\\s+", " ");  // normalize white space
-        int sp = s.indexOf(" ");
-        int lparen = s.indexOf("(");
-        int rparen = s.indexOf(")");
-        String seetext = (sp == -1) ? s
-                : (lparen == -1 || sp < lparen) ? s.substring(0, sp)
-                : s.substring(0, rparen + 1);
-
-        File file = new File(holder.position().file().getAbsoluteFile().toURI().normalize());
-
-        StringBuilder sb = new StringBuilder();
-        sb.append("+++ ").append(file).append(": ")
-                .append(name()).append(" ").append(seetext).append(": ");
-        sb.append(sym.getKind()).append(" ");
-        if (sym.kind == MTH || sym.kind == VAR)
-            sb.append(printer.visit(sym.owner, locale)).append(".");
-        sb.append(printer.visit(sym, locale));
-
-        System.err.println(sb);
-    }
-
-    /**
-     * get the class name part of @see, For instance,
-     * if the comment is @see String#startsWith(java.lang.String) .
-     *      This function returns String.
-     * Returns null if format was not that of java reference.
-     * Return empty string if class name was not specified..
-     */
-    public String referencedClassName() {
-        return where;
-    }
-
-    /**
-     * get the package referenced by  @see. For instance,
-     * if the comment is @see java.lang
-     *      This function returns a PackageDocImpl for java.lang
-     * Returns null if no known package found.
-     */
-    public PackageDoc referencedPackage() {
-        return referencedPackage;
-    }
-
-    /**
-     * get the class referenced by the class name part of @see, For instance,
-     * if the comment is @see String#startsWith(java.lang.String) .
-     *      This function returns a ClassDocImpl for java.lang.String.
-     * Returns null if class is not a class specified on the javadoc command line..
-     */
-    public ClassDoc referencedClass() {
-        return referencedClass;
-    }
-
-    /**
-     * get the name of the member referenced by the prototype part of @see,
-     * For instance,
-     * if the comment is @see String#startsWith(java.lang.String) .
-     *      This function returns "startsWith(java.lang.String)"
-     * Returns null if format was not that of java reference.
-     * Return empty string if member name was not specified..
-     */
-    public String referencedMemberName() {
-        return what;
-    }
-
-    /**
-     * get the member referenced by the prototype part of @see,
-     * For instance,
-     * if the comment is @see String#startsWith(java.lang.String) .
-     *      This function returns a MethodDocImpl for startsWith.
-     * Returns null if member could not be determined.
-     */
-    public MemberDoc referencedMember() {
-        return referencedMember;
-    }
-
-
-    /**
-     * parse @see part of comment. Determine 'where' and 'what'
-     */
-    private void parseSeeString() {
-        int len = text.length();
-        if (len == 0) {
-            return;
-        }
-        switch (text.charAt(0)) {
-            case '<':
-                if (text.charAt(len-1) != '>') {
-                    docenv().warning(holder,
-                                     "tag.see.no_close_bracket_on_url",
-                                     name, text);
-                }
-                return;
-            case '"':
-                if (len == 1 || text.charAt(len-1) != '"') {
-                    docenv().warning(holder,
-                                     "tag.see.no_close_quote",
-                                     name, text);
-                } else {
-//                    text = text.substring(1,len-1); // strip quotes
-                }
-                return;
-        }
-
-        // check that the text is one word, with possible parentheses
-        // this part of code doesn't allow
-        // @see <a href=.....>asfd</a>
-        // comment it.
-
-        // the code assumes that there is no initial white space.
-        int parens = 0;
-        int commentstart = 0;
-        int start = 0;
-        int cp;
-        for (int i = start; i < len ; i += Character.charCount(cp)) {
-            cp = text.codePointAt(i);
-            switch (cp) {
-                case '(': parens++; break;
-                case ')': parens--; break;
-                case '[': case ']': case '.': case '#': break;
-                case ',':
-                    if (parens <= 0) {
-                        docenv().warning(holder,
-                                         "tag.see.malformed_see_tag",
-                                         name, text);
-                        return;
-                    }
-                    break;
-                case ' ': case '\t': case '\n': case CR:
-                    if (parens == 0) { //here onwards the comment starts.
-                        commentstart = i;
-                        i = len;
-                    }
-                    break;
-                default:
-                    if (!Character.isJavaIdentifierPart(cp)) {
-                        docenv().warning(holder,
-                                         "tag.see.illegal_character",
-                                         name, ""+cp, text);
-                    }
-                    break;
-            }
-        }
-        if (parens != 0) {
-            docenv().warning(holder,
-                             "tag.see.malformed_see_tag",
-                             name, text);
-            return;
-        }
-
-        String seetext = "";
-        String labeltext = "";
-
-        if (commentstart > 0) {
-            seetext = text.substring(start, commentstart);
-            labeltext = text.substring(commentstart + 1);
-            // strip off the white space which can be between seetext and the
-            // actual label.
-            for (int i = 0; i < labeltext.length(); i++) {
-                char ch2 = labeltext.charAt(i);
-                if (!(ch2 == ' ' || ch2 == '\t' || ch2 == '\n')) {
-                    label = labeltext.substring(i);
-                    break;
-                }
-            }
-        } else {
-            seetext = text;
-            label = "";
-        }
-
-        int sharp = seetext.indexOf('#');
-        if (sharp >= 0) {
-            // class#member
-            where = seetext.substring(0, sharp);
-            what = seetext.substring(sharp + 1);
-        } else {
-            if (seetext.indexOf('(') >= 0) {
-                docenv().warning(holder,
-                                 "tag.see.missing_sharp",
-                                 name, text);
-                where = "";
-                what = seetext;
-            }
-            else {
-                // no member specified, text names class
-                where = seetext;
-                what = null;
-            }
-        }
-    }
-
-    /**
-     * Find what is referenced by the see also.  If possible, sets
-     * referencedClass and referencedMember.
-     *
-     * @param containingClass the class containing the comment containing
-     * the tag. May be null, if, for example, it is a package comment.
-     */
-    private void findReferenced(ClassDocImpl containingClass) {
-        if (where.length() > 0) {
-            if (containingClass != null) {
-                referencedClass = containingClass.findClass(where);
-            } else {
-                referencedClass = docenv().lookupClass(where);
-            }
-            if (referencedClass == null && holder() instanceof ProgramElementDoc) {
-                referencedClass = docenv().lookupClass(
-                    ((ProgramElementDoc) holder()).containingPackage().name() + "." + where);
-            }
-
-            if (referencedClass == null) { /* may just not be in this run */
-                // check if it's a package name
-                referencedPackage = docenv().lookupPackage(where);
-                return;
-            }
-        } else {
-            if (containingClass == null) {
-                docenv().warning(holder,
-                                 "tag.see.class_not_specified",
-                                 name, text);
-                return;
-            } else {
-                referencedClass = containingClass;
-            }
-        }
-        where = referencedClass.qualifiedName();
-
-        if (what == null) {
-            return;
-        } else {
-            int paren = what.indexOf('(');
-            String memName = (paren >= 0 ? what.substring(0, paren) : what);
-            String[] paramarr;
-            if (paren > 0) {
-                // has parameter list -- should be method or constructor
-                paramarr = new ParameterParseMachine(what.
-                        substring(paren, what.length())).parseParameters();
-                if (paramarr != null) {
-                    referencedMember = findExecutableMember(memName, paramarr,
-                                                            referencedClass);
-                } else {
-                    referencedMember = null;
-                }
-            } else {
-                // no parameter list -- should be field
-                referencedMember = findExecutableMember(memName, null,
-                                                        referencedClass);
-                FieldDoc fd = ((ClassDocImpl)referencedClass).
-                                                            findField(memName);
-                // when no args given, prefer fields over methods
-                if (referencedMember == null ||
-                    (fd != null &&
-                     fd.containingClass()
-                         .subclassOf(referencedMember.containingClass()))) {
-                    referencedMember = fd;
-                }
-            }
-            if (referencedMember == null) {
-                docenv().warning(holder,
-                                 "tag.see.can_not_find_member",
-                                 name, what, where);
-            }
-        }
-    }
-
-    private MemberDoc findReferencedMethod(String memName, String[] paramarr,
-                                           ClassDoc referencedClass) {
-        MemberDoc meth = findExecutableMember(memName, paramarr, referencedClass);
-        if (meth == null) {
-            for (ClassDoc nestedClass : referencedClass.innerClasses()) {
-                meth = findReferencedMethod(memName, paramarr, nestedClass);
-                if (meth != null) {
-                    return meth;
-                }
-            }
-        }
-        return null;
-    }
-
-    private MemberDoc findExecutableMember(String memName, String[] paramarr,
-                                           ClassDoc referencedClass) {
-        String className = referencedClass.name();
-        if (memName.equals(className.substring(className.lastIndexOf(".") + 1))) {
-            return ((ClassDocImpl)referencedClass).findConstructor(memName,
-                                                                   paramarr);
-        } else {   // it's a method.
-            return ((ClassDocImpl)referencedClass).findMethod(memName,
-                                                              paramarr);
-        }
-    }
-
-    // separate "int, String" from "(int, String)"
-    // (int i, String s) ==> [0] = "int",  [1] = String
-    // (int[][], String[]) ==> [0] = "int[][]" // [1] = "String[]"
-    class ParameterParseMachine {
-        static final int START = 0;
-        static final int TYPE = 1;
-        static final int NAME = 2;
-        static final int TNSPACE = 3;  // space between type and name
-        static final int ARRAYDECORATION = 4;
-        static final int ARRAYSPACE = 5;
-
-        String parameters;
-
-        StringBuilder typeId;
-
-        ListBuffer<String> paramList;
-
-        ParameterParseMachine(String parameters) {
-            this.parameters = parameters;
-            this.paramList = new ListBuffer<>();
-            typeId = new StringBuilder();
-        }
-
-        public String[] parseParameters() {
-            if (parameters.equals("()")) {
-                return new String[0];
-            }   // now strip off '(' and ')'
-            int state = START;
-            int prevstate = START;
-            parameters = parameters.substring(1, parameters.length() - 1);
-            int cp;
-            for (int index = 0; index < parameters.length(); index += Character.charCount(cp)) {
-                cp = parameters.codePointAt(index);
-                switch (state) {
-                    case START:
-                        if (Character.isJavaIdentifierStart(cp)) {
-                            typeId.append(Character.toChars(cp));
-                            state = TYPE;
-                        }
-                        prevstate = START;
-                        break;
-                    case TYPE:
-                        if (Character.isJavaIdentifierPart(cp) || cp == '.') {
-                            typeId.append(Character.toChars(cp));
-                        } else if (cp == '[') {
-                            typeId.append('[');
-                            state = ARRAYDECORATION;
-                        } else if (Character.isWhitespace(cp)) {
-                            state = TNSPACE;
-                        } else if (cp == ',') {  // no name, just type
-                            addTypeToParamList();
-                            state = START;
-                        }
-                        prevstate = TYPE;
-                        break;
-                    case TNSPACE:
-                        if (Character.isJavaIdentifierStart(cp)) { // name
-                            if (prevstate == ARRAYDECORATION) {
-                                docenv().warning(holder,
-                                                 "tag.missing_comma_space",
-                                                 name,
-                                                 "(" + parameters + ")");
-                                return (String[])null;
-                            }
-                            addTypeToParamList();
-                            state = NAME;
-                        } else if (cp == '[') {
-                            typeId.append('[');
-                            state = ARRAYDECORATION;
-                        } else if (cp == ',') {   // just the type
-                            addTypeToParamList();
-                            state = START;
-                        } // consume rest all
-                        prevstate = TNSPACE;
-                        break;
-                    case ARRAYDECORATION:
-                        if (cp == ']') {
-                            typeId.append(']');
-                            state = TNSPACE;
-                        } else if (!Character.isWhitespace(cp)) {
-                            docenv().warning(holder,
-                                             "tag.illegal_char_in_arr_dim",
-                                             name,
-                                             "(" + parameters + ")");
-                            return (String[])null;
-                        }
-                        prevstate = ARRAYDECORATION;
-                        break;
-                    case NAME:
-                        if (cp == ',') {  // just consume everything till ','
-                            state = START;
-                        }
-                        prevstate = NAME;
-                        break;
-                }
-            }
-            if (state == ARRAYDECORATION ||
-                (state == START && prevstate == TNSPACE)) {
-                docenv().warning(holder,
-                                 "tag.illegal_see_tag",
-                                 "(" + parameters + ")");
-            }
-            if (typeId.length() > 0) {
-                paramList.append(typeId.toString());
-            }
-            return paramList.toArray(new String[paramList.length()]);
-        }
-
-        void addTypeToParamList() {
-            if (typeId.length() > 0) {
-                paramList.append(typeId.toString());
-                typeId.setLength(0);
-            }
-        }
-    }
-
-    /**
-     * Return the kind of this tag.
-     */
-    @Override
-    public String kind() {
-        return "@see";
-    }
-
-    /**
-     * Return the label of the see tag.
-     */
-    public String label() {
-        return label;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SerialFieldTagImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,267 +0,0 @@
-/*
- * Copyright (c) 1998, 2012, 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.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-/**
- * Documents a Serializable field defined by an ObjectStreamField.
- * <pre>
- * The class parses and stores the three serialField tag parameters:
- *
- * - field name
- * - field type name
- *      (fully-qualified or visible from the current import context)
- * - description of the valid values for the field
-
- * </pre>
- * This tag is only allowed in the javadoc for the special member
- * serialPersistentFields.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Joe Fialli
- * @author Neal Gafter
- *
- * @see java.io.ObjectStreamField
- */
-class SerialFieldTagImpl
-    extends TagImpl
-    implements SerialFieldTag, Comparable<Object>
-{
-    //### These could be final, except that the constructor
-    //### does not set them directly.
-
-    private String fieldName;    // Required Argument 1 of serialField
-    private String fieldType;    // Required Argument 2 of serialField
-    private String description;  // Optional Remaining Arguments of serialField
-
-    private ClassDoc containingClass;   // Class containing serialPersistentField member
-    private ClassDoc fieldTypeDoc;      // ClassDocImpl of fieldType
-    private FieldDocImpl matchingField; // FieldDocImpl with same name as fieldName
-
-   /* Constructor. */
-   SerialFieldTagImpl(DocImpl holder, String name, String text) {
-        super(holder, name, text);
-        parseSerialFieldString();
-        if (holder instanceof MemberDoc) {
-            containingClass = ((MemberDocImpl)holder).containingClass();
-        }
-    }
-
-    /*
-     * The serialField tag is composed of three entities.
-     *
-     *   serialField  serializableFieldName serisliableFieldType
-     *                 description of field.
-     *
-     * The fieldName and fieldType must be legal Java Identifiers.
-     */
-    private void parseSerialFieldString() {
-        int len = text.length();
-        if (len == 0) {
-            return;
-        }
-
-        // if no white space found
-        /* Skip white space. */
-        int inx = 0;
-        int cp;
-        for (; inx < len; inx += Character.charCount(cp)) {
-             cp = text.codePointAt(inx);
-             if (!Character.isWhitespace(cp)) {
-                 break;
-             }
-        }
-
-        /* find first word. */
-        int first = inx;
-        int last = inx;
-        cp = text.codePointAt(inx);
-        if (! Character.isJavaIdentifierStart(cp)) {
-            docenv().warning(holder,
-                             "tag.serialField.illegal_character",
-                             new String(Character.toChars(cp)), text);
-            return;
-        }
-
-        for (inx += Character.charCount(cp); inx < len; inx += Character.charCount(cp)) {
-             cp = text.codePointAt(inx);
-             if (!Character.isJavaIdentifierPart(cp)) {
-                 break;
-             }
-        }
-
-        if (inx < len && ! Character.isWhitespace(cp = text.codePointAt(inx))) {
-            docenv().warning(holder,
-                             "tag.serialField.illegal_character",
-                             new String(Character.toChars(cp)), text);
-            return;
-        }
-
-        last = inx;
-        fieldName = text.substring(first, last);
-
-        /* Skip white space. */
-        for (; inx < len; inx += Character.charCount(cp)) {
-             cp = text.codePointAt(inx);
-             if (!Character.isWhitespace(cp)) {
-                 break;
-             }
-        }
-
-        /* find second word. */
-        first = inx;
-        last = inx;
-
-        for (; inx < len; inx += Character.charCount(cp)) {
-             cp = text.codePointAt(inx);
-             if (Character.isWhitespace(cp)) {
-                 break;
-             }
-        }
-        if (inx < len && ! Character.isWhitespace(cp = text.codePointAt(inx))) {
-            docenv().warning(holder,
-                             "tag.serialField.illegal_character",
-                             new String(Character.toChars(cp)), text);
-            return;
-        }
-        last = inx;
-        fieldType = text.substring(first, last);
-
-        /* Skip leading white space. Rest of string is description for serialField.*/
-        for (; inx < len; inx += Character.charCount(cp)) {
-             cp = text.codePointAt(inx);
-             if (!Character.isWhitespace(cp)) {
-                 break;
-             }
-        }
-        description = text.substring(inx);
-    }
-
-    /**
-     * return a key for sorting.
-     */
-    String key() {
-        return fieldName;
-    }
-
-    /*
-     * Optional. Link this serialField tag to its corrsponding
-     * field in the class. Note: there is no requirement that
-     * there be a field in the class that matches serialField tag.
-     */
-    void mapToFieldDocImpl(FieldDocImpl fd) {
-        matchingField = fd;
-    }
-
-    /**
-     * Return the serialziable field name.
-     */
-    public String fieldName() {
-        return fieldName;
-    }
-
-    /**
-     * Return the field type string.
-     */
-    public String fieldType() {
-        return fieldType;
-    }
-
-    /**
-     * Return the ClassDocImpl for field type.
-     *
-     * @returns null if no ClassDocImpl for field type is visible from
-     *          containingClass context.
-     */
-    public ClassDoc fieldTypeDoc() {
-        if (fieldTypeDoc == null && containingClass != null) {
-            fieldTypeDoc = containingClass.findClass(fieldType);
-        }
-        return fieldTypeDoc;
-    }
-
-    /**
-     * Return the corresponding FieldDocImpl for this SerialFieldTagImpl.
-     *
-     * @returns null if no matching FieldDocImpl.
-     */
-    FieldDocImpl getMatchingField() {
-        return matchingField;
-    }
-
-    /**
-     * Return the field comment. If there is no serialField comment, return
-     * javadoc comment of corresponding FieldDocImpl.
-     */
-    public String description() {
-        if (description.length() == 0 && matchingField != null) {
-
-            //check for javadoc comment of corresponding field.
-            Comment comment = matchingField.comment();
-            if (comment != null) {
-                return comment.commentText();
-            }
-        }
-        return description;
-    }
-
-    /**
-     * Return the kind of this tag.
-     */
-    public String kind() {
-        return "@serialField";
-    }
-
-    /**
-     * Convert this object to a string.
-     */
-    public String toString() {
-        return name + ":" + text;
-    }
-
-    /**
-     * Compares this Object with the specified Object for order.  Returns a
-     * negative integer, zero, or a positive integer as this Object is less
-     * than, equal to, or greater than the given Object.
-     * <p>
-     * Included to make SerialFieldTagImpl items java.lang.Comparable.
-     *
-     * @param   obj the <code>Object</code> to be compared.
-     * @return  a negative integer, zero, or a positive integer as this Object
-     *          is less than, equal to, or greater than the given Object.
-     * @exception ClassCastException the specified Object's type prevents it
-     *            from being compared to this Object.
-     * @since 1.2
-     */
-    public int compareTo(Object obj) {
-        return key().compareTo(((SerialFieldTagImpl)obj).key());
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SerializedForm.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,287 +0,0 @@
-/*
- * Copyright (c) 1998, 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 com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.MethodSymbol;
-import com.sun.tools.javac.code.Symbol.VarSymbol;
-import com.sun.tools.javac.util.*;
-
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
-
-/**
- * The serialized form is the specification of a class' serialization
- * state. <p>
- *
- * It consists of the following information:<p>
- *
- * <pre>
- * 1. Whether class is Serializable or Externalizable.
- * 2. Javadoc for serialization methods.
- *    a. For Serializable, the optional readObject, writeObject,
- *       readResolve and writeReplace.
- *       serialData tag describes, in prose, the sequence and type
- *       of optional data written by writeObject.
- *    b. For Externalizable, writeExternal and readExternal.
- *       serialData tag describes, in prose, the sequence and type
- *       of optional data written by writeExternal.
- * 3. Javadoc for serialization data layout.
- *    a. For Serializable, the name,type and description
- *       of each Serializable fields.
- *    b. For Externalizable, data layout is described by 2(b).
- * </pre>
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since 1.2
- * @author Joe Fialli
- * @author Neal Gafter (rewrite but not too proud)
- */
-class SerializedForm {
-    ListBuffer<MethodDoc> methods = new ListBuffer<>();
-
-    /* List of FieldDocImpl - Serializable fields.
-     * Singleton list if class defines Serializable fields explicitly.
-     * Otherwise, list of default serializable fields.
-     * 0 length list for Externalizable.
-     */
-    private final ListBuffer<FieldDocImpl> fields = new ListBuffer<>();
-
-    /* True if class specifies serializable fields explicitly.
-     * using special static member, serialPersistentFields.
-     */
-    private boolean definesSerializableFields = false;
-
-    // Specially treated field/method names defined by Serialization.
-    private static final String SERIALIZABLE_FIELDS = "serialPersistentFields";
-    private static final String READOBJECT  = "readObject";
-    private static final String WRITEOBJECT = "writeObject";
-    private static final String READRESOLVE  = "readResolve";
-    private static final String WRITEREPLACE = "writeReplace";
-    private static final String READOBJECTNODATA = "readObjectNoData";
-
-    /**
-     * Constructor.
-     *
-     * Catalog Serializable fields for Serializable class.
-     * Catalog serialization methods for Serializable and
-     * Externalizable classes.
-     */
-    SerializedForm(DocEnv env, ClassSymbol def, ClassDocImpl cd) {
-        if (cd.isExternalizable()) {
-            /* look up required public accessible methods,
-             *   writeExternal and readExternal.
-             */
-            String[] readExternalParamArr = { "java.io.ObjectInput" };
-            String[] writeExternalParamArr = { "java.io.ObjectOutput" };
-            MethodDoc md = cd.findMethod("readExternal", readExternalParamArr);
-            if (md != null) {
-                methods.append(md);
-            }
-            md = cd.findMethod("writeExternal", writeExternalParamArr);
-            if (md != null) {
-                methods.append(md);
-                Tag tag[] = md.tags("serialData");
-            }
-        // } else { // isSerializable() //### ???
-        } else if (cd.isSerializable()) {
-
-            VarSymbol dsf = getDefinedSerializableFields(def);
-            if (dsf != null) {
-
-                /* Define serializable fields with array of ObjectStreamField.
-                 * Each ObjectStreamField should be documented by a
-                 * serialField tag.
-                 */
-                definesSerializableFields = true;
-                //### No modifier filtering applied here.
-                FieldDocImpl dsfDoc = env.getFieldDoc(dsf);
-                fields.append(dsfDoc);
-                mapSerialFieldTagImplsToFieldDocImpls(dsfDoc, env, def);
-            } else {
-
-                /* Calculate default Serializable fields as all
-                 * non-transient, non-static fields.
-                 * Fields should be documented by serial tag.
-                 */
-                computeDefaultSerializableFields(env, def, cd);
-            }
-
-           /* Check for optional customized readObject, writeObject,
-            * readResolve and writeReplace, which can all contain
-            * the serialData tag.        */
-            addMethodIfExist(env, def, READOBJECT);
-            addMethodIfExist(env, def, WRITEOBJECT);
-            addMethodIfExist(env, def, READRESOLVE);
-            addMethodIfExist(env, def, WRITEREPLACE);
-            addMethodIfExist(env, def, READOBJECTNODATA);
-        }
-    }
-
-    /*
-     * Check for explicit Serializable fields.
-     * Check for a private static array of ObjectStreamField with
-     * name SERIALIZABLE_FIELDS.
-     */
-    private VarSymbol getDefinedSerializableFields(ClassSymbol def) {
-        Names names = def.name.table.names;
-
-        /* SERIALIZABLE_FIELDS can be private,
-         * so must lookup by ClassSymbol, not by ClassDocImpl.
-         */
-        for (Symbol sym : def.members().getSymbolsByName(names.fromString(SERIALIZABLE_FIELDS))) {
-            if (sym.kind == VAR) {
-                VarSymbol f = (VarSymbol)sym;
-                if ((f.flags() & Flags.STATIC) != 0 &&
-                    (f.flags() & Flags.PRIVATE) != 0) {
-                    return f;
-                }
-            }
-        }
-        return null;
-    }
-
-    /*
-     * Compute default Serializable fields from all members of ClassSymbol.
-     *
-     * Since the fields of ClassDocImpl might not contain private or
-     * package accessible fields, must walk over all members of ClassSymbol.
-     */
-    private void computeDefaultSerializableFields(DocEnv env,
-                                                  ClassSymbol def,
-                                                  ClassDocImpl cd) {
-        for (Symbol sym : def.members().getSymbols(NON_RECURSIVE)) {
-            if (sym != null && sym.kind == VAR) {
-                VarSymbol f = (VarSymbol)sym;
-                if ((f.flags() & Flags.STATIC) == 0 &&
-                    (f.flags() & Flags.TRANSIENT) == 0) {
-                    //### No modifier filtering applied here.
-                    FieldDocImpl fd = env.getFieldDoc(f);
-                    //### Add to beginning.
-                    //### Preserve order used by old 'javadoc'.
-                    fields.prepend(fd);
-                }
-            }
-        }
-    }
-
-    /*
-     * Catalog Serializable method if it exists in current ClassSymbol.
-     * Do not look for method in superclasses.
-     *
-     * Serialization requires these methods to be non-static.
-     *
-     * @param method should be an unqualified Serializable method
-     *               name either READOBJECT, WRITEOBJECT, READRESOLVE
-     *               or WRITEREPLACE.
-     * @param visibility the visibility flag for the given method.
-     */
-    private void addMethodIfExist(DocEnv env, ClassSymbol def, String methodName) {
-        Names names = def.name.table.names;
-
-        for (Symbol sym : def.members().getSymbolsByName(names.fromString(methodName))) {
-            if (sym.kind == MTH) {
-                MethodSymbol md = (MethodSymbol)sym;
-                if ((md.flags() & Flags.STATIC) == 0) {
-                    /*
-                     * WARNING: not robust if unqualifiedMethodName is overloaded
-                     *          method. Signature checking could make more robust.
-                     * READOBJECT takes a single parameter, java.io.ObjectInputStream.
-                     * WRITEOBJECT takes a single parameter, java.io.ObjectOutputStream.
-                     */
-                    methods.append(env.getMethodDoc(md));
-                }
-            }
-        }
-    }
-
-    /*
-     * Associate serialField tag fieldName with FieldDocImpl member.
-     * Note: A serialField tag does not have to map an existing field
-     *       of a class.
-     */
-    private void mapSerialFieldTagImplsToFieldDocImpls(FieldDocImpl spfDoc,
-                                                       DocEnv env,
-                                                       ClassSymbol def) {
-        Names names = def.name.table.names;
-        for (SerialFieldTag tag : spfDoc.serialFieldTags()) {
-            if (tag.fieldName() == null || tag.fieldType() == null) // ignore malformed @serialField tags
-                continue;
-
-            Name fieldName = names.fromString(tag.fieldName());
-
-            // Look for a FieldDocImpl that is documented by serialFieldTagImpl.
-            for (Symbol sym : def.members().getSymbolsByName(fieldName)) {
-                if (sym.kind == VAR) {
-                    VarSymbol f = (VarSymbol) sym;
-                    FieldDocImpl fdi = env.getFieldDoc(f);
-                    ((SerialFieldTagImpl) (tag)).mapToFieldDocImpl(fdi);
-                    break;
-                }
-            }
-        }
-    }
-
-    /**
-     * Return serializable fields in class. <p>
-     *
-     * Returns either a list of default fields documented by serial tag comment or
-     *         javadoc comment<p>
-     * Or Returns a single FieldDocImpl for serialPersistentField. There is a
-     *         serialField tag for each serializable field.<p>
-     *
-     * @return an array of FieldDocImpl for representing the visible
-     *         fields in this class.
-     */
-    FieldDoc[] fields() {
-        return (FieldDoc[])fields.toArray(new FieldDocImpl[fields.length()]);
-    }
-
-    /**
-     * Return serialization methods in class.
-     *
-     * @return an array of MethodDocImpl for serialization methods in this class.
-     */
-    MethodDoc[] methods() {
-        return methods.toArray(new MethodDoc[methods.length()]);
-    }
-
-    /**
-     * Returns true if Serializable fields are defined explicitly using
-     * member, serialPersistentFields.
-     *
-     * @see #fields()
-     */
-    boolean definesSerializableFields() {
-        return definesSerializableFields;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2001, 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 com.sun.tools.javadoc;
-
-import java.io.File;
-import javax.tools.FileObject;
-
-import com.sun.javadoc.SourcePosition;
-import com.sun.tools.javac.util.Position;
-
-/**
- * A source position: filename, line number, and column number.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since J2SE1.4
- * @author Neal M Gafter
- * @author Michael Van De Vanter (position representation changed to char offsets)
- */
-public class SourcePositionImpl implements SourcePosition {
-    FileObject filename;
-    int position;
-    Position.LineMap lineMap;
-
-    /** The source file. Returns null if no file information is
-     *  available. */
-    public File file() {
-        return (filename == null) ? null : new File(filename.getName());
-    }
-
-    /** The source file. Returns null if no file information is
-     *  available. */
-    public FileObject fileObject() {
-        return filename;
-    }
-
-    /** The line in the source file. The first line is numbered 1;
-     *  0 means no line number information is available. */
-    public int line() {
-        if (lineMap == null) {
-            return 0;
-        } else {
-            return lineMap.getLineNumber(position);
-        }
-    }
-
-    /** The column in the source file. The first column is
-     *  numbered 1; 0 means no column information is available.
-     *  Columns count characters in the input stream; a tab
-     *  advances the column number to the next 8-column tab stop.
-     */
-    public int column() {
-        if (lineMap == null) {
-            return 0;
-        }else {
-            return lineMap.getColumnNumber(position);
-        }
-    }
-
-    private SourcePositionImpl(FileObject file, int position,
-                               Position.LineMap lineMap) {
-        super();
-        this.filename = file;
-        this.position = position;
-        this.lineMap = lineMap;
-    }
-
-    public static SourcePosition make(FileObject file, int pos,
-                                      Position.LineMap lineMap) {
-        if (file == null) return null;
-        return new SourcePositionImpl(file, pos, lineMap);
-    }
-
-    public String toString() {
-        // Backwards compatibility hack. ZipFileObjects use the format
-        // zipfile(zipentry) but javadoc has been using zipfile/zipentry
-        String fn = filename.getName();
-        if (fn.endsWith(")")) {
-            int paren = fn.lastIndexOf("(");
-            if (paren != -1) {
-                int i = paren+1;
-                if (fn.charAt(i) == '/')
-                    i++;
-                fn = fn.substring(0, paren)
-                        + File.separatorChar
-                        + fn.substring(i, fn.length() - 1);
-            }
-        }
-
-        if (position == Position.NOPOS)
-            return fn;
-        else
-            return fn + ":" + line();
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,557 +0,0 @@
-/*
- * 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
- * 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.sun.tools.javadoc;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Objects;
-
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.StandardLocation;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.file.JavacFileManager;
-import com.sun.tools.javac.main.CommandLine;
-import com.sun.tools.javac.main.Option;
-import com.sun.tools.javac.file.BaseFileManager;
-import com.sun.tools.javac.platform.PlatformDescription;
-import com.sun.tools.javac.platform.PlatformUtils;
-import com.sun.tools.javac.util.ClientCodeException;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Log;
-import com.sun.tools.javac.util.Options;
-
-import static com.sun.tools.javac.code.Flags.*;
-
-/**
- * Main program of Javadoc.
- * Previously named "Main".
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @since 1.2
- * @author Robert Field
- * @author Neal Gafter (rewrite)
- */
-public class Start extends ToolOption.Helper {
-    /** Context for this invocation. */
-    private final Context context;
-
-    private final String defaultDocletClassName;
-    private final ClassLoader docletParentClassLoader;
-
-    private static final String javadocName = "javadoc";
-
-    private static final String standardDocletClassName =
-        "com.sun.tools.doclets.standard.Standard";
-
-    private final long defaultFilter = PUBLIC | PROTECTED;
-
-    private final Messager messager;
-
-    private DocletInvoker docletInvoker;
-
-    /**
-     * In API mode, exceptions thrown while calling the doclet are
-     * propagated using ClientCodeException.
-     */
-    private boolean apiMode;
-
-    private JavaFileManager fileManager;
-
-    Start(String programName,
-          PrintWriter errWriter,
-          PrintWriter warnWriter,
-          PrintWriter noticeWriter,
-          String defaultDocletClassName) {
-        this(programName, errWriter, warnWriter, noticeWriter, defaultDocletClassName, null);
-    }
-
-    public Start(PrintWriter pw) {
-        this(javadocName, pw, pw, pw, standardDocletClassName);
-    }
-
-    public Start(String programName,
-          PrintWriter errWriter,
-          PrintWriter warnWriter,
-          PrintWriter noticeWriter,
-          String defaultDocletClassName,
-          ClassLoader docletParentClassLoader) {
-        context = new Context();
-        messager = new Messager(context, programName, errWriter, warnWriter, noticeWriter);
-        this.defaultDocletClassName = defaultDocletClassName;
-        this.docletParentClassLoader = docletParentClassLoader;
-    }
-
-    Start(String programName, String defaultDocletClassName) {
-        this(programName, defaultDocletClassName, null);
-    }
-
-    Start(String programName, String defaultDocletClassName,
-          ClassLoader docletParentClassLoader) {
-        context = new Context();
-        messager = new Messager(context, programName);
-        this.defaultDocletClassName = defaultDocletClassName;
-        this.docletParentClassLoader = docletParentClassLoader;
-    }
-
-    Start(String programName, ClassLoader docletParentClassLoader) {
-        this(programName, standardDocletClassName, docletParentClassLoader);
-    }
-
-    Start(String programName) {
-        this(programName, standardDocletClassName);
-    }
-
-    Start(ClassLoader docletParentClassLoader) {
-        this(javadocName, docletParentClassLoader);
-    }
-
-    public Start() {
-        this(javadocName);
-    }
-
-    public Start(Context context) {
-        this.context = Objects.requireNonNull(context);
-        apiMode = true;
-        defaultDocletClassName = standardDocletClassName;
-        docletParentClassLoader = null;
-
-        Log log = context.get(Log.logKey);
-        if (log instanceof Messager)
-            messager = (Messager) log;
-        else {
-            PrintWriter out = context.get(Log.outKey);
-            messager = (out == null) ? new Messager(context, javadocName)
-                    : new Messager(context, javadocName, out, out, out);
-        }
-    }
-
-    /**
-     * Usage
-     */
-    @Override
-    void usage() {
-        usage(true);
-    }
-
-    void usage(boolean exit) {
-        usage("main.usage", "-help", null, exit);
-    }
-
-    @Override
-    void Xusage() {
-        Xusage(true);
-    }
-
-    void Xusage(boolean exit) {
-        usage("main.Xusage", "-X", "main.Xusage.foot", exit);
-    }
-
-    private void usage(String main, String doclet, String foot, boolean exit) {
-        // RFE: it would be better to replace the following with code to
-        // write a header, then help for each option, then a footer.
-        messager.notice(main);
-
-        // let doclet print usage information (does nothing on error)
-        if (docletInvoker != null) {
-            // RFE: this is a pretty bad way to get the doclet to show
-            // help info. Moreover, the output appears on stdout,
-            // and <i>not</i> on any of the standard streams passed
-            // to javadoc, and in particular, not to the noticeWriter
-            // But, to fix this, we need to fix the Doclet API.
-            docletInvoker.optionLength(doclet);
-        }
-
-        if (foot != null)
-            messager.notice(foot);
-
-        if (exit) exit();
-    }
-
-    /**
-     * Exit
-     */
-    private void exit() {
-        messager.exit();
-    }
-
-
-    /**
-     * Main program - external wrapper
-     */
-    public int begin(String... argv) {
-        boolean ok = begin(null, argv, Collections.<JavaFileObject> emptySet());
-        return ok ? 0 : 1;
-    }
-
-    public boolean begin(Class<?> docletClass, Iterable<String> options, Iterable<? extends JavaFileObject> fileObjects) {
-        Collection<String> opts = new ArrayList<>();
-        for (String opt: options) opts.add(opt);
-        return begin(docletClass, opts.toArray(new String[opts.size()]), fileObjects);
-    }
-
-    private boolean begin(Class<?> docletClass, String[] options, Iterable<? extends JavaFileObject> fileObjects) {
-        boolean failed = false;
-
-        try {
-            failed = !parseAndExecute(docletClass, options, fileObjects);
-        } catch (Messager.ExitJavadoc exc) {
-            // ignore, we just exit this way
-        } catch (OutOfMemoryError ee) {
-            messager.error(Messager.NOPOS, "main.out.of.memory");
-            failed = true;
-        } catch (ClientCodeException e) {
-            // simply rethrow these exceptions, to be caught and handled by JavadocTaskImpl
-            throw e;
-        } catch (Error ee) {
-            ee.printStackTrace(System.err);
-            messager.error(Messager.NOPOS, "main.fatal.error");
-            failed = true;
-        } catch (Exception ee) {
-            ee.printStackTrace(System.err);
-            messager.error(Messager.NOPOS, "main.fatal.exception");
-            failed = true;
-        } finally {
-            if (fileManager != null
-                    && fileManager instanceof BaseFileManager
-                    && ((BaseFileManager) fileManager).autoClose) {
-                try {
-                    fileManager.close();
-                } catch (IOException ignore) {
-                }
-            }
-            messager.exitNotice();
-            messager.flush();
-        }
-        failed |= messager.nerrors() > 0;
-        failed |= rejectWarnings && messager.nwarnings() > 0;
-        return !failed;
-    }
-
-    /**
-     * Main program - internal
-     */
-    private boolean parseAndExecute(
-            Class<?> docletClass,
-            String[] argv,
-            Iterable<? extends JavaFileObject> fileObjects) throws IOException {
-        long tm = System.currentTimeMillis();
-
-        ListBuffer<String> javaNames = new ListBuffer<>();
-
-        // Preprocess @file arguments
-        try {
-            argv = CommandLine.parse(argv);
-        } catch (FileNotFoundException e) {
-            messager.error(Messager.NOPOS, "main.cant.read", e.getMessage());
-            exit();
-        } catch (IOException e) {
-            e.printStackTrace(System.err);
-            exit();
-        }
-
-
-        fileManager = context.get(JavaFileManager.class);
-
-        setDocletInvoker(docletClass, fileManager, argv);
-
-        compOpts = Options.instance(context);
-        // Make sure no obsolete source/target messages are reported
-        compOpts.put("-Xlint:-options", "-Xlint:-options");
-
-        // Parse arguments
-        for (int i = 0 ; i < argv.length ; i++) {
-            String arg = argv[i];
-
-            ToolOption o = ToolOption.get(arg);
-            if (o != null) {
-                // hack: this restriction should be removed
-                if (o == ToolOption.LOCALE && i > 0)
-                    usageError("main.locale_first");
-
-                if (o.hasArg) {
-                    oneArg(argv, i++);
-                    o.process(this, argv[i]);
-                } else {
-                    setOption(arg);
-                    o.process(this);
-                }
-            } else if (arg.equals("-XDaccessInternalAPI")) {
-                // pass this hidden option down to the doclet, if it wants it
-                if (docletInvoker.optionLength("-XDaccessInternalAPI") == 1) {
-                    setOption(arg);
-                }
-            } else if (arg.startsWith("-XD")) {
-                // hidden javac options
-                String s = arg.substring("-XD".length());
-                int eq = s.indexOf('=');
-                String key = (eq < 0) ? s : s.substring(0, eq);
-                String value = (eq < 0) ? s : s.substring(eq+1);
-                compOpts.put(key, value);
-            }
-            // call doclet for its options
-            // other arg starts with - is invalid
-            else if (arg.startsWith("-")) {
-                int optionLength;
-                optionLength = docletInvoker.optionLength(arg);
-                if (optionLength < 0) {
-                    // error already displayed
-                    exit();
-                } else if (optionLength == 0) {
-                    // option not found
-                    usageError("main.invalid_flag", arg);
-                } else {
-                    // doclet added option
-                    if ((i + optionLength) > argv.length) {
-                        usageError("main.requires_argument", arg);
-                    }
-                    ListBuffer<String> args = new ListBuffer<>();
-                    for (int j = 0; j < optionLength-1; ++j) {
-                        args.append(argv[++i]);
-                    }
-                    setOption(arg, args.toList());
-                }
-            } else {
-                javaNames.append(arg);
-            }
-        }
-
-        if (fileManager == null) {
-            JavacFileManager.preRegister(context);
-            fileManager = context.get(JavaFileManager.class);
-            if (fileManager instanceof BaseFileManager) {
-                ((BaseFileManager) fileManager).autoClose = true;
-            }
-        }
-        if (fileManager instanceof BaseFileManager) {
-            ((BaseFileManager) fileManager).handleOptions(fileManagerOpts);
-        }
-
-        String platformString = compOpts.get("-release");
-
-        if (platformString != null) {
-            if (compOpts.isSet("-source")) {
-                usageError("main.release.bootclasspath.conflict", "-source");
-            }
-            if (fileManagerOpts.containsKey(Option.BOOTCLASSPATH)) {
-                usageError("main.release.bootclasspath.conflict", Option.BOOTCLASSPATH.getText());
-            }
-
-            PlatformDescription platformDescription =
-                    PlatformUtils.lookupPlatformDescription(platformString);
-
-            if (platformDescription == null) {
-                usageError("main.unsupported.release.version", platformString);
-            }
-
-            compOpts.put(Option.SOURCE, platformDescription.getSourceVersion());
-
-            context.put(PlatformDescription.class, platformDescription);
-
-            Collection<Path> platformCP = platformDescription.getPlatformPath();
-
-            if (platformCP != null) {
-                if (fileManager instanceof StandardJavaFileManager) {
-                    StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
-
-                    sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP);
-                } else {
-                    usageError("main.release.not.standard.file.manager", platformString);
-                }
-            }
-        }
-
-        compOpts.notifyListeners();
-
-        if (javaNames.isEmpty() && subPackages.isEmpty() && isEmpty(fileObjects)) {
-            usageError("main.No_packages_or_classes_specified");
-        }
-
-        if (!docletInvoker.validOptions(options.toList())) {
-            // error message already displayed
-            exit();
-        }
-
-        JavadocTool comp = JavadocTool.make0(context);
-        if (comp == null) return false;
-
-        if (showAccess == null) {
-            setFilter(defaultFilter);
-        }
-
-        LanguageVersion languageVersion = docletInvoker.languageVersion();
-        RootDocImpl root = comp.getRootDocImpl(
-                docLocale,
-                encoding,
-                showAccess,
-                javaNames.toList(),
-                options.toList(),
-                fileObjects,
-                breakiterator,
-                subPackages.toList(),
-                excludedPackages.toList(),
-                docClasses,
-                // legacy?
-                languageVersion == null || languageVersion == LanguageVersion.JAVA_1_1,
-                quiet);
-
-        // release resources
-        comp = null;
-
-        // pass off control to the doclet
-        boolean ok = root != null;
-        if (ok) ok = docletInvoker.start(root);
-
-        // We're done.
-        if (compOpts.get("-verbose") != null) {
-            tm = System.currentTimeMillis() - tm;
-            messager.notice("main.done_in", Long.toString(tm));
-        }
-
-        return ok;
-    }
-
-    private <T> boolean isEmpty(Iterable<T> iter) {
-        return !iter.iterator().hasNext();
-    }
-
-    /**
-     * Init the doclet invoker.
-     * The doclet class may be given explicitly, or via the -doclet option in
-     * argv.
-     * If the doclet class is not given explicitly, it will be loaded from
-     * the file manager's DOCLET_PATH location, if available, or via the
-     * -doclet path option in argv.
-     * @param docletClass The doclet class. May be null.
-     * @param fileManager The file manager used to get the class loader to load
-     * the doclet class if required. May be null.
-     * @param argv Args containing -doclet and -docletpath, in case they are required.
-     */
-    private void setDocletInvoker(Class<?> docletClass, JavaFileManager fileManager, String[] argv) {
-        boolean exportInternalAPI = false;
-        String docletClassName = null;
-        String docletPath = null;
-
-        // Parse doclet specifying arguments
-        for (int i = 0 ; i < argv.length ; i++) {
-            String arg = argv[i];
-            if (arg.equals(ToolOption.DOCLET.opt)) {
-                oneArg(argv, i++);
-                if (docletClassName != null) {
-                    usageError("main.more_than_one_doclet_specified_0_and_1",
-                               docletClassName, argv[i]);
-                }
-                docletClassName = argv[i];
-            } else if (arg.equals(ToolOption.DOCLETPATH.opt)) {
-                oneArg(argv, i++);
-                if (docletPath == null) {
-                    docletPath = argv[i];
-                } else {
-                    docletPath += File.pathSeparator + argv[i];
-                }
-            } else if (arg.equals("-XDaccessInternalAPI")) {
-                exportInternalAPI = true;
-            }
-        }
-
-        if (docletClass != null) {
-            // TODO, check no -doclet, -docletpath
-            docletInvoker = new DocletInvoker(messager, docletClass, apiMode, exportInternalAPI);
-        } else {
-            if (docletClassName == null) {
-                docletClassName = defaultDocletClassName;
-            }
-
-            // attempt to find doclet
-            docletInvoker = new DocletInvoker(messager, fileManager,
-                    docletClassName, docletPath,
-                    docletParentClassLoader,
-                    apiMode,
-                    exportInternalAPI);
-        }
-    }
-
-    /**
-     * Set one arg option.
-     * Error and exit if one argument is not provided.
-     */
-    private void oneArg(String[] args, int index) {
-        if ((index + 1) < args.length) {
-            setOption(args[index], args[index+1]);
-        } else {
-            usageError("main.requires_argument", args[index]);
-        }
-    }
-
-    @Override
-    void usageError(String key, Object... args) {
-        messager.error(Messager.NOPOS, key, args);
-        usage(true);
-    }
-
-    /**
-     * indicate an option with no arguments was given.
-     */
-    private void setOption(String opt) {
-        String[] option = { opt };
-        options.append(option);
-    }
-
-    /**
-     * indicate an option with one argument was given.
-     */
-    private void setOption(String opt, String argument) {
-        String[] option = { opt, argument };
-        options.append(option);
-    }
-
-    /**
-     * indicate an option with the specified list of arguments was given.
-     */
-    private void setOption(String opt, List<String> arguments) {
-        String[] args = new String[arguments.length() + 1];
-        int k = 0;
-        args[k++] = opt;
-        for (List<String> i = arguments; i.nonEmpty(); i=i.tail) {
-            args[k++] = i.head;
-        }
-        options.append(args);
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TagImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-/**
- * Represents a documentation tag, e.g. @since, @author, @version.
- * Given a tag (e.g. "@since 1.2"), holds tag name (e.g. "@since")
- * and tag text (e.g. "1.2").  TagImpls with structure or which require
- * special processing are handled by subclasses (ParamTagImpl, SeeTagImpl,
- * and ThrowsTagImpl
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Robert Field
- * @author Atul M Dambalkar
- * @author Neal M Gafter
- * @see SeeTagImpl
- * @see ParamTagImpl
- * @see ThrowsTagImpl
- * @see Doc#tags()
- *
- */
-class TagImpl implements Tag {
-
-    protected final String text;
-    protected final String name;
-    protected final DocImpl holder;
-
-    /**
-     * Cached first sentence.
-     */
-    private Tag[] firstSentence;
-
-    /**
-     * Cached inline tags.
-     */
-    private Tag[] inlineTags;
-
-    /**
-     *  Constructor
-     */
-    TagImpl(DocImpl holder, String name, String text) {
-        this.holder = holder;
-        this.name = name;
-        this.text = text;
-    }
-
-    /**
-     * Return the name of this tag.
-     */
-    public String name() {
-        return name;
-    }
-
-    /**
-     * Return the containing {@link Doc} of this Tag element.
-     */
-    public Doc holder() {
-        return holder;
-    }
-
-    /**
-     * Return the kind of this tag.
-     */
-    public String kind() {
-        return name;
-    }
-
-    /**
-     * Return the text of this tag, that is, portion beyond tag name.
-     */
-    public String text() {
-        return text;
-    }
-
-    DocEnv docenv() {
-        return holder.env;
-    }
-
-    /**
-     * for use by subclasses which have two part tag text.
-     */
-    String[] divideAtWhite() {
-        String[] sa = new String[2];
-        int len = text.length();
-        // if no white space found
-        sa[0] = text;
-        sa[1] = "";
-        for (int inx = 0; inx < len; ++inx) {
-            char ch = text.charAt(inx);
-            if (Character.isWhitespace(ch)) {
-                sa[0] = text.substring(0, inx);
-                for (; inx < len; ++inx) {
-                    ch = text.charAt(inx);
-                    if (!Character.isWhitespace(ch)) {
-                        sa[1] = text.substring(inx, len);
-                        break;
-                    }
-                }
-                break;
-            }
-        }
-        return sa;
-    }
-
-    /**
-     * convert this object to a string.
-     */
-    public String toString() {
-        return name + ":" + text;
-    }
-
-    /**
-     * For documentation comment with embedded @link tags, return the array of
-     * TagImpls consisting of SeeTagImpl(s) and text containing TagImpl(s).
-     * Within a comment string "This is an example of inline tags for a
-     * documentation comment {@link Doc {@link Doc commentlabel}}",
-     * where inside the inner braces, the first "Doc" carries exctly the same
-     * syntax as a SeeTagImpl and the second "commentlabel" is label for the Html
-     * Link, will return an array of TagImpl(s) with first element as TagImpl with
-     * comment text "This is an example of inline tags for a documentation
-     * comment" and second element as SeeTagImpl with referenced class as "Doc"
-     * and the label for the Html Link as "commentlabel".
-     *
-     * @return TagImpl[] Array of tags with inline SeeTagImpls.
-     * @see ParamTagImpl
-     * @see ThrowsTagImpl
-     */
-    public Tag[] inlineTags() {
-        if (inlineTags == null) {
-            inlineTags = Comment.getInlineTags(holder, text);
-        }
-        return inlineTags;
-    }
-
-    /**
-     * Return array of tags for the first sentence in the doc comment text.
-     */
-    public Tag[] firstSentenceTags() {
-        if (firstSentence == null) {
-            //Parse all sentences first to avoid duplicate warnings.
-            inlineTags();
-            try {
-                docenv().setSilent(true);
-                firstSentence = Comment.firstSentenceTags(holder, text);
-            } finally {
-                docenv().setSilent(false);
-            }
-        }
-        return firstSentence;
-    }
-
-    /**
-     * Return the doc item to which this tag is attached.
-     * @return the doc item to which this tag is attached.
-     */
-    public SourcePosition position() {
-        return holder.position();
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ThrowsTagImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-/**
- * Represents a @throws or @exception documentation tag.
- * Parses and holds the exception name and exception comment.
- * The exception name my be the name of a type variable.
- * Note: @exception is a backwards compatible synonymy for @throws.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Robert Field
- * @author Atul M Dambalkar
- * @see ExecutableMemberDocImpl#throwsTags()
- *
- */
-class ThrowsTagImpl extends TagImpl implements ThrowsTag {
-
-    private final String exceptionName;
-    private final String exceptionComment;
-
-    /**
-     * Cached inline tags.
-     */
-    private Tag[] inlineTags;
-
-    ThrowsTagImpl(DocImpl holder, String name, String text) {
-        super(holder, name, text);
-        String[] sa = divideAtWhite();
-        exceptionName = sa[0];
-        exceptionComment = sa[1];
-    }
-
-    /**
-     * Return the exception name.
-     */
-    public String exceptionName() {
-        return exceptionName;
-    }
-
-    /**
-     * Return the exception comment.
-     */
-    public String exceptionComment() {
-        return exceptionComment;
-    }
-
-    /**
-     * Return the exception as a ClassDocImpl.
-     */
-    public ClassDoc exception() {
-        ClassDocImpl exceptionClass;
-        if (!(holder instanceof ExecutableMemberDoc)) {
-            exceptionClass = null;
-        } else {
-            ExecutableMemberDocImpl emd = (ExecutableMemberDocImpl)holder;
-            ClassDocImpl con = (ClassDocImpl)emd.containingClass();
-            exceptionClass = (ClassDocImpl)con.findClass(exceptionName);
-        }
-        return exceptionClass;
-    }
-
-    /**
-     * Return the type that represents the exception.
-     * This may be a <code>ClassDoc</code> or a <code>TypeVariable</code>.
-     */
-    public Type exceptionType() {
-        //###(gj) TypeVariable not yet supported.
-        return exception();
-    }
-
-
-    /**
-     * Return the kind of this tag.  Always "@throws" for instances
-     * of ThrowsTagImpl.
-     */
-    @Override
-    public String kind() {
-        return "@throws";
-    }
-
-    /**
-     * For the exception comment with embedded @link tags return the array of
-     * TagImpls consisting of SeeTagImpl(s) and text containing TagImpl(s).
-     *
-     * @return TagImpl[] Array of tags with inline SeeTagImpls.
-     * @see TagImpl#inlineTags()
-     * @see ParamTagImpl#inlineTags()
-     */
-    @Override
-    public Tag[] inlineTags() {
-        if (inlineTags == null) {
-            inlineTags = Comment.getInlineTags(holder, exceptionComment());
-        }
-        return inlineTags;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,392 +0,0 @@
-/*
- * 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
- * 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.sun.tools.javadoc;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.main.Option;
-import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Options;
-
-
-/**
- * javadoc tool options.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- */
-public enum ToolOption {
-    // ----- options for underlying compiler -----
-
-    BOOTCLASSPATH("-bootclasspath", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setFileManagerOpt(Option.BOOTCLASSPATH, arg);
-        }
-    },
-
-    CLASSPATH("-classpath", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setFileManagerOpt(Option.CLASSPATH, arg);
-        }
-    },
-
-    CP("-cp", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setFileManagerOpt(Option.CP, arg);
-        }
-    },
-
-    EXTDIRS("-extdirs", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setFileManagerOpt(Option.EXTDIRS, arg);
-        }
-    },
-
-    SOURCEPATH("-sourcepath", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setFileManagerOpt(Option.SOURCEPATH, arg);
-        }
-    },
-
-    SYSCLASSPATH("-sysclasspath", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setFileManagerOpt(Option.BOOTCLASSPATH, arg);
-        }
-    },
-
-    MODULESOURCEPATH("-modulesourcepath", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setFileManagerOpt(Option.MODULESOURCEPATH, arg);
-        }
-    },
-
-    UPGRADEMODULEPATH("-upgrademodulepath", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setFileManagerOpt(Option.UPGRADEMODULEPATH, arg);
-        }
-    },
-
-    SYSTEM("-system", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setFileManagerOpt(Option.SYSTEM, arg);
-        }
-    },
-
-    MODULEPATH("-modulepath", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setFileManagerOpt(Option.MODULEPATH, arg);
-        }
-    },
-
-    ADDMODS("-addmods", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
-        }
-    },
-
-    LIMITMODS("-limitmods", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
-        }
-    },
-
-    ENCODING("-encoding", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.encoding = arg;
-            helper.setCompilerOpt(opt, arg);
-        }
-    },
-
-    RELEASE("-release", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
-        }
-    },
-
-    SOURCE("-source", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
-        }
-    },
-
-    XMAXERRS("-Xmaxerrs", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
-        }
-    },
-
-    XMAXWARNS("-Xmaxwarns", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
-        }
-    },
-
-    // ----- doclet options -----
-
-    DOCLET("-doclet", true), // handled in setDocletInvoker
-
-    DOCLETPATH("-docletpath", true), // handled in setDocletInvoker
-
-    // ----- selection options -----
-
-    SUBPACKAGES("-subpackages", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.addToList(helper.subPackages, arg);
-        }
-    },
-
-    EXCLUDE("-exclude", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.addToList(helper.excludedPackages, arg);
-        }
-    },
-
-    // ----- filtering options -----
-
-    PACKAGE("-package") {
-        @Override
-        public void process(Helper helper) {
-            helper.setFilter(
-                    Flags.PUBLIC | Flags.PROTECTED | ModifierFilter.PACKAGE);
-        }
-    },
-
-    PRIVATE("-private") {
-        @Override
-        public void process(Helper helper) {
-            helper.setFilter(ModifierFilter.ALL_ACCESS);
-        }
-    },
-
-    PROTECTED("-protected") {
-        @Override
-        public void process(Helper helper) {
-            helper.setFilter(Flags.PUBLIC | Flags.PROTECTED);
-        }
-    },
-
-    PUBLIC("-public") {
-        @Override
-        public void process(Helper helper) {
-            helper.setFilter(Flags.PUBLIC);
-        }
-    },
-
-    // ----- output control options -----
-
-    PROMPT("-prompt") {
-        @Override
-        public void process(Helper helper) {
-            helper.compOpts.put("-prompt", "-prompt");
-            helper.promptOnError = true;
-        }
-    },
-
-    QUIET("-quiet") {
-        @Override
-        public void process(Helper helper) {
-            helper.quiet = true;
-        }
-    },
-
-    VERBOSE("-verbose") {
-        @Override
-        public void process(Helper helper) {
-            helper.compOpts.put("-verbose", "");
-        }
-    },
-
-    XWERROR("-Xwerror") {
-        @Override
-        public void process(Helper helper) {
-            helper.rejectWarnings = true;
-
-        }
-    },
-
-    // ----- other options -----
-
-    BREAKITERATOR("-breakiterator") {
-        @Override
-        public void process(Helper helper) {
-            helper.breakiterator = true;
-        }
-    },
-
-    LOCALE("-locale", true) {
-        @Override
-        public void process(Helper helper, String arg) {
-            helper.docLocale = arg;
-        }
-    },
-
-    OVERVIEW("-overview", true),
-
-    XCLASSES("-Xclasses") {
-        @Override
-        public void process(Helper helper) {
-            helper.docClasses = true;
-
-        }
-    },
-
-    // ----- help options -----
-
-    HELP("-help") {
-        @Override
-        public void process(Helper helper) {
-            helper.usage();
-        }
-    },
-
-    X("-X") {
-        @Override
-        public void process(Helper helper) {
-            helper.Xusage();
-        }
-    };
-
-    public final String opt;
-    public final boolean hasArg;
-
-    ToolOption(String opt) {
-        this(opt, false);
-    }
-
-    ToolOption(String opt, boolean hasArg) {
-        this.opt = opt;
-        this.hasArg = hasArg;
-    }
-
-    void process(Helper helper, String arg) { }
-
-    void process(Helper helper) { }
-
-    static ToolOption get(String name) {
-        for (ToolOption o: values()) {
-            if (name.equals(o.opt))
-                return o;
-        }
-        return null;
-    }
-
-    static abstract class Helper {
-        /** List of decoded options. */
-        final ListBuffer<String[]> options = new ListBuffer<>();
-
-        /** Selected packages, from -subpackages. */
-        final ListBuffer<String> subPackages = new ListBuffer<>();
-
-        /** Excluded packages, from -exclude. */
-        final ListBuffer<String> excludedPackages = new ListBuffer<>();
-
-        // File manager options
-        final Map<Option, String> fileManagerOpts = new LinkedHashMap<>();
-
-        /** javac options, set by various options. */
-        Options compOpts; // = Options.instance(context)
-
-        /* Encoding for javac, and files written? set by -encoding. */
-        String encoding = null;
-
-        /** Set by -breakiterator. */
-        boolean breakiterator = false;
-
-        /** Set by -quiet. */
-        boolean quiet = false;
-
-        /** Set by -Xclasses. */
-        boolean docClasses = false;
-
-        /** Set by -Xwerror. */
-        boolean rejectWarnings = false;
-
-        /** Set by -prompt. */
-        boolean promptOnError;
-
-        /** Set by -locale. */
-        String docLocale = "";
-
-        /** Set by -public, private, -protected, -package. */
-        ModifierFilter showAccess = null;
-
-        abstract void usage();
-        abstract void Xusage();
-
-        abstract void usageError(String msg, Object... args);
-
-        void addToList(ListBuffer<String> list, String str){
-            StringTokenizer st = new StringTokenizer(str, ":");
-            String current;
-            while(st.hasMoreTokens()){
-                current = st.nextToken();
-                list.append(current);
-            }
-        }
-
-        void setFilter(long filterBits) {
-            if (showAccess != null) {
-                usageError("main.incompatible.access.flags");
-            }
-            showAccess = new ModifierFilter(filterBits);
-        }
-
-        void setCompilerOpt(String opt, String arg) {
-            if (compOpts.get(opt) != null) {
-                usageError("main.option.already.seen", opt);
-            }
-            compOpts.put(opt, arg);
-        }
-
-        void setFileManagerOpt(Option opt, String arg) {
-            fileManagerOpts.put(opt, arg);
-        }
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TypeMaker.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,350 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.CompletionFailure;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.ArrayType;
-import com.sun.tools.javac.code.Type.ClassType;
-import com.sun.tools.javac.code.Type.TypeVar;
-import com.sun.tools.javac.util.List;
-import static com.sun.tools.javac.code.TypeTag.ARRAY;
-
-/**
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- */
-public class TypeMaker {
-
-    public static com.sun.javadoc.Type getType(DocEnv env, Type t) {
-        return getType(env, t, true);
-    }
-
-    /**
-     * @param errToClassDoc  if true, ERROR type results in a ClassDoc;
-     *          false preserves legacy behavior
-     */
-    public static com.sun.javadoc.Type getType(DocEnv env, Type t,
-            boolean errorToClassDoc) {
-        return getType(env, t, errorToClassDoc, true);
-    }
-
-    public static com.sun.javadoc.Type getType(DocEnv env, Type t,
-            boolean errToClassDoc, boolean considerAnnotations) {
-        try {
-            return getTypeImpl(env, t, errToClassDoc, considerAnnotations);
-        } catch (CompletionFailure cf) {
-            /* Quietly ignore completion failures and try again - the type
-             * for which the CompletionFailure was thrown shouldn't be completed
-             * again by the completer that threw the CompletionFailure.
-             */
-            return getType(env, t, errToClassDoc, considerAnnotations);
-        }
-    }
-
-    @SuppressWarnings("fallthrough")
-    private static com.sun.javadoc.Type getTypeImpl(DocEnv env, Type t,
-            boolean errToClassDoc, boolean considerAnnotations) {
-        if (env.legacyDoclet) {
-            t = env.types.erasure(t);
-        }
-
-        if (considerAnnotations && t.isAnnotated()) {
-            return new AnnotatedTypeImpl(env, t);
-        }
-
-        switch (t.getTag()) {
-        case CLASS:
-            if (ClassDocImpl.isGeneric((ClassSymbol)t.tsym)) {
-                return env.getParameterizedType((ClassType)t);
-            } else {
-                return env.getClassDoc((ClassSymbol)t.tsym);
-            }
-        case WILDCARD:
-            Type.WildcardType a = (Type.WildcardType)t;
-            return new WildcardTypeImpl(env, a);
-        case TYPEVAR: return new TypeVariableImpl(env, (TypeVar)t);
-        case ARRAY: return new ArrayTypeImpl(env, t);
-        case BYTE: return PrimitiveType.byteType;
-        case CHAR: return PrimitiveType.charType;
-        case SHORT: return PrimitiveType.shortType;
-        case INT: return PrimitiveType.intType;
-        case LONG: return PrimitiveType.longType;
-        case FLOAT: return PrimitiveType.floatType;
-        case DOUBLE: return PrimitiveType.doubleType;
-        case BOOLEAN: return PrimitiveType.booleanType;
-        case VOID: return PrimitiveType.voidType;
-        case ERROR:
-            if (errToClassDoc)
-                return env.getClassDoc((ClassSymbol)t.tsym);
-            // FALLTHRU
-        default:
-            return new PrimitiveType(t.tsym.getQualifiedName().toString());
-        }
-    }
-
-    /**
-     * Convert a list of javac types into an array of javadoc types.
-     */
-    public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts) {
-        return getTypes(env, ts, new com.sun.javadoc.Type[ts.length()]);
-    }
-
-    /**
-     * Like the above version, but use and return the array given.
-     */
-    public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts,
-                                                  com.sun.javadoc.Type res[]) {
-        int i = 0;
-        for (Type t : ts) {
-            res[i++] = getType(env, t);
-        }
-        return res;
-    }
-
-    public static String getTypeName(Type t, boolean full) {
-        switch (t.getTag()) {
-        case ARRAY:
-            StringBuilder s = new StringBuilder();
-            while (t.hasTag(ARRAY)) {
-                s.append("[]");
-                t = ((ArrayType)t).elemtype;
-            }
-            s.insert(0, getTypeName(t, full));
-            return s.toString();
-        case CLASS:
-            return ClassDocImpl.getClassName((ClassSymbol)t.tsym, full);
-        default:
-            return t.tsym.getQualifiedName().toString();
-        }
-    }
-
-    /**
-     * Return the string representation of a type use.  Bounds of type
-     * variables are not included; bounds of wildcard types are.
-     * Class names are qualified if "full" is true.
-     */
-    static String getTypeString(DocEnv env, Type t, boolean full) {
-        // TODO: should annotations be included here?
-        switch (t.getTag()) {
-        case ARRAY:
-            StringBuilder s = new StringBuilder();
-            while (t.hasTag(ARRAY)) {
-                s.append("[]");
-                t = env.types.elemtype(t);
-            }
-            s.insert(0, getTypeString(env, t, full));
-            return s.toString();
-        case CLASS:
-            return ParameterizedTypeImpl.
-                        parameterizedTypeToString(env, (ClassType)t, full);
-        case WILDCARD:
-            Type.WildcardType a = (Type.WildcardType)t;
-            return WildcardTypeImpl.wildcardTypeToString(env, a, full);
-        default:
-            return t.tsym.getQualifiedName().toString();
-        }
-    }
-
-    /**
-     * Return the formal type parameters of a class or method as an
-     * angle-bracketed string.  Each parameter is a type variable with
-     * optional bounds.  Class names are qualified if "full" is true.
-     * Return "" if there are no type parameters or we're hiding generics.
-     */
-    static String typeParametersString(DocEnv env, Symbol sym, boolean full) {
-        if (env.legacyDoclet || sym.type.getTypeArguments().isEmpty()) {
-            return "";
-        }
-        StringBuilder s = new StringBuilder();
-        for (Type t : sym.type.getTypeArguments()) {
-            s.append(s.length() == 0 ? "<" : ", ");
-            s.append(TypeVariableImpl.typeVarToString(env, (TypeVar)t, full));
-        }
-        s.append(">");
-        return s.toString();
-    }
-
-    /**
-     * Return the actual type arguments of a parameterized type as an
-     * angle-bracketed string.  Class name are qualified if "full" is true.
-     * Return "" if there are no type arguments or we're hiding generics.
-     */
-    static String typeArgumentsString(DocEnv env, ClassType cl, boolean full) {
-        if (env.legacyDoclet || cl.getTypeArguments().isEmpty()) {
-            return "";
-        }
-        StringBuilder s = new StringBuilder();
-        for (Type t : cl.getTypeArguments()) {
-            s.append(s.length() == 0 ? "<" : ", ");
-            s.append(getTypeString(env, t, full));
-        }
-        s.append(">");
-        return s.toString();
-    }
-
-
-    private static class ArrayTypeImpl implements com.sun.javadoc.Type {
-
-        Type arrayType;
-
-        DocEnv env;
-
-        ArrayTypeImpl(DocEnv env, Type arrayType) {
-            this.env = env;
-            this.arrayType = arrayType;
-        }
-
-        private com.sun.javadoc.Type skipArraysCache = null;
-
-        public com.sun.javadoc.Type getElementType() {
-            return TypeMaker.getType(env, env.types.elemtype(arrayType));
-        }
-
-        private com.sun.javadoc.Type skipArrays() {
-            if (skipArraysCache == null) {
-                Type t;
-                for (t = arrayType; t.hasTag(ARRAY); t = env.types.elemtype(t)) { }
-                skipArraysCache = TypeMaker.getType(env, t);
-            }
-            return skipArraysCache;
-        }
-
-        /**
-         * Return the type's dimension information, as a string.
-         * <p>
-         * For example, a two dimensional array of String returns '[][]'.
-         */
-        public String dimension() {
-            StringBuilder dimension = new StringBuilder();
-            for (Type t = arrayType; t.hasTag(ARRAY); t = env.types.elemtype(t)) {
-                dimension.append("[]");
-            }
-            return dimension.toString();
-        }
-
-        /**
-         * Return unqualified name of type excluding any dimension information.
-         * <p>
-         * For example, a two dimensional array of String returns 'String'.
-         */
-        public String typeName() {
-            return skipArrays().typeName();
-        }
-
-        /**
-         * Return qualified name of type excluding any dimension information.
-         *<p>
-         * For example, a two dimensional array of String
-         * returns 'java.lang.String'.
-         */
-        public String qualifiedTypeName() {
-            return skipArrays().qualifiedTypeName();
-        }
-
-        /**
-         * Return the simple name of this type excluding any dimension information.
-         */
-        public String simpleTypeName() {
-            return skipArrays().simpleTypeName();
-        }
-
-        /**
-         * Return this type as a class.  Array dimensions are ignored.
-         *
-         * @return a ClassDocImpl if the type is a Class.
-         * Return null if it is a primitive type..
-         */
-        public ClassDoc asClassDoc() {
-            return skipArrays().asClassDoc();
-        }
-
-        /**
-         * Return this type as a <code>ParameterizedType</code> if it
-         * represents a parameterized type.  Array dimensions are ignored.
-         */
-        public ParameterizedType asParameterizedType() {
-            return skipArrays().asParameterizedType();
-        }
-
-        /**
-         * Return this type as a <code>TypeVariable</code> if it represents
-         * a type variable.  Array dimensions are ignored.
-         */
-        public TypeVariable asTypeVariable() {
-            return skipArrays().asTypeVariable();
-        }
-
-        /**
-         * Return null, as there are no arrays of wildcard types.
-         */
-        public WildcardType asWildcardType() {
-            return null;
-        }
-
-        /**
-         * Return null, as there are no annotations of the type
-         */
-        public AnnotatedType asAnnotatedType() {
-            return null;
-        }
-
-        /**
-         * Return this type as an <code>AnnotationTypeDoc</code> if it
-         * represents an annotation type.  Array dimensions are ignored.
-         */
-        public AnnotationTypeDoc asAnnotationTypeDoc() {
-            return skipArrays().asAnnotationTypeDoc();
-        }
-
-        /**
-         * Return true if this is an array of a primitive type.
-         */
-        public boolean isPrimitive() {
-            return skipArrays().isPrimitive();
-        }
-
-        /**
-         * Return a string representation of the type.
-         *
-         * Return name of type including any dimension information.
-         * <p>
-         * For example, a two dimensional array of String returns
-         * <code>String[][]</code>.
-         *
-         * @return name of type including any dimension information.
-         */
-        @Override
-        public String toString() {
-            return qualifiedTypeName() + dimension();
-        }
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.tools.javac.code.Attribute;
-import com.sun.tools.javac.code.Attribute.TypeCompound;
-import com.sun.tools.javac.code.Kinds;
-import com.sun.tools.javac.code.Kinds.KindSelector;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.MethodSymbol;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.TypeVar;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Names;
-
-/**
- * Implementation of <code>TypeVariable</code>, which
- * represents a type variable.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Scott Seligman
- * @since 1.5
- */
-public class TypeVariableImpl extends AbstractTypeImpl implements TypeVariable {
-
-    TypeVariableImpl(DocEnv env, TypeVar type) {
-        super(env, type);
-    }
-
-    /**
-     * Return the bounds of this type variable.
-     */
-    public com.sun.javadoc.Type[] bounds() {
-        return TypeMaker.getTypes(env, getBounds((TypeVar)type, env));
-    }
-
-    /**
-     * Return the class, interface, method, or constructor within
-     * which this type variable is declared.
-     */
-    public ProgramElementDoc owner() {
-        Symbol osym = type.tsym.owner;
-        if (osym.kind.matches(KindSelector.TYP)) {
-            return env.getClassDoc((ClassSymbol)osym);
-        }
-        Names names = osym.name.table.names;
-        if (osym.name == names.init) {
-            return env.getConstructorDoc((MethodSymbol)osym);
-        } else {
-            return env.getMethodDoc((MethodSymbol)osym);
-        }
-    }
-
-    /**
-     * Return the ClassDoc of the erasure of this type variable.
-     */
-    @Override
-    public ClassDoc asClassDoc() {
-        return env.getClassDoc((ClassSymbol)env.types.erasure(type).tsym);
-    }
-
-    @Override
-    public TypeVariable asTypeVariable() {
-        return this;
-    }
-
-    @Override
-    public String toString() {
-        return typeVarToString(env, (TypeVar)type, true);
-    }
-
-
-    /**
-     * Return the string form of a type variable along with any
-     * "extends" clause.  Class names are qualified if "full" is true.
-     */
-    static String typeVarToString(DocEnv env, TypeVar v, boolean full) {
-        StringBuilder s = new StringBuilder(v.toString());
-        List<Type> bounds = getBounds(v, env);
-        if (bounds.nonEmpty()) {
-            boolean first = true;
-            for (Type b : bounds) {
-                s.append(first ? " extends " : " & ");
-                s.append(TypeMaker.getTypeString(env, b, full));
-                first = false;
-            }
-        }
-        return s.toString();
-    }
-
-    /**
-     * Get the bounds of a type variable as listed in the "extends" clause.
-     */
-    private static List<Type> getBounds(TypeVar v, DocEnv env) {
-        final Type upperBound = v.getUpperBound();
-        Name boundname = upperBound.tsym.getQualifiedName();
-        if (boundname == boundname.table.names.java_lang_Object
-            && !upperBound.isAnnotated()) {
-            return List.nil();
-        } else {
-            return env.types.getBounds(v);
-        }
-    }
-
-    /**
-     * Get the annotations of this program element.
-     * Return an empty array if there are none.
-     */
-    public AnnotationDesc[] annotations() {
-        if (!type.isAnnotated()) {
-            return new AnnotationDesc[0];
-        }
-        List<? extends TypeCompound> tas = type.getAnnotationMirrors();
-        AnnotationDesc res[] = new AnnotationDesc[tas.length()];
-        int i = 0;
-        for (Attribute.Compound a : tas) {
-            res[i++] = new AnnotationDescImpl(env, a);
-        }
-        return res;
-    }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/WildcardTypeImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, 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.sun.tools.javadoc;
-
-import com.sun.javadoc.*;
-
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.util.List;
-
-
-/**
- * Implementation of <code>WildcardType</code>, which
- * represents a wildcard type.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Scott Seligman
- * @since 1.5
- */
-public class WildcardTypeImpl extends AbstractTypeImpl implements WildcardType {
-
-    WildcardTypeImpl(DocEnv env, Type.WildcardType type) {
-        super(env, type);
-    }
-
-    /**
-     * Return the upper bounds of this wildcard type argument
-     * as given by the <i>extends</i> clause.
-     * Return an empty array if no such bounds are explicitly given.
-     */
-    public com.sun.javadoc.Type[] extendsBounds() {
-        return TypeMaker.getTypes(env, getExtendsBounds((Type.WildcardType)type));
-    }
-
-    /**
-     * Return the lower bounds of this wildcard type argument
-     * as given by the <i>super</i> clause.
-     * Return an empty array if no such bounds are explicitly given.
-     */
-    public com.sun.javadoc.Type[] superBounds() {
-        return TypeMaker.getTypes(env, getSuperBounds((Type.WildcardType)type));
-    }
-
-    /**
-     * Return the ClassDoc of the erasure of this wildcard type.
-     */
-    @Override
-    public ClassDoc asClassDoc() {
-        return env.getClassDoc((ClassSymbol)env.types.erasure(type).tsym);
-    }
-
-    @Override
-    public WildcardType asWildcardType() {
-        return this;
-    }
-
-    @Override
-    public String typeName()            { return "?"; }
-    @Override
-    public String qualifiedTypeName()   { return "?"; }
-    @Override
-    public String simpleTypeName()      { return "?"; }
-
-    @Override
-    public String toString() {
-        return wildcardTypeToString(env, (Type.WildcardType)type, true);
-    }
-
-
-    /**
-     * Return the string form of a wildcard type ("?") along with any
-     * "extends" or "super" clause.  Delimiting brackets are not
-     * included.  Class names are qualified if "full" is true.
-     */
-    static String wildcardTypeToString(DocEnv env,
-                                       Type.WildcardType wildThing, boolean full) {
-        if (env.legacyDoclet) {
-            return TypeMaker.getTypeName(env.types.erasure(wildThing), full);
-        }
-        StringBuilder s = new StringBuilder("?");
-        List<Type> bounds = getExtendsBounds(wildThing);
-        if (bounds.nonEmpty()) {
-            s.append(" extends ");
-        } else {
-            bounds = getSuperBounds(wildThing);
-            if (bounds.nonEmpty()) {
-                s.append(" super ");
-            }
-        }
-        boolean first = true;   // currently only one bound is allowed
-        for (Type b : bounds) {
-            if (!first) {
-                s.append(" & ");
-            }
-            s.append(TypeMaker.getTypeString(env, b, full));
-            first = false;
-        }
-        return s.toString();
-    }
-
-    private static List<Type> getExtendsBounds(Type.WildcardType wild) {
-        return wild.isSuperBound()
-                ? List.<Type>nil()
-                : List.of(wild.type);
-    }
-
-    private static List<Type> getSuperBounds(Type.WildcardType wild) {
-        return wild.isExtendsBound()
-                ? List.<Type>nil()
-                : List.of(wild.type);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AbstractTypeImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.tools.javac.code.Type;
+
+
+/**
+ * Abstract implementation of <code>Type</code>, with useful
+ * defaults for the methods in <code>Type</code> (and a couple from
+ * <code>ProgramElementDoc</code>).
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Scott Seligman
+ * @since 1.5
+ */
+abstract class AbstractTypeImpl implements com.sun.javadoc.Type {
+
+    protected final DocEnv env;
+    protected final Type type;
+
+    protected AbstractTypeImpl(DocEnv env, Type type) {
+        this.env = env;
+        this.type = type;
+    }
+
+    public String typeName() {
+        return type.tsym.name.toString();
+    }
+
+    public String qualifiedTypeName() {
+        return type.tsym.getQualifiedName().toString();
+    }
+
+    public com.sun.javadoc.Type getElementType() {
+        return null;
+    }
+
+    public String simpleTypeName() {
+        return type.tsym.name.toString();
+    }
+
+    public String name() {
+        return typeName();
+    }
+
+    public String qualifiedName() {
+        return qualifiedTypeName();
+    }
+
+    public String toString() {
+        return qualifiedTypeName();
+    }
+
+    public String dimension() {
+        return "";
+    }
+
+    public boolean isPrimitive() {
+        return false;
+    }
+
+    public ClassDoc asClassDoc() {
+        return null;
+    }
+
+    public TypeVariable asTypeVariable() {
+        return null;
+    }
+
+    public WildcardType asWildcardType() {
+        return null;
+    }
+
+    public ParameterizedType asParameterizedType() {
+        return null;
+    }
+
+    public AnnotationTypeDoc asAnnotationTypeDoc() {
+        return null;
+    }
+
+    public AnnotatedType asAnnotatedType() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotatedTypeImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+import com.sun.tools.javac.code.Attribute;
+import com.sun.tools.javac.code.Attribute.TypeCompound;
+import com.sun.tools.javac.util.List;
+
+/**
+ * Implementation of <code>AnnotatedType</code>, which
+ * represents an annotated type.
+ *
+ * @author Mahmood Ali
+ * @since 1.8
+ */
+public class AnnotatedTypeImpl
+        extends AbstractTypeImpl implements AnnotatedType {
+
+    AnnotatedTypeImpl(DocEnv env, com.sun.tools.javac.code.Type type) {
+        super(env, type);
+    }
+
+    /**
+     * Get the annotations of this program element.
+     * Return an empty array if there are none.
+     */
+    @Override
+    public AnnotationDesc[] annotations() {
+        List<? extends TypeCompound> tas = type.getAnnotationMirrors();
+        if (tas == null ||
+                tas.isEmpty()) {
+            return new AnnotationDesc[0];
+        }
+        AnnotationDesc res[] = new AnnotationDesc[tas.length()];
+        int i = 0;
+        for (Attribute.Compound a : tas) {
+            res[i++] = new AnnotationDescImpl(env, a);
+        }
+        return res;
+    }
+
+    @Override
+    public com.sun.javadoc.Type underlyingType() {
+        return TypeMaker.getType(env, type, true, false);
+    }
+
+    @Override
+    public AnnotatedType asAnnotatedType() {
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return typeName();
+    }
+
+    @Override
+    public String typeName() {
+        return this.underlyingType().typeName();
+    }
+
+    @Override
+    public String qualifiedTypeName() {
+        return this.underlyingType().qualifiedTypeName();
+    }
+
+    @Override
+    public String simpleTypeName() {
+        return this.underlyingType().simpleTypeName();
+    }
+
+    @Override
+    public String dimension() {
+        return this.underlyingType().dimension();
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return this.underlyingType().isPrimitive();
+    }
+
+    @Override
+    public ClassDoc asClassDoc() {
+        return this.underlyingType().asClassDoc();
+    }
+
+    @Override
+    public TypeVariable asTypeVariable() {
+        return this.underlyingType().asTypeVariable();
+    }
+
+    @Override
+    public WildcardType asWildcardType() {
+        return this.underlyingType().asWildcardType();
+    }
+
+    @Override
+    public ParameterizedType asParameterizedType() {
+        return this.underlyingType().asParameterizedType();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationDescImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.tools.javac.code.Attribute;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Pair;
+
+
+/**
+ * Represents an annotation.
+ * An annotation associates a value with each element of an annotation type.
+ * Sure it ought to be called "Annotation", but that clashes with
+ * java.lang.annotation.Annotation.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Scott Seligman
+ * @since 1.5
+ */
+
+public class AnnotationDescImpl implements AnnotationDesc {
+
+    private final DocEnv env;
+    private final Attribute.Compound annotation;
+
+
+    AnnotationDescImpl(DocEnv env, Attribute.Compound annotation) {
+        this.env = env;
+        this.annotation = annotation;
+    }
+
+    /**
+     * Returns the annotation type of this annotation.
+     */
+    public AnnotationTypeDoc annotationType() {
+        ClassSymbol atsym = (ClassSymbol)annotation.type.tsym;
+        if (annotation.type.isErroneous()) {
+            env.warning(null, "javadoc.class_not_found", annotation.type.toString());
+            return new AnnotationTypeDocImpl(env, atsym);
+        } else {
+            return (AnnotationTypeDoc)env.getClassDoc(atsym);
+        }
+    }
+
+    /**
+     * Returns this annotation's elements and their values.
+     * Only those explicitly present in the annotation are
+     * included, not those assuming their default values.
+     * Returns an empty array if there are none.
+     */
+    public ElementValuePair[] elementValues() {
+        List<Pair<MethodSymbol,Attribute>> vals = annotation.values;
+        ElementValuePair res[] = new ElementValuePair[vals.length()];
+        int i = 0;
+        for (Pair<MethodSymbol,Attribute> val : vals) {
+            res[i++] = new ElementValuePairImpl(env, val.fst, val.snd);
+        }
+        return res;
+    }
+
+    /**
+     * Check for the synthesized bit on the annotation.
+     *
+     * @return true if the annotation is synthesized.
+     */
+    public boolean isSynthesized() {
+        return annotation.isSynthesized();
+    }
+
+    /**
+     * Returns a string representation of this annotation.
+     * String is of one of the forms:
+     * <pre>
+     *     {@code @com.example.foo(name1=val1, name2=val2)}
+     *     {@code @com.example.foo(val)}
+     *     {@code @com.example.foo}
+     * </pre>
+     * Omit parens for marker annotations, and omit "value=" when allowed.
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("@");
+        sb.append(annotation.type.tsym);
+
+        ElementValuePair vals[] = elementValues();
+        if (vals.length > 0) {          // omit parens for marker annotation
+            sb.append('(');
+            boolean first = true;
+            for (ElementValuePair val : vals) {
+                if (!first) {
+                    sb.append(", ");
+                }
+                first = false;
+
+                String name = val.element().name();
+                if (vals.length == 1 && name.equals("value")) {
+                    sb.append(val.value());
+                } else {
+                    sb.append(val);
+                }
+            }
+            sb.append(')');
+        }
+        return sb.toString();
+    }
+
+
+    /**
+     * Represents an association between an annotation type element
+     * and one of its values.
+     */
+    public static class ElementValuePairImpl implements ElementValuePair {
+
+        private final DocEnv env;
+        private final MethodSymbol meth;
+        private final Attribute value;
+
+        ElementValuePairImpl(DocEnv env, MethodSymbol meth, Attribute value) {
+            this.env = env;
+            this.meth = meth;
+            this.value = value;
+        }
+
+        /**
+         * Returns the annotation type element.
+         */
+        public AnnotationTypeElementDoc element() {
+            return env.getAnnotationTypeElementDoc(meth);
+        }
+
+        /**
+         * Returns the value associated with the annotation type element.
+         */
+        public AnnotationValue value() {
+            return new AnnotationValueImpl(env, value);
+        }
+
+        /**
+         * Returns a string representation of this pair
+         * of the form "name=value".
+         */
+        @Override
+        public String toString() {
+            return meth.name + "=" + value();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2003, 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 com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.util.List;
+
+import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
+
+import static com.sun.tools.javac.code.Kinds.Kind.*;
+
+/**
+ * Represents an annotation type.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Scott Seligman
+ * @since 1.5
+ */
+
+public class AnnotationTypeDocImpl
+        extends ClassDocImpl implements AnnotationTypeDoc {
+
+    public AnnotationTypeDocImpl(DocEnv env, ClassSymbol sym) {
+        this(env, sym, null);
+    }
+
+    public AnnotationTypeDocImpl(DocEnv env, ClassSymbol sym, TreePath treePath) {
+        super(env, sym, treePath);
+    }
+
+    /**
+     * Returns true, as this is an annotation type.
+     * (For legacy doclets, return false.)
+     */
+    public boolean isAnnotationType() {
+        return !isInterface();
+    }
+
+    /**
+     * Returns false.  Though technically an interface, an annotation
+     * type is not considered an interface for this purpose.
+     * (For legacy doclets, returns true.)
+     */
+    public boolean isInterface() {
+        return env.legacyDoclet;
+    }
+
+    /**
+     * Returns an empty array, as all methods are annotation type elements.
+     * (For legacy doclets, returns the elements.)
+     * @see #elements()
+     */
+    public MethodDoc[] methods(boolean filter) {
+        return env.legacyDoclet
+                ? (MethodDoc[])elements()
+                : new MethodDoc[0];
+    }
+
+    /**
+     * Returns the elements of this annotation type.
+     * Returns an empty array if there are none.
+     * Elements are always public, so no need to filter them.
+     */
+    public AnnotationTypeElementDoc[] elements() {
+        List<AnnotationTypeElementDoc> elements = List.nil();
+        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
+            if (sym != null && sym.kind == MTH) {
+                MethodSymbol s = (MethodSymbol)sym;
+                elements = elements.prepend(env.getAnnotationTypeElementDoc(s));
+            }
+        }
+        return
+            elements.toArray(new AnnotationTypeElementDoc[elements.length()]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationTypeElementDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Symbol.*;
+
+/**
+ * Represents an element of an annotation type.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Scott Seligman
+ * @since 1.5
+ */
+
+public class AnnotationTypeElementDocImpl
+        extends MethodDocImpl implements AnnotationTypeElementDoc {
+
+    public AnnotationTypeElementDocImpl(DocEnv env, MethodSymbol sym) {
+        super(env, sym);
+    }
+
+    public AnnotationTypeElementDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) {
+        super(env, sym, treePath);
+    }
+
+    /**
+     * Returns true, as this is an annotation type element.
+     * (For legacy doclets, return false.)
+     */
+    public boolean isAnnotationTypeElement() {
+        return !isMethod();
+    }
+
+    /**
+     * Returns false.  Although this is technically a method, we don't
+     * consider it one for this purpose.
+     * (For legacy doclets, return true.)
+     */
+    public boolean isMethod() {
+        return env.legacyDoclet;
+    }
+
+    /**
+     * Returns false, even though this is indeed abstract.  See
+     * MethodDocImpl.isAbstract() for the (il)logic behind this.
+     */
+    public boolean isAbstract() {
+        return false;
+    }
+
+    /**
+     * Returns the default value of this element.
+     * Returns null if this element has no default.
+     */
+    public AnnotationValue defaultValue() {
+        return (sym.defaultValue == null)
+               ? null
+               : new AnnotationValueImpl(env, sym.defaultValue);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/AnnotationValueImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.tools.javac.code.Attribute;
+
+import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
+
+/**
+ * Represents a value of an annotation type element.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Scott Seligman
+ * @since 1.5
+ */
+
+public class AnnotationValueImpl implements AnnotationValue {
+
+    private final DocEnv env;
+    private final Attribute attr;
+
+
+    AnnotationValueImpl(DocEnv env, Attribute attr) {
+        this.env = env;
+        this.attr = attr;
+    }
+
+    /**
+     * Returns the value.
+     * The type of the returned object is one of the following:
+     * <ul><li> a wrapper class for a primitive type
+     *     <li> <code>String</code>
+     *     <li> <code>Type</code> (representing a class literal)
+     *     <li> <code>FieldDoc</code> (representing an enum constant)
+     *     <li> <code>AnnotationDesc</code>
+     *     <li> <code>AnnotationValue[]</code>
+     * </ul>
+     */
+    public Object value() {
+        ValueVisitor vv = new ValueVisitor();
+        attr.accept(vv);
+        return vv.value;
+    }
+
+    private class ValueVisitor implements Attribute.Visitor {
+        public Object value;
+
+        public void visitConstant(Attribute.Constant c) {
+            if (c.type.hasTag(BOOLEAN)) {
+                // javac represents false and true as integers 0 and 1
+                value = Boolean.valueOf(
+                                ((Integer)c.value).intValue() != 0);
+            } else {
+                value = c.value;
+            }
+        }
+
+        public void visitClass(Attribute.Class c) {
+            value = TypeMaker.getType(env,
+                                      env.types.erasure(c.classType));
+        }
+
+        public void visitEnum(Attribute.Enum e) {
+            value = env.getFieldDoc(e.value);
+        }
+
+        public void visitCompound(Attribute.Compound c) {
+            value = new AnnotationDescImpl(env, c);
+        }
+
+        public void visitArray(Attribute.Array a) {
+            AnnotationValue vals[] = new AnnotationValue[a.values.length];
+            for (int i = 0; i < vals.length; i++) {
+                vals[i] = new AnnotationValueImpl(env, a.values[i]);
+            }
+            value = vals;
+        }
+
+        public void visitError(Attribute.Error e) {
+            value = "<error>";
+        }
+    }
+
+    /**
+     * Returns a string representation of the value.
+     *
+     * @return the text of a Java language annotation value expression
+     *          whose value is the value of this annotation type element.
+     */
+    @Override
+    public String toString() {
+        ToStringVisitor tv = new ToStringVisitor();
+        attr.accept(tv);
+        return tv.toString();
+    }
+
+    private class ToStringVisitor implements Attribute.Visitor {
+        private final StringBuilder sb = new StringBuilder();
+
+        @Override
+        public String toString() {
+            return sb.toString();
+        }
+
+        public void visitConstant(Attribute.Constant c) {
+            if (c.type.hasTag(BOOLEAN)) {
+                // javac represents false and true as integers 0 and 1
+                sb.append(((Integer)c.value).intValue() != 0);
+            } else {
+                sb.append(FieldDocImpl.constantValueExpression(c.value));
+            }
+        }
+
+        public void visitClass(Attribute.Class c) {
+            sb.append(c);
+        }
+
+        public void visitEnum(Attribute.Enum e) {
+            sb.append(e);
+        }
+
+        public void visitCompound(Attribute.Compound c) {
+            sb.append(new AnnotationDescImpl(env, c));
+        }
+
+        public void visitArray(Attribute.Array a) {
+            // Omit braces from singleton.
+            if (a.values.length != 1) sb.append('{');
+
+            boolean first = true;
+            for (Attribute elem : a.values) {
+                if (first) {
+                    first = false;
+                } else {
+                    sb.append(", ");
+                }
+                elem.accept(this);
+            }
+            // Omit braces from singleton.
+            if (a.values.length != 1) sb.append('}');
+        }
+
+        public void visitError(Attribute.Error e) {
+            sb.append("<error>");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ClassDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,1329 @@
+/*
+ * Copyright (c) 1997, 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 com.sun.tools.javadoc.main;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.tools.FileObject;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+
+import com.sun.javadoc.*;
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.Kinds.KindSelector;
+import com.sun.tools.javac.code.Scope;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.code.TypeTag;
+import com.sun.tools.javac.comp.AttrContext;
+import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
+import com.sun.tools.javac.tree.JCTree.JCImport;
+import com.sun.tools.javac.tree.TreeInfo;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+import com.sun.tools.javac.util.Position;
+import static com.sun.tools.javac.code.Kinds.Kind.*;
+import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
+import static com.sun.tools.javac.code.TypeTag.CLASS;
+import static com.sun.tools.javac.tree.JCTree.Tag.*;
+
+/**
+ * Represents a java class and provides access to information
+ * about the class, the class' comment and tags, and the
+ * members of the class.  A ClassDocImpl only exists if it was
+ * processed in this run of javadoc.  References to classes
+ * which may or may not have been processed in this run are
+ * referred to using Type (which can be converted to ClassDocImpl,
+ * if possible).
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @see Type
+ *
+ * @since 1.2
+ * @author Robert Field
+ * @author Neal Gafter (rewrite)
+ * @author Scott Seligman (generics, enums, annotations)
+ */
+
+public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
+
+    public final ClassType type;        // protected->public for debugging
+    public final ClassSymbol tsym;
+
+    boolean isIncluded = false;         // Set in RootDocImpl
+
+    private SerializedForm serializedForm;
+
+    /**
+     * Constructor
+     */
+    public ClassDocImpl(DocEnv env, ClassSymbol sym) {
+        this(env, sym, null);
+    }
+
+    /**
+     * Constructor
+     */
+    public ClassDocImpl(DocEnv env, ClassSymbol sym, TreePath treePath) {
+        super(env, sym, treePath);
+        this.type = (ClassType)sym.type;
+        this.tsym = sym;
+    }
+
+    public com.sun.javadoc.Type getElementType() {
+        return null;
+    }
+
+    /**
+     * Returns the flags in terms of javac's flags
+     */
+    protected long getFlags() {
+        return getFlags(tsym);
+    }
+
+    /**
+     * Returns the flags of a ClassSymbol in terms of javac's flags
+     */
+    static long getFlags(ClassSymbol clazz) {
+        try {
+            return clazz.flags();
+        } catch (CompletionFailure ex) {
+            /* Quietly ignore completion failures and try again - the type
+             * for which the CompletionFailure was thrown shouldn't be completed
+             * again by the completer that threw the CompletionFailure.
+             */
+            return getFlags(clazz);
+        }
+    }
+
+    /**
+     * Is a ClassSymbol an annotation type?
+     */
+    static boolean isAnnotationType(ClassSymbol clazz) {
+        return (getFlags(clazz) & Flags.ANNOTATION) != 0;
+    }
+
+    /**
+     * Identify the containing class
+     */
+    protected ClassSymbol getContainingClass() {
+        return tsym.owner.enclClass();
+    }
+
+    /**
+     * Return true if this is a class, not an interface.
+     */
+    @Override
+    public boolean isClass() {
+        return !Modifier.isInterface(getModifiers());
+    }
+
+    /**
+     * Return true if this is a ordinary class,
+     * not an enumeration, exception, an error, or an interface.
+     */
+    @Override
+    public boolean isOrdinaryClass() {
+        if (isEnum() || isInterface() || isAnnotationType()) {
+            return false;
+        }
+        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
+            if (t.tsym == env.syms.errorType.tsym ||
+                t.tsym == env.syms.exceptionType.tsym) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Return true if this is an enumeration.
+     * (For legacy doclets, return false.)
+     */
+    @Override
+    public boolean isEnum() {
+        return (getFlags() & Flags.ENUM) != 0
+               &&
+               !env.legacyDoclet;
+    }
+
+    /**
+     * Return true if this is an interface, but not an annotation type.
+     * Overridden by AnnotationTypeDocImpl.
+     */
+    @Override
+    public boolean isInterface() {
+        return Modifier.isInterface(getModifiers());
+    }
+
+    /**
+     * Return true if this is an exception class
+     */
+    @Override
+    public boolean isException() {
+        if (isEnum() || isInterface() || isAnnotationType()) {
+            return false;
+        }
+        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
+            if (t.tsym == env.syms.exceptionType.tsym) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return true if this is an error class
+     */
+    @Override
+    public boolean isError() {
+        if (isEnum() || isInterface() || isAnnotationType()) {
+            return false;
+        }
+        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
+            if (t.tsym == env.syms.errorType.tsym) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return true if this is a throwable class
+     */
+    public boolean isThrowable() {
+        if (isEnum() || isInterface() || isAnnotationType()) {
+            return false;
+        }
+        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
+            if (t.tsym == env.syms.throwableType.tsym) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return true if this class is abstract
+     */
+    public boolean isAbstract() {
+        return Modifier.isAbstract(getModifiers());
+    }
+
+    /**
+     * Returns true if this class was synthesized by the compiler.
+     */
+    public boolean isSynthetic() {
+        return (getFlags() & Flags.SYNTHETIC) != 0;
+    }
+
+    /**
+     * Return true if this class is included in the active set.
+     * A ClassDoc is included iff either it is specified on the
+     * commandline, or if it's containing package is specified
+     * on the command line, or if it is a member class of an
+     * included class.
+     */
+
+    public boolean isIncluded() {
+        if (isIncluded) {
+            return true;
+        }
+        if (env.shouldDocument(tsym)) {
+            // Class is nameable from top-level and
+            // the class and all enclosing classes
+            // pass the modifier filter.
+            if (containingPackage().isIncluded()) {
+                return isIncluded=true;
+            }
+            ClassDoc outer = containingClass();
+            if (outer != null && outer.isIncluded()) {
+                return isIncluded=true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return the package that this class is contained in.
+     */
+    @Override
+    public PackageDoc containingPackage() {
+        PackageDocImpl p = env.getPackageDoc(tsym.packge());
+        if (p.setDocPath == false) {
+            FileObject docPath;
+            try {
+                Location location = env.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
+                    ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
+
+                docPath = env.fileManager.getFileForInput(
+                        location, p.qualifiedName(), "package.html");
+            } catch (IOException e) {
+                docPath = null;
+            }
+
+            if (docPath == null) {
+                // fall back on older semantics of looking in same directory as
+                // source file for this class
+                SourcePosition po = position();
+                if (env.fileManager instanceof StandardJavaFileManager &&
+                        po instanceof SourcePositionImpl) {
+                    URI uri = ((SourcePositionImpl) po).filename.toUri();
+                    if ("file".equals(uri.getScheme())) {
+                        File f = new File(uri);
+                        File dir = f.getParentFile();
+                        if (dir != null) {
+                            File pf = new File(dir, "package.html");
+                            if (pf.exists()) {
+                                StandardJavaFileManager sfm = (StandardJavaFileManager) env.fileManager;
+                                docPath = sfm.getJavaFileObjects(pf).iterator().next();
+                            }
+                        }
+
+                    }
+                }
+            }
+
+            p.setDocPath(docPath);
+        }
+        return p;
+    }
+
+    /**
+     * Return the class name without package qualifier - but with
+     * enclosing class qualifier - as a String.
+     * <pre>
+     * Examples:
+     *  for java.util.Hashtable
+     *  return Hashtable
+     *  for java.util.Map.Entry
+     *  return Map.Entry
+     * </pre>
+     */
+    public String name() {
+        if (name == null) {
+            name = getClassName(tsym, false);
+        }
+        return name;
+    }
+
+    private String name;
+
+    /**
+     * Return the qualified class name as a String.
+     * <pre>
+     * Example:
+     *  for java.util.Hashtable
+     *  return java.util.Hashtable
+     *  if no qualifier, just return flat name
+     * </pre>
+     */
+    public String qualifiedName() {
+        if (qualifiedName == null) {
+            qualifiedName = getClassName(tsym, true);
+        }
+        return qualifiedName;
+    }
+
+    private String qualifiedName;
+
+    /**
+     * Return unqualified name of type excluding any dimension information.
+     * <p>
+     * For example, a two dimensional array of String returns 'String'.
+     */
+    public String typeName() {
+        return name();
+    }
+
+    /**
+     * Return qualified name of type excluding any dimension information.
+     *<p>
+     * For example, a two dimensional array of String
+     * returns 'java.lang.String'.
+     */
+    public String qualifiedTypeName() {
+        return qualifiedName();
+    }
+
+    /**
+     * Return the simple name of this type.
+     */
+    public String simpleTypeName() {
+        if (simpleTypeName == null) {
+            simpleTypeName = tsym.name.toString();
+        }
+        return simpleTypeName;
+    }
+
+    private String simpleTypeName;
+
+    /**
+     * Return the qualified name and any type parameters.
+     * Each parameter is a type variable with optional bounds.
+     */
+    @Override
+    public String toString() {
+        return classToString(env, tsym, true);
+    }
+
+    /**
+     * Return the class name as a string.  If "full" is true the name is
+     * qualified, otherwise it is qualified by its enclosing class(es) only.
+     */
+    static String getClassName(ClassSymbol c, boolean full) {
+        if (full) {
+            return c.getQualifiedName().toString();
+        } else {
+            String n = "";
+            for ( ; c != null; c = c.owner.enclClass()) {
+                n = c.name + (n.equals("") ? "" : ".") + n;
+            }
+            return n;
+        }
+    }
+
+    /**
+     * Return the class name with any type parameters as a string.
+     * Each parameter is a type variable with optional bounds.
+     * If "full" is true all names are qualified, otherwise they are
+     * qualified by their enclosing class(es) only.
+     */
+    static String classToString(DocEnv env, ClassSymbol c, boolean full) {
+        StringBuilder s = new StringBuilder();
+        if (!c.isInner()) {             // if c is not an inner class
+            s.append(getClassName(c, full));
+        } else {
+            // c is an inner class, so include type params of outer.
+            ClassSymbol encl = c.owner.enclClass();
+            s.append(classToString(env, encl, full))
+             .append('.')
+             .append(c.name);
+        }
+        s.append(TypeMaker.typeParametersString(env, c, full));
+        return s.toString();
+    }
+
+    /**
+     * Is this class (or any enclosing class) generic?  That is, does
+     * it have type parameters?
+     */
+    static boolean isGeneric(ClassSymbol c) {
+        return c.type.allparams().nonEmpty();
+    }
+
+    /**
+     * Return the formal type parameters of this class or interface.
+     * Return an empty array if there are none.
+     */
+    public TypeVariable[] typeParameters() {
+        if (env.legacyDoclet) {
+            return new TypeVariable[0];
+        }
+        TypeVariable res[] = new TypeVariable[type.getTypeArguments().length()];
+        TypeMaker.getTypes(env, type.getTypeArguments(), res);
+        return res;
+    }
+
+    /**
+     * Return the type parameter tags of this class or interface.
+     */
+    public ParamTag[] typeParamTags() {
+        return (env.legacyDoclet)
+            ? new ParamTag[0]
+            : comment().typeParamTags();
+    }
+
+    /**
+     * Return the modifier string for this class. If it's an interface
+     * exclude 'abstract' keyword from the modifier string
+     */
+    @Override
+    public String modifiers() {
+        return Modifier.toString(modifierSpecifier());
+    }
+
+    @Override
+    public int modifierSpecifier() {
+        int modifiers = getModifiers();
+        return (isInterface() || isAnnotationType())
+                ? modifiers & ~Modifier.ABSTRACT
+                : modifiers;
+    }
+
+    /**
+     * Return the superclass of this class
+     *
+     * @return the ClassDocImpl for the superclass of this class, null
+     * if there is no superclass.
+     */
+    public ClassDoc superclass() {
+        if (isInterface() || isAnnotationType()) return null;
+        if (tsym == env.syms.objectType.tsym) return null;
+        ClassSymbol c = (ClassSymbol)env.types.supertype(type).tsym;
+        if (c == null || c == tsym) c = (ClassSymbol)env.syms.objectType.tsym;
+        return env.getClassDoc(c);
+    }
+
+    /**
+     * Return the superclass of this class.  Return null if this is an
+     * interface.  A superclass is represented by either a
+     * <code>ClassDoc</code> or a <code>ParameterizedType</code>.
+     */
+    public com.sun.javadoc.Type superclassType() {
+        if (isInterface() || isAnnotationType() ||
+                (tsym == env.syms.objectType.tsym))
+            return null;
+        Type sup = env.types.supertype(type);
+        return TypeMaker.getType(env,
+                                 (sup.hasTag(TypeTag.NONE)) ? env.syms.objectType : sup);
+    }
+
+    /**
+     * Test whether this class is a subclass of the specified class.
+     *
+     * @param cd the candidate superclass.
+     * @return true if cd is a superclass of this class.
+     */
+    public boolean subclassOf(ClassDoc cd) {
+        return tsym.isSubClass(((ClassDocImpl)cd).tsym, env.types);
+    }
+
+    /**
+     * Return interfaces implemented by this class or interfaces
+     * extended by this interface.
+     *
+     * @return An array of ClassDocImpl representing the interfaces.
+     * Return an empty array if there are no interfaces.
+     */
+    public ClassDoc[] interfaces() {
+        ListBuffer<ClassDocImpl> ta = new ListBuffer<>();
+        for (Type t : env.types.interfaces(type)) {
+            ta.append(env.getClassDoc((ClassSymbol)t.tsym));
+        }
+        //### Cache ta here?
+        return ta.toArray(new ClassDocImpl[ta.length()]);
+    }
+
+    /**
+     * Return interfaces implemented by this class or interfaces extended
+     * by this interface. Includes only directly-declared interfaces, not
+     * inherited interfaces.
+     * Return an empty array if there are no interfaces.
+     */
+    public com.sun.javadoc.Type[] interfaceTypes() {
+        //### Cache result here?
+        return TypeMaker.getTypes(env, env.types.interfaces(type));
+    }
+
+    /**
+     * Return fields in class.
+     * @param filter include only the included fields if filter==true
+     */
+    public FieldDoc[] fields(boolean filter) {
+        return fields(filter, false);
+    }
+
+    /**
+     * Return included fields in class.
+     */
+    public FieldDoc[] fields() {
+        return fields(true, false);
+    }
+
+    /**
+     * Return the enum constants if this is an enum type.
+     */
+    public FieldDoc[] enumConstants() {
+        return fields(false, true);
+    }
+
+    /**
+     * Return fields in class.
+     * @param filter  if true, return only the included fields
+     * @param enumConstants  if true, return the enum constants instead
+     */
+    private FieldDoc[] fields(boolean filter, boolean enumConstants) {
+        List<FieldDocImpl> fields = List.nil();
+        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
+            if (sym != null && sym.kind == VAR) {
+                VarSymbol s = (VarSymbol)sym;
+                boolean isEnum = ((s.flags() & Flags.ENUM) != 0) &&
+                                 !env.legacyDoclet;
+                if (isEnum == enumConstants &&
+                        (!filter || env.shouldDocument(s))) {
+                    fields = fields.prepend(env.getFieldDoc(s));
+                }
+            }
+        }
+        return fields.toArray(new FieldDocImpl[fields.length()]);
+    }
+
+    /**
+     * Return methods in class.
+     * This method is overridden by AnnotationTypeDocImpl.
+     *
+     * @param filter include only the included methods if filter==true
+     * @return an array of MethodDocImpl for representing the visible
+     * methods in this class.  Does not include constructors.
+     */
+    public MethodDoc[] methods(boolean filter) {
+        Names names = tsym.name.table.names;
+        List<MethodDocImpl> methods = List.nil();
+        for (Symbol sym :tsym.members().getSymbols(NON_RECURSIVE)) {
+            if (sym != null
+                && sym.kind == MTH
+                && sym.name != names.init
+                && sym.name != names.clinit) {
+                MethodSymbol s = (MethodSymbol)sym;
+                if (!filter || env.shouldDocument(s)) {
+                    methods = methods.prepend(env.getMethodDoc(s));
+                }
+            }
+        }
+        //### Cache methods here?
+        return methods.toArray(new MethodDocImpl[methods.length()]);
+    }
+
+    /**
+     * Return included methods in class.
+     *
+     * @return an array of MethodDocImpl for representing the visible
+     * methods in this class.  Does not include constructors.
+     */
+    public MethodDoc[] methods() {
+        return methods(true);
+    }
+
+    /**
+     * Return constructors in class.
+     *
+     * @param filter include only the included constructors if filter==true
+     * @return an array of ConstructorDocImpl for representing the visible
+     * constructors in this class.
+     */
+    public ConstructorDoc[] constructors(boolean filter) {
+        Names names = tsym.name.table.names;
+        List<ConstructorDocImpl> constructors = List.nil();
+        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
+            if (sym != null &&
+                sym.kind == MTH && sym.name == names.init) {
+                MethodSymbol s = (MethodSymbol)sym;
+                if (!filter || env.shouldDocument(s)) {
+                    constructors = constructors.prepend(env.getConstructorDoc(s));
+                }
+            }
+        }
+        //### Cache constructors here?
+        return constructors.toArray(new ConstructorDocImpl[constructors.length()]);
+    }
+
+    /**
+     * Return included constructors in class.
+     *
+     * @return an array of ConstructorDocImpl for representing the visible
+     * constructors in this class.
+     */
+    public ConstructorDoc[] constructors() {
+        return constructors(true);
+    }
+
+    /**
+     * Adds all inner classes of this class, and their
+     * inner classes recursively, to the list l.
+     */
+    void addAllClasses(ListBuffer<ClassDocImpl> l, boolean filtered) {
+        try {
+            if (isSynthetic()) return;
+            // sometimes synthetic classes are not marked synthetic
+            if (!JavadocTool.isValidClassName(tsym.name.toString())) return;
+            if (filtered && !env.shouldDocument(tsym)) return;
+            if (l.contains(this)) return;
+            l.append(this);
+            List<ClassDocImpl> more = List.nil();
+            for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
+                if (sym != null && sym.kind == TYP) {
+                    ClassSymbol s = (ClassSymbol)sym;
+                    ClassDocImpl c = env.getClassDoc(s);
+                    if (c.isSynthetic()) continue;
+                    if (c != null) more = more.prepend(c);
+                }
+            }
+            // this extra step preserves the ordering from oldjavadoc
+            for (; more.nonEmpty(); more=more.tail) {
+                more.head.addAllClasses(l, filtered);
+            }
+        } catch (CompletionFailure e) {
+            // quietly ignore completion failures
+        }
+    }
+
+    /**
+     * Return inner classes within this class.
+     *
+     * @param filter include only the included inner classes if filter==true.
+     * @return an array of ClassDocImpl for representing the visible
+     * classes defined in this class. Anonymous and local classes
+     * are not included.
+     */
+    public ClassDoc[] innerClasses(boolean filter) {
+        ListBuffer<ClassDocImpl> innerClasses = new ListBuffer<>();
+        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
+            if (sym != null && sym.kind == TYP) {
+                ClassSymbol s = (ClassSymbol)sym;
+                if ((s.flags_field & Flags.SYNTHETIC) != 0) continue;
+                if (!filter || env.isVisible(s)) {
+                    innerClasses.prepend(env.getClassDoc(s));
+                }
+            }
+        }
+        //### Cache classes here?
+        return innerClasses.toArray(new ClassDocImpl[innerClasses.length()]);
+    }
+
+    /**
+     * Return included inner classes within this class.
+     *
+     * @return an array of ClassDocImpl for representing the visible
+     * classes defined in this class. Anonymous and local classes
+     * are not included.
+     */
+    public ClassDoc[] innerClasses() {
+        return innerClasses(true);
+    }
+
+    /**
+     * Find a class within the context of this class.
+     * Search order: qualified name, in this class (inner),
+     * in this package, in the class imports, in the package
+     * imports.
+     * Return the ClassDocImpl if found, null if not found.
+     */
+    //### The specified search order is not the normal rule the
+    //### compiler would use.  Leave as specified or change it?
+    public ClassDoc findClass(String className) {
+        ClassDoc searchResult = searchClass(className);
+        if (searchResult == null) {
+            ClassDocImpl enclosingClass = (ClassDocImpl)containingClass();
+            //Expand search space to include enclosing class.
+            while (enclosingClass != null && enclosingClass.containingClass() != null) {
+                enclosingClass = (ClassDocImpl)enclosingClass.containingClass();
+            }
+            searchResult = enclosingClass == null ?
+                null : enclosingClass.searchClass(className);
+        }
+        return searchResult;
+    }
+
+    private ClassDoc searchClass(String className) {
+        Names names = tsym.name.table.names;
+
+        // search by qualified name first
+        ClassDoc cd = env.lookupClass(className);
+        if (cd != null) {
+            return cd;
+        }
+
+        // search inner classes
+        //### Add private entry point to avoid creating array?
+        //### Replicate code in innerClasses here to avoid consing?
+        for (ClassDoc icd : innerClasses()) {
+            if (icd.name().equals(className) ||
+                    //### This is from original javadoc but it looks suspicious to me...
+                    //### I believe it is attempting to compensate for the confused
+                    //### convention of including the nested class qualifiers in the
+                    //### 'name' of the inner class, rather than the true simple name.
+                    icd.name().endsWith("." + className)) {
+                return icd;
+            } else {
+                ClassDoc innercd = ((ClassDocImpl) icd).searchClass(className);
+                if (innercd != null) {
+                    return innercd;
+                }
+            }
+        }
+
+        // check in this package
+        cd = containingPackage().findClass(className);
+        if (cd != null) {
+            return cd;
+        }
+
+        // make sure that this symbol has been completed
+        tsym.complete();
+
+        // search imports
+
+        if (tsym.sourcefile != null) {
+
+            //### This information is available only for source classes.
+
+            Env<AttrContext> compenv = env.enter.getEnv(tsym);
+            if (compenv == null) return null;
+
+            Scope s = compenv.toplevel.namedImportScope;
+            for (Symbol sym : s.getSymbolsByName(names.fromString(className))) {
+                if (sym.kind == TYP) {
+                    ClassDoc c = env.getClassDoc((ClassSymbol)sym);
+                    return c;
+                }
+            }
+
+            s = compenv.toplevel.starImportScope;
+            for (Symbol sym : s.getSymbolsByName(names.fromString(className))) {
+                if (sym.kind == TYP) {
+                    ClassDoc c = env.getClassDoc((ClassSymbol)sym);
+                    return c;
+                }
+            }
+        }
+
+        return null; // not found
+    }
+
+
+    private boolean hasParameterTypes(MethodSymbol method, String[] argTypes) {
+
+        if (argTypes == null) {
+            // wildcard
+            return true;
+        }
+
+        int i = 0;
+        List<Type> types = method.type.getParameterTypes();
+
+        if (argTypes.length != types.length()) {
+            return false;
+        }
+
+        for (Type t : types) {
+            String argType = argTypes[i++];
+            // For vararg method, "T..." matches type T[].
+            if (i == argTypes.length) {
+                argType = argType.replace("...", "[]");
+            }
+            if (!hasTypeName(env.types.erasure(t), argType)) {  //###(gj)
+                return false;
+            }
+        }
+        return true;
+    }
+    // where
+    private boolean hasTypeName(Type t, String name) {
+        return
+            name.equals(TypeMaker.getTypeName(t, true))
+            ||
+            name.equals(TypeMaker.getTypeName(t, false))
+            ||
+            (qualifiedName() + "." + name).equals(TypeMaker.getTypeName(t, true));
+    }
+
+
+
+    /**
+     * Find a method in this class scope.
+     * Search order: this class, interfaces, superclasses, outerclasses.
+     * Note that this is not necessarily what the compiler would do!
+     *
+     * @param methodName the unqualified name to search for.
+     * @param paramTypes the array of Strings for method parameter types.
+     * @return the first MethodDocImpl which matches, null if not found.
+     */
+    public MethodDocImpl findMethod(String methodName, String[] paramTypes) {
+        // Use hash table 'searched' to avoid searching same class twice.
+        //### It is not clear how this could happen.
+        return searchMethod(methodName, paramTypes, new HashSet<ClassDocImpl>());
+    }
+
+    private MethodDocImpl searchMethod(String methodName,
+                                       String[] paramTypes, Set<ClassDocImpl> searched) {
+        //### Note that this search is not necessarily what the compiler would do!
+
+        Names names = tsym.name.table.names;
+        // do not match constructors
+        if (names.init.contentEquals(methodName)) {
+            return null;
+        }
+
+        ClassDocImpl cdi;
+        MethodDocImpl mdi;
+
+        if (searched.contains(this)) {
+            return null;
+        }
+        searched.add(this);
+
+        //DEBUG
+        /*---------------------------------*
+         System.out.print("searching " + this + " for " + methodName);
+         if (paramTypes == null) {
+         System.out.println("()");
+         } else {
+         System.out.print("(");
+         for (int k=0; k < paramTypes.length; k++) {
+         System.out.print(paramTypes[k]);
+         if ((k + 1) < paramTypes.length) {
+         System.out.print(", ");
+         }
+         }
+         System.out.println(")");
+         }
+         *---------------------------------*/
+
+        // search current class
+
+        //### Using modifier filter here isn't really correct,
+        //### but emulates the old behavior.  Instead, we should
+        //### apply the normal rules of visibility and inheritance.
+
+        if (paramTypes == null) {
+            // If no parameters specified, we are allowed to return
+            // any method with a matching name.  In practice, the old
+            // code returned the first method, which is now the last!
+            // In order to provide textually identical results, we
+            // attempt to emulate the old behavior.
+            MethodSymbol lastFound = null;
+            for (Symbol sym : tsym.members().getSymbolsByName(names.fromString(methodName))) {
+                if (sym.kind == MTH) {
+                    //### Should intern methodName as Name.
+                    if (sym.name.toString().equals(methodName)) {
+                        lastFound = (MethodSymbol)sym;
+                    }
+                }
+            }
+            if (lastFound != null) {
+                return env.getMethodDoc(lastFound);
+            }
+        } else {
+            for (Symbol sym : tsym.members().getSymbolsByName(names.fromString(methodName))) {
+                if (sym != null &&
+                    sym.kind == MTH) {
+                    //### Should intern methodName as Name.
+                    if (hasParameterTypes((MethodSymbol)sym, paramTypes)) {
+                        return env.getMethodDoc((MethodSymbol)sym);
+                    }
+                }
+            }
+        }
+
+        //### If we found a MethodDoc above, but which did not pass
+        //### the modifier filter, we should return failure here!
+
+        // search superclass
+        cdi = (ClassDocImpl)superclass();
+        if (cdi != null) {
+            mdi = cdi.searchMethod(methodName, paramTypes, searched);
+            if (mdi != null) {
+                return mdi;
+            }
+        }
+
+        // search interfaces
+        for (ClassDoc intf : interfaces()) {
+            cdi = (ClassDocImpl) intf;
+            mdi = cdi.searchMethod(methodName, paramTypes, searched);
+            if (mdi != null) {
+                return mdi;
+            }
+        }
+
+        // search enclosing class
+        cdi = (ClassDocImpl)containingClass();
+        if (cdi != null) {
+            mdi = cdi.searchMethod(methodName, paramTypes, searched);
+            if (mdi != null) {
+                return mdi;
+            }
+        }
+
+        //###(gj) As a temporary measure until type variables are better
+        //### handled, try again without the parameter types.
+        //### This should most often find the right method, and occassionally
+        //### find the wrong one.
+        //if (paramTypes != null) {
+        //    return findMethod(methodName, null);
+        //}
+
+        return null;
+    }
+
+    /**
+     * Find constructor in this class.
+     *
+     * @param constrName the unqualified name to search for.
+     * @param paramTypes the array of Strings for constructor parameters.
+     * @return the first ConstructorDocImpl which matches, null if not found.
+     */
+    public ConstructorDoc findConstructor(String constrName,
+                                          String[] paramTypes) {
+        Names names = tsym.name.table.names;
+        for (Symbol sym : tsym.members().getSymbolsByName(names.fromString("<init>"))) {
+            if (sym.kind == MTH) {
+                if (hasParameterTypes((MethodSymbol)sym, paramTypes)) {
+                    return env.getConstructorDoc((MethodSymbol)sym);
+                }
+            }
+        }
+
+        //###(gj) As a temporary measure until type variables are better
+        //### handled, try again without the parameter types.
+        //### This will often find the right constructor, and occassionally
+        //### find the wrong one.
+        //if (paramTypes != null) {
+        //    return findConstructor(constrName, null);
+        //}
+
+        return null;
+    }
+
+    /**
+     * Find a field in this class scope.
+     * Search order: this class, outerclasses, interfaces,
+     * superclasses. IMP: If see tag is defined in an inner class,
+     * which extends a super class and if outerclass and the super
+     * class have a visible field in common then Java compiler cribs
+     * about the ambiguity, but the following code will search in the
+     * above given search order.
+     *
+     * @param fieldName the unqualified name to search for.
+     * @return the first FieldDocImpl which matches, null if not found.
+     */
+    public FieldDoc findField(String fieldName) {
+        return searchField(fieldName, new HashSet<ClassDocImpl>());
+    }
+
+    private FieldDocImpl searchField(String fieldName, Set<ClassDocImpl> searched) {
+        Names names = tsym.name.table.names;
+        if (searched.contains(this)) {
+            return null;
+        }
+        searched.add(this);
+
+        for (Symbol sym : tsym.members().getSymbolsByName(names.fromString(fieldName))) {
+            if (sym.kind == VAR) {
+                //### Should intern fieldName as Name.
+                return env.getFieldDoc((VarSymbol)sym);
+            }
+        }
+
+        //### If we found a FieldDoc above, but which did not pass
+        //### the modifier filter, we should return failure here!
+
+        ClassDocImpl cdi = (ClassDocImpl)containingClass();
+        if (cdi != null) {
+            FieldDocImpl fdi = cdi.searchField(fieldName, searched);
+            if (fdi != null) {
+                return fdi;
+            }
+        }
+
+        // search superclass
+        cdi = (ClassDocImpl)superclass();
+        if (cdi != null) {
+            FieldDocImpl fdi = cdi.searchField(fieldName, searched);
+            if (fdi != null) {
+                return fdi;
+            }
+        }
+
+        // search interfaces
+        for (ClassDoc intf : interfaces()) {
+            cdi = (ClassDocImpl) intf;
+            FieldDocImpl fdi = cdi.searchField(fieldName, searched);
+            if (fdi != null) {
+                return fdi;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the list of classes declared as imported.
+     * These are called "single-type-import declarations" in the JLS.
+     * This method is deprecated in the ClassDoc interface.
+     *
+     * @return an array of ClassDocImpl representing the imported classes.
+     *
+     * @deprecated  Import declarations are implementation details that
+     *          should not be exposed here.  In addition, not all imported
+     *          classes are imported through single-type-import declarations.
+     */
+    @Deprecated
+    public ClassDoc[] importedClasses() {
+        // information is not available for binary classfiles
+        if (tsym.sourcefile == null) return new ClassDoc[0];
+
+        ListBuffer<ClassDocImpl> importedClasses = new ListBuffer<>();
+
+        Env<AttrContext> compenv = env.enter.getEnv(tsym);
+        if (compenv == null) return new ClassDocImpl[0];
+
+        Name asterisk = tsym.name.table.names.asterisk;
+        for (JCTree t : compenv.toplevel.defs) {
+            if (t.hasTag(IMPORT)) {
+                JCTree imp = ((JCImport) t).qualid;
+                if ((TreeInfo.name(imp) != asterisk) &&
+                    imp.type.tsym.kind.matches(KindSelector.TYP)) {
+                    importedClasses.append(
+                            env.getClassDoc((ClassSymbol)imp.type.tsym));
+                }
+            }
+        }
+
+        return importedClasses.toArray(new ClassDocImpl[importedClasses.length()]);
+    }
+
+    /**
+     * Get the list of packages declared as imported.
+     * These are called "type-import-on-demand declarations" in the JLS.
+     * This method is deprecated in the ClassDoc interface.
+     *
+     * @return an array of PackageDocImpl representing the imported packages.
+     *
+     * ###NOTE: the syntax supports importing all inner classes from a class as well.
+     * @deprecated  Import declarations are implementation details that
+     *          should not be exposed here.  In addition, this method's
+     *          return type does not allow for all type-import-on-demand
+     *          declarations to be returned.
+     */
+    @Deprecated
+    public PackageDoc[] importedPackages() {
+        // information is not available for binary classfiles
+        if (tsym.sourcefile == null) return new PackageDoc[0];
+
+        ListBuffer<PackageDocImpl> importedPackages = new ListBuffer<>();
+
+        //### Add the implicit "import java.lang.*" to the result
+        Names names = tsym.name.table.names;
+        importedPackages.append(env.getPackageDoc(env.syms.enterPackage(env.syms.java_base, names.java_lang)));
+
+        Env<AttrContext> compenv = env.enter.getEnv(tsym);
+        if (compenv == null) return new PackageDocImpl[0];
+
+        for (JCTree t : compenv.toplevel.defs) {
+            if (t.hasTag(IMPORT)) {
+                JCTree imp = ((JCImport) t).qualid;
+                if (TreeInfo.name(imp) == names.asterisk) {
+                    JCFieldAccess sel = (JCFieldAccess)imp;
+                    Symbol s = sel.selected.type.tsym;
+                    PackageDocImpl pdoc = env.getPackageDoc(s.packge());
+                    if (!importedPackages.contains(pdoc))
+                        importedPackages.append(pdoc);
+                }
+            }
+        }
+
+        return importedPackages.toArray(new PackageDocImpl[importedPackages.length()]);
+    }
+
+    /**
+     * Return the type's dimension information.
+     * Always return "", as this is not an array type.
+     */
+    public String dimension() {
+        return "";
+    }
+
+    /**
+     * Return this type as a class, which it already is.
+     */
+    public ClassDoc asClassDoc() {
+        return this;
+    }
+
+    /**
+     * Return null (unless overridden), as this is not an annotation type.
+     */
+    public AnnotationTypeDoc asAnnotationTypeDoc() {
+        return null;
+    }
+
+    /**
+     * Return null, as this is not a class instantiation.
+     */
+    public ParameterizedType asParameterizedType() {
+        return null;
+    }
+
+    /**
+     * Return null, as this is not a type variable.
+     */
+    public TypeVariable asTypeVariable() {
+        return null;
+    }
+
+    /**
+     * Return null, as this is not a wildcard type.
+     */
+    public WildcardType asWildcardType() {
+        return null;
+    }
+
+    /**
+     * Returns null, as this is not an annotated type.
+     */
+    public AnnotatedType asAnnotatedType() {
+        return null;
+    }
+
+    /**
+     * Return false, as this is not a primitive type.
+     */
+    public boolean isPrimitive() {
+        return false;
+    }
+
+    //--- Serialization ---
+
+    //### These methods ignore modifier filter.
+
+    /**
+     * Return true if this class implements <code>java.io.Serializable</code>.
+     *
+     * Since <code>java.io.Externalizable</code> extends
+     * <code>java.io.Serializable</code>,
+     * Externalizable objects are also Serializable.
+     */
+    public boolean isSerializable() {
+        try {
+            return env.types.isSubtype(type, env.syms.serializableType);
+        } catch (CompletionFailure ex) {
+            // quietly ignore completion failures
+            return false;
+        }
+    }
+
+    /**
+     * Return true if this class implements
+     * <code>java.io.Externalizable</code>.
+     */
+    public boolean isExternalizable() {
+        try {
+            return env.types.isSubtype(type, env.externalizableSym.type);
+        } catch (CompletionFailure ex) {
+            // quietly ignore completion failures
+            return false;
+        }
+    }
+
+    /**
+     * Return the serialization methods for this class.
+     *
+     * @return an array of <code>MethodDocImpl</code> that represents
+     * the serialization methods for this class.
+     */
+    public MethodDoc[] serializationMethods() {
+        if (serializedForm == null) {
+            serializedForm = new SerializedForm(env, tsym, this);
+        }
+        //### Clone this?
+        return serializedForm.methods();
+    }
+
+    /**
+     * Return the Serializable fields of class.<p>
+     *
+     * Return either a list of default fields documented by
+     * <code>serial</code> tag<br>
+     * or return a single <code>FieldDoc</code> for
+     * <code>serialPersistentField</code> member.
+     * There should be a <code>serialField</code> tag for
+     * each Serializable field defined by an <code>ObjectStreamField</code>
+     * array component of <code>serialPersistentField</code>.
+     *
+     * @return an array of {@code FieldDoc} for the Serializable fields
+     *         of this class.
+     *
+     * @see #definesSerializableFields()
+     * @see SerialFieldTagImpl
+     */
+    public FieldDoc[] serializableFields() {
+        if (serializedForm == null) {
+            serializedForm = new SerializedForm(env, tsym, this);
+        }
+        //### Clone this?
+        return serializedForm.fields();
+    }
+
+    /**
+     * Return true if Serializable fields are explicitly defined with
+     * the special class member <code>serialPersistentFields</code>.
+     *
+     * @see #serializableFields()
+     * @see SerialFieldTagImpl
+     */
+    public boolean definesSerializableFields() {
+        if (!isSerializable() || isExternalizable()) {
+            return false;
+        } else {
+            if (serializedForm == null) {
+                serializedForm = new SerializedForm(env, tsym, this);
+            }
+            //### Clone this?
+            return serializedForm.definesSerializableFields();
+        }
+    }
+
+    /**
+     * Determine if a class is a RuntimeException.
+     * <p>
+     * Used only by ThrowsTagImpl.
+     */
+    boolean isRuntimeException() {
+        return tsym.isSubClass(env.syms.runtimeExceptionType.tsym, env.types);
+    }
+
+    /**
+     * Return the source position of the entity, or null if
+     * no position is available.
+     */
+    @Override
+    public SourcePosition position() {
+        if (tsym.sourcefile == null) return null;
+        return SourcePositionImpl.make(tsym.sourcefile,
+                                       (tree==null) ? Position.NOPOS : tree.pos,
+                                       lineMap);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Comment.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import com.sun.javadoc.*;
+import com.sun.tools.javac.util.ListBuffer;
+
+/**
+ * Comment contains all information in comment part.
+ *      It allows users to get first sentence of this comment, get
+ *      comment for different tags...
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Kaiyang Liu (original)
+ * @author Robert Field (rewrite)
+ * @author Atul M Dambalkar
+ * @author Neal Gafter (rewrite)
+ */
+class Comment {
+
+    /**
+     * sorted comments with different tags.
+     */
+    private final ListBuffer<Tag> tagList = new ListBuffer<>();
+
+    /**
+     * text minus any tags.
+     */
+    private String text;
+
+    /**
+     * Doc environment
+     */
+    private final DocEnv docenv;
+
+    /**
+     * constructor of Comment.
+     */
+    Comment(final DocImpl holder, final String commentString) {
+        this.docenv = holder.env;
+
+        /**
+         * Separate the comment into the text part and zero to N tags.
+         * Simple state machine is in one of three states:
+         * <pre>
+         * IN_TEXT: parsing the comment text or tag text.
+         * TAG_NAME: parsing the name of a tag.
+         * TAG_GAP: skipping through the gap between the tag name and
+         * the tag text.
+         * </pre>
+         */
+        @SuppressWarnings("fallthrough")
+        class CommentStringParser {
+            /**
+             * The entry point to the comment string parser
+             */
+            void parseCommentStateMachine() {
+                final int IN_TEXT = 1;
+                final int TAG_GAP = 2;
+                final int TAG_NAME = 3;
+                int state = TAG_GAP;
+                boolean newLine = true;
+                String tagName = null;
+                int tagStart = 0;
+                int textStart = 0;
+                int lastNonWhite = -1;
+                int len = commentString.length();
+                for (int inx = 0; inx < len; ++inx) {
+                    char ch = commentString.charAt(inx);
+                    boolean isWhite = Character.isWhitespace(ch);
+                    switch (state)  {
+                        case TAG_NAME:
+                            if (isWhite) {
+                                tagName = commentString.substring(tagStart, inx);
+                                state = TAG_GAP;
+                            }
+                            break;
+                        case TAG_GAP:
+                            if (isWhite) {
+                                break;
+                            }
+                            textStart = inx;
+                            state = IN_TEXT;
+                            /* fall thru */
+                        case IN_TEXT:
+                            if (newLine && ch == '@') {
+                                parseCommentComponent(tagName, textStart,
+                                                      lastNonWhite+1);
+                                tagStart = inx;
+                                state = TAG_NAME;
+                            }
+                            break;
+                    }
+                    if (ch == '\n') {
+                        newLine = true;
+                    } else if (!isWhite) {
+                        lastNonWhite = inx;
+                        newLine = false;
+                    }
+                }
+                // Finish what's currently being processed
+                switch (state)  {
+                    case TAG_NAME:
+                        tagName = commentString.substring(tagStart, len);
+                        /* fall thru */
+                    case TAG_GAP:
+                        textStart = len;
+                        /* fall thru */
+                    case IN_TEXT:
+                        parseCommentComponent(tagName, textStart, lastNonWhite+1);
+                        break;
+                }
+            }
+
+            /**
+             * Save away the last parsed item.
+             */
+            void parseCommentComponent(String tagName,
+                                       int from, int upto) {
+                String tx = upto <= from ? "" : commentString.substring(from, upto);
+                if (tagName == null) {
+                    text = tx;
+                } else {
+                    TagImpl tag;
+                    switch (tagName) {
+                        case "@exception":
+                        case "@throws":
+                            warnIfEmpty(tagName, tx);
+                            tag = new ThrowsTagImpl(holder, tagName, tx);
+                            break;
+                        case "@param":
+                            warnIfEmpty(tagName, tx);
+                            tag = new ParamTagImpl(holder, tagName, tx);
+                            break;
+                        case "@see":
+                            warnIfEmpty(tagName, tx);
+                            tag = new SeeTagImpl(holder, tagName, tx);
+                            break;
+                        case "@serialField":
+                            warnIfEmpty(tagName, tx);
+                            tag = new SerialFieldTagImpl(holder, tagName, tx);
+                            break;
+                        case "@return":
+                            warnIfEmpty(tagName, tx);
+                            tag = new TagImpl(holder, tagName, tx);
+                            break;
+                        case "@author":
+                            warnIfEmpty(tagName, tx);
+                            tag = new TagImpl(holder, tagName, tx);
+                            break;
+                        case "@version":
+                            warnIfEmpty(tagName, tx);
+                            tag = new TagImpl(holder, tagName, tx);
+                            break;
+                        default:
+                            tag = new TagImpl(holder, tagName, tx);
+                            break;
+                    }
+                    tagList.append(tag);
+                }
+            }
+
+            void warnIfEmpty(String tagName, String tx) {
+                if (tx.length() == 0) {
+                    docenv.warning(holder, "tag.tag_has_no_arguments", tagName);
+                }
+            }
+
+        }
+
+        new CommentStringParser().parseCommentStateMachine();
+    }
+
+    /**
+     * Return the text of the comment.
+     */
+    String commentText() {
+        return text;
+    }
+
+    /**
+     * Return all tags in this comment.
+     */
+    Tag[] tags() {
+        return tagList.toArray(new Tag[tagList.length()]);
+    }
+
+    /**
+     * Return tags of the specified kind in this comment.
+     */
+    Tag[] tags(String tagname) {
+        ListBuffer<Tag> found = new ListBuffer<>();
+        String target = tagname;
+        if (target.charAt(0) != '@') {
+            target = "@" + target;
+        }
+        for (Tag tag : tagList) {
+            if (tag.kind().equals(target)) {
+                found.append(tag);
+            }
+        }
+        return found.toArray(new Tag[found.length()]);
+    }
+
+    /**
+     * Return throws tags in this comment.
+     */
+    ThrowsTag[] throwsTags() {
+        ListBuffer<ThrowsTag> found = new ListBuffer<>();
+        for (Tag next : tagList) {
+            if (next instanceof ThrowsTag) {
+                found.append((ThrowsTag)next);
+            }
+        }
+        return found.toArray(new ThrowsTag[found.length()]);
+    }
+
+    /**
+     * Return param tags (excluding type param tags) in this comment.
+     */
+    ParamTag[] paramTags() {
+        return paramTags(false);
+    }
+
+    /**
+     * Return type param tags in this comment.
+     */
+    ParamTag[] typeParamTags() {
+        return paramTags(true);
+    }
+
+    /**
+     * Return param tags in this comment.  If typeParams is true
+     * include only type param tags, otherwise include only ordinary
+     * param tags.
+     */
+    private ParamTag[] paramTags(boolean typeParams) {
+        ListBuffer<ParamTag> found = new ListBuffer<>();
+        for (Tag next : tagList) {
+            if (next instanceof ParamTag) {
+                ParamTag p = (ParamTag)next;
+                if (typeParams == p.isTypeParameter()) {
+                    found.append(p);
+                }
+            }
+        }
+        return found.toArray(new ParamTag[found.length()]);
+    }
+
+    /**
+     * Return see also tags in this comment.
+     */
+    SeeTag[] seeTags() {
+        ListBuffer<SeeTag> found = new ListBuffer<>();
+        for (Tag next : tagList) {
+            if (next instanceof SeeTag) {
+                found.append((SeeTag)next);
+            }
+        }
+        return found.toArray(new SeeTag[found.length()]);
+    }
+
+    /**
+     * Return serialField tags in this comment.
+     */
+    SerialFieldTag[] serialFieldTags() {
+        ListBuffer<SerialFieldTag> found = new ListBuffer<>();
+        for (Tag next : tagList) {
+            if (next instanceof SerialFieldTag) {
+                found.append((SerialFieldTag)next);
+            }
+        }
+        return found.toArray(new SerialFieldTag[found.length()]);
+    }
+
+    /**
+     * Return array of tags with text and inline See Tags for a Doc comment.
+     */
+    static Tag[] getInlineTags(DocImpl holder, String inlinetext) {
+        ListBuffer<Tag> taglist = new ListBuffer<>();
+        int delimend = 0, textstart = 0, len = inlinetext.length();
+        boolean inPre = false;
+        DocEnv docenv = holder.env;
+
+        if (len == 0) {
+            return taglist.toArray(new Tag[taglist.length()]);
+        }
+        while (true) {
+            int linkstart;
+            if ((linkstart = inlineTagFound(holder, inlinetext,
+                                            textstart)) == -1) {
+                taglist.append(new TagImpl(holder, "Text",
+                                           inlinetext.substring(textstart)));
+                break;
+            } else {
+                inPre = scanForPre(inlinetext, textstart, linkstart, inPre);
+                int seetextstart = linkstart;
+                for (int i = linkstart; i < inlinetext.length(); i++) {
+                    char c = inlinetext.charAt(i);
+                    if (Character.isWhitespace(c) ||
+                        c == '}') {
+                        seetextstart = i;
+                        break;
+                     }
+                }
+                String linkName = inlinetext.substring(linkstart+2, seetextstart);
+                if (!(inPre && (linkName.equals("code") || linkName.equals("literal")))) {
+                    //Move past the white space after the inline tag name.
+                    while (Character.isWhitespace(inlinetext.
+                                                      charAt(seetextstart))) {
+                        if (inlinetext.length() <= seetextstart) {
+                            taglist.append(new TagImpl(holder, "Text",
+                                                       inlinetext.substring(textstart, seetextstart)));
+                            docenv.warning(holder,
+                                           "tag.Improper_Use_Of_Link_Tag",
+                                           inlinetext);
+                            return taglist.toArray(new Tag[taglist.length()]);
+                        } else {
+                            seetextstart++;
+                        }
+                    }
+                }
+                taglist.append(new TagImpl(holder, "Text",
+                                           inlinetext.substring(textstart, linkstart)));
+                textstart = seetextstart;   // this text is actually seetag
+                if ((delimend = findInlineTagDelim(inlinetext, textstart)) == -1) {
+                    //Missing closing '}' character.
+                    // store the text as it is with the {@link.
+                    taglist.append(new TagImpl(holder, "Text",
+                                               inlinetext.substring(textstart)));
+                    docenv.warning(holder,
+                                   "tag.End_delimiter_missing_for_possible_SeeTag",
+                                   inlinetext);
+                    return taglist.toArray(new Tag[taglist.length()]);
+                } else {
+                    //Found closing '}' character.
+                    if (linkName.equals("see")
+                           || linkName.equals("link")
+                           || linkName.equals("linkplain")) {
+                        taglist.append( new SeeTagImpl(holder, "@" + linkName,
+                              inlinetext.substring(textstart, delimend)));
+                    } else {
+                        taglist.append( new TagImpl(holder, "@" + linkName,
+                              inlinetext.substring(textstart, delimend)));
+                    }
+                    textstart = delimend + 1;
+                }
+            }
+            if (textstart == inlinetext.length()) {
+                break;
+            }
+        }
+        return taglist.toArray(new Tag[taglist.length()]);
+    }
+
+    /** regex for case-insensitive match for {@literal <pre> } and  {@literal </pre> }. */
+    private static final Pattern prePat = Pattern.compile("(?i)<(/?)pre>");
+
+    private static boolean scanForPre(String inlinetext, int start, int end, boolean inPre) {
+        Matcher m = prePat.matcher(inlinetext).region(start, end);
+        while (m.find()) {
+            inPre = m.group(1).isEmpty();
+        }
+        return inPre;
+    }
+
+    /**
+     * Recursively find the index of the closing '}' character for an inline tag
+     * and return it.  If it can't be found, return -1.
+     * @param inlineText the text to search in.
+     * @param searchStart the index of the place to start searching at.
+     * @return the index of the closing '}' character for an inline tag.
+     * If it can't be found, return -1.
+     */
+    private static int findInlineTagDelim(String inlineText, int searchStart) {
+        int delimEnd, nestedOpenBrace;
+        if ((delimEnd = inlineText.indexOf("}", searchStart)) == -1) {
+            return -1;
+        } else if (((nestedOpenBrace = inlineText.indexOf("{", searchStart)) != -1) &&
+            nestedOpenBrace < delimEnd){
+            //Found a nested open brace.
+            int nestedCloseBrace = findInlineTagDelim(inlineText, nestedOpenBrace + 1);
+            return (nestedCloseBrace != -1) ?
+                findInlineTagDelim(inlineText, nestedCloseBrace + 1) :
+                -1;
+        } else {
+            return delimEnd;
+        }
+    }
+
+    /**
+     * Recursively search for the characters '{', '@', followed by
+     * name of inline tag and white space,
+     * if found
+     *    return the index of the text following the white space.
+     * else
+     *    return -1.
+     */
+    private static int inlineTagFound(DocImpl holder, String inlinetext, int start) {
+        DocEnv docenv = holder.env;
+        int linkstart = inlinetext.indexOf("{@", start);
+        if (start == inlinetext.length() || linkstart == -1) {
+            return -1;
+        } else if (inlinetext.indexOf('}', linkstart) == -1) {
+            //Missing '}'.
+            docenv.warning(holder, "tag.Improper_Use_Of_Link_Tag",
+                    inlinetext.substring(linkstart, inlinetext.length()));
+            return -1;
+        } else {
+            return linkstart;
+        }
+    }
+
+
+    /**
+     * Return array of tags for the locale specific first sentence in the text.
+     */
+    static Tag[] firstSentenceTags(DocImpl holder, String text) {
+        DocLocale doclocale = holder.env.doclocale;
+        return getInlineTags(holder,
+                             doclocale.localeSpecificFirstSentence(holder, text));
+    }
+
+    /**
+     * Return text for this Doc comment.
+     */
+    @Override
+    public String toString() {
+        return text;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ConstructorDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+
+/**
+ * Represents a constructor of a java class.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since 1.2
+ * @author Robert Field
+ * @author Neal Gafter (rewrite)
+ */
+
+public class ConstructorDocImpl
+        extends ExecutableMemberDocImpl implements ConstructorDoc {
+
+    /**
+     * constructor.
+     */
+    public ConstructorDocImpl(DocEnv env, MethodSymbol sym) {
+        super(env, sym);
+    }
+
+    /**
+     * constructor.
+     */
+    public ConstructorDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) {
+        super(env, sym, treePath);
+    }
+
+    /**
+     * Return true if it is a constructor, which it is.
+     *
+     * @return true
+     */
+    public boolean isConstructor() {
+        return true;
+    }
+
+    /**
+     * Get the name.
+     *
+     * @return the name of the member.
+     */
+    public String name() {
+        ClassSymbol c = sym.enclClass();
+        return c.name.toString();
+    }
+
+    /**
+     * Get the name.
+     *
+     * @return the qualified name of the member.
+     */
+    public String qualifiedName() {
+        return sym.enclClass().getQualifiedName().toString();
+    }
+
+    /**
+     * Returns a string representation of this constructor.  Includes the
+     * qualified signature and any type parameters.
+     * Type parameters precede the class name, as they do in the syntax
+     * for invoking constructors with explicit type parameters using "new".
+     * (This is unlike the syntax for invoking methods with explicit type
+     * parameters.)
+     */
+    public String toString() {
+        return typeParametersString() + qualifiedName() + signature();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocEnv.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,869 @@
+/*
+ * Copyright (c) 2000, 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 com.sun.tools.javadoc.main;
+
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import javax.tools.JavaFileManager;
+
+import com.sun.javadoc.*;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TreePath;
+import com.sun.tools.doclint.DocLint;
+import com.sun.tools.javac.api.BasicJavacTask;
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
+import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.comp.Check;
+import com.sun.tools.javac.comp.Enter;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Convert;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+
+/**
+ * Holds the environment for a run of javadoc.
+ * Holds only the information needed throughout the
+ * run and not the compiler info that could be GC'ed
+ * or ported.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since 1.4
+ * @author Robert Field
+ * @author Neal Gafter (rewrite)
+ * @author Scott Seligman (generics)
+ */
+public class DocEnv {
+    protected static final Context.Key<DocEnv> docEnvKey = new Context.Key<>();
+
+    public static DocEnv instance(Context context) {
+        DocEnv instance = context.get(docEnvKey);
+        if (instance == null)
+            instance = new DocEnv(context);
+        return instance;
+    }
+
+    DocLocale doclocale;
+
+    private final Messager messager;
+
+    /** Predefined symbols known to the compiler. */
+    final Symtab syms;
+
+    /** Referenced directly in RootDocImpl. */
+    private final ClassFinder finder;
+
+    /** Javadoc's own version of the compiler's enter phase. */
+    final Enter enter;
+
+    /** The name table. */
+    private Names names;
+
+    /** The encoding name. */
+    private String encoding;
+
+    final Symbol externalizableSym;
+
+    /** Access filter (public, protected, ...).  */
+    protected ModifierFilter showAccess;
+
+    /** True if we are using a sentence BreakIterator. */
+    boolean breakiterator;
+
+    /**
+     * True if we do not want to print any notifications at all.
+     */
+    boolean quiet = false;
+
+    Check chk;
+    Types types;
+    JavaFileManager fileManager;
+    Context context;
+    DocLint doclint;
+
+    WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<>();
+
+    /** Allow documenting from class files? */
+    boolean docClasses = false;
+
+    /** Does the doclet only expect pre-1.5 doclet API? */
+    protected boolean legacyDoclet = true;
+
+    /**
+     * Set this to true if you would like to not emit any errors, warnings and
+     * notices.
+     */
+    private boolean silent = false;
+
+    /**
+     * The source language version.
+     */
+    protected Source source;
+
+    /**
+     * Constructor
+     *
+     * @param context      Context for this javadoc instance.
+     */
+    protected DocEnv(Context context) {
+        context.put(docEnvKey, this);
+        this.context = context;
+
+        messager = Messager.instance0(context);
+        syms = Symtab.instance(context);
+        finder = JavadocClassFinder.instance(context);
+        enter = JavadocEnter.instance(context);
+        names = Names.instance(context);
+        externalizableSym = syms.enterClass(syms.java_base, names.fromString("java.io.Externalizable"));
+        chk = Check.instance(context);
+        types = Types.instance(context);
+        fileManager = context.get(JavaFileManager.class);
+        if (fileManager instanceof JavacFileManager) {
+            ((JavacFileManager)fileManager).setSymbolFileEnabled(false);
+        }
+
+        // Default.  Should normally be reset with setLocale.
+        this.doclocale = new DocLocale(this, "", breakiterator);
+        source = Source.instance(context);
+    }
+
+    public void setSilent(boolean silent) {
+        this.silent = silent;
+    }
+
+    /**
+     * Look up ClassDoc by qualified name.
+     */
+    public ClassDocImpl lookupClass(String name) {
+        ClassSymbol c = getClassSymbol(name);
+        if (c != null) {
+            return getClassDoc(c);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Load ClassDoc by qualified name.
+     */
+    public ClassDocImpl loadClass(String name) {
+        try {
+            Name nameImpl = names.fromString(name);
+            ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
+            ClassSymbol c = finder.loadClass(mod != null ? mod : syms.errModule, nameImpl);
+            return getClassDoc(c);
+        } catch (CompletionFailure ex) {
+            chk.completionError(null, ex);
+            return null;
+        }
+    }
+
+    /**
+     * Look up PackageDoc by qualified name.
+     */
+    public PackageDocImpl lookupPackage(String name) {
+        //### Jing alleges that class check is needed
+        //### to avoid a compiler bug.  Most likely
+        //### instead a dummy created for error recovery.
+        //### Should investigate this.
+        Name nameImpl = names.fromString(name);
+        ModuleSymbol mod = syms.inferModule(nameImpl);
+        PackageSymbol p = mod != null ? syms.getPackage(mod, nameImpl) : null;
+        ClassSymbol c = getClassSymbol(name);
+        if (p != null && c == null) {
+            return getPackageDoc(p);
+        } else {
+            return null;
+        }
+    }
+        // where
+        /** Retrieve class symbol by fully-qualified name.
+         */
+        ClassSymbol getClassSymbol(String name) {
+            // Name may contain nested class qualification.
+            // Generate candidate flatnames with successively shorter
+            // package qualifiers and longer nested class qualifiers.
+            int nameLen = name.length();
+            char[] nameChars = name.toCharArray();
+            int idx = name.length();
+            for (;;) {
+                Name nameImpl = names.fromChars(nameChars, 0, nameLen);
+                ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
+                ClassSymbol s = mod != null ? syms.getClass(mod, nameImpl) : null;
+                if (s != null)
+                    return s; // found it!
+                idx = name.substring(0, idx).lastIndexOf('.');
+                if (idx < 0) break;
+                nameChars[idx] = '$';
+            }
+            return null;
+        }
+
+    /**
+     * Set the locale.
+     */
+    public void setLocale(String localeName) {
+        // create locale specifics
+        doclocale = new DocLocale(this, localeName, breakiterator);
+        // update Messager if locale has changed.
+        messager.setLocale(doclocale.locale);
+    }
+
+    /** Check whether this member should be documented. */
+    public boolean shouldDocument(VarSymbol sym) {
+        long mod = sym.flags();
+
+        if ((mod & Flags.SYNTHETIC) != 0) {
+            return false;
+        }
+
+        return showAccess.checkModifier(translateModifiers(mod));
+    }
+
+    /** Check whether this member should be documented. */
+    public boolean shouldDocument(MethodSymbol sym) {
+        long mod = sym.flags();
+
+        if ((mod & Flags.SYNTHETIC) != 0) {
+            return false;
+        }
+
+        return showAccess.checkModifier(translateModifiers(mod));
+    }
+
+    /** check whether this class should be documented. */
+    public boolean shouldDocument(ClassSymbol sym) {
+        return
+            (sym.flags_field&Flags.SYNTHETIC) == 0 && // no synthetics
+            (docClasses || getClassDoc(sym).tree != null) &&
+            isVisible(sym);
+    }
+
+    //### Comment below is inaccurate wrt modifier filter testing
+    /**
+     * Check the visibility if this is an nested class.
+     * if this is not a nested class, return true.
+     * if this is an static visible nested class,
+     *    return true.
+     * if this is an visible nested class
+     *    if the outer class is visible return true.
+     *    else return false.
+     * IMPORTANT: This also allows, static nested classes
+     * to be defined inside an nested class, which is not
+     * allowed by the compiler. So such an test case will
+     * not reach upto this method itself, but if compiler
+     * allows it, then that will go through.
+     */
+    protected boolean isVisible(ClassSymbol sym) {
+        long mod = sym.flags_field;
+        if (!showAccess.checkModifier(translateModifiers(mod))) {
+            return false;
+        }
+        ClassSymbol encl = sym.owner.enclClass();
+        return (encl == null || (mod & Flags.STATIC) != 0 || isVisible(encl));
+    }
+
+    //---------------- print forwarders ----------------//
+
+    /**
+     * Print error message, increment error count.
+     *
+     * @param msg message to print.
+     */
+    public void printError(String msg) {
+        if (silent)
+            return;
+        messager.printError(msg);
+    }
+
+    /**
+     * Print error message, increment error count.
+     *
+     * @param key selects message from resource
+     */
+    public void error(DocImpl doc, String key) {
+        if (silent)
+            return;
+        messager.error(doc==null ? null : doc.position(), key);
+    }
+
+    /**
+     * Print error message, increment error count.
+     *
+     * @param key selects message from resource
+     */
+    public void error(SourcePosition pos, String key) {
+        if (silent)
+            return;
+        messager.error(pos, key);
+    }
+
+    /**
+     * Print error message, increment error count.
+     *
+     * @param msg message to print.
+     */
+    public void printError(SourcePosition pos, String msg) {
+        if (silent)
+            return;
+        messager.printError(pos, msg);
+    }
+
+    /**
+     * Print error message, increment error count.
+     *
+     * @param key selects message from resource
+     * @param a1 first argument
+     */
+    public void error(DocImpl doc, String key, String a1) {
+        if (silent)
+            return;
+        messager.error(doc==null ? null : doc.position(), key, a1);
+    }
+
+    /**
+     * Print error message, increment error count.
+     *
+     * @param key selects message from resource
+     * @param a1 first argument
+     * @param a2 second argument
+     */
+    public void error(DocImpl doc, String key, String a1, String a2) {
+        if (silent)
+            return;
+        messager.error(doc==null ? null : doc.position(), key, a1, a2);
+    }
+
+    /**
+     * Print error message, increment error count.
+     *
+     * @param key selects message from resource
+     * @param a1 first argument
+     * @param a2 second argument
+     * @param a3 third argument
+     */
+    public void error(DocImpl doc, String key, String a1, String a2, String a3) {
+        if (silent)
+            return;
+        messager.error(doc==null ? null : doc.position(), key, a1, a2, a3);
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     *
+     * @param msg message to print.
+     */
+    public void printWarning(String msg) {
+        if (silent)
+            return;
+        messager.printWarning(msg);
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     *
+     * @param key selects message from resource
+     */
+    public void warning(DocImpl doc, String key) {
+        if (silent)
+            return;
+        messager.warning(doc==null ? null : doc.position(), key);
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     *
+     * @param msg message to print.
+     */
+    public void printWarning(SourcePosition pos, String msg) {
+        if (silent)
+            return;
+        messager.printWarning(pos, msg);
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     *
+     * @param key selects message from resource
+     * @param a1 first argument
+     */
+    public void warning(DocImpl doc, String key, String a1) {
+        if (silent)
+            return;
+        // suppress messages that have (probably) been covered by doclint
+        if (doclint != null && doc != null && key.startsWith("tag"))
+            return;
+        messager.warning(doc==null ? null : doc.position(), key, a1);
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     *
+     * @param key selects message from resource
+     * @param a1 first argument
+     * @param a2 second argument
+     */
+    public void warning(DocImpl doc, String key, String a1, String a2) {
+        if (silent)
+            return;
+        messager.warning(doc==null ? null : doc.position(), key, a1, a2);
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     *
+     * @param key selects message from resource
+     * @param a1 first argument
+     * @param a2 second argument
+     * @param a3 third argument
+     */
+    public void warning(DocImpl doc, String key, String a1, String a2, String a3) {
+        if (silent)
+            return;
+        messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3);
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     *
+     * @param key selects message from resource
+     * @param a1 first argument
+     * @param a2 second argument
+     * @param a3 third argument
+     */
+    public void warning(DocImpl doc, String key, String a1, String a2, String a3,
+                        String a4) {
+        if (silent)
+            return;
+        messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3, a4);
+    }
+
+    /**
+     * Print a message.
+     *
+     * @param msg message to print.
+     */
+    public void printNotice(String msg) {
+        if (silent || quiet)
+            return;
+        messager.printNotice(msg);
+    }
+
+
+    /**
+     * Print a message.
+     *
+     * @param key selects message from resource
+     */
+    public void notice(String key) {
+        if (silent || quiet)
+            return;
+        messager.notice(key);
+    }
+
+    /**
+     * Print a message.
+     *
+     * @param msg message to print.
+     */
+    public void printNotice(SourcePosition pos, String msg) {
+        if (silent || quiet)
+            return;
+        messager.printNotice(pos, msg);
+    }
+
+    /**
+     * Print a message.
+     *
+     * @param key selects message from resource
+     * @param a1 first argument
+     */
+    public void notice(String key, String a1) {
+        if (silent || quiet)
+            return;
+        messager.notice(key, a1);
+    }
+
+    /**
+     * Print a message.
+     *
+     * @param key selects message from resource
+     * @param a1 first argument
+     * @param a2 second argument
+     */
+    public void notice(String key, String a1, String a2) {
+        if (silent || quiet)
+            return;
+        messager.notice(key, a1, a2);
+    }
+
+    /**
+     * Print a message.
+     *
+     * @param key selects message from resource
+     * @param a1 first argument
+     * @param a2 second argument
+     * @param a3 third argument
+     */
+    public void notice(String key, String a1, String a2, String a3) {
+        if (silent || quiet)
+            return;
+        messager.notice(key, a1, a2, a3);
+    }
+
+    /**
+     * Exit, reporting errors and warnings.
+     */
+    public void exit() {
+        // Messager should be replaced by a more general
+        // compilation environment.  This can probably
+        // subsume DocEnv as well.
+        messager.exit();
+    }
+
+    protected Map<PackageSymbol, PackageDocImpl> packageMap = new HashMap<>();
+    /**
+     * Return the PackageDoc of this package symbol.
+     */
+    public PackageDocImpl getPackageDoc(PackageSymbol pack) {
+        PackageDocImpl result = packageMap.get(pack);
+        if (result != null) return result;
+        result = new PackageDocImpl(this, pack);
+        packageMap.put(pack, result);
+        return result;
+    }
+
+    /**
+     * Create the PackageDoc (or a subtype) for a package symbol.
+     */
+    void makePackageDoc(PackageSymbol pack, TreePath treePath) {
+        PackageDocImpl result = packageMap.get(pack);
+        if (result != null) {
+            if (treePath != null) result.setTreePath(treePath);
+        } else {
+            result = new PackageDocImpl(this, pack, treePath);
+            packageMap.put(pack, result);
+        }
+    }
+
+
+    protected Map<ClassSymbol, ClassDocImpl> classMap = new HashMap<>();
+    /**
+     * Return the ClassDoc (or a subtype) of this class symbol.
+     */
+    public ClassDocImpl getClassDoc(ClassSymbol clazz) {
+        ClassDocImpl result = classMap.get(clazz);
+        if (result != null) return result;
+        if (isAnnotationType(clazz)) {
+            result = new AnnotationTypeDocImpl(this, clazz);
+        } else {
+            result = new ClassDocImpl(this, clazz);
+        }
+        classMap.put(clazz, result);
+        return result;
+    }
+
+    /**
+     * Create the ClassDoc (or a subtype) for a class symbol.
+     */
+    protected void makeClassDoc(ClassSymbol clazz, TreePath treePath) {
+        ClassDocImpl result = classMap.get(clazz);
+        if (result != null) {
+            if (treePath != null) result.setTreePath(treePath);
+            return;
+        }
+        if (isAnnotationType((JCClassDecl) treePath.getLeaf())) {   // flags of clazz may not yet be set
+            result = new AnnotationTypeDocImpl(this, clazz, treePath);
+        } else {
+            result = new ClassDocImpl(this, clazz, treePath);
+        }
+        classMap.put(clazz, result);
+    }
+
+    protected static boolean isAnnotationType(ClassSymbol clazz) {
+        return ClassDocImpl.isAnnotationType(clazz);
+    }
+
+    protected static boolean isAnnotationType(JCClassDecl tree) {
+        return (tree.mods.flags & Flags.ANNOTATION) != 0;
+    }
+
+    protected Map<VarSymbol, FieldDocImpl> fieldMap = new HashMap<>();
+    /**
+     * Return the FieldDoc of this var symbol.
+     */
+    public FieldDocImpl getFieldDoc(VarSymbol var) {
+        FieldDocImpl result = fieldMap.get(var);
+        if (result != null) return result;
+        result = new FieldDocImpl(this, var);
+        fieldMap.put(var, result);
+        return result;
+    }
+    /**
+     * Create a FieldDoc for a var symbol.
+     */
+    protected void makeFieldDoc(VarSymbol var, TreePath treePath) {
+        FieldDocImpl result = fieldMap.get(var);
+        if (result != null) {
+            if (treePath != null) result.setTreePath(treePath);
+        } else {
+            result = new FieldDocImpl(this, var, treePath);
+            fieldMap.put(var, result);
+        }
+    }
+
+    protected Map<MethodSymbol, ExecutableMemberDocImpl> methodMap = new HashMap<>();
+    /**
+     * Create a MethodDoc for this MethodSymbol.
+     * Should be called only on symbols representing methods.
+     */
+    protected void makeMethodDoc(MethodSymbol meth, TreePath treePath) {
+        MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);
+        if (result != null) {
+            if (treePath != null) result.setTreePath(treePath);
+        } else {
+            result = new MethodDocImpl(this, meth, treePath);
+            methodMap.put(meth, result);
+        }
+    }
+
+    /**
+     * Return the MethodDoc for a MethodSymbol.
+     * Should be called only on symbols representing methods.
+     */
+    public MethodDocImpl getMethodDoc(MethodSymbol meth) {
+        assert !meth.isConstructor() : "not expecting a constructor symbol";
+        MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);
+        if (result != null) return result;
+        result = new MethodDocImpl(this, meth);
+        methodMap.put(meth, result);
+        return result;
+    }
+
+    /**
+     * Create the ConstructorDoc for a MethodSymbol.
+     * Should be called only on symbols representing constructors.
+     */
+    protected void makeConstructorDoc(MethodSymbol meth, TreePath treePath) {
+        ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);
+        if (result != null) {
+            if (treePath != null) result.setTreePath(treePath);
+        } else {
+            result = new ConstructorDocImpl(this, meth, treePath);
+            methodMap.put(meth, result);
+        }
+    }
+
+    /**
+     * Return the ConstructorDoc for a MethodSymbol.
+     * Should be called only on symbols representing constructors.
+     */
+    public ConstructorDocImpl getConstructorDoc(MethodSymbol meth) {
+        assert meth.isConstructor() : "expecting a constructor symbol";
+        ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);
+        if (result != null) return result;
+        result = new ConstructorDocImpl(this, meth);
+        methodMap.put(meth, result);
+        return result;
+    }
+
+    /**
+     * Create the AnnotationTypeElementDoc for a MethodSymbol.
+     * Should be called only on symbols representing annotation type elements.
+     */
+    protected void makeAnnotationTypeElementDoc(MethodSymbol meth, TreePath treePath) {
+        AnnotationTypeElementDocImpl result =
+            (AnnotationTypeElementDocImpl)methodMap.get(meth);
+        if (result != null) {
+            if (treePath != null) result.setTreePath(treePath);
+        } else {
+            result =
+                new AnnotationTypeElementDocImpl(this, meth, treePath);
+            methodMap.put(meth, result);
+        }
+    }
+
+    /**
+     * Return the AnnotationTypeElementDoc for a MethodSymbol.
+     * Should be called only on symbols representing annotation type elements.
+     */
+    public AnnotationTypeElementDocImpl getAnnotationTypeElementDoc(
+            MethodSymbol meth) {
+
+        AnnotationTypeElementDocImpl result =
+            (AnnotationTypeElementDocImpl)methodMap.get(meth);
+        if (result != null) return result;
+        result = new AnnotationTypeElementDocImpl(this, meth);
+        methodMap.put(meth, result);
+        return result;
+    }
+
+//  private Map<ClassType, ParameterizedTypeImpl> parameterizedTypeMap =
+//          new HashMap<ClassType, ParameterizedTypeImpl>();
+    /**
+     * Return the ParameterizedType of this instantiation.
+//   * ### Could use Type.sameTypeAs() instead of equality matching in hashmap
+//   * ### to avoid some duplication.
+     */
+    ParameterizedTypeImpl getParameterizedType(ClassType t) {
+        return new ParameterizedTypeImpl(this, t);
+//      ParameterizedTypeImpl result = parameterizedTypeMap.get(t);
+//      if (result != null) return result;
+//      result = new ParameterizedTypeImpl(this, t);
+//      parameterizedTypeMap.put(t, result);
+//      return result;
+    }
+
+    TreePath getTreePath(JCCompilationUnit tree) {
+        TreePath p = treePaths.get(tree);
+        if (p == null)
+            treePaths.put(tree, p = new TreePath(tree));
+        return p;
+    }
+
+    TreePath getTreePath(JCCompilationUnit toplevel, JCPackageDecl tree) {
+        TreePath p = treePaths.get(tree);
+        if (p == null)
+            treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree));
+        return p;
+    }
+
+    TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) {
+        TreePath p = treePaths.get(tree);
+        if (p == null)
+            treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree));
+        return p;
+    }
+
+    TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) {
+        return new TreePath(getTreePath(toplevel, cdecl), tree);
+    }
+
+    /**
+     * Set the encoding.
+     */
+    public void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+
+    /**
+     * Get the encoding.
+     */
+    public String getEncoding() {
+        return encoding;
+    }
+
+    /**
+     * Convert modifier bits from private coding used by
+     * the compiler to that of java.lang.reflect.Modifier.
+     */
+    static int translateModifiers(long flags) {
+        int result = 0;
+        if ((flags & Flags.ABSTRACT) != 0)
+            result |= Modifier.ABSTRACT;
+        if ((flags & Flags.FINAL) != 0)
+            result |= Modifier.FINAL;
+        if ((flags & Flags.INTERFACE) != 0)
+            result |= Modifier.INTERFACE;
+        if ((flags & Flags.NATIVE) != 0)
+            result |= Modifier.NATIVE;
+        if ((flags & Flags.PRIVATE) != 0)
+            result |= Modifier.PRIVATE;
+        if ((flags & Flags.PROTECTED) != 0)
+            result |= Modifier.PROTECTED;
+        if ((flags & Flags.PUBLIC) != 0)
+            result |= Modifier.PUBLIC;
+        if ((flags & Flags.STATIC) != 0)
+            result |= Modifier.STATIC;
+        if ((flags & Flags.SYNCHRONIZED) != 0)
+            result |= Modifier.SYNCHRONIZED;
+        if ((flags & Flags.TRANSIENT) != 0)
+            result |= Modifier.TRANSIENT;
+        if ((flags & Flags.VOLATILE) != 0)
+            result |= Modifier.VOLATILE;
+        return result;
+    }
+
+    void initDoclint(Collection<String> opts, Collection<String> customTagNames, String htmlVersion) {
+        ArrayList<String> doclintOpts = new ArrayList<>();
+        boolean msgOptionSeen = false;
+
+        for (String opt : opts) {
+            if (opt.startsWith(DocLint.XMSGS_OPTION)) {
+                if (opt.equals(DocLint.XMSGS_CUSTOM_PREFIX + "none"))
+                    return;
+                msgOptionSeen = true;
+            }
+            doclintOpts.add(opt);
+        }
+
+        if (!msgOptionSeen) {
+            doclintOpts.add(DocLint.XMSGS_OPTION);
+        }
+
+        String sep = "";
+        StringBuilder customTags = new StringBuilder();
+        for (String customTag : customTagNames) {
+            customTags.append(sep);
+            customTags.append(customTag);
+            sep = DocLint.SEPARATOR;
+        }
+        doclintOpts.add(DocLint.XCUSTOM_TAGS_PREFIX + customTags.toString());
+        doclintOpts.add(DocLint.XHTML_VERSION_PREFIX + htmlVersion);
+
+        JavacTask t = BasicJavacTask.instance(context);
+        doclint = new DocLint();
+        // standard doclet normally generates H1, H2
+        doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2");
+        doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false);
+    }
+
+    boolean showTagMessages() {
+        return (doclint == null);
+    }
+
+    Map<CompilationUnitTree, Boolean> shouldCheck = new HashMap<>();
+
+    boolean shouldCheck(CompilationUnitTree unit) {
+        return shouldCheck.computeIfAbsent(unit, doclint :: shouldCheck);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.CollationKey;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.tools.FileObject;
+
+import com.sun.javadoc.*;
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.Position;
+
+/**
+ * abstract base class of all Doc classes.  Doc item's are representations
+ * of java language constructs (class, package, method,...) which have
+ * comments and have been processed by this run of javadoc.  All Doc items
+ * are unique, that is, they are == comparable.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since 1.2
+ * @author Robert Field
+ * @author Atul M Dambalkar
+ * @author Neal Gafter (rewrite)
+ */
+public abstract class DocImpl implements Doc, Comparable<Object> {
+
+    /**
+     * Doc environment
+     */
+    protected final DocEnv env;   //### Rename this everywhere to 'docenv' ?
+
+    /**
+     * Back pointer to the tree node for this doc item.
+     * May be null if there is no associated tree.
+     */
+    protected TreePath treePath;
+
+    /**
+     *  The complex comment object, lazily initialized.
+     */
+    private Comment comment;
+
+    /**
+     * The cached sort key, to take care of Natural Language Text sorting.
+     */
+    private CollationKey collationkey = null;
+
+    /**
+     *  Raw documentation string.
+     */
+    protected String documentation;  // Accessed in PackageDocImpl, RootDocImpl
+
+    /**
+     * Cached first sentence.
+     */
+    private Tag[] firstSentence;
+
+    /**
+     * Cached inline tags.
+     */
+    private Tag[] inlineTags;
+
+    /**
+     * Constructor.
+     */
+    DocImpl(DocEnv env, TreePath treePath) {
+        this.treePath = treePath;
+        this.documentation = getCommentText(treePath);
+        this.env = env;
+    }
+
+    private static String getCommentText(TreePath p) {
+        if (p == null)
+            return null;
+
+        JCCompilationUnit topLevel = (JCCompilationUnit) p.getCompilationUnit();
+        JCTree tree = (JCTree) p.getLeaf();
+        return topLevel.docComments.getCommentText(tree);
+    }
+
+    /**
+     * So subclasses have the option to do lazy initialization of
+     * "documentation" string.
+     */
+    protected String documentation() {
+        if (documentation == null) documentation = "";
+        return documentation;
+    }
+
+    /**
+     * For lazy initialization of comment.
+     */
+    Comment comment() {
+        if (comment == null) {
+            String d = documentation();
+            if (env.doclint != null
+                    && treePath != null
+                    && env.shouldCheck(treePath.getCompilationUnit())
+                    && d.equals(getCommentText(treePath))) {
+                env.doclint.scan(treePath);
+            }
+            comment = new Comment(this, d);
+        }
+        return comment;
+    }
+
+    /**
+     * Return the text of the comment for this doc item.
+     * TagImpls have been removed.
+     */
+    public String commentText() {
+        return comment().commentText();
+    }
+
+    /**
+     * Return all tags in this Doc item.
+     *
+     * @return an array of TagImpl containing all tags on this Doc item.
+     */
+    public Tag[] tags() {
+        return comment().tags();
+    }
+
+    /**
+     * Return tags of the specified kind in this Doc item.
+     *
+     * @param tagname name of the tag kind to search for.
+     * @return an array of TagImpl containing all tags whose 'kind()'
+     * matches 'tagname'.
+     */
+    public Tag[] tags(String tagname) {
+        return comment().tags(tagname);
+    }
+
+    /**
+     * Return the see also tags in this Doc item.
+     *
+     * @return an array of SeeTag containing all &#64;see tags.
+     */
+    public SeeTag[] seeTags() {
+        return comment().seeTags();
+    }
+
+    public Tag[] inlineTags() {
+        if (inlineTags == null) {
+            inlineTags = Comment.getInlineTags(this, commentText());
+        }
+        return inlineTags;
+    }
+
+    public Tag[] firstSentenceTags() {
+        if (firstSentence == null) {
+            //Parse all sentences first to avoid duplicate warnings.
+            inlineTags();
+            try {
+                env.setSilent(true);
+                firstSentence = Comment.firstSentenceTags(this, commentText());
+            } finally {
+                env.setSilent(false);
+            }
+        }
+        return firstSentence;
+    }
+
+    /**
+     * Utility for subclasses which read HTML documentation files.
+     */
+    String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException {
+        byte[] filecontents = new byte[input.available()];
+        try {
+            DataInputStream dataIn = new DataInputStream(input);
+            dataIn.readFully(filecontents);
+        } finally {
+            input.close();
+        }
+        String encoding = env.getEncoding();
+        String rawDoc = (encoding!=null)
+            ? new String(filecontents, encoding)
+            : new String(filecontents);
+        Pattern bodyPat = Pattern.compile("(?is).*<body\\b[^>]*>(.*)</body\\b.*");
+        Matcher m = bodyPat.matcher(rawDoc);
+        if (m.matches()) {
+            return m.group(1);
+        } else {
+            String key = rawDoc.matches("(?is).*<body\\b.*")
+                    ? "javadoc.End_body_missing_from_html_file"
+                    : "javadoc.Body_missing_from_html_file";
+            env.error(SourcePositionImpl.make(filename, Position.NOPOS, null), key);
+            return "";
+        }
+    }
+
+    /**
+     * Return the full unprocessed text of the comment.  Tags
+     * are included as text.  Used mainly for store and retrieve
+     * operations like internalization.
+     */
+    public String getRawCommentText() {
+        return documentation();
+    }
+
+    /**
+     * Set the full unprocessed text of the comment.  Tags
+     * are included as text.  Used mainly for store and retrieve
+     * operations like internalization.
+     */
+    public void setRawCommentText(String rawDocumentation) {
+        treePath = null;
+        documentation = rawDocumentation;
+        comment = null;
+    }
+
+    /**
+     * Set the full unprocessed text of the comment and tree path.
+     */
+    void setTreePath(TreePath treePath) {
+        this.treePath = treePath;
+        documentation = getCommentText(treePath);
+        comment = null;
+    }
+
+    /**
+     * return a key for sorting.
+     */
+    CollationKey key() {
+        if (collationkey == null) {
+            collationkey = generateKey();
+        }
+        return collationkey;
+    }
+
+    /**
+     * Generate a key for sorting.
+     * <p>
+     * Default is name().
+     */
+    CollationKey generateKey() {
+        String k = name();
+        // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
+        return env.doclocale.collator.getCollationKey(k);
+    }
+
+    /**
+     * Returns a string representation of this Doc item.
+     */
+    @Override
+    public String toString() {
+        return qualifiedName();
+    }
+
+    /**
+     * Returns the name of this Doc item.
+     *
+     * @return  the name
+     */
+    public abstract String name();
+
+    /**
+     * Returns the qualified name of this Doc item.
+     *
+     * @return  the name
+     */
+    public abstract String qualifiedName();
+
+    /**
+     * Compares this Object with the specified Object for order.  Returns a
+     * negative integer, zero, or a positive integer as this Object is less
+     * than, equal to, or greater than the given Object.
+     * <p>
+     * Included so that Doc item are java.lang.Comparable.
+     *
+     * @param   obj the {@code Object} to be compared.
+     * @return  a negative integer, zero, or a positive integer as this Object
+     *          is less than, equal to, or greater than the given Object.
+     * @exception ClassCastException the specified Object's type prevents it
+     *            from being compared to this Object.
+     */
+    public int compareTo(Object obj) {
+        // System.out.println("COMPARE \"" + this + "\" to \"" + obj + "\" = " + key().compareTo(((DocImpl)obj).key()));
+        return key().compareTo(((DocImpl)obj).key());
+    }
+
+    /**
+     * Is this Doc item a field?  False until overridden.
+     *
+     * @return true if it represents a field
+     */
+    public boolean isField() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item an enum constant?  False until overridden.
+     *
+     * @return true if it represents an enum constant
+     */
+    public boolean isEnumConstant() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item a constructor?  False until overridden.
+     *
+     * @return true if it represents a constructor
+     */
+    public boolean isConstructor() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item a method (but not a constructor or annotation
+     * type element)?
+     * False until overridden.
+     *
+     * @return true if it represents a method
+     */
+    public boolean isMethod() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item an annotation type element?
+     * False until overridden.
+     *
+     * @return true if it represents an annotation type element
+     */
+    public boolean isAnnotationTypeElement() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item a interface (but not an annotation type)?
+     * False until overridden.
+     *
+     * @return true if it represents a interface
+     */
+    public boolean isInterface() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item a exception class?  False until overridden.
+     *
+     * @return true if it represents a exception
+     */
+    public boolean isException() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item a error class?  False until overridden.
+     *
+     * @return true if it represents a error
+     */
+    public boolean isError() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item an enum type?  False until overridden.
+     *
+     * @return true if it represents an enum type
+     */
+    public boolean isEnum() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item an annotation type?  False until overridden.
+     *
+     * @return true if it represents an annotation type
+     */
+    public boolean isAnnotationType() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item an ordinary class (i.e. not an interface,
+     * annotation type, enumeration, exception, or error)?
+     * False until overridden.
+     *
+     * @return true if it represents an ordinary class
+     */
+    public boolean isOrdinaryClass() {
+        return false;
+    }
+
+    /**
+     * Is this Doc item a class
+     * (and not an interface or annotation type)?
+     * This includes ordinary classes, enums, errors and exceptions.
+     * False until overridden.
+     *
+     * @return true if it represents a class
+     */
+    public boolean isClass() {
+        return false;
+    }
+
+    /**
+     * return true if this Doc is include in the active set.
+     */
+    public abstract boolean isIncluded();
+
+    /**
+     * Return the source position of the entity, or null if
+     * no position is available.
+     */
+    public SourcePosition position() { return null; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocLocale.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2000, 2012, 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.sun.tools.javadoc.main;
+
+import java.text.BreakIterator;
+import java.text.Collator;
+import java.util.Locale;
+
+/**
+ * This class holds the information about locales.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since 1.4
+ * @author Robert Field
+ */
+class DocLocale {
+
+    /**
+     * The locale name will be set by Main, if option is provided on the
+     * command line.
+     */
+    final String localeName;
+
+    /**
+     * The locale to be used. If user doesn't provide this,
+     * then set it to default locale value.
+     */
+    final Locale locale;
+
+    /**
+     * The collator for this application. This is to take care of Locale
+     * Specific or Natural Language Text sorting.
+     */
+    final Collator collator;
+
+    /**
+     * Enclosing DocEnv
+     */
+    private final DocEnv docenv;
+
+    /**
+     * Sentence instance from the BreakIterator.
+     */
+    private final BreakIterator sentenceBreaker;
+
+    /**
+     * True is we should use <code>BreakIterator</code>
+     * to compute first sentence.
+     */
+    private boolean useBreakIterator = false;
+
+    /**
+     * The HTML sentence terminators.
+     */
+    static final String[] sentenceTerminators =
+                    {
+                        "<p>", "</p>", "<h1>", "<h2>",
+                        "<h3>", "<h4>", "<h5>", "<h6>",
+                        "</h1>", "</h2>", "</h3>", "</h4>", "</h5>",
+                        "</h6>", "<hr>", "<pre>", "</pre>"
+                    };
+
+    /**
+     * Constructor
+     */
+    DocLocale(DocEnv docenv, String localeName, boolean useBreakIterator) {
+        this.docenv = docenv;
+        this.localeName = localeName;
+        this.useBreakIterator = useBreakIterator;
+        locale = getLocale();
+        if (locale == null) {
+            docenv.exit();
+        } else {
+            Locale.setDefault(locale); // NOTE: updating global state
+        }
+        collator = Collator.getInstance(locale);
+        sentenceBreaker = BreakIterator.getSentenceInstance(locale);
+    }
+
+    /**
+     * Get the locale if specified on the command line
+     * else return null and if locale option is not used
+     * then return default locale.
+     */
+    private Locale getLocale() {
+        Locale userlocale = null;
+        if (localeName.length() > 0) {
+            int firstuscore = localeName.indexOf('_');
+            int seconduscore = -1;
+            String language = null;
+            String country = null;
+            String variant = null;
+            if (firstuscore == 2) {
+                language = localeName.substring(0, firstuscore);
+                seconduscore = localeName.indexOf('_', firstuscore + 1);
+                if (seconduscore > 0) {
+                    if (seconduscore != firstuscore + 3 ||
+                           localeName.length() <= seconduscore + 1) {
+                        docenv.error(null, "main.malformed_locale_name", localeName);
+                        return null;
+                    }
+                    country = localeName.substring(firstuscore + 1,
+                                                   seconduscore);
+                    variant = localeName.substring(seconduscore + 1);
+                } else if (localeName.length() == firstuscore + 3) {
+                    country = localeName.substring(firstuscore + 1);
+                } else {
+                    docenv.error(null, "main.malformed_locale_name", localeName);
+                    return null;
+                }
+            } else if (firstuscore == -1 && localeName.length() == 2) {
+                language = localeName;
+            } else {
+                docenv.error(null, "main.malformed_locale_name", localeName);
+                return null;
+            }
+            userlocale = searchLocale(language, country, variant);
+            if (userlocale == null) {
+                docenv.error(null, "main.illegal_locale_name", localeName);
+                return null;
+            } else {
+                return userlocale;
+            }
+        } else {
+            return Locale.getDefault();
+        }
+    }
+
+    /**
+     * Search the locale for specified language, specified country and
+     * specified variant.
+     */
+    private Locale searchLocale(String language, String country,
+                                String variant) {
+        for (Locale loc : Locale.getAvailableLocales()) {
+            if (loc.getLanguage().equals(language) &&
+                (country == null || loc.getCountry().equals(country)) &&
+                (variant == null || loc.getVariant().equals(variant))) {
+                return loc;
+            }
+        }
+        return null;
+    }
+
+    String localeSpecificFirstSentence(DocImpl doc, String s) {
+        if (s == null || s.length() == 0) {
+            return "";
+        }
+        int index = s.indexOf("-->");
+        if(s.trim().startsWith("<!--") && index != -1) {
+            return localeSpecificFirstSentence(doc, s.substring(index + 3, s.length()));
+        }
+        if (useBreakIterator || !locale.getLanguage().equals("en")) {
+            sentenceBreaker.setText(s.replace('\n', ' '));
+            int start = sentenceBreaker.first();
+            int end = sentenceBreaker.next();
+            return s.substring(start, end).trim();
+        } else {
+            return englishLanguageFirstSentence(s).trim();
+        }
+    }
+
+    /**
+     * Return the first sentence of a string, where a sentence ends
+     * with a period followed be white space.
+     */
+    private String englishLanguageFirstSentence(String s) {
+        if (s == null) {
+            return null;
+        }
+        int len = s.length();
+        boolean period = false;
+        for (int i = 0 ; i < len ; i++) {
+            switch (s.charAt(i)) {
+                case '.':
+                    period = true;
+                    break;
+                case ' ':
+                case '\t':
+                case '\n':
+            case '\r':
+            case '\f':
+                    if (period) {
+                        return s.substring(0, i);
+                    }
+                    break;
+            case '<':
+                    if (i > 0) {
+                        if (htmlSentenceTerminatorFound(s, i)) {
+                            return s.substring(0, i);
+                        }
+                    }
+                    break;
+                default:
+                    period = false;
+            }
+        }
+        return s;
+    }
+
+    /**
+     * Find out if there is any HTML tag in the given string. If found
+     * return true else return false.
+     */
+    private boolean htmlSentenceTerminatorFound(String str, int index) {
+        for (String terminator : sentenceTerminators) {
+            if (str.regionMatches(true, index, terminator,
+                                  0, terminator.length())) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocletInvoker.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,439 @@
+/*
+ * 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
+ * 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.sun.tools.javadoc.main;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+import javax.tools.DocumentationTool;
+import javax.tools.JavaFileManager;
+
+import com.sun.javadoc.*;
+import com.sun.tools.javac.util.ClientCodeException;
+import com.sun.tools.javac.util.List;
+
+import static com.sun.javadoc.LanguageVersion.*;
+
+
+/**
+ * Class creates, controls and invokes doclets.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Neal Gafter (rewrite)
+ */
+public class DocletInvoker {
+
+    private final Class<?> docletClass;
+
+    private final String docletClassName;
+
+    private final ClassLoader appClassLoader;
+
+    private final Messager messager;
+
+    /**
+     * In API mode, exceptions thrown while calling the doclet are
+     * propagated using ClientCodeException.
+     */
+    private final boolean apiMode;
+
+    /**
+     * Whether javadoc internal API should be exported to doclets
+     * and (indirectly) to taglets
+     */
+    private final boolean exportInternalAPI;
+
+    private static class DocletInvokeException extends Exception {
+        private static final long serialVersionUID = 0;
+    }
+
+    private String appendPath(String path1, String path2) {
+        if (path1 == null || path1.length() == 0) {
+            return path2 == null ? "." : path2;
+        } else if (path2 == null || path2.length() == 0) {
+            return path1;
+        } else {
+            return path1  + File.pathSeparator + path2;
+        }
+    }
+
+    public DocletInvoker(Messager messager, Class<?> docletClass, boolean apiMode, boolean exportInternalAPI) {
+        this.messager = messager;
+        this.docletClass = docletClass;
+        docletClassName = docletClass.getName();
+        appClassLoader = null;
+        this.apiMode = apiMode;
+        this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets
+
+        // this may not be soon enough if the class has already been loaded
+        if (exportInternalAPI) {
+            exportInternalAPI(docletClass.getClassLoader());
+        }
+    }
+
+    public DocletInvoker(Messager messager, JavaFileManager fileManager,
+                         String docletClassName, String docletPath,
+                         ClassLoader docletParentClassLoader,
+                         boolean apiMode,
+                         boolean exportInternalAPI) {
+        this.messager = messager;
+        this.docletClassName = docletClassName;
+        this.apiMode = apiMode;
+        this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets
+
+        if (fileManager != null && fileManager.hasLocation(DocumentationTool.Location.DOCLET_PATH)) {
+            appClassLoader = fileManager.getClassLoader(DocumentationTool.Location.DOCLET_PATH);
+        } else {
+            // construct class loader
+            String cpString = null;   // make sure env.class.path defaults to dot
+
+            // do prepends to get correct ordering
+            cpString = appendPath(System.getProperty("env.class.path"), cpString);
+            cpString = appendPath(System.getProperty("java.class.path"), cpString);
+            cpString = appendPath(docletPath, cpString);
+            URL[] urls = pathToURLs(cpString);
+            if (docletParentClassLoader == null)
+                appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName));
+            else
+                appClassLoader = new URLClassLoader(urls, docletParentClassLoader);
+        }
+
+        if (exportInternalAPI) {
+            exportInternalAPI(appClassLoader);
+        }
+
+        // attempt to find doclet
+        Class<?> dc = null;
+        try {
+            dc = appClassLoader.loadClass(docletClassName);
+        } catch (ClassNotFoundException exc) {
+            messager.error(Messager.NOPOS, "main.doclet_class_not_found", docletClassName);
+            messager.exit();
+        }
+        docletClass = dc;
+    }
+
+    /*
+     * Returns the delegation class loader to use when creating
+     * appClassLoader (used to load the doclet).  The context class
+     * loader is the best choice, but legacy behavior was to use the
+     * default delegation class loader (aka system class loader).
+     *
+     * Here we favor using the context class loader.  To ensure
+     * compatibility with existing apps, we revert to legacy
+     * behavior if either or both of the following conditions hold:
+     *
+     * 1) the doclet is loadable from the system class loader but not
+     *    from the context class loader,
+     *
+     * 2) this.getClass() is loadable from the system class loader but not
+     *    from the context class loader.
+     */
+    private ClassLoader getDelegationClassLoader(String docletClassName) {
+        ClassLoader ctxCL = Thread.currentThread().getContextClassLoader();
+        ClassLoader sysCL = ClassLoader.getSystemClassLoader();
+        if (sysCL == null)
+            return ctxCL;
+        if (ctxCL == null)
+            return sysCL;
+
+        // Condition 1.
+        try {
+            sysCL.loadClass(docletClassName);
+            try {
+                ctxCL.loadClass(docletClassName);
+            } catch (ClassNotFoundException e) {
+                return sysCL;
+            }
+        } catch (ClassNotFoundException e) {
+        }
+
+        // Condition 2.
+        try {
+            if (getClass() == sysCL.loadClass(getClass().getName())) {
+                try {
+                    if (getClass() != ctxCL.loadClass(getClass().getName()))
+                        return sysCL;
+                } catch (ClassNotFoundException e) {
+                    return sysCL;
+                }
+            }
+        } catch (ClassNotFoundException e) {
+        }
+
+        return ctxCL;
+    }
+
+    /**
+     * Generate documentation here.  Return true on success.
+     */
+    public boolean start(RootDoc root) {
+        Object retVal;
+        String methodName = "start";
+        Class<?>[] paramTypes = { RootDoc.class };
+        Object[] params = { root };
+        try {
+            retVal = invoke(methodName, null, paramTypes, params);
+        } catch (DocletInvokeException exc) {
+            return false;
+        }
+        if (retVal instanceof Boolean) {
+            return ((Boolean)retVal);
+        } else {
+            messager.error(Messager.NOPOS, "main.must_return_boolean",
+                           docletClassName, methodName);
+            return false;
+        }
+    }
+
+    /**
+     * Check for doclet added options here. Zero return means
+     * option not known.  Positive value indicates number of
+     * arguments to option.  Negative value means error occurred.
+     */
+    public int optionLength(String option) {
+        Object retVal;
+        String methodName = "optionLength";
+        Class<?>[] paramTypes = { String.class };
+        Object[] params = { option };
+        try {
+            retVal = invoke(methodName, 0, paramTypes, params);
+        } catch (DocletInvokeException exc) {
+            return -1;
+        }
+        if (retVal instanceof Integer) {
+            return ((Integer)retVal);
+        } else {
+            messager.error(Messager.NOPOS, "main.must_return_int",
+                           docletClassName, methodName);
+            return -1;
+        }
+    }
+
+    /**
+     * Let doclet check that all options are OK. Returning true means
+     * options are OK.  If method does not exist, assume true.
+     */
+    public boolean validOptions(List<String[]> optlist) {
+        Object retVal;
+        String options[][] = optlist.toArray(new String[optlist.length()][]);
+        String methodName = "validOptions";
+        DocErrorReporter reporter = messager;
+        Class<?>[] paramTypes = { String[][].class, DocErrorReporter.class };
+        Object[] params = { options, reporter };
+        try {
+            retVal = invoke(methodName, Boolean.TRUE, paramTypes, params);
+        } catch (DocletInvokeException exc) {
+            return false;
+        }
+        if (retVal instanceof Boolean) {
+            return ((Boolean)retVal);
+        } else {
+            messager.error(Messager.NOPOS, "main.must_return_boolean",
+                           docletClassName, methodName);
+            return false;
+        }
+    }
+
+    /**
+     * Return the language version supported by this doclet.
+     * If the method does not exist in the doclet, assume version 1.1.
+     */
+    public LanguageVersion languageVersion() {
+        try {
+            Object retVal;
+            String methodName = "languageVersion";
+            Class<?>[] paramTypes = new Class<?>[0];
+            Object[] params = new Object[0];
+            try {
+                retVal = invoke(methodName, JAVA_1_1, paramTypes, params);
+            } catch (DocletInvokeException exc) {
+                return JAVA_1_1;
+            }
+            if (retVal instanceof LanguageVersion) {
+                return (LanguageVersion)retVal;
+            } else {
+                messager.error(Messager.NOPOS, "main.must_return_languageversion",
+                               docletClassName, methodName);
+                return JAVA_1_1;
+            }
+        } catch (NoClassDefFoundError ex) { // for boostrapping, no Enum class.
+            return null;
+        }
+    }
+
+    /**
+     * Utility method for calling doclet functionality
+     */
+    private Object invoke(String methodName, Object returnValueIfNonExistent,
+                          Class<?>[] paramTypes, Object[] params)
+        throws DocletInvokeException {
+            Method meth;
+            try {
+                meth = docletClass.getMethod(methodName, paramTypes);
+            } catch (NoSuchMethodException exc) {
+                if (returnValueIfNonExistent == null) {
+                    messager.error(Messager.NOPOS, "main.doclet_method_not_found",
+                                   docletClassName, methodName);
+                    throw new DocletInvokeException();
+                } else {
+                    return returnValueIfNonExistent;
+                }
+            } catch (SecurityException exc) {
+                messager.error(Messager.NOPOS, "main.doclet_method_not_accessible",
+                               docletClassName, methodName);
+                throw new DocletInvokeException();
+            }
+            if (!Modifier.isStatic(meth.getModifiers())) {
+                messager.error(Messager.NOPOS, "main.doclet_method_must_be_static",
+                               docletClassName, methodName);
+                throw new DocletInvokeException();
+            }
+            ClassLoader savedCCL =
+                Thread.currentThread().getContextClassLoader();
+            try {
+                if (appClassLoader != null) // will be null if doclet class provided via API
+                    Thread.currentThread().setContextClassLoader(appClassLoader);
+                return meth.invoke(null , params);
+            } catch (IllegalArgumentException | NullPointerException exc) {
+                messager.error(Messager.NOPOS, "main.internal_error_exception_thrown",
+                               docletClassName, methodName, exc.toString());
+                throw new DocletInvokeException();
+            } catch (IllegalAccessException exc) {
+                messager.error(Messager.NOPOS, "main.doclet_method_not_accessible",
+                               docletClassName, methodName);
+                throw new DocletInvokeException();
+            }
+            catch (InvocationTargetException exc) {
+                Throwable err = exc.getTargetException();
+                if (apiMode)
+                    throw new ClientCodeException(err);
+                if (err instanceof java.lang.OutOfMemoryError) {
+                    messager.error(Messager.NOPOS, "main.out.of.memory");
+                } else {
+                    messager.error(Messager.NOPOS, "main.exception_thrown",
+                               docletClassName, methodName, exc.toString());
+                    exc.getTargetException().printStackTrace(System.err);
+                }
+                throw new DocletInvokeException();
+            } finally {
+                Thread.currentThread().setContextClassLoader(savedCCL);
+            }
+    }
+
+    /**
+     * Export javadoc internal API to the unnamed module for a classloader.
+     * This is to support continued use of existing non-standard doclets that
+     * use the internal toolkit API and related classes.
+     * @param cl the classloader
+     */
+    private void exportInternalAPI(ClassLoader cl) {
+        String[] packages = {
+            "com.sun.tools.doclets",
+            "com.sun.tools.doclets.standard",
+            "com.sun.tools.doclets.internal.toolkit",
+            "com.sun.tools.doclets.internal.toolkit.taglets",
+            "com.sun.tools.doclets.internal.toolkit.builders",
+            "com.sun.tools.doclets.internal.toolkit.util",
+            "com.sun.tools.doclets.internal.toolkit.util.links",
+            "com.sun.tools.doclets.formats.html",
+            "com.sun.tools.doclets.formats.html.markup"
+        };
+
+        try {
+            Method getModuleMethod = Class.class.getDeclaredMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(getClass());
+
+            Class<?> moduleClass = Class.forName("java.lang.reflect.Module");
+            Method addExportsMethod = moduleClass.getDeclaredMethod("addExports", String.class, moduleClass);
+
+            Method getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule");
+            Object target = getUnnamedModuleMethod.invoke(cl);
+
+            for (String pack : packages) {
+                addExportsMethod.invoke(thisModule, pack, target);
+            }
+        } catch (Exception e) {
+            // do nothing
+        }
+    }
+
+    /**
+     * Utility method for converting a search path string to an array of directory and JAR file
+     * URLs.
+     *
+     * Note that this method is called by the DocletInvoker.
+     *
+     * @param path the search path string
+     * @return the resulting array of directory and JAR file URLs
+     */
+    private static URL[] pathToURLs(String path) {
+        java.util.List<URL> urls = new ArrayList<>();
+        for (String s: path.split(Pattern.quote(File.pathSeparator))) {
+            if (!s.isEmpty()) {
+                URL url = fileToURL(Paths.get(s));
+                if (url != null) {
+                    urls.add(url);
+                }
+            }
+        }
+        return urls.toArray(new URL[urls.size()]);
+    }
+
+    /**
+     * Returns the directory or JAR file URL corresponding to the specified local file name.
+     *
+     * @param file the Path object
+     * @return the resulting directory or JAR file URL, or null if unknown
+     */
+    private static URL fileToURL(Path file) {
+        Path p;
+        try {
+            p = file.toRealPath();
+        } catch (IOException e) {
+            p = file.toAbsolutePath();
+        }
+        try {
+            return p.normalize().toUri().toURL();
+        } catch (MalformedURLException e) {
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ExecutableMemberDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import java.lang.reflect.Modifier;
+import java.text.CollationKey;
+
+import com.sun.javadoc.*;
+
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+
+/**
+ * Represents a method or constructor of a java class.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since 1.2
+ * @author Robert Field
+ * @author Neal Gafter (rewrite)
+ * @author Scott Seligman (generics, annotations)
+ */
+
+public abstract class ExecutableMemberDocImpl
+        extends MemberDocImpl implements ExecutableMemberDoc {
+
+    protected final MethodSymbol sym;
+
+    /**
+     * Constructor.
+     */
+    public ExecutableMemberDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) {
+        super(env, sym, treePath);
+        this.sym = sym;
+    }
+
+    /**
+     * Constructor.
+     */
+    public ExecutableMemberDocImpl(DocEnv env, MethodSymbol sym) {
+        this(env, sym, null);
+    }
+
+    /**
+     * Returns the flags in terms of javac's flags
+     */
+    protected long getFlags() {
+        return sym.flags();
+    }
+
+    /**
+     * Identify the containing class
+     */
+    protected ClassSymbol getContainingClass() {
+        return sym.enclClass();
+    }
+
+    /**
+     * Return true if this method is native
+     */
+    public boolean isNative() {
+        return Modifier.isNative(getModifiers());
+    }
+
+    /**
+     * Return true if this method is synchronized
+     */
+    public boolean isSynchronized() {
+        return Modifier.isSynchronized(getModifiers());
+    }
+
+    /**
+     * Return true if this method was declared to take a variable number
+     * of arguments.
+     */
+    public boolean isVarArgs() {
+        return ((sym.flags() & Flags.VARARGS) != 0
+                && !env.legacyDoclet);
+    }
+
+    /**
+     * Returns true if this field was synthesized by the compiler.
+     */
+    public boolean isSynthetic() {
+        return ((sym.flags() & Flags.SYNTHETIC) != 0);
+    }
+
+    public boolean isIncluded() {
+        return containingClass().isIncluded() && env.shouldDocument(sym);
+    }
+
+    /**
+     * Return the throws tags in this method.
+     *
+     * @return an array of ThrowTagImpl containing all {@code @exception}
+     * and {@code @throws} tags.
+     */
+    public ThrowsTag[] throwsTags() {
+        return comment().throwsTags();
+    }
+
+    /**
+     * Return the param tags in this method, excluding the type
+     * parameter tags.
+     *
+     * @return an array of ParamTagImpl containing all {@code @param} tags.
+     */
+    public ParamTag[] paramTags() {
+        return comment().paramTags();
+    }
+
+    /**
+     * Return the type parameter tags in this method.
+     */
+    public ParamTag[] typeParamTags() {
+        return env.legacyDoclet
+            ? new ParamTag[0]
+            : comment().typeParamTags();
+    }
+
+    /**
+     * Return exceptions this method or constructor throws.
+     *
+     * @return an array of ClassDoc[] representing the exceptions
+     * thrown by this method.
+     */
+    public ClassDoc[] thrownExceptions() {
+        ListBuffer<ClassDocImpl> l = new ListBuffer<>();
+        for (Type ex : sym.type.getThrownTypes()) {
+            ex = env.types.erasure(ex);
+            //### Will these casts succeed in the face of static semantic
+            //### errors in the documented code?
+            ClassDocImpl cdi = env.getClassDoc((ClassSymbol)ex.tsym);
+            if (cdi != null) l.append(cdi);
+        }
+        return l.toArray(new ClassDocImpl[l.length()]);
+    }
+
+    /**
+     * Return exceptions this method or constructor throws.
+     * Each array element is either a <code>ClassDoc</code> or a
+     * <code>TypeVariable</code>.
+     */
+    public com.sun.javadoc.Type[] thrownExceptionTypes() {
+        return TypeMaker.getTypes(env, sym.type.getThrownTypes());
+    }
+
+    /**
+     * Get argument information.
+     *
+     * @see ParameterImpl
+     *
+     * @return an array of ParameterImpl, one element per argument
+     * in the order the arguments are present.
+     */
+    public Parameter[] parameters() {
+        // generate the parameters on the fly:  they're not cached
+        List<VarSymbol> params = sym.params();
+        Parameter result[] = new Parameter[params.length()];
+
+        int i = 0;
+        for (VarSymbol param : params) {
+            result[i++] = new ParameterImpl(env, param);
+        }
+        return result;
+    }
+
+    /**
+     * Get the receiver type of this executable element.
+     *
+     * @return the receiver type of this executable element.
+     * @since 1.8
+     */
+    public com.sun.javadoc.Type receiverType() {
+        Type recvtype = sym.type.asMethodType().recvtype;
+        return (recvtype != null) ? TypeMaker.getType(env, recvtype, false, true) : null;
+    }
+
+    /**
+     * Return the formal type parameters of this method or constructor.
+     * Return an empty array if there are none.
+     */
+    public TypeVariable[] typeParameters() {
+        if (env.legacyDoclet) {
+            return new TypeVariable[0];
+        }
+        TypeVariable res[] = new TypeVariable[sym.type.getTypeArguments().length()];
+        TypeMaker.getTypes(env, sym.type.getTypeArguments(), res);
+        return res;
+    }
+
+    /**
+     * Get the signature. It is the parameter list, type is qualified.
+     * For instance, for a method <code>mymethod(String x, int y)</code>,
+     * it will return <code>(java.lang.String,int)</code>.
+     */
+    public String signature() {
+        return makeSignature(true);
+    }
+
+    /**
+     * Get flat signature.  All types are not qualified.
+     * Return a String, which is the flat signiture of this member.
+     * It is the parameter list, type is not qualified.
+     * For instance, for a method <code>mymethod(String x, int y)</code>,
+     * it will return <code>(String, int)</code>.
+     */
+    public String flatSignature() {
+        return makeSignature(false);
+    }
+
+    private String makeSignature(boolean full) {
+        StringBuilder result = new StringBuilder();
+        result.append("(");
+        for (List<Type> types = sym.type.getParameterTypes(); types.nonEmpty(); ) {
+            Type t = types.head;
+            result.append(TypeMaker.getTypeString(env, t, full));
+            types = types.tail;
+            if (types.nonEmpty()) {
+                result.append(", ");
+            }
+        }
+        if (isVarArgs()) {
+            int len = result.length();
+            result.replace(len - 2, len, "...");
+        }
+        result.append(")");
+        return result.toString();
+    }
+
+    protected String typeParametersString() {
+        return TypeMaker.typeParametersString(env, sym, true);
+    }
+
+    /**
+     * Generate a key for sorting.
+     */
+    @Override
+    CollationKey generateKey() {
+        String k = name() + flatSignature() + typeParametersString();
+        // ',' and '&' are between '$' and 'a':  normalize to spaces.
+        k = k.replace(',', ' ').replace('&', ' ');
+        // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
+        return env.doclocale.collator.getCollationKey(k);
+    }
+
+    /**
+     * Return the source position of the entity, or null if
+     * no position is available.
+     */
+    @Override
+    public SourcePosition position() {
+        if (sym.enclClass().sourcefile == null) return null;
+        return SourcePositionImpl.make(sym.enclClass().sourcefile,
+                                       (tree==null) ? 0 : tree.pos,
+                                       lineMap);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/FieldDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.source.util.TreePath;
+import java.lang.reflect.Modifier;
+
+import com.sun.javadoc.*;
+
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
+
+import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
+
+/**
+ * Represents a field in a java class.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @see MemberDocImpl
+ *
+ * @since 1.2
+ * @author Robert Field
+ * @author Neal Gafter (rewrite)
+ * @author Scott Seligman (generics, enums, annotations)
+ */
+public class FieldDocImpl extends MemberDocImpl implements FieldDoc {
+
+    protected final VarSymbol sym;
+
+    /**
+     * Constructor.
+     */
+    public FieldDocImpl(DocEnv env, VarSymbol sym, TreePath treePath) {
+        super(env, sym, treePath);
+        this.sym = sym;
+    }
+
+    /**
+     * Constructor.
+     */
+    public FieldDocImpl(DocEnv env, VarSymbol sym) {
+        this(env, sym, null);
+    }
+
+    /**
+     * Returns the flags in terms of javac's flags
+     */
+    protected long getFlags() {
+        return sym.flags();
+    }
+
+    /**
+     * Identify the containing class
+     */
+    protected ClassSymbol getContainingClass() {
+        return sym.enclClass();
+    }
+
+    /**
+     * Get type of this field.
+     */
+    public com.sun.javadoc.Type type() {
+        return TypeMaker.getType(env, sym.type, false);
+    }
+
+    /**
+     * Get the value of a constant field.
+     *
+     * @return the value of a constant field. The value is
+     * automatically wrapped in an object if it has a primitive type.
+     * If the field is not constant, returns null.
+     */
+    public Object constantValue() {
+        Object result = sym.getConstValue();
+        if (result != null && sym.type.hasTag(BOOLEAN))
+            // javac represents false and true as Integers 0 and 1
+            result = Boolean.valueOf(((Integer)result).intValue() != 0);
+        return result;
+    }
+
+    /**
+     * Get the value of a constant field.
+     *
+     * @return the text of a Java language expression whose value
+     * is the value of the constant. The expression uses no identifiers
+     * other than primitive literals. If the field is
+     * not constant, returns null.
+     */
+    public String constantValueExpression() {
+        return constantValueExpression(constantValue());
+    }
+
+    /**
+     * A static version of the above.
+     */
+    static String constantValueExpression(Object cb) {
+        if (cb == null) return null;
+        if (cb instanceof Character) return sourceForm(((Character)cb).charValue());
+        if (cb instanceof Byte) return sourceForm(((Byte)cb).byteValue());
+        if (cb instanceof String) return sourceForm((String)cb);
+        if (cb instanceof Double) return sourceForm(((Double)cb).doubleValue(), 'd');
+        if (cb instanceof Float) return sourceForm(((Float)cb).doubleValue(), 'f');
+        if (cb instanceof Long) return cb + "L";
+        return cb.toString(); // covers int, short
+    }
+        // where
+        private static String sourceForm(double v, char suffix) {
+            if (Double.isNaN(v))
+                return "0" + suffix + "/0" + suffix;
+            if (v == Double.POSITIVE_INFINITY)
+                return "1" + suffix + "/0" + suffix;
+            if (v == Double.NEGATIVE_INFINITY)
+                return "-1" + suffix + "/0" + suffix;
+            return v + (suffix == 'f' || suffix == 'F' ? "" + suffix : "");
+        }
+        private static String sourceForm(char c) {
+            StringBuilder buf = new StringBuilder(8);
+            buf.append('\'');
+            sourceChar(c, buf);
+            buf.append('\'');
+            return buf.toString();
+        }
+        private static String sourceForm(byte c) {
+            return "0x" + Integer.toString(c & 0xff, 16);
+        }
+        private static String sourceForm(String s) {
+            StringBuilder buf = new StringBuilder(s.length() + 5);
+            buf.append('\"');
+            for (int i=0; i<s.length(); i++) {
+                char c = s.charAt(i);
+                sourceChar(c, buf);
+            }
+            buf.append('\"');
+            return buf.toString();
+        }
+        private static void sourceChar(char c, StringBuilder buf) {
+            switch (c) {
+            case '\b': buf.append("\\b"); return;
+            case '\t': buf.append("\\t"); return;
+            case '\n': buf.append("\\n"); return;
+            case '\f': buf.append("\\f"); return;
+            case '\r': buf.append("\\r"); return;
+            case '\"': buf.append("\\\""); return;
+            case '\'': buf.append("\\\'"); return;
+            case '\\': buf.append("\\\\"); return;
+            default:
+                if (isPrintableAscii(c)) {
+                    buf.append(c); return;
+                }
+                unicodeEscape(c, buf);
+                return;
+            }
+        }
+        private static void unicodeEscape(char c, StringBuilder buf) {
+            final String chars = "0123456789abcdef";
+            buf.append("\\u");
+            buf.append(chars.charAt(15 & (c>>12)));
+            buf.append(chars.charAt(15 & (c>>8)));
+            buf.append(chars.charAt(15 & (c>>4)));
+            buf.append(chars.charAt(15 & (c>>0)));
+        }
+        private static boolean isPrintableAscii(char c) {
+            return c >= ' ' && c <= '~';
+        }
+
+    /**
+     * Return true if this field is included in the active set.
+     */
+    public boolean isIncluded() {
+        return containingClass().isIncluded() && env.shouldDocument(sym);
+    }
+
+    /**
+     * Is this Doc item a field (but not an enum constant?
+     */
+    @Override
+    public boolean isField() {
+        return !isEnumConstant();
+    }
+
+    /**
+     * Is this Doc item an enum constant?
+     * (For legacy doclets, return false.)
+     */
+    @Override
+    public boolean isEnumConstant() {
+        return (getFlags() & Flags.ENUM) != 0 &&
+               !env.legacyDoclet;
+    }
+
+    /**
+     * Return true if this field is transient
+     */
+    public boolean isTransient() {
+        return Modifier.isTransient(getModifiers());
+    }
+
+    /**
+     * Return true if this field is volatile
+     */
+    public boolean isVolatile() {
+        return Modifier.isVolatile(getModifiers());
+    }
+
+    /**
+     * Returns true if this field was synthesized by the compiler.
+     */
+    public boolean isSynthetic() {
+        return (getFlags() & Flags.SYNTHETIC) != 0;
+    }
+
+    /**
+     * Return the serialField tags in this FieldDocImpl item.
+     *
+     * @return an array of <tt>SerialFieldTagImpl</tt> containing all
+     *         <code>&#64;serialField</code> tags.
+     */
+    public SerialFieldTag[] serialFieldTags() {
+        return comment().serialFieldTags();
+    }
+
+    public String name() {
+        if (name == null) {
+            name = sym.name.toString();
+        }
+        return name;
+    }
+
+    private String name;
+
+    public String qualifiedName() {
+        if (qualifiedName == null) {
+            qualifiedName = sym.enclClass().getQualifiedName() + "." + name();
+        }
+        return qualifiedName;
+    }
+
+    private String qualifiedName;
+
+    /**
+     * Return the source position of the entity, or null if
+     * no position is available.
+     */
+    @Override
+    public SourcePosition position() {
+        if (sym.enclClass().sourcefile == null) return null;
+        return SourcePositionImpl.make(sym.enclClass().sourcefile,
+                                       (tree==null) ? 0 : tree.pos,
+                                       lineMap);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocClassFinder.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2001, 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 com.sun.tools.javadoc.main;
+
+import java.util.EnumSet;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.code.ClassFinder;
+import com.sun.tools.javac.util.Context;
+
+/** Javadoc uses an extended class finder that records package.html entries
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ *  @author Neal Gafter
+ */
+public class JavadocClassFinder extends ClassFinder {
+
+    public static JavadocClassFinder instance(Context context) {
+        ClassFinder instance = context.get(classFinderKey);
+        if (instance == null)
+            instance = new JavadocClassFinder(context);
+        return (JavadocClassFinder)instance;
+    }
+
+    public static void preRegister(Context context) {
+        context.put(classFinderKey, new Context.Factory<ClassFinder>() {
+            public ClassFinder make(Context c) {
+                return new JavadocClassFinder(c);
+            }
+        });
+    }
+
+    private DocEnv docenv;
+    private EnumSet<JavaFileObject.Kind> all = EnumSet.of(JavaFileObject.Kind.CLASS,
+                                                          JavaFileObject.Kind.SOURCE,
+                                                          JavaFileObject.Kind.HTML);
+    private EnumSet<JavaFileObject.Kind> noSource = EnumSet.of(JavaFileObject.Kind.CLASS,
+                                                               JavaFileObject.Kind.HTML);
+
+    public JavadocClassFinder(Context context) {
+        super(context);
+        docenv = DocEnv.instance(context);
+        preferSource = true;
+    }
+
+    /**
+     * Override getPackageFileKinds to include search for package.html
+     */
+    @Override
+    protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
+        return docenv.docClasses ? noSource : all;
+    }
+
+    /**
+     * Override extraFileActions to check for package documentation
+     */
+    @Override
+    protected void extraFileActions(PackageSymbol pack, JavaFileObject fo) {
+        if (fo.isNameCompatible("package", JavaFileObject.Kind.HTML))
+            docenv.getPackageDoc(pack).setDocPath(fo);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocEnter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2001, 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 com.sun.tools.javadoc.main;
+
+import javax.tools.JavaFileObject;
+
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.comp.Enter;
+import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.List;
+
+import static com.sun.tools.javac.code.Kinds.Kind.*;
+
+/**
+ *  Javadoc's own enter phase does a few things above and beyond that
+ *  done by javac.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ *  @author Neal Gafter
+ */
+public class JavadocEnter extends Enter {
+    public static JavadocEnter instance(Context context) {
+        Enter instance = context.get(enterKey);
+        if (instance == null)
+            instance = new JavadocEnter(context);
+        return (JavadocEnter)instance;
+    }
+
+    public static void preRegister(Context context) {
+        context.put(enterKey, new Context.Factory<Enter>() {
+               public Enter make(Context c) {
+                   return new JavadocEnter(c);
+               }
+        });
+    }
+
+    protected JavadocEnter(Context context) {
+        super(context);
+        messager = Messager.instance0(context);
+        docenv = DocEnv.instance(context);
+    }
+
+    final Messager messager;
+    final DocEnv docenv;
+
+    @Override
+    public void main(List<JCCompilationUnit> trees) {
+        // count all Enter errors as warnings.
+        int nerrors = messager.nerrors;
+        super.main(trees);
+        messager.nwarnings += (messager.nerrors - nerrors);
+        messager.nerrors = nerrors;
+    }
+
+    @Override
+    public void visitTopLevel(JCCompilationUnit tree) {
+        super.visitTopLevel(tree);
+        if (tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE)) {
+            JCPackageDecl pd = tree.getPackage();
+            TreePath tp = pd == null ? docenv.getTreePath(tree) : docenv.getTreePath(tree, pd);
+            docenv.makePackageDoc(tree.packge, tp);
+        }
+    }
+
+    @Override
+    public void visitClassDef(JCClassDecl tree) {
+        super.visitClassDef(tree);
+        if (tree.sym == null) return;
+        if (tree.sym.kind == TYP || tree.sym.kind == ERR) {
+            ClassSymbol c = tree.sym;
+            docenv.makeClassDoc(c, docenv.getTreePath(env.toplevel, tree));
+        }
+    }
+
+    /** Don't complain about a duplicate class. */
+    @Override
+    protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) {}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocMemberEnter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.comp.MemberEnter;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.util.Context;
+
+import static com.sun.tools.javac.code.Flags.*;
+import static com.sun.tools.javac.code.Kinds.Kind.*;
+
+/**
+ *  Javadoc's own memberEnter phase does a few things above and beyond that
+ *  done by javac.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ *  @author Neal Gafter
+ */
+public class JavadocMemberEnter extends MemberEnter {
+    public static JavadocMemberEnter instance0(Context context) {
+        MemberEnter instance = context.get(memberEnterKey);
+        if (instance == null)
+            instance = new JavadocMemberEnter(context);
+        return (JavadocMemberEnter)instance;
+    }
+
+    public static void preRegister(Context context) {
+        context.put(memberEnterKey, new Context.Factory<MemberEnter>() {
+               public MemberEnter make(Context c) {
+                   return new JavadocMemberEnter(c);
+               }
+        });
+    }
+
+    final DocEnv docenv;
+
+    protected JavadocMemberEnter(Context context) {
+        super(context);
+        docenv = DocEnv.instance(context);
+    }
+
+    @Override
+    public void visitMethodDef(JCMethodDecl tree) {
+        super.visitMethodDef(tree);
+        MethodSymbol meth = tree.sym;
+        if (meth == null || meth.kind != MTH) return;
+        TreePath treePath = docenv.getTreePath(env.toplevel, env.enclClass, tree);
+        if (meth.isConstructor())
+            docenv.makeConstructorDoc(meth, treePath);
+        else if (isAnnotationTypeElement(meth))
+            docenv.makeAnnotationTypeElementDoc(meth, treePath);
+        else
+            docenv.makeMethodDoc(meth, treePath);
+
+        // release resources
+        tree.body = null;
+    }
+
+    @Override
+    public void visitVarDef(JCVariableDecl tree) {
+        if (tree.init != null) {
+            boolean isFinal = (tree.mods.flags & FINAL) != 0
+                    || (env.enclClass.mods.flags & INTERFACE) != 0;
+            if (!isFinal || containsNonConstantExpression(tree.init)) {
+                // Avoid unnecessary analysis and release resources.
+                // In particular, remove non-constant expressions
+                // which may trigger Attr.attribClass, since
+                // method bodies are also removed, in visitMethodDef.
+                tree.init = null;
+            }
+        }
+        super.visitVarDef(tree);
+        if (tree.sym != null &&
+                tree.sym.kind == VAR &&
+                !isParameter(tree.sym)) {
+            docenv.makeFieldDoc(tree.sym, docenv.getTreePath(env.toplevel, env.enclClass, tree));
+        }
+    }
+
+    private static boolean isAnnotationTypeElement(MethodSymbol meth) {
+        return ClassDocImpl.isAnnotationType(meth.enclClass());
+    }
+
+    private static boolean isParameter(VarSymbol var) {
+        return (var.flags() & Flags.PARAMETER) != 0;
+    }
+
+    /**
+     * Simple analysis of an expression tree to see if it contains tree nodes
+     * for any non-constant expression. This does not include checking references
+     * to other fields which may or may not be constant.
+     */
+    private static boolean containsNonConstantExpression(JCExpression tree) {
+        return new MaybeConstantExpressionScanner().containsNonConstantExpression(tree);
+    }
+
+    /**
+     * See JLS 15.18, Constant Expression
+     */
+    private static class MaybeConstantExpressionScanner extends JCTree.Visitor {
+        boolean maybeConstantExpr = true;
+
+        public boolean containsNonConstantExpression(JCExpression tree) {
+            scan(tree);
+            return !maybeConstantExpr;
+        }
+
+        public void scan(JCTree tree) {
+            // short circuit scan when end result is definitely false
+            if (maybeConstantExpr && tree != null)
+                tree.accept(this);
+        }
+
+        @Override
+        /** default for any non-overridden visit method. */
+        public void visitTree(JCTree tree) {
+            maybeConstantExpr = false;
+        }
+
+        @Override
+        public void visitBinary(JCBinary tree) {
+            switch (tree.getTag()) {
+                case MUL: case DIV: case MOD:
+                case PLUS: case MINUS:
+                case SL: case SR: case USR:
+                case LT: case LE: case GT: case GE:
+                case EQ: case NE:
+                case BITAND: case BITXOR: case BITOR:
+                case AND: case OR:
+                    break;
+                default:
+                    maybeConstantExpr = false;
+            }
+        }
+
+        @Override
+        public void visitConditional(JCConditional tree) {
+            scan(tree.cond);
+            scan(tree.truepart);
+            scan(tree.falsepart);
+        }
+
+        @Override
+        public void visitIdent(JCIdent tree) { }
+
+        @Override
+        public void visitLiteral(JCLiteral tree) { }
+
+        @Override
+        public void visitParens(JCParens tree) {
+            scan(tree.expr);
+        }
+
+        @Override
+        public void visitSelect(JCTree.JCFieldAccess tree) {
+            scan(tree.selected);
+        }
+
+        @Override
+        public void visitTypeCast(JCTypeCast tree) {
+            scan(tree.clazz);
+            scan(tree.expr);
+        }
+
+        @Override
+        public void visitTypeIdent(JCPrimitiveTypeTree tree) { }
+
+        @Override
+        public void visitUnary(JCUnary tree) {
+            switch (tree.getTag()) {
+                case POS: case NEG: case COMPL: case NOT:
+                    break;
+                default:
+                    maybeConstantExpr = false;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTodo.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2003, 2012, 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.sun.tools.javadoc.main;
+
+import com.sun.tools.javac.comp.*;
+import com.sun.tools.javac.util.*;
+
+/**
+ *  Javadoc's own todo queue doesn't queue its inputs, as javadoc
+ *  doesn't perform attribution of method bodies or semantic checking.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ *  @author Neal Gafter
+ */
+public class JavadocTodo extends Todo {
+    public static void preRegister(Context context) {
+        context.put(todoKey, new Context.Factory<Todo>() {
+               public Todo make(Context c) {
+                   return new JavadocTodo(c);
+               }
+        });
+    }
+
+    protected JavadocTodo(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void append(Env<AttrContext> e) {
+        // do nothing; Javadoc doesn't perform attribution.
+    }
+
+    @Override
+    public boolean offer(Env<AttrContext> e) {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,430 @@
+/*
+ * 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
+ * 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.sun.tools.javadoc.main;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.code.ClassFinder;
+import com.sun.tools.javac.code.Symbol.Completer;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.comp.Enter;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.Abort;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+
+
+/**
+ *  This class could be the main entry point for Javadoc when Javadoc is used as a
+ *  component in a larger software system. It provides operations to
+ *  construct a new javadoc processor, and to run it on a set of source
+ *  files.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ *  @author Neal Gafter
+ */
+public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
+    DocEnv docenv;
+
+    final Messager messager;
+    final ClassFinder javadocFinder;
+    final Enter javadocEnter;
+    final Set<JavaFileObject> uniquefiles;
+
+    /**
+     * Construct a new JavaCompiler processor, using appropriately
+     * extended phases of the underlying compiler.
+     */
+    protected JavadocTool(Context context) {
+        super(context);
+        messager = Messager.instance0(context);
+        javadocFinder = JavadocClassFinder.instance(context);
+        javadocEnter = JavadocEnter.instance(context);
+        uniquefiles = new HashSet<>();
+    }
+
+    /**
+     * For javadoc, the parser needs to keep comments. Overrides method from JavaCompiler.
+     */
+    @Override
+    protected boolean keepComments() {
+        return true;
+    }
+
+    /**
+     *  Construct a new javadoc tool.
+     */
+    public static JavadocTool make0(Context context) {
+        // force the use of Javadoc's class finder
+        JavadocClassFinder.preRegister(context);
+
+        // force the use of Javadoc's own enter phase
+        JavadocEnter.preRegister(context);
+
+        // force the use of Javadoc's own member enter phase
+        JavadocMemberEnter.preRegister(context);
+
+        // force the use of Javadoc's own todo phase
+        JavadocTodo.preRegister(context);
+
+        // force the use of Messager as a Log
+        Messager.instance0(context);
+
+        return new JavadocTool(context);
+    }
+
+    public RootDocImpl getRootDocImpl(String doclocale,
+                                      String encoding,
+                                      ModifierFilter filter,
+                                      List<String> args,
+                                      List<String[]> options,
+                                      Iterable<? extends JavaFileObject> fileObjects,
+                                      boolean breakiterator,
+                                      List<String> subPackages,
+                                      List<String> excludedPackages,
+                                      boolean docClasses,
+                                      boolean legacyDoclet,
+                      boolean quiet) throws IOException {
+        docenv = DocEnv.instance(context);
+        docenv.showAccess = filter;
+        docenv.quiet = quiet;
+        docenv.breakiterator = breakiterator;
+        docenv.setLocale(doclocale);
+        docenv.setEncoding(encoding);
+        docenv.docClasses = docClasses;
+        docenv.legacyDoclet = legacyDoclet;
+
+        javadocFinder.sourceCompleter = docClasses ? Completer.NULL_COMPLETER : sourceCompleter;
+
+        if (docClasses) {
+            // If -Xclasses is set, the args should be a series of class names
+            for (String arg: args) {
+                if (!isValidPackageName(arg)) // checks
+                    docenv.error(null, "main.illegal_class_name", arg);
+            }
+            if (messager.nerrors() != 0) {
+                return null;
+            }
+            return new RootDocImpl(docenv, args, options);
+        }
+
+        ListBuffer<JCCompilationUnit> classTrees = new ListBuffer<>();
+        Set<String> includedPackages = new LinkedHashSet<>();
+
+        try {
+            StandardJavaFileManager fm = docenv.fileManager instanceof StandardJavaFileManager
+                    ? (StandardJavaFileManager) docenv.fileManager : null;
+            Set<String> packageNames = new LinkedHashSet<>();
+            // Normally, the args should be a series of package names or file names.
+            // Parse the files and collect the package names.
+            for (String arg: args) {
+                if (fm != null && arg.endsWith(".java") && new File(arg).exists()) {
+                    if (new File(arg).getName().equals("module-info.java")) {
+                        docenv.warning(null, "main.file_ignored", arg);
+                    } else {
+                        parse(fm.getJavaFileObjects(arg), classTrees, true);
+                    }
+                } else if (isValidPackageName(arg)) {
+                    packageNames.add(arg);
+                } else if (arg.endsWith(".java")) {
+                    if (fm == null)
+                        throw new IllegalArgumentException();
+                    else
+                        docenv.error(null, "main.file_not_found", arg);
+                } else {
+                    docenv.error(null, "main.illegal_package_name", arg);
+                }
+            }
+
+            // Parse file objects provide via the DocumentationTool API
+            parse(fileObjects, classTrees, true);
+            modules.enter(classTrees.toList(), null);
+
+            syms.unnamedModule.complete(); // TEMP to force reading all named modules
+
+            // Build up the complete list of any packages to be documented
+            Location location =
+                    modules.multiModuleMode && !modules.noModules ? StandardLocation.MODULE_SOURCE_PATH
+                    : docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH
+                    : StandardLocation.CLASS_PATH;
+
+            PackageTable t = new PackageTable(docenv.fileManager, location)
+                    .packages(packageNames)
+                    .subpackages(subPackages, excludedPackages);
+
+            includedPackages = t.getIncludedPackages();
+
+            // Parse the files in the packages to be documented
+            ListBuffer<JCCompilationUnit> packageTrees = new ListBuffer<>();
+            for (String packageName: includedPackages) {
+                List<JavaFileObject> files = t.getFiles(packageName);
+                docenv.notice("main.Loading_source_files_for_package", packageName);
+
+                if (files.isEmpty())
+                    messager.warning(Messager.NOPOS, "main.no_source_files_for_package", packageName);
+                parse(files, packageTrees, false);
+            }
+            modules.enter(packageTrees.toList(), null);
+
+            if (messager.nerrors() != 0) {
+                return null;
+            }
+
+            // Enter symbols for all files
+            docenv.notice("main.Building_tree");
+            javadocEnter.main(classTrees.toList().appendList(packageTrees.toList()));
+            enterDone = true;
+        } catch (Abort ex) {}
+
+        if (messager.nerrors() != 0)
+            return null;
+
+        return new RootDocImpl(docenv, listClasses(classTrees.toList()), List.from(includedPackages), options);
+    }
+
+    /** Is the given string a valid package name? */
+    boolean isValidPackageName(String s) {
+        int index;
+        while ((index = s.indexOf('.')) != -1) {
+            if (!isValidClassName(s.substring(0, index))) return false;
+            s = s.substring(index+1);
+        }
+        return isValidClassName(s);
+    }
+
+    private void parse(Iterable<? extends JavaFileObject> files, ListBuffer<JCCompilationUnit> trees,
+                       boolean trace) {
+        for (JavaFileObject fo: files) {
+            if (uniquefiles.add(fo)) { // ignore duplicates
+                if (trace)
+                    docenv.notice("main.Loading_source_file", fo.getName());
+                trees.append(parse(fo));
+            }
+        }
+    }
+
+    /** Are surrogates supported?
+     */
+    final static boolean surrogatesSupported = surrogatesSupported();
+    private static boolean surrogatesSupported() {
+        try {
+            boolean b = Character.isHighSurrogate('a');
+            return true;
+        } catch (NoSuchMethodError ex) {
+            return false;
+        }
+    }
+
+    /**
+     * Return true if given file name is a valid class name
+     * (including "package-info").
+     * @param s the name of the class to check.
+     * @return true if given class name is a valid class name
+     * and false otherwise.
+     */
+    public static boolean isValidClassName(String s) {
+        if (s.length() < 1) return false;
+        if (s.equals("package-info")) return true;
+        if (surrogatesSupported) {
+            int cp = s.codePointAt(0);
+            if (!Character.isJavaIdentifierStart(cp))
+                return false;
+            for (int j=Character.charCount(cp); j<s.length(); j+=Character.charCount(cp)) {
+                cp = s.codePointAt(j);
+                if (!Character.isJavaIdentifierPart(cp))
+                    return false;
+            }
+        } else {
+            if (!Character.isJavaIdentifierStart(s.charAt(0)))
+                return false;
+            for (int j=1; j<s.length(); j++)
+                if (!Character.isJavaIdentifierPart(s.charAt(j)))
+                    return false;
+        }
+        return true;
+    }
+
+    /**
+     * From a list of top level trees, return the list of contained class definitions
+     */
+    List<JCClassDecl> listClasses(List<JCCompilationUnit> trees) {
+        ListBuffer<JCClassDecl> result = new ListBuffer<>();
+        for (JCCompilationUnit t : trees) {
+            for (JCTree def : t.defs) {
+                if (def.hasTag(JCTree.Tag.CLASSDEF))
+                    result.append((JCClassDecl)def);
+            }
+        }
+        return result.toList();
+    }
+
+    /**
+     * A table to manage included and excluded packages.
+     */
+    class PackageTable {
+        private final Map<String, Entry> entries = new LinkedHashMap<>();
+        private final Set<String> includedPackages = new LinkedHashSet<>();
+        private final JavaFileManager fm;
+        private final Location location;
+        private final Set<JavaFileObject.Kind> sourceKinds = EnumSet.of(JavaFileObject.Kind.SOURCE);
+
+        /**
+         * Creates a table to manage included and excluded packages.
+         * @param fm The file manager used to locate source files
+         * @param locn the location used to locate source files
+         */
+        PackageTable(JavaFileManager fm, Location locn) {
+            this.fm = fm;
+            this.location = locn;
+            getEntry("").excluded = false;
+        }
+
+        PackageTable packages(Collection<String> packageNames) {
+            includedPackages.addAll(packageNames);
+            return this;
+        }
+
+        PackageTable subpackages(Collection<String> packageNames, Collection<String> excludePackageNames)
+                throws IOException {
+            for (String p: excludePackageNames) {
+                getEntry(p).excluded = true;
+            }
+
+            for (String packageName: packageNames) {
+                Location packageLocn = getLocation(packageName);
+                for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, true)) {
+                    String binaryName = fm.inferBinaryName(packageLocn, fo);
+                    String pn = getPackageName(binaryName);
+                    String simpleName = getSimpleName(binaryName);
+                    Entry e = getEntry(pn);
+                    if (!e.isExcluded() && isValidClassName(simpleName)) {
+                        includedPackages.add(pn);
+                        e.files = (e.files == null ? List.of(fo) : e.files.prepend(fo));
+                    }
+                }
+            }
+            return this;
+        }
+
+        /**
+         * Returns the aggregate set of included packages.
+         * @return the aggregate set of included packages
+         */
+        Set<String> getIncludedPackages() {
+            return includedPackages;
+        }
+
+        /**
+         * Returns the set of source files for a package.
+         * @param packageName the specified package
+         * @return the set of file objects for the specified package
+         * @throws IOException if an error occurs while accessing the files
+         */
+        List<JavaFileObject> getFiles(String packageName) throws IOException {
+            Entry e = getEntry(packageName);
+            // The files may have been found as a side effect of searching for subpackages
+            if (e.files != null)
+                return e.files;
+
+            ListBuffer<JavaFileObject> lb = new ListBuffer<>();
+            Location packageLocn = getLocation(packageName);
+            for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, false)) {
+                String binaryName = fm.inferBinaryName(packageLocn, fo);
+                String simpleName = getSimpleName(binaryName);
+                if (isValidClassName(simpleName)) {
+                    lb.append(fo);
+                }
+            }
+
+            return lb.toList();
+        }
+
+        private Location getLocation(String packageName) throws IOException {
+            if (location == StandardLocation.MODULE_SOURCE_PATH) {
+                // TODO: handle invalid results
+                ModuleSymbol msym = syms.inferModule(names.fromString(packageName));
+                return fm.getModuleLocation(location, msym.name.toString());
+            } else {
+                return location;
+            }
+        }
+
+        private Entry getEntry(String name) {
+            Entry e = entries.get(name);
+            if (e == null)
+                entries.put(name, e = new Entry(name));
+            return e;
+        }
+
+        private String getPackageName(String name) {
+            int lastDot = name.lastIndexOf(".");
+            return (lastDot == -1 ? "" : name.substring(0, lastDot));
+        }
+
+        private String getSimpleName(String name) {
+            int lastDot = name.lastIndexOf(".");
+            return (lastDot == -1 ? name : name.substring(lastDot + 1));
+        }
+
+        class Entry {
+            final String name;
+            Boolean excluded;
+            List<JavaFileObject> files;
+
+            Entry(String name) {
+                this.name = name;
+            }
+
+            boolean isExcluded() {
+                if (excluded == null)
+                    excluded = getEntry(getPackageName(name)).isExcluded();
+                return excluded;
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MemberDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1997, 2012, 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.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Symbol;
+
+/**
+ * Represents a member of a java class: field, constructor, or method.
+ * This is an abstract class dealing with information common to
+ * method, constructor and field members. Class members of a class
+ * (nested classes) are represented instead by ClassDocImpl.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @see MethodDocImpl
+ * @see FieldDocImpl
+ * @see ClassDocImpl
+ *
+ * @author Robert Field
+ * @author Neal Gafter
+ */
+
+public abstract class MemberDocImpl
+    extends ProgramElementDocImpl
+    implements MemberDoc {
+
+    /**
+     * constructor.
+     */
+    public MemberDocImpl(DocEnv env, Symbol sym, TreePath treePath) {
+        super(env, sym, treePath);
+    }
+
+    /**
+     * Returns true if this field was synthesized by the compiler.
+     */
+    public abstract boolean isSynthetic();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Messager.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 1997, 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 com.sun.tools.javadoc.main;
+
+import java.io.PrintWriter;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import com.sun.javadoc.*;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
+import com.sun.tools.javac.util.JavacMessages;
+import com.sun.tools.javac.util.Log;
+
+/**
+ * Utility for integrating with javadoc tools and for localization.
+ * Handle Resources. Access to error and warning counts.
+ * Message formatting.
+ * <br>
+ * Also provides implementation for DocErrorReporter.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @see java.util.ResourceBundle
+ * @see java.text.MessageFormat
+ * @author Neal Gafter (rewrite)
+ */
+public class Messager extends Log implements DocErrorReporter {
+    public static final SourcePosition NOPOS = null;
+
+    /** Get the current messager, which is also the compiler log. */
+    public static Messager instance0(Context context) {
+        Log instance = context.get(logKey);
+        if (instance == null || !(instance instanceof Messager))
+            throw new InternalError("no messager instance!");
+        return (Messager)instance;
+    }
+
+    public static void preRegister(Context context,
+                                   final String programName) {
+        context.put(logKey, new Context.Factory<Log>() {
+            public Log make(Context c) {
+                return new Messager(c,
+                                    programName);
+            }
+        });
+    }
+    public static void preRegister(Context context,
+                                   final String programName,
+                                   final PrintWriter errWriter,
+                                   final PrintWriter warnWriter,
+                                   final PrintWriter noticeWriter) {
+        context.put(logKey, new Context.Factory<Log>() {
+            public Log make(Context c) {
+                return new Messager(c,
+                                    programName,
+                                    errWriter,
+                                    warnWriter,
+                                    noticeWriter);
+            }
+        });
+    }
+
+    public class ExitJavadoc extends Error {
+        private static final long serialVersionUID = 0;
+    }
+
+    final String programName;
+
+    private Locale locale;
+    private final JavacMessages messages;
+    private final JCDiagnostic.Factory javadocDiags;
+
+    /** The default writer for diagnostics
+     */
+    static final PrintWriter defaultErrWriter = new PrintWriter(System.err);
+    static final PrintWriter defaultWarnWriter = new PrintWriter(System.err);
+    static final PrintWriter defaultNoticeWriter = new PrintWriter(System.out);
+
+    /**
+     * Constructor
+     * @param programName  Name of the program (for error messages).
+     */
+    protected Messager(Context context, String programName) {
+        this(context, programName, defaultErrWriter, defaultWarnWriter, defaultNoticeWriter);
+    }
+
+    /**
+     * Constructor
+     * @param programName  Name of the program (for error messages).
+     * @param errWriter    Stream for error messages
+     * @param warnWriter   Stream for warnings
+     * @param noticeWriter Stream for other messages
+     */
+    @SuppressWarnings("deprecation")
+    protected Messager(Context context,
+                       String programName,
+                       PrintWriter errWriter,
+                       PrintWriter warnWriter,
+                       PrintWriter noticeWriter) {
+        super(context, errWriter, warnWriter, noticeWriter);
+        messages = JavacMessages.instance(context);
+        messages.add(locale -> ResourceBundle.getBundle("com.sun.tools.javadoc.resources.javadoc",
+                                                         locale));
+        javadocDiags = new JCDiagnostic.Factory(messages, "javadoc");
+        this.programName = programName;
+
+    }
+
+    public void setLocale(Locale locale) {
+        this.locale = locale;
+    }
+
+    /**
+     * get and format message string from resource
+     *
+     * @param key selects message from resource
+     * @param args arguments for the message
+     */
+    String getText(String key, Object... args) {
+        return messages.getLocalizedString(locale, key, args);
+    }
+
+    /**
+     * Print error message, increment error count.
+     * Part of DocErrorReporter.
+     *
+     * @param msg message to print
+     */
+    public void printError(String msg) {
+        printError(null, msg);
+    }
+
+    /**
+     * Print error message, increment error count.
+     * Part of DocErrorReporter.
+     *
+     * @param pos the position where the error occurs
+     * @param msg message to print
+     */
+    public void printError(SourcePosition pos, String msg) {
+        if (diagListener != null) {
+            report(DiagnosticType.ERROR, pos, msg);
+            return;
+        }
+
+        if (nerrors < MaxErrors) {
+            String prefix = (pos == null) ? programName : pos.toString();
+            errWriter.println(prefix + ": " + getText("javadoc.error") + " - " + msg);
+            errWriter.flush();
+            prompt();
+            nerrors++;
+        }
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     * Part of DocErrorReporter.
+     *
+     * @param msg message to print
+     */
+    public void printWarning(String msg) {
+        printWarning(null, msg);
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     * Part of DocErrorReporter.
+     *
+     * @param pos the position where the error occurs
+     * @param msg message to print
+     */
+    public void printWarning(SourcePosition pos, String msg) {
+        if (diagListener != null) {
+            report(DiagnosticType.WARNING, pos, msg);
+            return;
+        }
+
+        if (nwarnings < MaxWarnings) {
+            String prefix = (pos == null) ? programName : pos.toString();
+            warnWriter.println(prefix +  ": " + getText("javadoc.warning") +" - " + msg);
+            warnWriter.flush();
+            nwarnings++;
+        }
+    }
+
+    /**
+     * Print a message.
+     * Part of DocErrorReporter.
+     *
+     * @param msg message to print
+     */
+    public void printNotice(String msg) {
+        printNotice(null, msg);
+    }
+
+    /**
+     * Print a message.
+     * Part of DocErrorReporter.
+     *
+     * @param pos the position where the error occurs
+     * @param msg message to print
+     */
+    public void printNotice(SourcePosition pos, String msg) {
+        if (diagListener != null) {
+            report(DiagnosticType.NOTE, pos, msg);
+            return;
+        }
+
+        if (pos == null)
+            noticeWriter.println(msg);
+        else
+            noticeWriter.println(pos + ": " + msg);
+        noticeWriter.flush();
+    }
+
+    /**
+     * Print error message, increment error count.
+     *
+     * @param key selects message from resource
+     */
+    public void error(SourcePosition pos, String key, Object... args) {
+        printError(pos, getText(key, args));
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     *
+     * @param key selects message from resource
+     */
+    public void warning(SourcePosition pos, String key, Object... args) {
+        printWarning(pos, getText(key, args));
+    }
+
+    /**
+     * Print a message.
+     *
+     * @param key selects message from resource
+     */
+    public void notice(String key, Object... args) {
+        printNotice(getText(key, args));
+    }
+
+    /**
+     * Return total number of errors, including those recorded
+     * in the compilation log.
+     */
+    public int nerrors() { return nerrors; }
+
+    /**
+     * Return total number of warnings, including those recorded
+     * in the compilation log.
+     */
+    public int nwarnings() { return nwarnings; }
+
+    /**
+     * Print exit message.
+     */
+    public void exitNotice() {
+        if (nerrors > 0) {
+            notice((nerrors > 1) ? "main.errors" : "main.error",
+                   "" + nerrors);
+        }
+        if (nwarnings > 0) {
+            notice((nwarnings > 1) ?  "main.warnings" : "main.warning",
+                   "" + nwarnings);
+        }
+    }
+
+    /**
+     * Force program exit, e.g., from a fatal error.
+     * <p>
+     * TODO: This method does not really belong here.
+     */
+    public void exit() {
+        throw new ExitJavadoc();
+    }
+
+    private void report(DiagnosticType type, SourcePosition pos, String msg) {
+        switch (type) {
+            case ERROR:
+            case WARNING:
+                Object prefix = (pos == null) ? programName : pos;
+                report(javadocDiags.create(type, null, null, "msg", prefix, msg));
+                break;
+
+            case NOTE:
+                String key = (pos == null) ? "msg" : "pos.msg";
+                report(javadocDiags.create(type, null, null, key, pos, msg));
+                break;
+
+            default:
+                throw new IllegalArgumentException(type.toString());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/MethodDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1997, 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 com.sun.tools.javadoc.main;
+
+import java.lang.reflect.Modifier;
+
+import com.sun.javadoc.*;
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type;
+import static com.sun.tools.javac.code.TypeTag.CLASS;
+
+/**
+ * Represents a method of a java class.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since 1.2
+ * @author Robert Field
+ * @author Neal Gafter (rewrite)
+ */
+
+public class MethodDocImpl
+        extends ExecutableMemberDocImpl implements MethodDoc {
+
+    /**
+     * constructor.
+     */
+    public MethodDocImpl(DocEnv env, MethodSymbol sym) {
+        super(env, sym);
+    }
+
+    /**
+     * constructor.
+     */
+    public MethodDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) {
+        super(env, sym, treePath);
+    }
+
+    /**
+     * Return true if it is a method, which it is.
+     * Note: constructors are not methods.
+     * This method is overridden by AnnotationTypeElementDocImpl.
+     *
+     * @return true
+     */
+    public boolean isMethod() {
+        return true;
+    }
+
+    /**
+     * Return true if this method is default
+     */
+    public boolean isDefault() {
+        return (sym.flags() & Flags.DEFAULT) != 0;
+    }
+
+    /**
+     * Return true if this method is abstract
+     */
+    public boolean isAbstract() {
+        return (Modifier.isAbstract(getModifiers()) && !isDefault());
+    }
+
+    /**
+     * Get return type.
+     *
+     * @return the return type of this method, null if it
+     * is a constructor.
+     */
+    public com.sun.javadoc.Type returnType() {
+        return TypeMaker.getType(env, sym.type.getReturnType(), false);
+    }
+
+    /**
+     * Return the class that originally defined the method that
+     * is overridden by the current definition, or null if no
+     * such class exists.
+     *
+     * @return a ClassDocImpl representing the superclass that
+     * originally defined this method, null if this method does
+     * not override a definition in a superclass.
+     */
+    public ClassDoc overriddenClass() {
+        com.sun.javadoc.Type t = overriddenType();
+        return (t != null) ? t.asClassDoc() : null;
+    }
+
+    /**
+     * Return the type containing the method that this method overrides.
+     * It may be a <code>ClassDoc</code> or a <code>ParameterizedType</code>.
+     */
+    public com.sun.javadoc.Type overriddenType() {
+
+        if ((sym.flags() & Flags.STATIC) != 0) {
+            return null;
+        }
+
+        ClassSymbol origin = (ClassSymbol)sym.owner;
+        for (Type t = env.types.supertype(origin.type);
+             t.hasTag(CLASS);
+             t = env.types.supertype(t)) {
+            ClassSymbol c = (ClassSymbol)t.tsym;
+            for (Symbol sym2 : membersOf(c).getSymbolsByName(sym.name)) {
+                if (sym.overrides(sym2, origin, env.types, true)) {
+                    return TypeMaker.getType(env, t);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return the method that this method overrides.
+     *
+     * @return a MethodDoc representing a method definition
+     * in a superclass this method overrides, null if
+     * this method does not override.
+     */
+    public MethodDoc overriddenMethod() {
+
+        // Real overriding only.  Static members are simply hidden.
+        // Likewise for constructors, but the MethodSymbol.overrides
+        // method takes this into account.
+        if ((sym.flags() & Flags.STATIC) != 0) {
+            return null;
+        }
+
+        // Derived from  com.sun.tools.javac.comp.Check.checkOverride .
+
+        ClassSymbol origin = (ClassSymbol)sym.owner;
+        for (Type t = env.types.supertype(origin.type);
+             t.hasTag(CLASS);
+             t = env.types.supertype(t)) {
+            ClassSymbol c = (ClassSymbol)t.tsym;
+            for (Symbol sym2 : membersOf(c).getSymbolsByName(sym.name)) {
+                if (sym.overrides(sym2, origin, env.types, true)) {
+                    return env.getMethodDoc((MethodSymbol)sym2);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**Retrieve members of c, ignoring any CompletionFailures that occur. */
+    private Scope membersOf(ClassSymbol c) {
+        try {
+            return c.members();
+        } catch (CompletionFailure cf) {
+            /* Quietly ignore completion failures and try again - the type
+             * for which the CompletionFailure was thrown shouldn't be completed
+             * again by the completer that threw the CompletionFailure.
+             */
+            return membersOf(c);
+        }
+    }
+
+    /**
+     * Tests whether this method overrides another.
+     * The overridden method may be one declared in a superclass or
+     * a superinterface (unlike {@link #overriddenMethod()}).
+     *
+     * <p> When a non-abstract method overrides an abstract one, it is
+     * also said to <i>implement</i> the other.
+     *
+     * @param meth  the other method to examine
+     * @return <tt>true</tt> if this method overrides the other
+     */
+    public boolean overrides(MethodDoc meth) {
+        MethodSymbol overridee = ((MethodDocImpl) meth).sym;
+        ClassSymbol origin = (ClassSymbol) sym.owner;
+
+        return sym.name == overridee.name &&
+
+               // not reflexive as per JLS
+               sym != overridee &&
+
+               // we don't care if overridee is static, though that wouldn't
+               // compile
+               !sym.isStatic() &&
+
+               // sym, whose declaring type is the origin, must be
+               // in a subtype of overridee's type
+               env.types.asSuper(origin.type, overridee.owner) != null &&
+
+               // check access and signatures; don't check return types
+               sym.overrides(overridee, origin, env.types, false);
+    }
+
+
+    public String name() {
+        if (name == null) {
+            name = sym.name.toString();
+        }
+        return name;
+    }
+
+    private String name;
+
+    public String qualifiedName() {
+        if (qualifiedName == null) {
+            qualifiedName =  sym.enclClass().getQualifiedName() + "." + sym.name;
+        }
+        return qualifiedName;
+    }
+
+    private String qualifiedName;
+
+    /**
+     * Returns a string representation of this method.  Includes the
+     * qualified signature, the qualified method name, and any type
+     * parameters.  Type parameters follow the class name, as they do
+     * in the syntax for invoking methods with explicit type parameters.
+     */
+    public String toString() {
+        return sym.enclClass().getQualifiedName() +
+                "." + typeParametersString() + name() + signature();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ModifierFilter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2000, 2012, 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.sun.tools.javadoc.main;
+
+import static com.sun.tools.javac.code.Flags.*;
+
+/**
+ *   A class whose instances are filters over Modifier bits.
+ *   Filtering is done by returning boolean values.
+ *   Classes, methods and fields can be filtered, or filtering
+ *   can be done directly on modifier bits.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ *   @see com.sun.tools.javac.code.Flags
+ *   @author Robert Field
+ */
+
+public class ModifierFilter {
+
+    /**
+    * Package private access.
+    * A "pseudo-" modifier bit that can be used in the
+    * constructors of this class to specify package private
+    * access. This is needed since there is no Modifier.PACKAGE.
+    */
+    public static final long PACKAGE = 0x8000000000000000L;
+
+    /**
+    * All access modifiers.
+    * A short-hand set of modifier bits that can be used in the
+    * constructors of this class to specify all access modifiers,
+    * Same as PRIVATE | PROTECTED | PUBLIC | PACKAGE.
+    */
+    public static final long ALL_ACCESS =
+                PRIVATE | PROTECTED | PUBLIC | PACKAGE;
+
+    private long oneOf;
+    private long must;
+    private long cannot;
+
+    private static final int ACCESS_BITS = PRIVATE | PROTECTED | PUBLIC;
+
+    /**
+     * Constructor - Specify a filter.
+     *
+     * @param   oneOf   If zero, everything passes the filter.
+     *                  If non-zero, at least one of the specified
+     *                  bits must be on in the modifier bits to
+     *                  pass the filter.
+     */
+    public ModifierFilter(long oneOf) {
+        this(oneOf, 0, 0);
+    }
+
+    /**
+     * Constructor - Specify a filter.
+     * For example, the filter below  will only pass synchronized
+     * methods that are private or package private access and are
+     * not native or static.
+     * <pre>
+     * ModifierFilter(  Modifier.PRIVATE | ModifierFilter.PACKAGE,
+     *                  Modifier.SYNCHRONIZED,
+     *                  Modifier.NATIVE | Modifier.STATIC)
+     * </pre><p>
+     * Each of the three arguments must either be
+     * zero or the or'ed combination of the bits specified in the
+     * class Modifier or this class. During filtering, these values
+     * are compared against the modifier bits as follows:
+     *
+     * @param   oneOf   If zero, ignore this argument.
+     *                  If non-zero, at least one of the bits must be on.
+     * @param   must    All bits specified must be on.
+     * @param   cannot  None of the bits specified can be on.
+     */
+    public ModifierFilter(long oneOf, long must, long cannot) {
+        this.oneOf = oneOf;
+        this.must = must;
+        this.cannot = cannot;
+    }
+
+    /**
+     * Filter on modifier bits.
+     *
+     * @param   modifierBits    Bits as specified in the Modifier class
+     *
+     * @return                  Whether the modifierBits pass this filter.
+     */
+    public boolean checkModifier(int modifierBits) {
+        // Add in the "pseudo-" modifier bit PACKAGE, if needed
+        long fmod = ((modifierBits & ACCESS_BITS) == 0) ?
+                        modifierBits | PACKAGE :
+                        modifierBits;
+        return ((oneOf == 0) || ((oneOf & fmod) != 0)) &&
+                ((must & fmod) == must) &&
+                ((cannot & fmod) == 0);
+    }
+
+} // end ModifierFilter
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PackageDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 1997, 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 com.sun.tools.javadoc.main;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.tools.FileObject;
+
+import com.sun.javadoc.*;
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Attribute;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Position;
+
+import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
+
+/**
+ * Represents a java package.  Provides access to information
+ * about the package, the package's comment and tags, and the
+ * classes in the package.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since 1.2
+ * @author Kaiyang Liu (original)
+ * @author Robert Field (rewrite)
+ * @author Neal Gafter (rewrite)
+ * @author Scott Seligman (package-info.java)
+ */
+
+public class PackageDocImpl extends DocImpl implements PackageDoc {
+
+    public final PackageSymbol sym;
+    private JCCompilationUnit tree = null;    // for source position
+
+    public FileObject docPath = null;
+    private boolean foundDoc;   // found a doc comment in either
+                                // package.html or package-info.java
+
+    boolean isIncluded = false;  // Set in RootDocImpl.
+    public boolean setDocPath = false;  //Flag to avoid setting doc path multiple times.
+
+    /**
+     * Constructor
+     */
+    public PackageDocImpl(DocEnv env, PackageSymbol sym) {
+        this(env, sym, null);
+    }
+
+    /**
+     * Constructor
+     */
+    public PackageDocImpl(DocEnv env, PackageSymbol sym, TreePath treePath) {
+        super(env, treePath);
+        this.sym = sym;
+        this.tree = (treePath == null) ? null : (JCCompilationUnit) treePath.getCompilationUnit();
+        foundDoc = (documentation != null);
+    }
+
+    void setTree(JCTree tree) {
+        this.tree = (JCCompilationUnit) tree;
+    }
+
+    public void setTreePath(TreePath treePath) {
+        super.setTreePath(treePath);
+        checkDoc();
+    }
+
+    /**
+     * Do lazy initialization of "documentation" string.
+     */
+    protected String documentation() {
+        if (documentation != null)
+            return documentation;
+        if (docPath != null) {
+            // read from file
+            try {
+                InputStream s = docPath.openInputStream();
+                documentation = readHTMLDocumentation(s, docPath);
+            } catch (IOException exc) {
+                documentation = "";
+                env.error(null, "javadoc.File_Read_Error", docPath.getName());
+            }
+        } else {
+            // no doc file to be had
+            documentation = "";
+        }
+        return documentation;
+    }
+
+    /**
+     * Cache of all classes contained in this package, including
+     * member classes of those classes, and their member classes, etc.
+     * Includes only those classes at the specified protection level
+     * and weaker.
+     */
+    private List<ClassDocImpl> allClassesFiltered = null;
+
+    /**
+     * Cache of all classes contained in this package, including
+     * member classes of those classes, and their member classes, etc.
+     */
+    private List<ClassDocImpl> allClasses = null;
+
+    /**
+     * Return a list of all classes contained in this package, including
+     * member classes of those classes, and their member classes, etc.
+     */
+    private List<ClassDocImpl> getClasses(boolean filtered) {
+        if (allClasses != null && !filtered) {
+            return allClasses;
+        }
+        if (allClassesFiltered != null && filtered) {
+            return allClassesFiltered;
+        }
+        ListBuffer<ClassDocImpl> classes = new ListBuffer<>();
+        for (Symbol enumerated : sym.members().getSymbols(NON_RECURSIVE)) {
+            if (enumerated != null) {
+                ClassSymbol s = (ClassSymbol)enumerated;
+                ClassDocImpl c = env.getClassDoc(s);
+                if (c != null && !c.isSynthetic())
+                    c.addAllClasses(classes, filtered);
+            }
+        }
+        if (filtered)
+            return allClassesFiltered = classes.toList();
+        else
+            return allClasses = classes.toList();
+    }
+
+    /**
+     * Add all included classes (including Exceptions and Errors)
+     * and interfaces.
+     */
+    public void addAllClassesTo(ListBuffer<ClassDocImpl> list) {
+        list.appendList(getClasses(true));
+    }
+
+    /**
+     * Get all classes (including Exceptions and Errors)
+     * and interfaces.
+     * @since J2SE1.4.
+     *
+     * @return all classes and interfaces in this package, filtered to include
+     * only the included classes if filter==true.
+     */
+    public ClassDoc[] allClasses(boolean filter) {
+        List<ClassDocImpl> classes = getClasses(filter);
+        return classes.toArray(new ClassDocImpl[classes.length()]);
+    }
+
+    /**
+     * Get all included classes (including Exceptions and Errors)
+     * and interfaces.  Same as allClasses(true).
+     *
+     * @return all included classes and interfaces in this package.
+     */
+    public ClassDoc[] allClasses() {
+        return allClasses(true);
+    }
+
+    /**
+     * Get ordinary classes (that is, exclude exceptions, errors,
+     * enums, interfaces, and annotation types) in this package.
+     *
+     * @return included ordinary classes in this package.
+     */
+    public ClassDoc[] ordinaryClasses() {
+        ListBuffer<ClassDocImpl> ret = new ListBuffer<>();
+        for (ClassDocImpl c : getClasses(true)) {
+            if (c.isOrdinaryClass()) {
+                ret.append(c);
+            }
+        }
+        return ret.toArray(new ClassDocImpl[ret.length()]);
+    }
+
+    /**
+     * Get Exception classes in this package.
+     *
+     * @return included Exceptions in this package.
+     */
+    public ClassDoc[] exceptions() {
+        ListBuffer<ClassDocImpl> ret = new ListBuffer<>();
+        for (ClassDocImpl c : getClasses(true)) {
+            if (c.isException()) {
+                ret.append(c);
+            }
+        }
+        return ret.toArray(new ClassDocImpl[ret.length()]);
+    }
+
+    /**
+     * Get Error classes in this package.
+     *
+     * @return included Errors in this package.
+     */
+    public ClassDoc[] errors() {
+        ListBuffer<ClassDocImpl> ret = new ListBuffer<>();
+        for (ClassDocImpl c : getClasses(true)) {
+            if (c.isError()) {
+                ret.append(c);
+            }
+        }
+        return ret.toArray(new ClassDocImpl[ret.length()]);
+    }
+
+    /**
+     * Get included enum types in this package.
+     *
+     * @return included enum types in this package.
+     */
+    public ClassDoc[] enums() {
+        ListBuffer<ClassDocImpl> ret = new ListBuffer<>();
+        for (ClassDocImpl c : getClasses(true)) {
+            if (c.isEnum()) {
+                ret.append(c);
+            }
+        }
+        return ret.toArray(new ClassDocImpl[ret.length()]);
+    }
+
+    /**
+     * Get included interfaces in this package, omitting annotation types.
+     *
+     * @return included interfaces in this package.
+     */
+    public ClassDoc[] interfaces() {
+        ListBuffer<ClassDocImpl> ret = new ListBuffer<>();
+        for (ClassDocImpl c : getClasses(true)) {
+            if (c.isInterface()) {
+                ret.append(c);
+            }
+        }
+        return ret.toArray(new ClassDocImpl[ret.length()]);
+    }
+
+    /**
+     * Get included annotation types in this package.
+     *
+     * @return included annotation types in this package.
+     */
+    public AnnotationTypeDoc[] annotationTypes() {
+        ListBuffer<AnnotationTypeDocImpl> ret = new ListBuffer<>();
+        for (ClassDocImpl c : getClasses(true)) {
+            if (c.isAnnotationType()) {
+                ret.append((AnnotationTypeDocImpl)c);
+            }
+        }
+        return ret.toArray(new AnnotationTypeDocImpl[ret.length()]);
+    }
+
+    /**
+     * Get the annotations of this package.
+     * Return an empty array if there are none.
+     */
+    public AnnotationDesc[] annotations() {
+        AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()];
+        int i = 0;
+        for (Attribute.Compound a : sym.getRawAttributes()) {
+            res[i++] = new AnnotationDescImpl(env, a);
+        }
+        return res;
+    }
+
+
+    /**
+     * Lookup for a class within this package.
+     *
+     * @return ClassDocImpl of found class, or null if not found.
+     */
+    public ClassDoc findClass(String className) {
+        final boolean filtered = true;
+        for (ClassDocImpl c : getClasses(filtered)) {
+            if (c.name().equals(className)) {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return true if this package is included in the active set.
+     */
+    public boolean isIncluded() {
+        return isIncluded;
+    }
+
+    /**
+     * Get package name.
+     *
+     * Note that we do not provide a means of obtaining the simple
+     * name of a package -- package names are always returned in their
+     * uniquely qualified form.
+     */
+    public String name() {
+        return qualifiedName();
+    }
+
+    /**
+     * Get package name.
+     */
+    public String qualifiedName() {
+        if (qualifiedName == null) {
+            Name fullname = sym.getQualifiedName();
+            // Some bogus tests depend on the interned "" being returned.
+            // See 6457276.
+            qualifiedName = fullname.isEmpty() ? "" : fullname.toString();
+        }
+        return qualifiedName;
+    }
+
+    private String qualifiedName;
+
+    /**
+     * set doc path for an unzipped directory
+     */
+    public void setDocPath(FileObject path) {
+        setDocPath = true;
+        if (path == null)
+            return;
+        if (!path.equals(docPath)) {
+            docPath = path;
+            checkDoc();
+        }
+    }
+
+    // Has checkDoc() sounded off yet?
+    private boolean checkDocWarningEmitted = false;
+
+    /**
+     * Invoked when a source of package doc comments is located.
+     * Emits a diagnostic if this is the second one.
+     */
+    private void checkDoc() {
+        if (foundDoc) {
+            if (!checkDocWarningEmitted) {
+                env.warning(null, "javadoc.Multiple_package_comments", name());
+                checkDocWarningEmitted = true;
+            }
+        } else {
+            foundDoc = true;
+        }
+    }
+
+    /**
+     * Return the source position of the entity, or null if
+     * no position is available.
+     */
+    public SourcePosition position() {
+        return (tree != null)
+                ? SourcePositionImpl.make(tree.sourcefile, tree.pos, tree.lineMap)
+                : SourcePositionImpl.make(docPath, Position.NOPOS, null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParamTagImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1997, 2012, 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.sun.tools.javadoc.main;
+
+import java.util.regex.*;
+
+import com.sun.javadoc.*;
+
+/**
+ * Represents an @param documentation tag.
+ * Parses and stores the name and comment parts of the parameter tag.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Robert Field
+ *
+ */
+class ParamTagImpl extends TagImpl implements ParamTag {
+
+    private static final Pattern typeParamRE = Pattern.compile("<([^<>]+)>");
+
+    private final String parameterName;
+    private final String parameterComment;
+    private final boolean isTypeParameter;
+
+    /**
+     * Cached inline tags.
+     */
+    private Tag[] inlineTags;
+
+    ParamTagImpl(DocImpl holder, String name, String text) {
+        super(holder, name, text);
+        String[] sa = divideAtWhite();
+
+        Matcher m = typeParamRE.matcher(sa[0]);
+        isTypeParameter = m.matches();
+        parameterName = isTypeParameter ? m.group(1) : sa[0];
+        parameterComment = sa[1];
+    }
+
+    /**
+     * Return the parameter name.
+     */
+    public String parameterName() {
+        return parameterName;
+    }
+
+    /**
+     * Return the parameter comment.
+     */
+    public String parameterComment() {
+        return parameterComment;
+    }
+
+    /**
+     * Return the kind of this tag.
+     */
+    @Override
+    public String kind() {
+        return "@param";
+    }
+
+    /**
+     * Return true if this ParamTag corresponds to a type parameter.
+     */
+    public boolean isTypeParameter() {
+        return isTypeParameter;
+    }
+
+    /**
+     * convert this object to a string.
+     */
+    @Override
+    public String toString() {
+        return name + ":" + text;
+    }
+
+    /**
+     * For the parameter comment with embedded @link tags return the array of
+     * TagImpls consisting of SeeTagImpl(s) and text containing TagImpl(s).
+     *
+     * @return TagImpl[] Array of tags with inline SeeTagImpls.
+     * @see TagImpl#inlineTags()
+     * @see ThrowsTagImpl#inlineTags()
+     */
+    @Override
+    public Tag[] inlineTags() {
+        if (inlineTags == null) {
+            inlineTags = Comment.getInlineTags(holder, parameterComment);
+        }
+        return inlineTags;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1997, 2012, 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.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.tools.javac.code.Attribute;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
+
+/**
+ * ParameterImpl information.
+ * This includes a parameter type and parameter name.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Kaiyang Liu (original)
+ * @author Robert Field (rewrite)
+ * @author Scott Seligman (generics, annotations)
+ */
+class ParameterImpl implements Parameter {
+
+    private final DocEnv env;
+    private final VarSymbol sym;
+    private final com.sun.javadoc.Type type;
+
+    /**
+     * Constructor of parameter info class.
+     */
+    ParameterImpl(DocEnv env, VarSymbol sym) {
+        this.env = env;
+        this.sym = sym;
+        this.type = TypeMaker.getType(env, sym.type, false);
+    }
+
+    /**
+     * Get the type of this parameter.
+     */
+    public com.sun.javadoc.Type type() {
+        return type;
+    }
+
+    /**
+     * Get local name of this parameter.
+     * For example if parameter is the short 'index', returns "index".
+     */
+    public String name() {
+        return sym.toString();
+    }
+
+    /**
+     * Get type name of this parameter.
+     * For example if parameter is the short 'index', returns "short".
+     */
+    public String typeName() {
+        return (type instanceof ClassDoc || type instanceof TypeVariable)
+                ? type.typeName()       // omit formal type params or bounds
+                : type.toString();
+    }
+
+    /**
+     * Returns a string representation of the parameter.
+     * <p>
+     * For example if parameter is the short 'index', returns "short index".
+     *
+     * @return type name and parameter name of this parameter.
+     */
+    public String toString() {
+        return typeName() + " " + sym;
+    }
+
+    /**
+     * Get the annotations of this parameter.
+     * Return an empty array if there are none.
+     */
+    public AnnotationDesc[] annotations() {
+        AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()];
+        int i = 0;
+        for (Attribute.Compound a : sym.getRawAttributes()) {
+            res[i++] = new AnnotationDescImpl(env, a);
+        }
+        return res;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ParameterizedTypeImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2003, 2012, 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.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.ClassType;
+
+import static com.sun.tools.javac.code.TypeTag.CLASS;
+
+
+/**
+ * Implementation of <code>ParameterizedType</code>, which
+ * represents an invocation of a generic class or interface.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Scott Seligman
+ * @since 1.5
+ */
+public class ParameterizedTypeImpl
+        extends AbstractTypeImpl implements ParameterizedType {
+
+    ParameterizedTypeImpl(DocEnv env, Type type) {
+        super(env, type);
+    }
+
+    /**
+     * Return the generic class or interface that declared this type.
+     */
+    @Override
+    public ClassDoc asClassDoc() {
+        return env.getClassDoc((ClassSymbol)type.tsym);
+    }
+
+    /**
+     * Return the actual type arguments of this type.
+     */
+    public com.sun.javadoc.Type[] typeArguments() {
+        return TypeMaker.getTypes(env, type.getTypeArguments());
+    }
+
+    /**
+     * Return the class type that is a direct supertype of this one.
+     * Return null if this is an interface type.
+     */
+    public com.sun.javadoc.Type superclassType() {
+        if (asClassDoc().isInterface()) {
+            return null;
+        }
+        Type sup = env.types.supertype(type);
+        return TypeMaker.getType(env,
+                                 (sup != type) ? sup : env.syms.objectType);
+    }
+
+    /**
+     * Return the interface types directly implemented by or extended by this
+     * parameterized type.
+     * Return an empty array if there are no interfaces.
+     */
+    public com.sun.javadoc.Type[] interfaceTypes() {
+        return TypeMaker.getTypes(env, env.types.interfaces(type));
+    }
+
+    /**
+     * Return the type that contains this type as a member.
+     * Return null is this is a top-level type.
+     */
+    public com.sun.javadoc.Type containingType() {
+        if (type.getEnclosingType().hasTag(CLASS)) {
+            // This is the type of an inner class.
+            return TypeMaker.getType(env, type.getEnclosingType());
+        }
+        ClassSymbol enclosing = type.tsym.owner.enclClass();
+        if (enclosing != null) {
+            // Nested but not inner.  Return the ClassDoc of the enclosing
+            // class or interface.
+            // See java.lang.reflect.ParameterizedType.getOwnerType().
+            return env.getClassDoc(enclosing);
+        }
+        return null;
+    }
+
+
+    // Asking for the "name" of a parameterized type doesn't exactly make
+    // sense.  It's a type expression.  Return the name of its generic
+    // type.
+    @Override
+    public String typeName() {
+        return TypeMaker.getTypeName(type, false);
+    }
+
+    @Override
+    public ParameterizedType asParameterizedType() {
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return parameterizedTypeToString(env, (ClassType)type, true);
+    }
+
+    static String parameterizedTypeToString(DocEnv env, ClassType cl,
+                                            boolean full) {
+        if (env.legacyDoclet) {
+            return TypeMaker.getTypeName(cl, full);
+        }
+        StringBuilder s = new StringBuilder();
+        if (!(cl.getEnclosingType().hasTag(CLASS))) {               // if not an inner class...
+            s.append(TypeMaker.getTypeName(cl, full));
+        } else {
+            ClassType encl = (ClassType)cl.getEnclosingType();
+            s.append(parameterizedTypeToString(env, encl, full))
+             .append('.')
+             .append(cl.tsym.name.toString());
+        }
+        s.append(TypeMaker.typeArgumentsString(env, cl, full));
+        return s.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/PrimitiveType.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+/**
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+class PrimitiveType implements com.sun.javadoc.Type {
+
+    private final String name;
+
+    static final PrimitiveType voidType = new PrimitiveType("void");
+    static final PrimitiveType booleanType = new PrimitiveType("boolean");
+    static final PrimitiveType byteType = new PrimitiveType("byte");
+    static final PrimitiveType charType = new PrimitiveType("char");
+    static final PrimitiveType shortType = new PrimitiveType("short");
+    static final PrimitiveType intType = new PrimitiveType("int");
+    static final PrimitiveType longType = new PrimitiveType("long");
+    static final PrimitiveType floatType = new PrimitiveType("float");
+    static final PrimitiveType doubleType = new PrimitiveType("double");
+
+    // error type, should never actually be used
+    static final PrimitiveType errorType = new PrimitiveType("");
+
+    PrimitiveType(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Return unqualified name of type excluding any dimension information.
+     * <p>
+     * For example, a two dimensional array of String returns 'String'.
+     */
+    public String typeName() {
+        return name;
+    }
+
+    public com.sun.javadoc.Type getElementType() {
+        return null;
+    }
+
+    /**
+     * Return qualified name of type excluding any dimension information.
+     *<p>
+     * For example, a two dimensional array of String
+     * returns 'java.lang.String'.
+     */
+    public String qualifiedTypeName() {
+        return name;
+    }
+
+    /**
+     * Return the simple name of this type.
+     */
+    public String simpleTypeName() {
+        return name;
+    }
+
+    /**
+     * Return the type's dimension information, as a string.
+     * <p>
+     * For example, a two dimensional array of String returns '[][]'.
+     */
+    public String dimension() {
+        return "";
+    }
+
+    /**
+     * Return this type as a class.  Array dimensions are ignored.
+     *
+     * @return a ClassDocImpl if the type is a Class.
+     * Return null if it is a primitive type..
+     */
+    public ClassDoc asClassDoc() {
+        return null;
+    }
+
+    /**
+     * Return null, as this is not an annotation type.
+     */
+    public AnnotationTypeDoc asAnnotationTypeDoc() {
+        return null;
+    }
+
+    /**
+     * Return null, as this is not an instantiation.
+     */
+    public ParameterizedType asParameterizedType() {
+        return null;
+    }
+
+    /**
+     * Return null, as this is not a type variable.
+     */
+    public TypeVariable asTypeVariable() {
+        return null;
+    }
+
+    /**
+     * Return null, as this is not a wildcard type.
+     */
+    public WildcardType asWildcardType() {
+        return null;
+    }
+
+    /**
+     * Return null, as this is not an annotated type.
+     */
+    public AnnotatedType asAnnotatedType() {
+        return null;
+    }
+
+    /**
+     * Returns a string representation of the type.
+     *
+     * Return name of type including any dimension information.
+     * <p>
+     * For example, a two dimensional array of String returns
+     * <code>String[][]</code>.
+     *
+     * @return name of type including any dimension information.
+     */
+    public String toString() {
+        return qualifiedTypeName();
+    }
+
+    /**
+     * Return true if this is a primitive type.
+     */
+    public boolean isPrimitive() {
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ProgramElementDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 1997, 2012, 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.sun.tools.javadoc.main;
+
+import java.lang.reflect.Modifier;
+import java.text.CollationKey;
+
+import com.sun.javadoc.*;
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Attribute;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.Position;
+
+/**
+ * Represents a java program element: class, interface, field,
+ * constructor, or method.
+ * This is an abstract class dealing with information common to
+ * these elements.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @see MemberDocImpl
+ * @see ClassDocImpl
+ *
+ * @author Robert Field
+ * @author Neal Gafter (rewrite)
+ * @author Scott Seligman (generics, enums, annotations)
+ */
+public abstract class ProgramElementDocImpl
+        extends DocImpl implements ProgramElementDoc {
+
+    private final Symbol sym;
+
+    // For source position information.
+    JCTree tree = null;
+    Position.LineMap lineMap = null;
+
+
+    // Cache for getModifiers().
+    private int modifiers = -1;
+
+    protected ProgramElementDocImpl(DocEnv env, Symbol sym, TreePath treePath) {
+        super(env, treePath);
+        this.sym = sym;
+        if (treePath != null) {
+            tree = (JCTree) treePath.getLeaf();
+            lineMap = ((JCCompilationUnit) treePath.getCompilationUnit()).lineMap;
+        }
+    }
+
+    @Override
+    void setTreePath(TreePath treePath) {
+        super.setTreePath(treePath);
+        this.tree = (JCTree) treePath.getLeaf();
+        this.lineMap = ((JCCompilationUnit) treePath.getCompilationUnit()).lineMap;
+    }
+
+    /**
+     * Subclasses override to identify the containing class
+     */
+    protected abstract ClassSymbol getContainingClass();
+
+    /**
+     * Returns the flags in terms of javac's flags
+     */
+    abstract protected long getFlags();
+
+    /**
+     * Returns the modifier flags in terms of java.lang.reflect.Modifier.
+     */
+    protected int getModifiers() {
+        if (modifiers == -1) {
+            modifiers = DocEnv.translateModifiers(getFlags());
+        }
+        return modifiers;
+    }
+
+    /**
+     * Get the containing class of this program element.
+     *
+     * @return a ClassDocImpl for this element's containing class.
+     * If this is a class with no outer class, return null.
+     */
+    public ClassDoc containingClass() {
+        if (getContainingClass() == null) {
+            return null;
+        }
+        return env.getClassDoc(getContainingClass());
+    }
+
+    /**
+     * Return the package that this member is contained in.
+     * Return "" if in unnamed package.
+     */
+    public PackageDoc containingPackage() {
+        return env.getPackageDoc(getContainingClass().packge());
+    }
+
+    /**
+     * Get the modifier specifier integer.
+     *
+     * @see java.lang.reflect.Modifier
+     */
+    public int modifierSpecifier() {
+        int modifiers = getModifiers();
+        if (isMethod() && containingClass().isInterface())
+            // Remove the implicit abstract modifier.
+            return modifiers & ~Modifier.ABSTRACT;
+        return modifiers;
+    }
+
+    /**
+     * Get modifiers string.
+     * <pre>
+     * Example, for:
+     *   public abstract int foo() { ... }
+     * modifiers() would return:
+     *   'public abstract'
+     * </pre>
+     * Annotations are not included.
+     */
+    public String modifiers() {
+        int modifiers = getModifiers();
+        if (isAnnotationTypeElement() ||
+                (isMethod() && containingClass().isInterface())) {
+            // Remove the implicit abstract modifier.
+            return Modifier.toString(modifiers & ~Modifier.ABSTRACT);
+        } else {
+            return Modifier.toString(modifiers);
+        }
+    }
+
+    /**
+     * Get the annotations of this program element.
+     * Return an empty array if there are none.
+     */
+    public AnnotationDesc[] annotations() {
+        AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()];
+        int i = 0;
+        for (Attribute.Compound a : sym.getRawAttributes()) {
+            res[i++] = new AnnotationDescImpl(env, a);
+        }
+        return res;
+    }
+
+    /**
+     * Return true if this program element is public
+     */
+    public boolean isPublic() {
+        int modifiers = getModifiers();
+        return Modifier.isPublic(modifiers);
+    }
+
+    /**
+     * Return true if this program element is protected
+     */
+    public boolean isProtected() {
+        int modifiers = getModifiers();
+        return Modifier.isProtected(modifiers);
+    }
+
+    /**
+     * Return true if this program element is private
+     */
+    public boolean isPrivate() {
+        int modifiers = getModifiers();
+        return Modifier.isPrivate(modifiers);
+    }
+
+    /**
+     * Return true if this program element is package private
+     */
+    public boolean isPackagePrivate() {
+        return !(isPublic() || isPrivate() || isProtected());
+    }
+
+    /**
+     * Return true if this program element is static
+     */
+    public boolean isStatic() {
+        int modifiers = getModifiers();
+        return Modifier.isStatic(modifiers);
+    }
+
+    /**
+     * Return true if this program element is final
+     */
+    public boolean isFinal() {
+        int modifiers = getModifiers();
+        return Modifier.isFinal(modifiers);
+    }
+
+    /**
+     * Generate a key for sorting.
+     */
+    CollationKey generateKey() {
+        String k = name();
+        // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
+        return env.doclocale.collator.getCollationKey(k);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 1997, 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 com.sun.tools.javadoc.main;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Locale;
+
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+
+import com.sun.javadoc.*;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Position;
+
+/**
+ * This class holds the information from one run of javadoc.
+ * Particularly the packages, classes and options specified
+ * by the user.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since 1.2
+ * @author Robert Field
+ * @author Atul M Dambalkar
+ * @author Neal Gafter (rewrite)
+ */
+public class RootDocImpl extends DocImpl implements RootDoc {
+
+    /**
+     * list of classes specified on the command line.
+     */
+    private List<ClassDocImpl> cmdLineClasses;
+
+    /**
+     * list of packages specified on the command line.
+     */
+    private List<PackageDocImpl> cmdLinePackages;
+
+    /**
+     * a collection of all options.
+     */
+    private List<String[]> options;
+
+    /**
+     * Constructor used when reading source files.
+     *
+     * @param env the documentation environment, state for this javadoc run
+     * @param classes list of classes specified on the commandline
+     * @param packages list of package names specified on the commandline
+     * @param options list of options
+     */
+    public RootDocImpl(DocEnv env, List<JCClassDecl> classes, List<String> packages, List<String[]> options) {
+        super(env, null);
+        this.options = options;
+        setPackages(env, packages);
+        setClasses(env, classes);
+    }
+
+    /**
+     * Constructor used when reading class files.
+     *
+     * @param env the documentation environment, state for this javadoc run
+     * @param classes list of class names specified on the commandline
+     * @param options list of options
+     */
+    public RootDocImpl(DocEnv env, List<String> classes, List<String[]> options) {
+        super(env, null);
+        this.options = options;
+        cmdLinePackages = List.nil();
+        ListBuffer<ClassDocImpl> classList = new ListBuffer<>();
+        for (String className : classes) {
+            ClassDocImpl c = env.loadClass(className);
+            if (c == null)
+                env.error(null, "javadoc.class_not_found", className);
+            else
+                classList = classList.append(c);
+        }
+        cmdLineClasses = classList.toList();
+    }
+
+    /**
+     * Initialize classes information. Those classes are input from
+     * command line.
+     *
+     * @param env the compilation environment
+     * @param classes a list of ClassDeclaration
+     */
+    private void setClasses(DocEnv env, List<JCClassDecl> classes) {
+        ListBuffer<ClassDocImpl> result = new ListBuffer<>();
+        for (JCClassDecl def : classes) {
+            //### Do we want modifier check here?
+            if (env.shouldDocument(def.sym)) {
+                ClassDocImpl cd = env.getClassDoc(def.sym);
+                if (cd != null) {
+                    cd.isIncluded = true;
+                    result.append(cd);
+                } //else System.out.println(" (classdoc is null)");//DEBUG
+            } //else System.out.println(" (env.shouldDocument() returned false)");//DEBUG
+        }
+        cmdLineClasses = result.toList();
+    }
+
+    /**
+     * Initialize packages information.
+     *
+     * @param env the compilation environment
+     * @param packages a list of package names (String)
+     */
+    private void setPackages(DocEnv env, List<String> packages) {
+        ListBuffer<PackageDocImpl> packlist = new ListBuffer<>();
+        for (String name : packages) {
+            PackageDocImpl pkg = env.lookupPackage(name);
+            if (pkg != null) {
+                pkg.isIncluded = true;
+                packlist.append(pkg);
+            } else {
+                env.warning(null, "main.no_source_files_for_package", name);
+            }
+        }
+        cmdLinePackages = packlist.toList();
+    }
+
+    /**
+     * Command line options.
+     *
+     * <pre>
+     * For example, given:
+     *     javadoc -foo this that -bar other ...
+     *
+     * This method will return:
+     *      options()[0][0] = "-foo"
+     *      options()[0][1] = "this"
+     *      options()[0][2] = "that"
+     *      options()[1][0] = "-bar"
+     *      options()[1][1] = "other"
+     * </pre>
+     *
+     * @return an array of arrays of String.
+     */
+    public String[][] options() {
+        return options.toArray(new String[options.length()][]);
+    }
+
+    /**
+     * Packages specified on the command line.
+     */
+    public PackageDoc[] specifiedPackages() {
+        return (PackageDoc[])cmdLinePackages
+            .toArray(new PackageDocImpl[cmdLinePackages.length()]);
+    }
+
+    /**
+     * Classes and interfaces specified on the command line.
+     */
+    public ClassDoc[] specifiedClasses() {
+        ListBuffer<ClassDocImpl> classesToDocument = new ListBuffer<>();
+        for (ClassDocImpl cd : cmdLineClasses) {
+            cd.addAllClasses(classesToDocument, true);
+        }
+        return (ClassDoc[])classesToDocument.toArray(new ClassDocImpl[classesToDocument.length()]);
+    }
+
+    /**
+     * Return all classes and interfaces (including those inside
+     * packages) to be documented.
+     */
+    public ClassDoc[] classes() {
+        ListBuffer<ClassDocImpl> classesToDocument = new ListBuffer<>();
+        for (ClassDocImpl cd : cmdLineClasses) {
+            cd.addAllClasses(classesToDocument, true);
+        }
+        for (PackageDocImpl pd : cmdLinePackages) {
+            pd.addAllClassesTo(classesToDocument);
+        }
+        return classesToDocument.toArray(new ClassDocImpl[classesToDocument.length()]);
+    }
+
+    /**
+     * Return a ClassDoc for the specified class/interface name
+     *
+     * @param qualifiedName qualified class name
+     *                        (i.e. includes package name).
+     *
+     * @return a ClassDocImpl holding the specified class, null if
+     * this class is not referenced.
+     */
+    public ClassDoc classNamed(String qualifiedName) {
+        return env.lookupClass(qualifiedName);
+    }
+
+    /**
+     * Return a PackageDoc for the specified package name
+     *
+     * @param name package name
+     *
+     * @return a PackageDoc holding the specified package, null if
+     * this package is not referenced.
+     */
+    public PackageDoc packageNamed(String name) {
+        return env.lookupPackage(name);
+    }
+
+    /**
+     * Return the name of this Doc item.
+     *
+     * @return the string <code>"*RootDocImpl*"</code>.
+     */
+    public String name() {
+        return "*RootDocImpl*";
+    }
+
+    /**
+     * Return the name of this Doc item.
+     *
+     * @return the string <code>"*RootDocImpl*"</code>.
+     */
+    public String qualifiedName() {
+        return "*RootDocImpl*";
+    }
+
+    /**
+     * Return true if this Doc is include in the active set.
+     * RootDocImpl isn't even a program entity so it is always false.
+     */
+    public boolean isIncluded() {
+        return false;
+    }
+
+    /**
+     * Print error message, increment error count.
+     *
+     * @param msg message to print
+     */
+    public void printError(String msg) {
+        env.printError(msg);
+    }
+
+    /**
+     * Print error message, increment error count.
+     *
+     * @param msg message to print
+     */
+    public void printError(SourcePosition pos, String msg) {
+        env.printError(pos, msg);
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     *
+     * @param msg message to print
+     */
+    public void printWarning(String msg) {
+        env.printWarning(msg);
+    }
+
+    /**
+     * Print warning message, increment warning count.
+     *
+     * @param msg message to print
+     */
+    public void printWarning(SourcePosition pos, String msg) {
+        env.printWarning(pos, msg);
+    }
+
+    /**
+     * Print a message.
+     *
+     * @param msg message to print
+     */
+    public void printNotice(String msg) {
+        env.printNotice(msg);
+    }
+
+    /**
+     * Print a message.
+     *
+     * @param msg message to print
+     */
+    public void printNotice(SourcePosition pos, String msg) {
+        env.printNotice(pos, msg);
+    }
+
+    /**
+     * Return the path of the overview file and null if it does not exist.
+     * @return the path of the overview file and null if it does not exist.
+     */
+    private JavaFileObject getOverviewPath() {
+        for (String[] opt : options) {
+            if (opt[0].equals("-overview")) {
+                if (env.fileManager instanceof StandardJavaFileManager) {
+                    StandardJavaFileManager fm = (StandardJavaFileManager) env.fileManager;
+                    return fm.getJavaFileObjects(opt[1]).iterator().next();
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Do lazy initialization of "documentation" string.
+     */
+    @Override
+    protected String documentation() {
+        if (documentation == null) {
+            JavaFileObject overviewPath = getOverviewPath();
+            if (overviewPath == null) {
+                // no doc file to be had
+                documentation = "";
+            } else {
+                // read from file
+                try {
+                    documentation = readHTMLDocumentation(
+                        overviewPath.openInputStream(),
+                        overviewPath);
+                } catch (IOException exc) {
+                    documentation = "";
+                    env.error(null, "javadoc.File_Read_Error", overviewPath.getName());
+                }
+            }
+        }
+        return documentation;
+    }
+
+    /**
+     * Return the source position of the entity, or null if
+     * no position is available.
+     */
+    @Override
+    public SourcePosition position() {
+        JavaFileObject path;
+        return ((path = getOverviewPath()) == null) ?
+            null :
+            SourcePositionImpl.make(path, Position.NOPOS, null);
+    }
+
+    /**
+     * Return the locale provided by the user or the default locale value.
+     */
+    public Locale getLocale() {
+        return env.doclocale.locale;
+    }
+
+    /**
+     * Return the current file manager.
+     */
+    public JavaFileManager getFileManager() {
+        return env.fileManager;
+    }
+
+    public void initDocLint(Collection<String> opts, Collection<String> customTagNames,
+            String htmlVersion) {
+        env.initDoclint(opts, customTagNames, htmlVersion);
+    }
+
+    public boolean isFunctionalInterface(AnnotationDesc annotationDesc) {
+        return env.source.allowLambda()
+            && annotationDesc.annotationType().qualifiedName().equals(
+                env.syms.functionalInterfaceType.toString());
+    }
+
+    public boolean showTagMessages() {
+        return env.showTagMessages();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SeeTagImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 1997, 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 com.sun.tools.javadoc.main;
+
+import java.io.File;
+import java.util.Locale;
+
+import com.sun.javadoc.*;
+import com.sun.tools.javac.code.Printer;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Type.CapturedType;
+import com.sun.tools.javac.util.*;
+
+import static com.sun.tools.javac.code.Kinds.Kind.*;
+
+/**
+ * Represents a see also documentation tag.
+ * The @see tag can be plain text, or reference a class or member.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Kaiyang Liu (original)
+ * @author Robert Field (rewrite)
+ * @author Atul M Dambalkar
+ *
+ */
+class SeeTagImpl extends TagImpl implements SeeTag, LayoutCharacters {
+
+    //### TODO: Searching for classes, fields, and methods
+    //### should follow the normal rules applied by the compiler.
+
+    /**
+     * where of  where#what - i.e. the class name (may be empty)
+     */
+    private String where;
+
+    /**
+     * what of  where#what - i.e. the member (may be null)
+     */
+    private String what;
+
+    private PackageDoc referencedPackage;
+    private ClassDoc referencedClass;
+    private MemberDoc referencedMember;
+
+    String label = "";
+
+    SeeTagImpl(DocImpl holder, String name, String text) {
+        super(holder, name, text);
+        parseSeeString();
+        if (where != null) {
+            ClassDocImpl container = null;
+            if (holder instanceof MemberDoc) {
+                container =
+                  (ClassDocImpl)((ProgramElementDoc)holder).containingClass();
+            } else if (holder instanceof ClassDoc) {
+                container = (ClassDocImpl)holder;
+            }
+            findReferenced(container);
+            if (showRef) showRef();
+        }
+    }
+
+    private static final boolean showRef = false;
+
+    private void showRef() {
+        Symbol sym;
+        if (referencedMember != null) {
+            if (referencedMember instanceof MethodDocImpl)
+                sym = ((MethodDocImpl) referencedMember).sym;
+            else if (referencedMember instanceof FieldDocImpl)
+                sym = ((FieldDocImpl) referencedMember).sym;
+            else
+                sym = ((ConstructorDocImpl) referencedMember).sym;
+        } else if (referencedClass != null) {
+            sym = ((ClassDocImpl) referencedClass).tsym;
+        } else if (referencedPackage != null) {
+            sym = ((PackageDocImpl) referencedPackage).sym;
+        } else
+            return;
+
+        final JavacMessages messages = JavacMessages.instance(docenv().context);
+        Locale locale = Locale.getDefault();
+        Printer printer = new Printer() {
+            int count;
+            @Override
+            protected String localize(Locale locale, String key, Object... args) {
+                return messages.getLocalizedString(locale, key, args);
+            }
+            @Override
+            protected String capturedVarId(CapturedType t, Locale locale) {
+                return "CAP#" + (++count);
+            }
+        };
+
+        String s = text.replaceAll("\\s+", " ");  // normalize white space
+        int sp = s.indexOf(" ");
+        int lparen = s.indexOf("(");
+        int rparen = s.indexOf(")");
+        String seetext = (sp == -1) ? s
+                : (lparen == -1 || sp < lparen) ? s.substring(0, sp)
+                : s.substring(0, rparen + 1);
+
+        File file = new File(holder.position().file().getAbsoluteFile().toURI().normalize());
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("+++ ").append(file).append(": ")
+                .append(name()).append(" ").append(seetext).append(": ");
+        sb.append(sym.getKind()).append(" ");
+        if (sym.kind == MTH || sym.kind == VAR)
+            sb.append(printer.visit(sym.owner, locale)).append(".");
+        sb.append(printer.visit(sym, locale));
+
+        System.err.println(sb);
+    }
+
+    /**
+     * get the class name part of @see, For instance,
+     * if the comment is @see String#startsWith(java.lang.String) .
+     *      This function returns String.
+     * Returns null if format was not that of java reference.
+     * Return empty string if class name was not specified..
+     */
+    public String referencedClassName() {
+        return where;
+    }
+
+    /**
+     * get the package referenced by  @see. For instance,
+     * if the comment is @see java.lang
+     *      This function returns a PackageDocImpl for java.lang
+     * Returns null if no known package found.
+     */
+    public PackageDoc referencedPackage() {
+        return referencedPackage;
+    }
+
+    /**
+     * get the class referenced by the class name part of @see, For instance,
+     * if the comment is @see String#startsWith(java.lang.String) .
+     *      This function returns a ClassDocImpl for java.lang.String.
+     * Returns null if class is not a class specified on the javadoc command line..
+     */
+    public ClassDoc referencedClass() {
+        return referencedClass;
+    }
+
+    /**
+     * get the name of the member referenced by the prototype part of @see,
+     * For instance,
+     * if the comment is @see String#startsWith(java.lang.String) .
+     *      This function returns "startsWith(java.lang.String)"
+     * Returns null if format was not that of java reference.
+     * Return empty string if member name was not specified..
+     */
+    public String referencedMemberName() {
+        return what;
+    }
+
+    /**
+     * get the member referenced by the prototype part of @see,
+     * For instance,
+     * if the comment is @see String#startsWith(java.lang.String) .
+     *      This function returns a MethodDocImpl for startsWith.
+     * Returns null if member could not be determined.
+     */
+    public MemberDoc referencedMember() {
+        return referencedMember;
+    }
+
+
+    /**
+     * parse @see part of comment. Determine 'where' and 'what'
+     */
+    private void parseSeeString() {
+        int len = text.length();
+        if (len == 0) {
+            return;
+        }
+        switch (text.charAt(0)) {
+            case '<':
+                if (text.charAt(len-1) != '>') {
+                    docenv().warning(holder,
+                                     "tag.see.no_close_bracket_on_url",
+                                     name, text);
+                }
+                return;
+            case '"':
+                if (len == 1 || text.charAt(len-1) != '"') {
+                    docenv().warning(holder,
+                                     "tag.see.no_close_quote",
+                                     name, text);
+                } else {
+//                    text = text.substring(1,len-1); // strip quotes
+                }
+                return;
+        }
+
+        // check that the text is one word, with possible parentheses
+        // this part of code doesn't allow
+        // @see <a href=.....>asfd</a>
+        // comment it.
+
+        // the code assumes that there is no initial white space.
+        int parens = 0;
+        int commentstart = 0;
+        int start = 0;
+        int cp;
+        for (int i = start; i < len ; i += Character.charCount(cp)) {
+            cp = text.codePointAt(i);
+            switch (cp) {
+                case '(': parens++; break;
+                case ')': parens--; break;
+                case '[': case ']': case '.': case '#': break;
+                case ',':
+                    if (parens <= 0) {
+                        docenv().warning(holder,
+                                         "tag.see.malformed_see_tag",
+                                         name, text);
+                        return;
+                    }
+                    break;
+                case ' ': case '\t': case '\n': case CR:
+                    if (parens == 0) { //here onwards the comment starts.
+                        commentstart = i;
+                        i = len;
+                    }
+                    break;
+                default:
+                    if (!Character.isJavaIdentifierPart(cp)) {
+                        docenv().warning(holder,
+                                         "tag.see.illegal_character",
+                                         name, ""+cp, text);
+                    }
+                    break;
+            }
+        }
+        if (parens != 0) {
+            docenv().warning(holder,
+                             "tag.see.malformed_see_tag",
+                             name, text);
+            return;
+        }
+
+        String seetext = "";
+        String labeltext = "";
+
+        if (commentstart > 0) {
+            seetext = text.substring(start, commentstart);
+            labeltext = text.substring(commentstart + 1);
+            // strip off the white space which can be between seetext and the
+            // actual label.
+            for (int i = 0; i < labeltext.length(); i++) {
+                char ch2 = labeltext.charAt(i);
+                if (!(ch2 == ' ' || ch2 == '\t' || ch2 == '\n')) {
+                    label = labeltext.substring(i);
+                    break;
+                }
+            }
+        } else {
+            seetext = text;
+            label = "";
+        }
+
+        int sharp = seetext.indexOf('#');
+        if (sharp >= 0) {
+            // class#member
+            where = seetext.substring(0, sharp);
+            what = seetext.substring(sharp + 1);
+        } else {
+            if (seetext.indexOf('(') >= 0) {
+                docenv().warning(holder,
+                                 "tag.see.missing_sharp",
+                                 name, text);
+                where = "";
+                what = seetext;
+            }
+            else {
+                // no member specified, text names class
+                where = seetext;
+                what = null;
+            }
+        }
+    }
+
+    /**
+     * Find what is referenced by the see also.  If possible, sets
+     * referencedClass and referencedMember.
+     *
+     * @param containingClass the class containing the comment containing
+     * the tag. May be null, if, for example, it is a package comment.
+     */
+    private void findReferenced(ClassDocImpl containingClass) {
+        if (where.length() > 0) {
+            if (containingClass != null) {
+                referencedClass = containingClass.findClass(where);
+            } else {
+                referencedClass = docenv().lookupClass(where);
+            }
+            if (referencedClass == null && holder() instanceof ProgramElementDoc) {
+                referencedClass = docenv().lookupClass(
+                    ((ProgramElementDoc) holder()).containingPackage().name() + "." + where);
+            }
+
+            if (referencedClass == null) { /* may just not be in this run */
+                // check if it's a package name
+                referencedPackage = docenv().lookupPackage(where);
+                return;
+            }
+        } else {
+            if (containingClass == null) {
+                docenv().warning(holder,
+                                 "tag.see.class_not_specified",
+                                 name, text);
+                return;
+            } else {
+                referencedClass = containingClass;
+            }
+        }
+        where = referencedClass.qualifiedName();
+
+        if (what == null) {
+            return;
+        } else {
+            int paren = what.indexOf('(');
+            String memName = (paren >= 0 ? what.substring(0, paren) : what);
+            String[] paramarr;
+            if (paren > 0) {
+                // has parameter list -- should be method or constructor
+                paramarr = new ParameterParseMachine(what.
+                        substring(paren, what.length())).parseParameters();
+                if (paramarr != null) {
+                    referencedMember = findExecutableMember(memName, paramarr,
+                                                            referencedClass);
+                } else {
+                    referencedMember = null;
+                }
+            } else {
+                // no parameter list -- should be field
+                referencedMember = findExecutableMember(memName, null,
+                                                        referencedClass);
+                FieldDoc fd = ((ClassDocImpl)referencedClass).
+                                                            findField(memName);
+                // when no args given, prefer fields over methods
+                if (referencedMember == null ||
+                    (fd != null &&
+                     fd.containingClass()
+                         .subclassOf(referencedMember.containingClass()))) {
+                    referencedMember = fd;
+                }
+            }
+            if (referencedMember == null) {
+                docenv().warning(holder,
+                                 "tag.see.can_not_find_member",
+                                 name, what, where);
+            }
+        }
+    }
+
+    private MemberDoc findReferencedMethod(String memName, String[] paramarr,
+                                           ClassDoc referencedClass) {
+        MemberDoc meth = findExecutableMember(memName, paramarr, referencedClass);
+        if (meth == null) {
+            for (ClassDoc nestedClass : referencedClass.innerClasses()) {
+                meth = findReferencedMethod(memName, paramarr, nestedClass);
+                if (meth != null) {
+                    return meth;
+                }
+            }
+        }
+        return null;
+    }
+
+    private MemberDoc findExecutableMember(String memName, String[] paramarr,
+                                           ClassDoc referencedClass) {
+        String className = referencedClass.name();
+        if (memName.equals(className.substring(className.lastIndexOf(".") + 1))) {
+            return ((ClassDocImpl)referencedClass).findConstructor(memName,
+                                                                   paramarr);
+        } else {   // it's a method.
+            return ((ClassDocImpl)referencedClass).findMethod(memName,
+                                                              paramarr);
+        }
+    }
+
+    // separate "int, String" from "(int, String)"
+    // (int i, String s) ==> [0] = "int",  [1] = String
+    // (int[][], String[]) ==> [0] = "int[][]" // [1] = "String[]"
+    class ParameterParseMachine {
+        static final int START = 0;
+        static final int TYPE = 1;
+        static final int NAME = 2;
+        static final int TNSPACE = 3;  // space between type and name
+        static final int ARRAYDECORATION = 4;
+        static final int ARRAYSPACE = 5;
+
+        String parameters;
+
+        StringBuilder typeId;
+
+        ListBuffer<String> paramList;
+
+        ParameterParseMachine(String parameters) {
+            this.parameters = parameters;
+            this.paramList = new ListBuffer<>();
+            typeId = new StringBuilder();
+        }
+
+        public String[] parseParameters() {
+            if (parameters.equals("()")) {
+                return new String[0];
+            }   // now strip off '(' and ')'
+            int state = START;
+            int prevstate = START;
+            parameters = parameters.substring(1, parameters.length() - 1);
+            int cp;
+            for (int index = 0; index < parameters.length(); index += Character.charCount(cp)) {
+                cp = parameters.codePointAt(index);
+                switch (state) {
+                    case START:
+                        if (Character.isJavaIdentifierStart(cp)) {
+                            typeId.append(Character.toChars(cp));
+                            state = TYPE;
+                        }
+                        prevstate = START;
+                        break;
+                    case TYPE:
+                        if (Character.isJavaIdentifierPart(cp) || cp == '.') {
+                            typeId.append(Character.toChars(cp));
+                        } else if (cp == '[') {
+                            typeId.append('[');
+                            state = ARRAYDECORATION;
+                        } else if (Character.isWhitespace(cp)) {
+                            state = TNSPACE;
+                        } else if (cp == ',') {  // no name, just type
+                            addTypeToParamList();
+                            state = START;
+                        }
+                        prevstate = TYPE;
+                        break;
+                    case TNSPACE:
+                        if (Character.isJavaIdentifierStart(cp)) { // name
+                            if (prevstate == ARRAYDECORATION) {
+                                docenv().warning(holder,
+                                                 "tag.missing_comma_space",
+                                                 name,
+                                                 "(" + parameters + ")");
+                                return (String[])null;
+                            }
+                            addTypeToParamList();
+                            state = NAME;
+                        } else if (cp == '[') {
+                            typeId.append('[');
+                            state = ARRAYDECORATION;
+                        } else if (cp == ',') {   // just the type
+                            addTypeToParamList();
+                            state = START;
+                        } // consume rest all
+                        prevstate = TNSPACE;
+                        break;
+                    case ARRAYDECORATION:
+                        if (cp == ']') {
+                            typeId.append(']');
+                            state = TNSPACE;
+                        } else if (!Character.isWhitespace(cp)) {
+                            docenv().warning(holder,
+                                             "tag.illegal_char_in_arr_dim",
+                                             name,
+                                             "(" + parameters + ")");
+                            return (String[])null;
+                        }
+                        prevstate = ARRAYDECORATION;
+                        break;
+                    case NAME:
+                        if (cp == ',') {  // just consume everything till ','
+                            state = START;
+                        }
+                        prevstate = NAME;
+                        break;
+                }
+            }
+            if (state == ARRAYDECORATION ||
+                (state == START && prevstate == TNSPACE)) {
+                docenv().warning(holder,
+                                 "tag.illegal_see_tag",
+                                 "(" + parameters + ")");
+            }
+            if (typeId.length() > 0) {
+                paramList.append(typeId.toString());
+            }
+            return paramList.toArray(new String[paramList.length()]);
+        }
+
+        void addTypeToParamList() {
+            if (typeId.length() > 0) {
+                paramList.append(typeId.toString());
+                typeId.setLength(0);
+            }
+        }
+    }
+
+    /**
+     * Return the kind of this tag.
+     */
+    @Override
+    public String kind() {
+        return "@see";
+    }
+
+    /**
+     * Return the label of the see tag.
+     */
+    public String label() {
+        return label;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerialFieldTagImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 1998, 2012, 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.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+/**
+ * Documents a Serializable field defined by an ObjectStreamField.
+ * <pre>
+ * The class parses and stores the three serialField tag parameters:
+ *
+ * - field name
+ * - field type name
+ *      (fully-qualified or visible from the current import context)
+ * - description of the valid values for the field
+
+ * </pre>
+ * This tag is only allowed in the javadoc for the special member
+ * serialPersistentFields.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Joe Fialli
+ * @author Neal Gafter
+ *
+ * @see java.io.ObjectStreamField
+ */
+class SerialFieldTagImpl
+    extends TagImpl
+    implements SerialFieldTag, Comparable<Object>
+{
+    //### These could be final, except that the constructor
+    //### does not set them directly.
+
+    private String fieldName;    // Required Argument 1 of serialField
+    private String fieldType;    // Required Argument 2 of serialField
+    private String description;  // Optional Remaining Arguments of serialField
+
+    private ClassDoc containingClass;   // Class containing serialPersistentField member
+    private ClassDoc fieldTypeDoc;      // ClassDocImpl of fieldType
+    private FieldDocImpl matchingField; // FieldDocImpl with same name as fieldName
+
+   /* Constructor. */
+   SerialFieldTagImpl(DocImpl holder, String name, String text) {
+        super(holder, name, text);
+        parseSerialFieldString();
+        if (holder instanceof MemberDoc) {
+            containingClass = ((MemberDocImpl)holder).containingClass();
+        }
+    }
+
+    /*
+     * The serialField tag is composed of three entities.
+     *
+     *   serialField  serializableFieldName serisliableFieldType
+     *                 description of field.
+     *
+     * The fieldName and fieldType must be legal Java Identifiers.
+     */
+    private void parseSerialFieldString() {
+        int len = text.length();
+        if (len == 0) {
+            return;
+        }
+
+        // if no white space found
+        /* Skip white space. */
+        int inx = 0;
+        int cp;
+        for (; inx < len; inx += Character.charCount(cp)) {
+             cp = text.codePointAt(inx);
+             if (!Character.isWhitespace(cp)) {
+                 break;
+             }
+        }
+
+        /* find first word. */
+        int first = inx;
+        int last = inx;
+        cp = text.codePointAt(inx);
+        if (! Character.isJavaIdentifierStart(cp)) {
+            docenv().warning(holder,
+                             "tag.serialField.illegal_character",
+                             new String(Character.toChars(cp)), text);
+            return;
+        }
+
+        for (inx += Character.charCount(cp); inx < len; inx += Character.charCount(cp)) {
+             cp = text.codePointAt(inx);
+             if (!Character.isJavaIdentifierPart(cp)) {
+                 break;
+             }
+        }
+
+        if (inx < len && ! Character.isWhitespace(cp = text.codePointAt(inx))) {
+            docenv().warning(holder,
+                             "tag.serialField.illegal_character",
+                             new String(Character.toChars(cp)), text);
+            return;
+        }
+
+        last = inx;
+        fieldName = text.substring(first, last);
+
+        /* Skip white space. */
+        for (; inx < len; inx += Character.charCount(cp)) {
+             cp = text.codePointAt(inx);
+             if (!Character.isWhitespace(cp)) {
+                 break;
+             }
+        }
+
+        /* find second word. */
+        first = inx;
+        last = inx;
+
+        for (; inx < len; inx += Character.charCount(cp)) {
+             cp = text.codePointAt(inx);
+             if (Character.isWhitespace(cp)) {
+                 break;
+             }
+        }
+        if (inx < len && ! Character.isWhitespace(cp = text.codePointAt(inx))) {
+            docenv().warning(holder,
+                             "tag.serialField.illegal_character",
+                             new String(Character.toChars(cp)), text);
+            return;
+        }
+        last = inx;
+        fieldType = text.substring(first, last);
+
+        /* Skip leading white space. Rest of string is description for serialField.*/
+        for (; inx < len; inx += Character.charCount(cp)) {
+             cp = text.codePointAt(inx);
+             if (!Character.isWhitespace(cp)) {
+                 break;
+             }
+        }
+        description = text.substring(inx);
+    }
+
+    /**
+     * return a key for sorting.
+     */
+    String key() {
+        return fieldName;
+    }
+
+    /*
+     * Optional. Link this serialField tag to its corrsponding
+     * field in the class. Note: there is no requirement that
+     * there be a field in the class that matches serialField tag.
+     */
+    void mapToFieldDocImpl(FieldDocImpl fd) {
+        matchingField = fd;
+    }
+
+    /**
+     * Return the serialziable field name.
+     */
+    public String fieldName() {
+        return fieldName;
+    }
+
+    /**
+     * Return the field type string.
+     */
+    public String fieldType() {
+        return fieldType;
+    }
+
+    /**
+     * Return the ClassDocImpl for field type.
+     *
+     * @returns null if no ClassDocImpl for field type is visible from
+     *          containingClass context.
+     */
+    public ClassDoc fieldTypeDoc() {
+        if (fieldTypeDoc == null && containingClass != null) {
+            fieldTypeDoc = containingClass.findClass(fieldType);
+        }
+        return fieldTypeDoc;
+    }
+
+    /**
+     * Return the corresponding FieldDocImpl for this SerialFieldTagImpl.
+     *
+     * @returns null if no matching FieldDocImpl.
+     */
+    FieldDocImpl getMatchingField() {
+        return matchingField;
+    }
+
+    /**
+     * Return the field comment. If there is no serialField comment, return
+     * javadoc comment of corresponding FieldDocImpl.
+     */
+    public String description() {
+        if (description.length() == 0 && matchingField != null) {
+
+            //check for javadoc comment of corresponding field.
+            Comment comment = matchingField.comment();
+            if (comment != null) {
+                return comment.commentText();
+            }
+        }
+        return description;
+    }
+
+    /**
+     * Return the kind of this tag.
+     */
+    public String kind() {
+        return "@serialField";
+    }
+
+    /**
+     * Convert this object to a string.
+     */
+    public String toString() {
+        return name + ":" + text;
+    }
+
+    /**
+     * Compares this Object with the specified Object for order.  Returns a
+     * negative integer, zero, or a positive integer as this Object is less
+     * than, equal to, or greater than the given Object.
+     * <p>
+     * Included to make SerialFieldTagImpl items java.lang.Comparable.
+     *
+     * @param   obj the <code>Object</code> to be compared.
+     * @return  a negative integer, zero, or a positive integer as this Object
+     *          is less than, equal to, or greater than the given Object.
+     * @exception ClassCastException the specified Object's type prevents it
+     *            from being compared to this Object.
+     * @since 1.2
+     */
+    public int compareTo(Object obj) {
+        return key().compareTo(((SerialFieldTagImpl)obj).key());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SerializedForm.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 1998, 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 com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
+import com.sun.tools.javac.util.*;
+
+import static com.sun.tools.javac.code.Kinds.Kind.*;
+import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
+
+/**
+ * The serialized form is the specification of a class' serialization
+ * state. <p>
+ *
+ * It consists of the following information:<p>
+ *
+ * <pre>
+ * 1. Whether class is Serializable or Externalizable.
+ * 2. Javadoc for serialization methods.
+ *    a. For Serializable, the optional readObject, writeObject,
+ *       readResolve and writeReplace.
+ *       serialData tag describes, in prose, the sequence and type
+ *       of optional data written by writeObject.
+ *    b. For Externalizable, writeExternal and readExternal.
+ *       serialData tag describes, in prose, the sequence and type
+ *       of optional data written by writeExternal.
+ * 3. Javadoc for serialization data layout.
+ *    a. For Serializable, the name,type and description
+ *       of each Serializable fields.
+ *    b. For Externalizable, data layout is described by 2(b).
+ * </pre>
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since 1.2
+ * @author Joe Fialli
+ * @author Neal Gafter (rewrite but not too proud)
+ */
+class SerializedForm {
+    ListBuffer<MethodDoc> methods = new ListBuffer<>();
+
+    /* List of FieldDocImpl - Serializable fields.
+     * Singleton list if class defines Serializable fields explicitly.
+     * Otherwise, list of default serializable fields.
+     * 0 length list for Externalizable.
+     */
+    private final ListBuffer<FieldDocImpl> fields = new ListBuffer<>();
+
+    /* True if class specifies serializable fields explicitly.
+     * using special static member, serialPersistentFields.
+     */
+    private boolean definesSerializableFields = false;
+
+    // Specially treated field/method names defined by Serialization.
+    private static final String SERIALIZABLE_FIELDS = "serialPersistentFields";
+    private static final String READOBJECT  = "readObject";
+    private static final String WRITEOBJECT = "writeObject";
+    private static final String READRESOLVE  = "readResolve";
+    private static final String WRITEREPLACE = "writeReplace";
+    private static final String READOBJECTNODATA = "readObjectNoData";
+
+    /**
+     * Constructor.
+     *
+     * Catalog Serializable fields for Serializable class.
+     * Catalog serialization methods for Serializable and
+     * Externalizable classes.
+     */
+    SerializedForm(DocEnv env, ClassSymbol def, ClassDocImpl cd) {
+        if (cd.isExternalizable()) {
+            /* look up required public accessible methods,
+             *   writeExternal and readExternal.
+             */
+            String[] readExternalParamArr = { "java.io.ObjectInput" };
+            String[] writeExternalParamArr = { "java.io.ObjectOutput" };
+            MethodDoc md = cd.findMethod("readExternal", readExternalParamArr);
+            if (md != null) {
+                methods.append(md);
+            }
+            md = cd.findMethod("writeExternal", writeExternalParamArr);
+            if (md != null) {
+                methods.append(md);
+                Tag tag[] = md.tags("serialData");
+            }
+        // } else { // isSerializable() //### ???
+        } else if (cd.isSerializable()) {
+
+            VarSymbol dsf = getDefinedSerializableFields(def);
+            if (dsf != null) {
+
+                /* Define serializable fields with array of ObjectStreamField.
+                 * Each ObjectStreamField should be documented by a
+                 * serialField tag.
+                 */
+                definesSerializableFields = true;
+                //### No modifier filtering applied here.
+                FieldDocImpl dsfDoc = env.getFieldDoc(dsf);
+                fields.append(dsfDoc);
+                mapSerialFieldTagImplsToFieldDocImpls(dsfDoc, env, def);
+            } else {
+
+                /* Calculate default Serializable fields as all
+                 * non-transient, non-static fields.
+                 * Fields should be documented by serial tag.
+                 */
+                computeDefaultSerializableFields(env, def, cd);
+            }
+
+           /* Check for optional customized readObject, writeObject,
+            * readResolve and writeReplace, which can all contain
+            * the serialData tag.        */
+            addMethodIfExist(env, def, READOBJECT);
+            addMethodIfExist(env, def, WRITEOBJECT);
+            addMethodIfExist(env, def, READRESOLVE);
+            addMethodIfExist(env, def, WRITEREPLACE);
+            addMethodIfExist(env, def, READOBJECTNODATA);
+        }
+    }
+
+    /*
+     * Check for explicit Serializable fields.
+     * Check for a private static array of ObjectStreamField with
+     * name SERIALIZABLE_FIELDS.
+     */
+    private VarSymbol getDefinedSerializableFields(ClassSymbol def) {
+        Names names = def.name.table.names;
+
+        /* SERIALIZABLE_FIELDS can be private,
+         * so must lookup by ClassSymbol, not by ClassDocImpl.
+         */
+        for (Symbol sym : def.members().getSymbolsByName(names.fromString(SERIALIZABLE_FIELDS))) {
+            if (sym.kind == VAR) {
+                VarSymbol f = (VarSymbol)sym;
+                if ((f.flags() & Flags.STATIC) != 0 &&
+                    (f.flags() & Flags.PRIVATE) != 0) {
+                    return f;
+                }
+            }
+        }
+        return null;
+    }
+
+    /*
+     * Compute default Serializable fields from all members of ClassSymbol.
+     *
+     * Since the fields of ClassDocImpl might not contain private or
+     * package accessible fields, must walk over all members of ClassSymbol.
+     */
+    private void computeDefaultSerializableFields(DocEnv env,
+                                                  ClassSymbol def,
+                                                  ClassDocImpl cd) {
+        for (Symbol sym : def.members().getSymbols(NON_RECURSIVE)) {
+            if (sym != null && sym.kind == VAR) {
+                VarSymbol f = (VarSymbol)sym;
+                if ((f.flags() & Flags.STATIC) == 0 &&
+                    (f.flags() & Flags.TRANSIENT) == 0) {
+                    //### No modifier filtering applied here.
+                    FieldDocImpl fd = env.getFieldDoc(f);
+                    //### Add to beginning.
+                    //### Preserve order used by old 'javadoc'.
+                    fields.prepend(fd);
+                }
+            }
+        }
+    }
+
+    /*
+     * Catalog Serializable method if it exists in current ClassSymbol.
+     * Do not look for method in superclasses.
+     *
+     * Serialization requires these methods to be non-static.
+     *
+     * @param method should be an unqualified Serializable method
+     *               name either READOBJECT, WRITEOBJECT, READRESOLVE
+     *               or WRITEREPLACE.
+     * @param visibility the visibility flag for the given method.
+     */
+    private void addMethodIfExist(DocEnv env, ClassSymbol def, String methodName) {
+        Names names = def.name.table.names;
+
+        for (Symbol sym : def.members().getSymbolsByName(names.fromString(methodName))) {
+            if (sym.kind == MTH) {
+                MethodSymbol md = (MethodSymbol)sym;
+                if ((md.flags() & Flags.STATIC) == 0) {
+                    /*
+                     * WARNING: not robust if unqualifiedMethodName is overloaded
+                     *          method. Signature checking could make more robust.
+                     * READOBJECT takes a single parameter, java.io.ObjectInputStream.
+                     * WRITEOBJECT takes a single parameter, java.io.ObjectOutputStream.
+                     */
+                    methods.append(env.getMethodDoc(md));
+                }
+            }
+        }
+    }
+
+    /*
+     * Associate serialField tag fieldName with FieldDocImpl member.
+     * Note: A serialField tag does not have to map an existing field
+     *       of a class.
+     */
+    private void mapSerialFieldTagImplsToFieldDocImpls(FieldDocImpl spfDoc,
+                                                       DocEnv env,
+                                                       ClassSymbol def) {
+        Names names = def.name.table.names;
+        for (SerialFieldTag tag : spfDoc.serialFieldTags()) {
+            if (tag.fieldName() == null || tag.fieldType() == null) // ignore malformed @serialField tags
+                continue;
+
+            Name fieldName = names.fromString(tag.fieldName());
+
+            // Look for a FieldDocImpl that is documented by serialFieldTagImpl.
+            for (Symbol sym : def.members().getSymbolsByName(fieldName)) {
+                if (sym.kind == VAR) {
+                    VarSymbol f = (VarSymbol) sym;
+                    FieldDocImpl fdi = env.getFieldDoc(f);
+                    ((SerialFieldTagImpl) (tag)).mapToFieldDocImpl(fdi);
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Return serializable fields in class. <p>
+     *
+     * Returns either a list of default fields documented by serial tag comment or
+     *         javadoc comment<p>
+     * Or Returns a single FieldDocImpl for serialPersistentField. There is a
+     *         serialField tag for each serializable field.<p>
+     *
+     * @return an array of FieldDocImpl for representing the visible
+     *         fields in this class.
+     */
+    FieldDoc[] fields() {
+        return (FieldDoc[])fields.toArray(new FieldDocImpl[fields.length()]);
+    }
+
+    /**
+     * Return serialization methods in class.
+     *
+     * @return an array of MethodDocImpl for serialization methods in this class.
+     */
+    MethodDoc[] methods() {
+        return methods.toArray(new MethodDoc[methods.length()]);
+    }
+
+    /**
+     * Returns true if Serializable fields are defined explicitly using
+     * member, serialPersistentFields.
+     *
+     * @see #fields()
+     */
+    boolean definesSerializableFields() {
+        return definesSerializableFields;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/SourcePositionImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2001, 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 com.sun.tools.javadoc.main;
+
+import java.io.File;
+import javax.tools.FileObject;
+
+import com.sun.javadoc.SourcePosition;
+import com.sun.tools.javac.util.Position;
+
+/**
+ * A source position: filename, line number, and column number.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since J2SE1.4
+ * @author Neal M Gafter
+ * @author Michael Van De Vanter (position representation changed to char offsets)
+ */
+public class SourcePositionImpl implements SourcePosition {
+    FileObject filename;
+    int position;
+    Position.LineMap lineMap;
+
+    /** The source file. Returns null if no file information is
+     *  available. */
+    public File file() {
+        return (filename == null) ? null : new File(filename.getName());
+    }
+
+    /** The source file. Returns null if no file information is
+     *  available. */
+    public FileObject fileObject() {
+        return filename;
+    }
+
+    /** The line in the source file. The first line is numbered 1;
+     *  0 means no line number information is available. */
+    public int line() {
+        if (lineMap == null) {
+            return 0;
+        } else {
+            return lineMap.getLineNumber(position);
+        }
+    }
+
+    /** The column in the source file. The first column is
+     *  numbered 1; 0 means no column information is available.
+     *  Columns count characters in the input stream; a tab
+     *  advances the column number to the next 8-column tab stop.
+     */
+    public int column() {
+        if (lineMap == null) {
+            return 0;
+        }else {
+            return lineMap.getColumnNumber(position);
+        }
+    }
+
+    private SourcePositionImpl(FileObject file, int position,
+                               Position.LineMap lineMap) {
+        super();
+        this.filename = file;
+        this.position = position;
+        this.lineMap = lineMap;
+    }
+
+    public static SourcePosition make(FileObject file, int pos,
+                                      Position.LineMap lineMap) {
+        if (file == null) return null;
+        return new SourcePositionImpl(file, pos, lineMap);
+    }
+
+    public String toString() {
+        // Backwards compatibility hack. ZipFileObjects use the format
+        // zipfile(zipentry) but javadoc has been using zipfile/zipentry
+        String fn = filename.getName();
+        if (fn.endsWith(")")) {
+            int paren = fn.lastIndexOf("(");
+            if (paren != -1) {
+                int i = paren+1;
+                if (fn.charAt(i) == '/')
+                    i++;
+                fn = fn.substring(0, paren)
+                        + File.separatorChar
+                        + fn.substring(i, fn.length() - 1);
+            }
+        }
+
+        if (position == Position.NOPOS)
+            return fn;
+        else
+            return fn + ":" + line();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/Start.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,557 @@
+/*
+ * 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
+ * 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.sun.tools.javadoc.main;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
+
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+
+import com.sun.javadoc.*;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.main.CommandLine;
+import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.file.BaseFileManager;
+import com.sun.tools.javac.platform.PlatformDescription;
+import com.sun.tools.javac.platform.PlatformUtils;
+import com.sun.tools.javac.util.ClientCodeException;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Options;
+
+import static com.sun.tools.javac.code.Flags.*;
+
+/**
+ * Main program of Javadoc.
+ * Previously named "Main".
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @since 1.2
+ * @author Robert Field
+ * @author Neal Gafter (rewrite)
+ */
+public class Start extends ToolOption.Helper {
+    /** Context for this invocation. */
+    private final Context context;
+
+    private final String defaultDocletClassName;
+    private final ClassLoader docletParentClassLoader;
+
+    private static final String javadocName = "javadoc";
+
+    private static final String standardDocletClassName =
+        "com.sun.tools.doclets.standard.Standard";
+
+    private final long defaultFilter = PUBLIC | PROTECTED;
+
+    private final Messager messager;
+
+    private DocletInvoker docletInvoker;
+
+    /**
+     * In API mode, exceptions thrown while calling the doclet are
+     * propagated using ClientCodeException.
+     */
+    private boolean apiMode;
+
+    private JavaFileManager fileManager;
+
+    public Start(String programName,
+          PrintWriter errWriter,
+          PrintWriter warnWriter,
+          PrintWriter noticeWriter,
+          String defaultDocletClassName) {
+        this(programName, errWriter, warnWriter, noticeWriter, defaultDocletClassName, null);
+    }
+
+    public Start(PrintWriter pw) {
+        this(javadocName, pw, pw, pw, standardDocletClassName);
+    }
+
+    public Start(String programName,
+          PrintWriter errWriter,
+          PrintWriter warnWriter,
+          PrintWriter noticeWriter,
+          String defaultDocletClassName,
+          ClassLoader docletParentClassLoader) {
+        context = new Context();
+        messager = new Messager(context, programName, errWriter, warnWriter, noticeWriter);
+        this.defaultDocletClassName = defaultDocletClassName;
+        this.docletParentClassLoader = docletParentClassLoader;
+    }
+
+    public Start(String programName, String defaultDocletClassName) {
+        this(programName, defaultDocletClassName, null);
+    }
+
+    public Start(String programName, String defaultDocletClassName,
+          ClassLoader docletParentClassLoader) {
+        context = new Context();
+        messager = new Messager(context, programName);
+        this.defaultDocletClassName = defaultDocletClassName;
+        this.docletParentClassLoader = docletParentClassLoader;
+    }
+
+    public Start(String programName, ClassLoader docletParentClassLoader) {
+        this(programName, standardDocletClassName, docletParentClassLoader);
+    }
+
+    public Start(String programName) {
+        this(programName, standardDocletClassName);
+    }
+
+    public Start(ClassLoader docletParentClassLoader) {
+        this(javadocName, docletParentClassLoader);
+    }
+
+    public Start() {
+        this(javadocName);
+    }
+
+    public Start(Context context) {
+        this.context = Objects.requireNonNull(context);
+        apiMode = true;
+        defaultDocletClassName = standardDocletClassName;
+        docletParentClassLoader = null;
+
+        Log log = context.get(Log.logKey);
+        if (log instanceof Messager)
+            messager = (Messager) log;
+        else {
+            PrintWriter out = context.get(Log.outKey);
+            messager = (out == null) ? new Messager(context, javadocName)
+                    : new Messager(context, javadocName, out, out, out);
+        }
+    }
+
+    /**
+     * Usage
+     */
+    @Override
+    void usage() {
+        usage(true);
+    }
+
+    void usage(boolean exit) {
+        usage("main.usage", "-help", null, exit);
+    }
+
+    @Override
+    void Xusage() {
+        Xusage(true);
+    }
+
+    void Xusage(boolean exit) {
+        usage("main.Xusage", "-X", "main.Xusage.foot", exit);
+    }
+
+    private void usage(String main, String doclet, String foot, boolean exit) {
+        // RFE: it would be better to replace the following with code to
+        // write a header, then help for each option, then a footer.
+        messager.notice(main);
+
+        // let doclet print usage information (does nothing on error)
+        if (docletInvoker != null) {
+            // RFE: this is a pretty bad way to get the doclet to show
+            // help info. Moreover, the output appears on stdout,
+            // and <i>not</i> on any of the standard streams passed
+            // to javadoc, and in particular, not to the noticeWriter
+            // But, to fix this, we need to fix the Doclet API.
+            docletInvoker.optionLength(doclet);
+        }
+
+        if (foot != null)
+            messager.notice(foot);
+
+        if (exit) exit();
+    }
+
+    /**
+     * Exit
+     */
+    private void exit() {
+        messager.exit();
+    }
+
+
+    /**
+     * Main program - external wrapper
+     */
+    public int begin(String... argv) {
+        boolean ok = begin(null, argv, Collections.<JavaFileObject> emptySet());
+        return ok ? 0 : 1;
+    }
+
+    public boolean begin(Class<?> docletClass, Iterable<String> options, Iterable<? extends JavaFileObject> fileObjects) {
+        Collection<String> opts = new ArrayList<>();
+        for (String opt: options) opts.add(opt);
+        return begin(docletClass, opts.toArray(new String[opts.size()]), fileObjects);
+    }
+
+    private boolean begin(Class<?> docletClass, String[] options, Iterable<? extends JavaFileObject> fileObjects) {
+        boolean failed = false;
+
+        try {
+            failed = !parseAndExecute(docletClass, options, fileObjects);
+        } catch (Messager.ExitJavadoc exc) {
+            // ignore, we just exit this way
+        } catch (OutOfMemoryError ee) {
+            messager.error(Messager.NOPOS, "main.out.of.memory");
+            failed = true;
+        } catch (ClientCodeException e) {
+            // simply rethrow these exceptions, to be caught and handled by JavadocTaskImpl
+            throw e;
+        } catch (Error ee) {
+            ee.printStackTrace(System.err);
+            messager.error(Messager.NOPOS, "main.fatal.error");
+            failed = true;
+        } catch (Exception ee) {
+            ee.printStackTrace(System.err);
+            messager.error(Messager.NOPOS, "main.fatal.exception");
+            failed = true;
+        } finally {
+            if (fileManager != null
+                    && fileManager instanceof BaseFileManager
+                    && ((BaseFileManager) fileManager).autoClose) {
+                try {
+                    fileManager.close();
+                } catch (IOException ignore) {
+                }
+            }
+            messager.exitNotice();
+            messager.flush();
+        }
+        failed |= messager.nerrors() > 0;
+        failed |= rejectWarnings && messager.nwarnings() > 0;
+        return !failed;
+    }
+
+    /**
+     * Main program - internal
+     */
+    private boolean parseAndExecute(
+            Class<?> docletClass,
+            String[] argv,
+            Iterable<? extends JavaFileObject> fileObjects) throws IOException {
+        long tm = System.currentTimeMillis();
+
+        ListBuffer<String> javaNames = new ListBuffer<>();
+
+        // Preprocess @file arguments
+        try {
+            argv = CommandLine.parse(argv);
+        } catch (FileNotFoundException e) {
+            messager.error(Messager.NOPOS, "main.cant.read", e.getMessage());
+            exit();
+        } catch (IOException e) {
+            e.printStackTrace(System.err);
+            exit();
+        }
+
+
+        fileManager = context.get(JavaFileManager.class);
+
+        setDocletInvoker(docletClass, fileManager, argv);
+
+        compOpts = Options.instance(context);
+        // Make sure no obsolete source/target messages are reported
+        compOpts.put("-Xlint:-options", "-Xlint:-options");
+
+        // Parse arguments
+        for (int i = 0 ; i < argv.length ; i++) {
+            String arg = argv[i];
+
+            ToolOption o = ToolOption.get(arg);
+            if (o != null) {
+                // hack: this restriction should be removed
+                if (o == ToolOption.LOCALE && i > 0)
+                    usageError("main.locale_first");
+
+                if (o.hasArg) {
+                    oneArg(argv, i++);
+                    o.process(this, argv[i]);
+                } else {
+                    setOption(arg);
+                    o.process(this);
+                }
+            } else if (arg.equals("-XDaccessInternalAPI")) {
+                // pass this hidden option down to the doclet, if it wants it
+                if (docletInvoker.optionLength("-XDaccessInternalAPI") == 1) {
+                    setOption(arg);
+                }
+            } else if (arg.startsWith("-XD")) {
+                // hidden javac options
+                String s = arg.substring("-XD".length());
+                int eq = s.indexOf('=');
+                String key = (eq < 0) ? s : s.substring(0, eq);
+                String value = (eq < 0) ? s : s.substring(eq+1);
+                compOpts.put(key, value);
+            }
+            // call doclet for its options
+            // other arg starts with - is invalid
+            else if (arg.startsWith("-")) {
+                int optionLength;
+                optionLength = docletInvoker.optionLength(arg);
+                if (optionLength < 0) {
+                    // error already displayed
+                    exit();
+                } else if (optionLength == 0) {
+                    // option not found
+                    usageError("main.invalid_flag", arg);
+                } else {
+                    // doclet added option
+                    if ((i + optionLength) > argv.length) {
+                        usageError("main.requires_argument", arg);
+                    }
+                    ListBuffer<String> args = new ListBuffer<>();
+                    for (int j = 0; j < optionLength-1; ++j) {
+                        args.append(argv[++i]);
+                    }
+                    setOption(arg, args.toList());
+                }
+            } else {
+                javaNames.append(arg);
+            }
+        }
+
+        if (fileManager == null) {
+            JavacFileManager.preRegister(context);
+            fileManager = context.get(JavaFileManager.class);
+            if (fileManager instanceof BaseFileManager) {
+                ((BaseFileManager) fileManager).autoClose = true;
+            }
+        }
+        if (fileManager instanceof BaseFileManager) {
+            ((BaseFileManager) fileManager).handleOptions(fileManagerOpts);
+        }
+
+        String platformString = compOpts.get("-release");
+
+        if (platformString != null) {
+            if (compOpts.isSet("-source")) {
+                usageError("main.release.bootclasspath.conflict", "-source");
+            }
+            if (fileManagerOpts.containsKey(Option.BOOTCLASSPATH)) {
+                usageError("main.release.bootclasspath.conflict", Option.BOOTCLASSPATH.getText());
+            }
+
+            PlatformDescription platformDescription =
+                    PlatformUtils.lookupPlatformDescription(platformString);
+
+            if (platformDescription == null) {
+                usageError("main.unsupported.release.version", platformString);
+            }
+
+            compOpts.put(Option.SOURCE, platformDescription.getSourceVersion());
+
+            context.put(PlatformDescription.class, platformDescription);
+
+            Collection<Path> platformCP = platformDescription.getPlatformPath();
+
+            if (platformCP != null) {
+                if (fileManager instanceof StandardJavaFileManager) {
+                    StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
+
+                    sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP);
+                } else {
+                    usageError("main.release.not.standard.file.manager", platformString);
+                }
+            }
+        }
+
+        compOpts.notifyListeners();
+
+        if (javaNames.isEmpty() && subPackages.isEmpty() && isEmpty(fileObjects)) {
+            usageError("main.No_packages_or_classes_specified");
+        }
+
+        if (!docletInvoker.validOptions(options.toList())) {
+            // error message already displayed
+            exit();
+        }
+
+        JavadocTool comp = JavadocTool.make0(context);
+        if (comp == null) return false;
+
+        if (showAccess == null) {
+            setFilter(defaultFilter);
+        }
+
+        LanguageVersion languageVersion = docletInvoker.languageVersion();
+        RootDocImpl root = comp.getRootDocImpl(
+                docLocale,
+                encoding,
+                showAccess,
+                javaNames.toList(),
+                options.toList(),
+                fileObjects,
+                breakiterator,
+                subPackages.toList(),
+                excludedPackages.toList(),
+                docClasses,
+                // legacy?
+                languageVersion == null || languageVersion == LanguageVersion.JAVA_1_1,
+                quiet);
+
+        // release resources
+        comp = null;
+
+        // pass off control to the doclet
+        boolean ok = root != null;
+        if (ok) ok = docletInvoker.start(root);
+
+        // We're done.
+        if (compOpts.get("-verbose") != null) {
+            tm = System.currentTimeMillis() - tm;
+            messager.notice("main.done_in", Long.toString(tm));
+        }
+
+        return ok;
+    }
+
+    private <T> boolean isEmpty(Iterable<T> iter) {
+        return !iter.iterator().hasNext();
+    }
+
+    /**
+     * Init the doclet invoker.
+     * The doclet class may be given explicitly, or via the -doclet option in
+     * argv.
+     * If the doclet class is not given explicitly, it will be loaded from
+     * the file manager's DOCLET_PATH location, if available, or via the
+     * -doclet path option in argv.
+     * @param docletClass The doclet class. May be null.
+     * @param fileManager The file manager used to get the class loader to load
+     * the doclet class if required. May be null.
+     * @param argv Args containing -doclet and -docletpath, in case they are required.
+     */
+    private void setDocletInvoker(Class<?> docletClass, JavaFileManager fileManager, String[] argv) {
+        boolean exportInternalAPI = false;
+        String docletClassName = null;
+        String docletPath = null;
+
+        // Parse doclet specifying arguments
+        for (int i = 0 ; i < argv.length ; i++) {
+            String arg = argv[i];
+            if (arg.equals(ToolOption.DOCLET.opt)) {
+                oneArg(argv, i++);
+                if (docletClassName != null) {
+                    usageError("main.more_than_one_doclet_specified_0_and_1",
+                               docletClassName, argv[i]);
+                }
+                docletClassName = argv[i];
+            } else if (arg.equals(ToolOption.DOCLETPATH.opt)) {
+                oneArg(argv, i++);
+                if (docletPath == null) {
+                    docletPath = argv[i];
+                } else {
+                    docletPath += File.pathSeparator + argv[i];
+                }
+            } else if (arg.equals("-XDaccessInternalAPI")) {
+                exportInternalAPI = true;
+            }
+        }
+
+        if (docletClass != null) {
+            // TODO, check no -doclet, -docletpath
+            docletInvoker = new DocletInvoker(messager, docletClass, apiMode, exportInternalAPI);
+        } else {
+            if (docletClassName == null) {
+                docletClassName = defaultDocletClassName;
+            }
+
+            // attempt to find doclet
+            docletInvoker = new DocletInvoker(messager, fileManager,
+                    docletClassName, docletPath,
+                    docletParentClassLoader,
+                    apiMode,
+                    exportInternalAPI);
+        }
+    }
+
+    /**
+     * Set one arg option.
+     * Error and exit if one argument is not provided.
+     */
+    private void oneArg(String[] args, int index) {
+        if ((index + 1) < args.length) {
+            setOption(args[index], args[index+1]);
+        } else {
+            usageError("main.requires_argument", args[index]);
+        }
+    }
+
+    @Override
+    void usageError(String key, Object... args) {
+        messager.error(Messager.NOPOS, key, args);
+        usage(true);
+    }
+
+    /**
+     * indicate an option with no arguments was given.
+     */
+    private void setOption(String opt) {
+        String[] option = { opt };
+        options.append(option);
+    }
+
+    /**
+     * indicate an option with one argument was given.
+     */
+    private void setOption(String opt, String argument) {
+        String[] option = { opt, argument };
+        options.append(option);
+    }
+
+    /**
+     * indicate an option with the specified list of arguments was given.
+     */
+    private void setOption(String opt, List<String> arguments) {
+        String[] args = new String[arguments.length() + 1];
+        int k = 0;
+        args[k++] = opt;
+        for (List<String> i = arguments; i.nonEmpty(); i=i.tail) {
+            args[k++] = i.head;
+        }
+        options.append(args);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TagImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1997, 2012, 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.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+/**
+ * Represents a documentation tag, e.g. @since, @author, @version.
+ * Given a tag (e.g. "@since 1.2"), holds tag name (e.g. "@since")
+ * and tag text (e.g. "1.2").  TagImpls with structure or which require
+ * special processing are handled by subclasses (ParamTagImpl, SeeTagImpl,
+ * and ThrowsTagImpl
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Robert Field
+ * @author Atul M Dambalkar
+ * @author Neal M Gafter
+ * @see SeeTagImpl
+ * @see ParamTagImpl
+ * @see ThrowsTagImpl
+ * @see Doc#tags()
+ *
+ */
+class TagImpl implements Tag {
+
+    protected final String text;
+    protected final String name;
+    protected final DocImpl holder;
+
+    /**
+     * Cached first sentence.
+     */
+    private Tag[] firstSentence;
+
+    /**
+     * Cached inline tags.
+     */
+    private Tag[] inlineTags;
+
+    /**
+     *  Constructor
+     */
+    TagImpl(DocImpl holder, String name, String text) {
+        this.holder = holder;
+        this.name = name;
+        this.text = text;
+    }
+
+    /**
+     * Return the name of this tag.
+     */
+    public String name() {
+        return name;
+    }
+
+    /**
+     * Return the containing {@link Doc} of this Tag element.
+     */
+    public Doc holder() {
+        return holder;
+    }
+
+    /**
+     * Return the kind of this tag.
+     */
+    public String kind() {
+        return name;
+    }
+
+    /**
+     * Return the text of this tag, that is, portion beyond tag name.
+     */
+    public String text() {
+        return text;
+    }
+
+    DocEnv docenv() {
+        return holder.env;
+    }
+
+    /**
+     * for use by subclasses which have two part tag text.
+     */
+    String[] divideAtWhite() {
+        String[] sa = new String[2];
+        int len = text.length();
+        // if no white space found
+        sa[0] = text;
+        sa[1] = "";
+        for (int inx = 0; inx < len; ++inx) {
+            char ch = text.charAt(inx);
+            if (Character.isWhitespace(ch)) {
+                sa[0] = text.substring(0, inx);
+                for (; inx < len; ++inx) {
+                    ch = text.charAt(inx);
+                    if (!Character.isWhitespace(ch)) {
+                        sa[1] = text.substring(inx, len);
+                        break;
+                    }
+                }
+                break;
+            }
+        }
+        return sa;
+    }
+
+    /**
+     * convert this object to a string.
+     */
+    public String toString() {
+        return name + ":" + text;
+    }
+
+    /**
+     * For documentation comment with embedded @link tags, return the array of
+     * TagImpls consisting of SeeTagImpl(s) and text containing TagImpl(s).
+     * Within a comment string "This is an example of inline tags for a
+     * documentation comment {@link Doc {@link Doc commentlabel}}",
+     * where inside the inner braces, the first "Doc" carries exctly the same
+     * syntax as a SeeTagImpl and the second "commentlabel" is label for the Html
+     * Link, will return an array of TagImpl(s) with first element as TagImpl with
+     * comment text "This is an example of inline tags for a documentation
+     * comment" and second element as SeeTagImpl with referenced class as "Doc"
+     * and the label for the Html Link as "commentlabel".
+     *
+     * @return TagImpl[] Array of tags with inline SeeTagImpls.
+     * @see ParamTagImpl
+     * @see ThrowsTagImpl
+     */
+    public Tag[] inlineTags() {
+        if (inlineTags == null) {
+            inlineTags = Comment.getInlineTags(holder, text);
+        }
+        return inlineTags;
+    }
+
+    /**
+     * Return array of tags for the first sentence in the doc comment text.
+     */
+    public Tag[] firstSentenceTags() {
+        if (firstSentence == null) {
+            //Parse all sentences first to avoid duplicate warnings.
+            inlineTags();
+            try {
+                docenv().setSilent(true);
+                firstSentence = Comment.firstSentenceTags(holder, text);
+            } finally {
+                docenv().setSilent(false);
+            }
+        }
+        return firstSentence;
+    }
+
+    /**
+     * Return the doc item to which this tag is attached.
+     * @return the doc item to which this tag is attached.
+     */
+    public SourcePosition position() {
+        return holder.position();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ThrowsTagImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1997, 2012, 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.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+/**
+ * Represents a @throws or @exception documentation tag.
+ * Parses and holds the exception name and exception comment.
+ * The exception name my be the name of a type variable.
+ * Note: @exception is a backwards compatible synonymy for @throws.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Robert Field
+ * @author Atul M Dambalkar
+ * @see ExecutableMemberDocImpl#throwsTags()
+ *
+ */
+class ThrowsTagImpl extends TagImpl implements ThrowsTag {
+
+    private final String exceptionName;
+    private final String exceptionComment;
+
+    /**
+     * Cached inline tags.
+     */
+    private Tag[] inlineTags;
+
+    ThrowsTagImpl(DocImpl holder, String name, String text) {
+        super(holder, name, text);
+        String[] sa = divideAtWhite();
+        exceptionName = sa[0];
+        exceptionComment = sa[1];
+    }
+
+    /**
+     * Return the exception name.
+     */
+    public String exceptionName() {
+        return exceptionName;
+    }
+
+    /**
+     * Return the exception comment.
+     */
+    public String exceptionComment() {
+        return exceptionComment;
+    }
+
+    /**
+     * Return the exception as a ClassDocImpl.
+     */
+    public ClassDoc exception() {
+        ClassDocImpl exceptionClass;
+        if (!(holder instanceof ExecutableMemberDoc)) {
+            exceptionClass = null;
+        } else {
+            ExecutableMemberDocImpl emd = (ExecutableMemberDocImpl)holder;
+            ClassDocImpl con = (ClassDocImpl)emd.containingClass();
+            exceptionClass = (ClassDocImpl)con.findClass(exceptionName);
+        }
+        return exceptionClass;
+    }
+
+    /**
+     * Return the type that represents the exception.
+     * This may be a <code>ClassDoc</code> or a <code>TypeVariable</code>.
+     */
+    public Type exceptionType() {
+        //###(gj) TypeVariable not yet supported.
+        return exception();
+    }
+
+
+    /**
+     * Return the kind of this tag.  Always "@throws" for instances
+     * of ThrowsTagImpl.
+     */
+    @Override
+    public String kind() {
+        return "@throws";
+    }
+
+    /**
+     * For the exception comment with embedded @link tags return the array of
+     * TagImpls consisting of SeeTagImpl(s) and text containing TagImpl(s).
+     *
+     * @return TagImpl[] Array of tags with inline SeeTagImpls.
+     * @see TagImpl#inlineTags()
+     * @see ParamTagImpl#inlineTags()
+     */
+    @Override
+    public Tag[] inlineTags() {
+        if (inlineTags == null) {
+            inlineTags = Comment.getInlineTags(holder, exceptionComment());
+        }
+        return inlineTags;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/ToolOption.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,392 @@
+/*
+ * 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
+ * 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.sun.tools.javadoc.main;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Options;
+
+
+/**
+ * javadoc tool options.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public enum ToolOption {
+    // ----- options for underlying compiler -----
+
+    BOOTCLASSPATH("-bootclasspath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.BOOTCLASSPATH, arg);
+        }
+    },
+
+    CLASSPATH("-classpath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.CLASSPATH, arg);
+        }
+    },
+
+    CP("-cp", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.CP, arg);
+        }
+    },
+
+    EXTDIRS("-extdirs", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.EXTDIRS, arg);
+        }
+    },
+
+    SOURCEPATH("-sourcepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.SOURCEPATH, arg);
+        }
+    },
+
+    SYSCLASSPATH("-sysclasspath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.BOOTCLASSPATH, arg);
+        }
+    },
+
+    MODULESOURCEPATH("-modulesourcepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULESOURCEPATH, arg);
+        }
+    },
+
+    UPGRADEMODULEPATH("-upgrademodulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.UPGRADEMODULEPATH, arg);
+        }
+    },
+
+    SYSTEM("-system", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.SYSTEM, arg);
+        }
+    },
+
+    MODULEPATH("-modulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULEPATH, arg);
+        }
+    },
+
+    ADDMODS("-addmods", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    LIMITMODS("-limitmods", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    ENCODING("-encoding", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.encoding = arg;
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    RELEASE("-release", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    SOURCE("-source", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    XMAXERRS("-Xmaxerrs", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    XMAXWARNS("-Xmaxwarns", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    // ----- doclet options -----
+
+    DOCLET("-doclet", true), // handled in setDocletInvoker
+
+    DOCLETPATH("-docletpath", true), // handled in setDocletInvoker
+
+    // ----- selection options -----
+
+    SUBPACKAGES("-subpackages", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.addToList(helper.subPackages, arg);
+        }
+    },
+
+    EXCLUDE("-exclude", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.addToList(helper.excludedPackages, arg);
+        }
+    },
+
+    // ----- filtering options -----
+
+    PACKAGE("-package") {
+        @Override
+        public void process(Helper helper) {
+            helper.setFilter(
+                    Flags.PUBLIC | Flags.PROTECTED | ModifierFilter.PACKAGE);
+        }
+    },
+
+    PRIVATE("-private") {
+        @Override
+        public void process(Helper helper) {
+            helper.setFilter(ModifierFilter.ALL_ACCESS);
+        }
+    },
+
+    PROTECTED("-protected") {
+        @Override
+        public void process(Helper helper) {
+            helper.setFilter(Flags.PUBLIC | Flags.PROTECTED);
+        }
+    },
+
+    PUBLIC("-public") {
+        @Override
+        public void process(Helper helper) {
+            helper.setFilter(Flags.PUBLIC);
+        }
+    },
+
+    // ----- output control options -----
+
+    PROMPT("-prompt") {
+        @Override
+        public void process(Helper helper) {
+            helper.compOpts.put("-prompt", "-prompt");
+            helper.promptOnError = true;
+        }
+    },
+
+    QUIET("-quiet") {
+        @Override
+        public void process(Helper helper) {
+            helper.quiet = true;
+        }
+    },
+
+    VERBOSE("-verbose") {
+        @Override
+        public void process(Helper helper) {
+            helper.compOpts.put("-verbose", "");
+        }
+    },
+
+    XWERROR("-Xwerror") {
+        @Override
+        public void process(Helper helper) {
+            helper.rejectWarnings = true;
+
+        }
+    },
+
+    // ----- other options -----
+
+    BREAKITERATOR("-breakiterator") {
+        @Override
+        public void process(Helper helper) {
+            helper.breakiterator = true;
+        }
+    },
+
+    LOCALE("-locale", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.docLocale = arg;
+        }
+    },
+
+    OVERVIEW("-overview", true),
+
+    XCLASSES("-Xclasses") {
+        @Override
+        public void process(Helper helper) {
+            helper.docClasses = true;
+
+        }
+    },
+
+    // ----- help options -----
+
+    HELP("-help") {
+        @Override
+        public void process(Helper helper) {
+            helper.usage();
+        }
+    },
+
+    X("-X") {
+        @Override
+        public void process(Helper helper) {
+            helper.Xusage();
+        }
+    };
+
+    public final String opt;
+    public final boolean hasArg;
+
+    ToolOption(String opt) {
+        this(opt, false);
+    }
+
+    ToolOption(String opt, boolean hasArg) {
+        this.opt = opt;
+        this.hasArg = hasArg;
+    }
+
+    void process(Helper helper, String arg) { }
+
+    void process(Helper helper) { }
+
+    static ToolOption get(String name) {
+        for (ToolOption o: values()) {
+            if (name.equals(o.opt))
+                return o;
+        }
+        return null;
+    }
+
+    static abstract class Helper {
+        /** List of decoded options. */
+        final ListBuffer<String[]> options = new ListBuffer<>();
+
+        /** Selected packages, from -subpackages. */
+        final ListBuffer<String> subPackages = new ListBuffer<>();
+
+        /** Excluded packages, from -exclude. */
+        final ListBuffer<String> excludedPackages = new ListBuffer<>();
+
+        // File manager options
+        final Map<Option, String> fileManagerOpts = new LinkedHashMap<>();
+
+        /** javac options, set by various options. */
+        Options compOpts; // = Options.instance(context)
+
+        /* Encoding for javac, and files written? set by -encoding. */
+        String encoding = null;
+
+        /** Set by -breakiterator. */
+        boolean breakiterator = false;
+
+        /** Set by -quiet. */
+        boolean quiet = false;
+
+        /** Set by -Xclasses. */
+        boolean docClasses = false;
+
+        /** Set by -Xwerror. */
+        boolean rejectWarnings = false;
+
+        /** Set by -prompt. */
+        boolean promptOnError;
+
+        /** Set by -locale. */
+        String docLocale = "";
+
+        /** Set by -public, private, -protected, -package. */
+        ModifierFilter showAccess = null;
+
+        abstract void usage();
+        abstract void Xusage();
+
+        abstract void usageError(String msg, Object... args);
+
+        void addToList(ListBuffer<String> list, String str){
+            StringTokenizer st = new StringTokenizer(str, ":");
+            String current;
+            while(st.hasMoreTokens()){
+                current = st.nextToken();
+                list.append(current);
+            }
+        }
+
+        void setFilter(long filterBits) {
+            if (showAccess != null) {
+                usageError("main.incompatible.access.flags");
+            }
+            showAccess = new ModifierFilter(filterBits);
+        }
+
+        void setCompilerOpt(String opt, String arg) {
+            if (compOpts.get(opt) != null) {
+                usageError("main.option.already.seen", opt);
+            }
+            compOpts.put(opt, arg);
+        }
+
+        void setFileManagerOpt(Option opt, String arg) {
+            fileManagerOpts.put(opt, arg);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeMaker.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.ArrayType;
+import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.code.Type.TypeVar;
+import com.sun.tools.javac.util.List;
+import static com.sun.tools.javac.code.TypeTag.ARRAY;
+
+/**
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class TypeMaker {
+
+    public static com.sun.javadoc.Type getType(DocEnv env, Type t) {
+        return getType(env, t, true);
+    }
+
+    /**
+     * @param errToClassDoc  if true, ERROR type results in a ClassDoc;
+     *          false preserves legacy behavior
+     */
+    public static com.sun.javadoc.Type getType(DocEnv env, Type t,
+            boolean errorToClassDoc) {
+        return getType(env, t, errorToClassDoc, true);
+    }
+
+    public static com.sun.javadoc.Type getType(DocEnv env, Type t,
+            boolean errToClassDoc, boolean considerAnnotations) {
+        try {
+            return getTypeImpl(env, t, errToClassDoc, considerAnnotations);
+        } catch (CompletionFailure cf) {
+            /* Quietly ignore completion failures and try again - the type
+             * for which the CompletionFailure was thrown shouldn't be completed
+             * again by the completer that threw the CompletionFailure.
+             */
+            return getType(env, t, errToClassDoc, considerAnnotations);
+        }
+    }
+
+    @SuppressWarnings("fallthrough")
+    private static com.sun.javadoc.Type getTypeImpl(DocEnv env, Type t,
+            boolean errToClassDoc, boolean considerAnnotations) {
+        if (env.legacyDoclet) {
+            t = env.types.erasure(t);
+        }
+
+        if (considerAnnotations && t.isAnnotated()) {
+            return new AnnotatedTypeImpl(env, t);
+        }
+
+        switch (t.getTag()) {
+        case CLASS:
+            if (ClassDocImpl.isGeneric((ClassSymbol)t.tsym)) {
+                return env.getParameterizedType((ClassType)t);
+            } else {
+                return env.getClassDoc((ClassSymbol)t.tsym);
+            }
+        case WILDCARD:
+            Type.WildcardType a = (Type.WildcardType)t;
+            return new WildcardTypeImpl(env, a);
+        case TYPEVAR: return new TypeVariableImpl(env, (TypeVar)t);
+        case ARRAY: return new ArrayTypeImpl(env, t);
+        case BYTE: return PrimitiveType.byteType;
+        case CHAR: return PrimitiveType.charType;
+        case SHORT: return PrimitiveType.shortType;
+        case INT: return PrimitiveType.intType;
+        case LONG: return PrimitiveType.longType;
+        case FLOAT: return PrimitiveType.floatType;
+        case DOUBLE: return PrimitiveType.doubleType;
+        case BOOLEAN: return PrimitiveType.booleanType;
+        case VOID: return PrimitiveType.voidType;
+        case ERROR:
+            if (errToClassDoc)
+                return env.getClassDoc((ClassSymbol)t.tsym);
+            // FALLTHRU
+        default:
+            return new PrimitiveType(t.tsym.getQualifiedName().toString());
+        }
+    }
+
+    /**
+     * Convert a list of javac types into an array of javadoc types.
+     */
+    public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts) {
+        return getTypes(env, ts, new com.sun.javadoc.Type[ts.length()]);
+    }
+
+    /**
+     * Like the above version, but use and return the array given.
+     */
+    public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts,
+                                                  com.sun.javadoc.Type res[]) {
+        int i = 0;
+        for (Type t : ts) {
+            res[i++] = getType(env, t);
+        }
+        return res;
+    }
+
+    public static String getTypeName(Type t, boolean full) {
+        switch (t.getTag()) {
+        case ARRAY:
+            StringBuilder s = new StringBuilder();
+            while (t.hasTag(ARRAY)) {
+                s.append("[]");
+                t = ((ArrayType)t).elemtype;
+            }
+            s.insert(0, getTypeName(t, full));
+            return s.toString();
+        case CLASS:
+            return ClassDocImpl.getClassName((ClassSymbol)t.tsym, full);
+        default:
+            return t.tsym.getQualifiedName().toString();
+        }
+    }
+
+    /**
+     * Return the string representation of a type use.  Bounds of type
+     * variables are not included; bounds of wildcard types are.
+     * Class names are qualified if "full" is true.
+     */
+    static String getTypeString(DocEnv env, Type t, boolean full) {
+        // TODO: should annotations be included here?
+        switch (t.getTag()) {
+        case ARRAY:
+            StringBuilder s = new StringBuilder();
+            while (t.hasTag(ARRAY)) {
+                s.append("[]");
+                t = env.types.elemtype(t);
+            }
+            s.insert(0, getTypeString(env, t, full));
+            return s.toString();
+        case CLASS:
+            return ParameterizedTypeImpl.
+                        parameterizedTypeToString(env, (ClassType)t, full);
+        case WILDCARD:
+            Type.WildcardType a = (Type.WildcardType)t;
+            return WildcardTypeImpl.wildcardTypeToString(env, a, full);
+        default:
+            return t.tsym.getQualifiedName().toString();
+        }
+    }
+
+    /**
+     * Return the formal type parameters of a class or method as an
+     * angle-bracketed string.  Each parameter is a type variable with
+     * optional bounds.  Class names are qualified if "full" is true.
+     * Return "" if there are no type parameters or we're hiding generics.
+     */
+    static String typeParametersString(DocEnv env, Symbol sym, boolean full) {
+        if (env.legacyDoclet || sym.type.getTypeArguments().isEmpty()) {
+            return "";
+        }
+        StringBuilder s = new StringBuilder();
+        for (Type t : sym.type.getTypeArguments()) {
+            s.append(s.length() == 0 ? "<" : ", ");
+            s.append(TypeVariableImpl.typeVarToString(env, (TypeVar)t, full));
+        }
+        s.append(">");
+        return s.toString();
+    }
+
+    /**
+     * Return the actual type arguments of a parameterized type as an
+     * angle-bracketed string.  Class name are qualified if "full" is true.
+     * Return "" if there are no type arguments or we're hiding generics.
+     */
+    static String typeArgumentsString(DocEnv env, ClassType cl, boolean full) {
+        if (env.legacyDoclet || cl.getTypeArguments().isEmpty()) {
+            return "";
+        }
+        StringBuilder s = new StringBuilder();
+        for (Type t : cl.getTypeArguments()) {
+            s.append(s.length() == 0 ? "<" : ", ");
+            s.append(getTypeString(env, t, full));
+        }
+        s.append(">");
+        return s.toString();
+    }
+
+
+    private static class ArrayTypeImpl implements com.sun.javadoc.Type {
+
+        Type arrayType;
+
+        DocEnv env;
+
+        ArrayTypeImpl(DocEnv env, Type arrayType) {
+            this.env = env;
+            this.arrayType = arrayType;
+        }
+
+        private com.sun.javadoc.Type skipArraysCache = null;
+
+        public com.sun.javadoc.Type getElementType() {
+            return TypeMaker.getType(env, env.types.elemtype(arrayType));
+        }
+
+        private com.sun.javadoc.Type skipArrays() {
+            if (skipArraysCache == null) {
+                Type t;
+                for (t = arrayType; t.hasTag(ARRAY); t = env.types.elemtype(t)) { }
+                skipArraysCache = TypeMaker.getType(env, t);
+            }
+            return skipArraysCache;
+        }
+
+        /**
+         * Return the type's dimension information, as a string.
+         * <p>
+         * For example, a two dimensional array of String returns '[][]'.
+         */
+        public String dimension() {
+            StringBuilder dimension = new StringBuilder();
+            for (Type t = arrayType; t.hasTag(ARRAY); t = env.types.elemtype(t)) {
+                dimension.append("[]");
+            }
+            return dimension.toString();
+        }
+
+        /**
+         * Return unqualified name of type excluding any dimension information.
+         * <p>
+         * For example, a two dimensional array of String returns 'String'.
+         */
+        public String typeName() {
+            return skipArrays().typeName();
+        }
+
+        /**
+         * Return qualified name of type excluding any dimension information.
+         *<p>
+         * For example, a two dimensional array of String
+         * returns 'java.lang.String'.
+         */
+        public String qualifiedTypeName() {
+            return skipArrays().qualifiedTypeName();
+        }
+
+        /**
+         * Return the simple name of this type excluding any dimension information.
+         */
+        public String simpleTypeName() {
+            return skipArrays().simpleTypeName();
+        }
+
+        /**
+         * Return this type as a class.  Array dimensions are ignored.
+         *
+         * @return a ClassDocImpl if the type is a Class.
+         * Return null if it is a primitive type..
+         */
+        public ClassDoc asClassDoc() {
+            return skipArrays().asClassDoc();
+        }
+
+        /**
+         * Return this type as a <code>ParameterizedType</code> if it
+         * represents a parameterized type.  Array dimensions are ignored.
+         */
+        public ParameterizedType asParameterizedType() {
+            return skipArrays().asParameterizedType();
+        }
+
+        /**
+         * Return this type as a <code>TypeVariable</code> if it represents
+         * a type variable.  Array dimensions are ignored.
+         */
+        public TypeVariable asTypeVariable() {
+            return skipArrays().asTypeVariable();
+        }
+
+        /**
+         * Return null, as there are no arrays of wildcard types.
+         */
+        public WildcardType asWildcardType() {
+            return null;
+        }
+
+        /**
+         * Return null, as there are no annotations of the type
+         */
+        public AnnotatedType asAnnotatedType() {
+            return null;
+        }
+
+        /**
+         * Return this type as an <code>AnnotationTypeDoc</code> if it
+         * represents an annotation type.  Array dimensions are ignored.
+         */
+        public AnnotationTypeDoc asAnnotationTypeDoc() {
+            return skipArrays().asAnnotationTypeDoc();
+        }
+
+        /**
+         * Return true if this is an array of a primitive type.
+         */
+        public boolean isPrimitive() {
+            return skipArrays().isPrimitive();
+        }
+
+        /**
+         * Return a string representation of the type.
+         *
+         * Return name of type including any dimension information.
+         * <p>
+         * For example, a two dimensional array of String returns
+         * <code>String[][]</code>.
+         *
+         * @return name of type including any dimension information.
+         */
+        @Override
+        public String toString() {
+            return qualifiedTypeName() + dimension();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/TypeVariableImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.tools.javac.code.Attribute;
+import com.sun.tools.javac.code.Attribute.TypeCompound;
+import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.Kinds.KindSelector;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.TypeVar;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+
+/**
+ * Implementation of <code>TypeVariable</code>, which
+ * represents a type variable.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Scott Seligman
+ * @since 1.5
+ */
+public class TypeVariableImpl extends AbstractTypeImpl implements TypeVariable {
+
+    TypeVariableImpl(DocEnv env, TypeVar type) {
+        super(env, type);
+    }
+
+    /**
+     * Return the bounds of this type variable.
+     */
+    public com.sun.javadoc.Type[] bounds() {
+        return TypeMaker.getTypes(env, getBounds((TypeVar)type, env));
+    }
+
+    /**
+     * Return the class, interface, method, or constructor within
+     * which this type variable is declared.
+     */
+    public ProgramElementDoc owner() {
+        Symbol osym = type.tsym.owner;
+        if (osym.kind.matches(KindSelector.TYP)) {
+            return env.getClassDoc((ClassSymbol)osym);
+        }
+        Names names = osym.name.table.names;
+        if (osym.name == names.init) {
+            return env.getConstructorDoc((MethodSymbol)osym);
+        } else {
+            return env.getMethodDoc((MethodSymbol)osym);
+        }
+    }
+
+    /**
+     * Return the ClassDoc of the erasure of this type variable.
+     */
+    @Override
+    public ClassDoc asClassDoc() {
+        return env.getClassDoc((ClassSymbol)env.types.erasure(type).tsym);
+    }
+
+    @Override
+    public TypeVariable asTypeVariable() {
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return typeVarToString(env, (TypeVar)type, true);
+    }
+
+
+    /**
+     * Return the string form of a type variable along with any
+     * "extends" clause.  Class names are qualified if "full" is true.
+     */
+    static String typeVarToString(DocEnv env, TypeVar v, boolean full) {
+        StringBuilder s = new StringBuilder(v.toString());
+        List<Type> bounds = getBounds(v, env);
+        if (bounds.nonEmpty()) {
+            boolean first = true;
+            for (Type b : bounds) {
+                s.append(first ? " extends " : " & ");
+                s.append(TypeMaker.getTypeString(env, b, full));
+                first = false;
+            }
+        }
+        return s.toString();
+    }
+
+    /**
+     * Get the bounds of a type variable as listed in the "extends" clause.
+     */
+    private static List<Type> getBounds(TypeVar v, DocEnv env) {
+        final Type upperBound = v.getUpperBound();
+        Name boundname = upperBound.tsym.getQualifiedName();
+        if (boundname == boundname.table.names.java_lang_Object
+            && !upperBound.isAnnotated()) {
+            return List.nil();
+        } else {
+            return env.types.getBounds(v);
+        }
+    }
+
+    /**
+     * Get the annotations of this program element.
+     * Return an empty array if there are none.
+     */
+    public AnnotationDesc[] annotations() {
+        if (!type.isAnnotated()) {
+            return new AnnotationDesc[0];
+        }
+        List<? extends TypeCompound> tas = type.getAnnotationMirrors();
+        AnnotationDesc res[] = new AnnotationDesc[tas.length()];
+        int i = 0;
+        for (Attribute.Compound a : tas) {
+            res[i++] = new AnnotationDescImpl(env, a);
+        }
+        return res;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/WildcardTypeImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2003, 2012, 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.sun.tools.javadoc.main;
+
+import com.sun.javadoc.*;
+
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.util.List;
+
+
+/**
+ * Implementation of <code>WildcardType</code>, which
+ * represents a wildcard type.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Scott Seligman
+ * @since 1.5
+ */
+public class WildcardTypeImpl extends AbstractTypeImpl implements WildcardType {
+
+    WildcardTypeImpl(DocEnv env, Type.WildcardType type) {
+        super(env, type);
+    }
+
+    /**
+     * Return the upper bounds of this wildcard type argument
+     * as given by the <i>extends</i> clause.
+     * Return an empty array if no such bounds are explicitly given.
+     */
+    public com.sun.javadoc.Type[] extendsBounds() {
+        return TypeMaker.getTypes(env, getExtendsBounds((Type.WildcardType)type));
+    }
+
+    /**
+     * Return the lower bounds of this wildcard type argument
+     * as given by the <i>super</i> clause.
+     * Return an empty array if no such bounds are explicitly given.
+     */
+    public com.sun.javadoc.Type[] superBounds() {
+        return TypeMaker.getTypes(env, getSuperBounds((Type.WildcardType)type));
+    }
+
+    /**
+     * Return the ClassDoc of the erasure of this wildcard type.
+     */
+    @Override
+    public ClassDoc asClassDoc() {
+        return env.getClassDoc((ClassSymbol)env.types.erasure(type).tsym);
+    }
+
+    @Override
+    public WildcardType asWildcardType() {
+        return this;
+    }
+
+    @Override
+    public String typeName()            { return "?"; }
+    @Override
+    public String qualifiedTypeName()   { return "?"; }
+    @Override
+    public String simpleTypeName()      { return "?"; }
+
+    @Override
+    public String toString() {
+        return wildcardTypeToString(env, (Type.WildcardType)type, true);
+    }
+
+
+    /**
+     * Return the string form of a wildcard type ("?") along with any
+     * "extends" or "super" clause.  Delimiting brackets are not
+     * included.  Class names are qualified if "full" is true.
+     */
+    static String wildcardTypeToString(DocEnv env,
+                                       Type.WildcardType wildThing, boolean full) {
+        if (env.legacyDoclet) {
+            return TypeMaker.getTypeName(env.types.erasure(wildThing), full);
+        }
+        StringBuilder s = new StringBuilder("?");
+        List<Type> bounds = getExtendsBounds(wildThing);
+        if (bounds.nonEmpty()) {
+            s.append(" extends ");
+        } else {
+            bounds = getSuperBounds(wildThing);
+            if (bounds.nonEmpty()) {
+                s.append(" super ");
+            }
+        }
+        boolean first = true;   // currently only one bound is allowed
+        for (Type b : bounds) {
+            if (!first) {
+                s.append(" & ");
+            }
+            s.append(TypeMaker.getTypeString(env, b, full));
+            first = false;
+        }
+        return s.toString();
+    }
+
+    private static List<Type> getExtendsBounds(Type.WildcardType wild) {
+        return wild.isSuperBound()
+                ? List.<Type>nil()
+                : List.of(wild.type);
+    }
+
+    private static List<Type> getSuperBounds(Type.WildcardType wild) {
+        return wild.isExtendsBound()
+                ? List.<Type>nil()
+                : List.of(wild.type);
+    }
+}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -91,6 +91,19 @@
     }
 
     /**
+     * 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.
      *
      * @return a content tree for the package link
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -505,6 +505,19 @@
     }
 
     /**
+     * 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.
      *
      * @return a content tree for the package link
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -105,6 +105,19 @@
     }
 
     /**
+     * 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.
      *
      * @return a content tree for the package link
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -570,6 +570,11 @@
             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()) {
@@ -679,6 +684,28 @@
     }
 
     /**
+     * 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.
      *
      * @param pkg Package to which link will be generated
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -268,6 +268,17 @@
     }
 
     /**
+     * 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.
      *
      * @return a content tree for the previous link
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -224,6 +224,19 @@
     }
 
     /**
+     * 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.
      *
      * @return a content tree for the package link
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Wed Jul 05 21:42:16 2017 +0200
@@ -304,6 +304,19 @@
     }
 
     /**
+     * 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.
      *
      * @return a content tree for the package link
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -376,6 +376,19 @@
     }
 
     /**
+     * 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.
      *
      * @return a content tree for the package link
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java	Wed Jul 05 21:42:16 2017 +0200
@@ -329,6 +329,7 @@
     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 @@
                 s.add(p);
             }
         }
+        modules = new TreeSet<>(utils.makeModuleComparator());
+        modules.addAll(modulePackages.keySet());
         showModules = (modulePackages.size() > 1);
     }
 
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java	Wed Jul 05 21:42:16 2017 +0200
@@ -283,8 +283,8 @@
             }
         } 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");
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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.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.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 @@
         }
     }
 
+    //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 @@
             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 @@
                         .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 @@
         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 @@
                     } else {
                         header.append(p.asType());
                     }
-                    header.append(" ");
-                    header.append(p.getSimpleName());
+                    if (includeParameterNames) {
+                        header.append(" ");
+                        header.append(p.getSimpleName());
+                    }
                     sep = ", ";
                 }
                 header.append(")");
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java	Wed Jul 05 21:42:16 2017 +0200
@@ -215,17 +215,21 @@
 
         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 @@
 
         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() {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
         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;
--- a/langtools/test/Makefile	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/test/Makefile	Wed Jul 05 21:42:16 2017 +0200
@@ -86,6 +86,8 @@
 # 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 @@
 #
 # 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 @@
 	-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 @@
 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 @@
 	  -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 \
 	)
--- a/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java	Wed Jul 05 21:42:16 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8154119
+ * @bug 8154119 8154262
  * @summary Test modules support in javadoc.
  * @author bpatel
  * @library ../lib
@@ -41,46 +41,58 @@
 
     @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 @@
                 + "<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>");
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/testpkgnomodule/TestClassNoModule.java	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 testpkgnomodule;
+
+public class TestClassNoModule {
+}
--- a/langtools/test/jdk/jshell/CompletionSuggestionTest.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/test/jdk/jshell/CompletionSuggestionTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
         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 @@
                                                      "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 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 @@
         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 @@
         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]);
+    }
 }
--- a/langtools/test/tools/javac/6330997/T6330997.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/test/tools/javac/6330997/T6330997.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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
  */
 
--- a/langtools/test/tools/javac/classfiles/ClassVersionChecker.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/test/tools/javac/classfiles/ClassVersionChecker.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 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 @@
          * -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++) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/importscope/TestDeepFinishClassStack.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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();
+    }
+
+}
--- a/langtools/test/tools/javac/versions/Versions.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/langtools/test/tools/javac/versions/Versions.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
 
     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 @@
         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");
--- a/make/Images.gmk	Wed Jul 05 21:41:02 2017 +0200
+++ b/make/Images.gmk	Wed Jul 05 21:42:16 2017 +0200
@@ -114,8 +114,18 @@
 # 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)
--- a/make/common/NativeCompilation.gmk	Wed Jul 05 21:41:02 2017 +0200
+++ b/make/common/NativeCompilation.gmk	Wed Jul 05 21:42:16 2017 +0200
@@ -770,13 +770,20 @@
 		$$(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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/idea.gmk	Wed Jul 05 21:42:16 2017 +0200
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/.name	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,1 @@
+jdk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/ant.xml	Wed Jul 05 21:42:16 2017 +0200
@@ -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>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/build.xml	Wed Jul 05 21:42:16 2017 +0200
@@ -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>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/compiler.xml	Wed Jul 05 21:42:16 2017 +0200
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/copyright/profiles_settings.xml	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,3 @@
+<component name="CopyrightManager">
+  <settings default="" />
+</component>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/jdk.iml	Wed Jul 05 21:42:16 2017 +0200
@@ -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>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/misc.xml	Wed Jul 05 21:42:16 2017 +0200
@@ -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>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/modules.xml	Wed Jul 05 21:42:16 2017 +0200
@@ -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>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/scopes/scope_settings.xml	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,5 @@
+<component name="DependencyValidationManager">
+  <state>
+    <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+  </state>
+</component>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/src/idea/JdkIdeaAntLogger.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/vcs.xml	Wed Jul 05 21:42:16 2017 +0200
@@ -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>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/idea/template/workspace.xml	Wed Jul 05 21:42:16 2017 +0200
@@ -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>
--- a/nashorn/.hgtags	Wed Jul 05 21:41:02 2017 +0200
+++ b/nashorn/.hgtags	Wed Jul 05 21:42:16 2017 +0200
@@ -351,3 +351,4 @@
 295ac208a4443d433214d0c1f32d2ea45a3a32d2 jdk-9+115
 208388a5622dcca8227d6ad6c268f2c88087d283 jdk-9+116
 5267e91811614bac129817e566f730e9d63cf22a jdk-9+117
+05679aac2f7ec3d8dd2a96d7e7899906224bf5cf jdk-9+118
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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 @@
     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 @@
      *         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 @@
      *
      * @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 @@
      *
      * @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());
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java	Wed Jul 05 21:42:16 2017 +0200
@@ -174,10 +174,8 @@
                 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 @@
         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'
      *
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilerConstants.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilerConstants.java	Wed Jul 05 21:42:16 2017 +0200
@@ -78,6 +78,12 @@
     /** 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"),
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Namespace.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Namespace.java	Wed Jul 05 21:42:16 2017 +0200
@@ -68,7 +68,7 @@
     }
 
     /**
-     * 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 @@
             if (counter != null) {
                 final int count = counter + 1;
                 namespaceDirectory.put(truncatedBase, count);
-                return truncatedBase + '-' + count;
+                return truncatedBase + CompilerConstants.ID_FUNCTION_SEPARATOR.symbolName() + count;
             }
         }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java	Wed Jul 05 21:42:16 2017 +0200
@@ -203,8 +203,10 @@
      * @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.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Wed Jul 05 21:42:16 2017 +0200
@@ -534,7 +534,7 @@
 
         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 @@
 
     /**
      * ExpressionStatement :
-     *      Expression ; // [lookahead ~( or  function )]
+     *      Expression ; // [lookahead ~({ or  function )]
      *
      * See 12.4
      *
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java	Wed Jul 05 21:41:02 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java	Wed Jul 05 21:42:16 2017 +0200
@@ -313,18 +313,8 @@
         }
     }
 
-    /**
-     * 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,18 +342,38 @@
             };
         }
 
+        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();
         }
 
+        final Iterator<?> itr = iteratorForJavaArrayOrList(obj);
+        if (itr != null) {
+            return itr;
+        }
+
         if (obj instanceof Map) {
             return ((Map<?,?>)obj).values().iterator();
         }
 
-        if (obj instanceof Iterable) {
-            return ((Iterable<?>)obj).iterator();
-        }
-
         final Object wrapped = Global.instance().wrapAsObject(obj);
         if (wrapped instanceof ScriptObject) {
             return ((ScriptObject)wrapped).valueIterator();
@@ -380,6 +390,14 @@
      * @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);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/Makefile	Wed Jul 05 21:42:16 2017 +0200
@@ -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)
+
+################################################################
--- a/nashorn/test/script/basic/JDK-8025515.js	Wed Jul 05 21:41:02 2017 +0200
+++ b/nashorn/test/script/basic/JDK-8025515.js	Wed Jul 05 21:42:16 2017 +0200
@@ -61,8 +61,8 @@
 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");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8156714.js	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +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.
+ * 
+ * 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-8156714: Parsing issue with automatic semicolon insertion
+ *
+ * @test
+ * @run
+ */
+
+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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8156896.js	Wed Jul 05 21:42:16 2017 +0200
@@ -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());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/JDK-8156665.js	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +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.
+ * 
+ * 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-8156665: ES6 for..of should work on Java Iterables and Java arrays
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+var ca = new (Java.type("char[]"))(3);
+ca[0] = 'a', ca[1] = 'b', ca[2] = 'c';
+for (i of ca) print(i);
+
+var al = new java.util.ArrayList();
+al.add("hello");
+al.add("world");
+
+for (i of al) print(i);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/JDK-8156665.js.EXPECTED	Wed Jul 05 21:42:16 2017 +0200
@@ -0,0 +1,5 @@
+a
+b
+c
+hello
+world
--- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED	Wed Jul 05 21:41:02 2017 +0200
+++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED	Wed Jul 05 21:42:16 2017 +0200
@@ -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": {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/dynalink/test/LinkedCallSiteLocationTest.java	Wed Jul 05 21:42:16 2017 +0200
@@ -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() {
+        }
+    }
+}
--- a/test/Makefile	Wed Jul 05 21:41:02 2017 +0200
+++ b/test/Makefile	Wed Jul 05 21:42:16 2017 +0200
@@ -87,7 +87,7 @@
 #
 # 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/make/TestIdea.gmk	Wed Jul 05 21:42:16 2017 +0200
@@ -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
--- a/test/make/TestMake.gmk	Wed Jul 05 21:41:02 2017 +0200
+++ b/test/make/TestMake.gmk	Wed Jul 05 21:42:16 2017 +0200
@@ -33,7 +33,10 @@
 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