changeset 37916:627154540b60

Merge
author duke
date Wed, 05 Jul 2017 21:41:36 +0200
parents be4ff50b6cb6 a2f43d835fa1
children 3560b89fb532
files jdk/make/non-build-utils/src/build/tools/makeclasslist/makeClasslist.js jdk/make/src/classes/build/tools/addjsum/AddJsum.java jdk/src/java.base/share/classes/java/util/regex/UnicodeProp.java jdk/src/java.httpclient/share/classes/java/net/http/CharsetToolkit.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/libsoftcrypto.h jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SortResourcesPlugin.java jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java jdk/test/java/rmi/transport/httpSocket/security.policy jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy jdk/test/tools/jlink/plugins/SorterPluginTest.java
diffstat 255 files changed, 13771 insertions(+), 9456 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Thu May 12 15:15:02 2016 +0000
+++ b/.hgignore	Wed Jul 05 21:41:36 2017 +0200
@@ -1,5 +1,6 @@
 ^build/
 ^dist/
+^.idea/
 nbproject/private/
 ^webrev
 ^.hgtip
--- a/.hgtags-top-repo	Thu May 12 15:15:02 2016 +0000
+++ b/.hgtags-top-repo	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/common/autoconf/flags.m4	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/common/autoconf/toolchain.m4	Wed Jul 05 21:41:36 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:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/common/bin/jib.sh	Wed Jul 05 21:41:36 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/hotspot/.hgtags	Thu May 12 15:15:02 2016 +0000
+++ b/hotspot/.hgtags	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/hotspot/test/Makefile	Wed Jul 05 21:41:36 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/jdk/.hgtags	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/.hgtags	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/make/Tools.gmk	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/make/launcher/Launcher-java.base.gmk	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/make/lib/Awt2dLibraries.gmk	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/make/mapfiles/libj2ucrypto/mapfile-vers	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ /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	Thu May 12 15:15:02 2016 +0000
+++ /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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Integer.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Long.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Field.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/InaccessibleObjectException.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/net/URLDecoder.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/net/URLEncoder.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/security/DrbgParameters.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/security/InvalidAlgorithmParameterException.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/security/InvalidKeyException.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/security/Provider.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/security/Security.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/security/spec/InvalidKeySpecException.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/text/MessageFormat.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/Instant.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/LocalDateTime.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/LocalTime.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/OffsetDateTime.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/OffsetTime.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/ZonedDateTime.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/Comparator.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java	Wed Jul 05 21:41:36 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:41:36 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:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/regex/Matcher.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/regex/Pattern.java	Wed Jul 05 21:41:36 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.
+     * 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 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);
+    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;
                 }
-                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);
+                cc++;
+            } else if (c == ']' && last != '\\') {
+                cc--;
+                if (cc == 0) {
+                    normalizeClazz(pattern, lastStart, i + 1, pbuf);
+                    lastStart = i + 1;
+                }
             }
-            lastCodePoint = c;
-            i += Character.charCount(c);
-        }
-        normalizedPattern = newPattern.toString();
+            last = c;
+            i++;
+        }
+        assert (cc == 0);
+        if (lastStart < plen)
+            normalizeSlice(pattern, lastStart, plen, pbuf);
+        return pbuf.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.
-     */
-    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 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;
+            }
+            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 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++;
             }
-            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;
+            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);
+                return new Ques(prev, Qtype.LAZY);
             } else if (ch == '+') {
                 next();
-                return new Ques(prev, POSSESSIVE);
+                return new Ques(prev, Qtype.POSSESSIVE);
             }
-            return new Ques(prev, GREEDY);
+            return new Ques(prev, Qtype.GREEDY);
         case '*':
-            ch = next();
-            if (ch == '?') {
-                next();
-                return new Curly(prev, 0, MAX_REPS, LAZY);
-            } else if (ch == '+') {
-                next();
-                return new Curly(prev, 0, MAX_REPS, POSSESSIVE);
-            }
-            return new Curly(prev, 0, MAX_REPS, GREEDY);
+            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:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ /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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/javax/security/auth/callback/UnsupportedCallbackException.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/net/ftp/FtpClient.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/HashDrbg.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/HmacDrbg.java	Wed Jul 05 21:41:36 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:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SecureRandom.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPNonceExtension.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/conf/security/java.security	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/share/native/libjava/VM.c	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/unix/classes/sun/security/provider/NativePRNG.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Wed Jul 05 21:41:36 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));
+        strncpy(if2.ifr_name, ifreqP->ifr_name, sizeof(if2.ifr_name) - 1);
 
-        memset((char *)&if2, 0, sizeof(if2));
-        strcpy(if2.ifr_name, ifreqP->ifr_name);
-
-        /*
-         * 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;
+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);
 
-  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;
+    }
 
-  /* 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;
-  }
+    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;
+        }
 
-  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;
-      }
+        ret = brdcast_store;
+        memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
+    }
 
-      ret = brdcast_store;
-      memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
-  }
-
-  return ret;
+    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.
-      */
 
-    if (! alreadyV6 ){
-        memset((char *) &if2, 0, sizeof(if2));
-        strcpy(if2.lifr_name, ifname);
+    // 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));
+        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));
+    strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
 
-    memset((char *) &if2, 0, sizeof(if2));
-    strcpy(if2.lifr_name, ifname);
-
-    /* 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);
 
-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 *)&if2) < 0) {
+         return -1;
+    }
 
-     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
-         return -1;
-     }
-
-     *flags = lifr.lifr_flags;
-     return 0;
+    *flags = if2.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;
+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);
 
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
+    // 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;
+    }
 
-  /* 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;
-  }
+    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;
+        }
 
-  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;
-      }
+        ret = brdcast_store;
+        memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
+    }
 
-      ret = brdcast_store;
-      memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
-  }
-
-  return ret;
+    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	Thu May 12 15:15:02 2016 +0000
+++ /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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java	Wed Jul 05 21:41:36 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	Thu May 12 15:15:02 2016 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java	Wed Jul 05 21:41:36 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:41:36 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 + "]");
+        }
+    }
+<